2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.analysis.AnnotationSorter;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.bin.Cache;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.SearchResults;
28 import jalview.datamodel.SequenceFeature;
29 import jalview.datamodel.SequenceGroup;
30 import jalview.datamodel.SequenceI;
31 import jalview.jbgui.GAlignmentPanel;
32 import jalview.math.AlignmentDimension;
33 import jalview.schemes.ResidueProperties;
34 import jalview.structure.StructureSelectionManager;
35 import jalview.util.MessageManager;
37 import java.awt.BorderLayout;
38 import java.awt.Color;
39 import java.awt.Container;
40 import java.awt.Dimension;
42 import java.awt.FontMetrics;
43 import java.awt.Graphics;
44 import java.awt.event.AdjustmentEvent;
45 import java.awt.event.AdjustmentListener;
46 import java.awt.print.PageFormat;
47 import java.awt.print.Printable;
48 import java.awt.print.PrinterException;
49 import java.beans.PropertyChangeEvent;
50 import java.beans.PropertyChangeListener;
52 import java.io.FileWriter;
53 import java.io.PrintWriter;
55 import javax.swing.SwingUtilities;
61 * @version $Revision: 1.161 $
63 public class AlignmentPanel extends GAlignmentPanel implements
64 AdjustmentListener, Printable, AlignmentViewPanel
66 public AlignViewport av;
68 OverviewPanel overviewPanel;
70 private SeqPanel seqPanel;
72 private IdPanel idPanel;
74 private boolean headless;
75 IdwidthAdjuster idwidthAdjuster;
78 public AlignFrame alignFrame;
80 private ScalePanel scalePanel;
82 private AnnotationPanel annotationPanel;
84 private AnnotationLabels alabels;
86 // this value is set false when selection area being dragged
87 boolean fastPaint = true;
94 * Creates a new AlignmentPanel object.
101 public AlignmentPanel(AlignFrame af, final AlignViewport av)
105 setSeqPanel(new SeqPanel(av, this));
106 setIdPanel(new IdPanel(av, this));
108 setScalePanel(new ScalePanel(av, this));
110 idPanelHolder.add(getIdPanel(), BorderLayout.CENTER);
111 idwidthAdjuster = new IdwidthAdjuster(this);
112 idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
114 setAnnotationPanel(new AnnotationPanel(this));
115 setAlabels(new AnnotationLabels(this));
117 annotationScroller.setViewportView(getAnnotationPanel());
118 annotationSpaceFillerHolder.add(getAlabels(), BorderLayout.CENTER);
120 scalePanelHolder.add(getScalePanel(), BorderLayout.CENTER);
121 seqPanelHolder.add(getSeqPanel(), BorderLayout.CENTER);
123 setScrollValues(0, 0);
125 setAnnotationVisible(av.getShowAnnotation());
127 hscroll.addAdjustmentListener(this);
128 vscroll.addAdjustmentListener(this);
130 final AlignmentPanel ap = this;
131 av.addPropertyChangeListener(new PropertyChangeListener()
133 public void propertyChange(PropertyChangeEvent evt)
135 if (evt.getPropertyName().equals("alignment"))
137 PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
143 adjustAnnotationHeight();
147 public void alignmentChanged()
149 av.alignmentChanged(this);
151 alignFrame.updateEditMenuBar();
153 paintAlignment(true);
160 public void fontChanged()
162 // set idCanvas bufferedImage to null
163 // to prevent drawing old image
164 FontMetrics fm = getFontMetrics(av.getFont());
166 scalePanelHolder.setPreferredSize(new Dimension(10, av.charHeight
168 idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight
171 getIdPanel().getIdCanvas().gg = null;
172 getSeqPanel().seqCanvas.img = null;
173 getAnnotationPanel().adjustPanelHeight();
175 Dimension d = calculateIdWidth();
176 d.setSize(d.width + 4, d.height);
177 getIdPanel().getIdCanvas().setPreferredSize(d);
178 hscrollFillerPanel.setPreferredSize(d);
180 if (overviewPanel != null)
182 overviewPanel.setBoxPosition();
189 * Calculate the width of the alignment labels based on the displayed names
190 * and any bounds on label width set in preferences.
192 * @return Dimension giving the maximum width of the alignment label panel
193 * that should be used.
195 public Dimension calculateIdWidth()
197 // calculate sensible default width when no preference is available
199 int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
200 int maxwidth = Math.max(20,
201 Math.min(afwidth - 200, 2 * afwidth / 3));
202 return calculateIdWidth(maxwidth);
206 * Calculate the width of the alignment labels based on the displayed names
207 * and any bounds on label width set in preferences.
210 * -1 or maximum width allowed for IdWidth
211 * @return Dimension giving the maximum width of the alignment label panel
212 * that should be used.
214 public Dimension calculateIdWidth(int maxwidth)
216 Container c = new Container();
218 FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
219 Font.ITALIC, av.font.getSize()));
221 AlignmentI al = av.getAlignment();
226 while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
228 SequenceI s = al.getSequenceAt(i);
230 id = s.getDisplayId(av.getShowJVSuffix());
232 if (fm.stringWidth(id) > idWidth)
234 idWidth = fm.stringWidth(id);
240 // Also check annotation label widths
243 if (al.getAlignmentAnnotation() != null)
245 fm = c.getFontMetrics(getAlabels().getFont());
247 while (i < al.getAlignmentAnnotation().length)
249 String label = al.getAlignmentAnnotation()[i].label;
251 if (fm.stringWidth(label) > idWidth)
253 idWidth = fm.stringWidth(label);
260 return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
265 * Highlight the given results on the alignment.
268 public void highlightSearchResults(SearchResults results)
270 scrollToPosition(results);
271 getSeqPanel().seqCanvas.highlightSearchResults(results);
275 * scroll the view to show the position of the highlighted region in results
276 * (if any) and redraw the overview
280 public boolean scrollToPosition(SearchResults results)
282 return scrollToPosition(results, true);
286 * scroll the view to show the position of the highlighted region in results
290 * @param redrawOverview
291 * - when set, the overview will be recalculated (takes longer)
292 * @return false if results were not found
294 public boolean scrollToPosition(SearchResults results,
295 boolean redrawOverview)
297 int startv, endv, starts, ends, width;
298 // TODO: properly locate search results in view when large numbers of hidden
299 // columns exist before highlighted region
300 // do we need to scroll the panel?
301 // TODO: tons of nullpointereexceptions raised here.
302 if (results != null && results.getSize() > 0 && av != null
303 && av.getAlignment() != null)
305 int seqIndex = av.getAlignment().findIndex(results);
310 SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
312 int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
319 // System.err.println("Seq : "+seqIndex+" Scroll to "+start+","+end); //
325 if (end == seq.getEnd())
329 if (av.hasHiddenColumns())
331 start = av.getColumnSelection().findColumnPosition(start);
332 end = av.getColumnSelection().findColumnPosition(end);
335 if (!av.getColumnSelection().isVisible(r[0]))
337 // don't scroll - position isn't visible
342 if (!av.wrapAlignment)
344 if ((startv = av.getStartRes()) >= start)
346 setScrollValues(start - 1, seqIndex);
348 else if ((endv = av.getEndRes()) <= end)
350 setScrollValues(startv + 1 + end - endv, seqIndex);
352 else if ((starts = av.getStartSeq()) > seqIndex)
354 setScrollValues(av.getStartRes(), seqIndex);
356 else if ((ends = av.getEndSeq()) <= seqIndex)
358 setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
363 scrollToWrappedVisible(start);
366 if (redrawOverview && overviewPanel != null)
368 overviewPanel.setBoxPosition();
370 paintAlignment(redrawOverview);
374 void scrollToWrappedVisible(int res)
376 int cwidth = getSeqPanel().seqCanvas
377 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
378 if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
380 vscroll.setValue((res / cwidth));
381 av.startRes = vscroll.getValue() * cwidth;
389 * @return DOCUMENT ME!
391 public OverviewPanel getOverviewPanel()
393 return overviewPanel;
402 public void setOverviewPanel(OverviewPanel op)
410 * Hide or show annotation panel
413 public void setAnnotationVisible(boolean b)
415 if (!av.wrapAlignment)
417 annotationSpaceFillerHolder.setVisible(b);
418 annotationScroller.setVisible(b);
424 * automatically adjust annotation panel height for new annotation whilst
425 * ensuring the alignment is still visible.
427 public void adjustAnnotationHeight()
429 // TODO: display vertical annotation scrollbar if necessary
430 // this is called after loading new annotation onto alignment
431 if (alignFrame.getHeight() == 0)
433 System.out.println("NEEDS FIXING");
435 validateAnnotationDimensions(true);
437 paintAlignment(true);
441 * calculate the annotation dimensions and refresh slider values accordingly.
442 * need to do repaints/notifys afterwards.
444 protected void validateAnnotationDimensions(boolean adjustPanelHeight)
446 int height = getAnnotationPanel().adjustPanelHeight();
448 int theight = av.getCharHeight()
449 * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0
450 : av.getAlignment().getHiddenSequences().getSize()));
451 float sscaling = (float) (theight / (1.0 * theight + height));
452 float ascaling = (float) (height * 1.0 / alignFrame.getHeight());
453 int rheight = alignFrame.getHeight() - height - av.getCharHeight();
454 if (adjustPanelHeight)
456 // NOTE: this logic is different in the applet. Need a better algorithm to
458 // try and set height according to alignment
459 if (ascaling > 0 && sscaling < 0.5)
461 // if the alignment is too big then
462 // default is 0.5 split
463 height = alignFrame.getHeight() / 2;
467 // if space for more than one sequence row left when annotation is fully
468 // displayed then set height to annotation height
469 // otherwise, leave at least two lines of sequence shown.
470 height = (rheight > av.getCharHeight()) ? height
471 : (-av.getCharHeight() * 3 + (int) (alignFrame.getHeight() * (1 - sscaling)));
476 // maintain same window layout whilst updating sliders
477 height = annotationScroller.getSize().height;
481 annotationScroller.setPreferredSize(new Dimension(annotationScroller
482 .getWidth(), height));
484 annotationSpaceFillerHolder.setPreferredSize(new Dimension(
485 annotationSpaceFillerHolder.getWidth(), height));
486 annotationScroller.validate();// repaint();
487 annotationScroller.addNotify();
496 public void setWrapAlignment(boolean wrap)
499 scalePanelHolder.setVisible(!wrap);
500 hscroll.setVisible(!wrap);
501 idwidthAdjuster.setVisible(!wrap);
505 annotationScroller.setVisible(false);
506 annotationSpaceFillerHolder.setVisible(false);
508 else if (av.isShowAnnotation())
510 annotationScroller.setVisible(true);
511 annotationSpaceFillerHolder.setVisible(true);
514 idSpaceFillerPanel1.setVisible(!wrap);
519 // return value is true if the scroll is valid
520 public boolean scrollUp(boolean up)
524 if (vscroll.getValue() < 1)
530 vscroll.setValue(vscroll.getValue() - 1);
534 if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())
540 vscroll.setValue(vscroll.getValue() + 1);
554 * @return DOCUMENT ME!
556 public boolean scrollRight(boolean right)
560 if (hscroll.getValue() < 1)
566 hscroll.setValue(hscroll.getValue() - 1);
570 if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())
576 hscroll.setValue(hscroll.getValue() + 1);
585 * Adjust row/column scrollers to show a visible position in the alignment.
588 * visible column to scroll to DOCUMENT ME!
590 * visible row to scroll to
593 public void setScrollValues(int x, int y)
595 // System.err.println("Scroll to "+x+","+y);
596 if (av == null || av.getAlignment() == null)
600 int width = av.getAlignment().getWidth();
601 int height = av.getAlignment().getHeight();
603 if (av.hasHiddenColumns())
605 width = av.getColumnSelection().findColumnPosition(width);
608 av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av.charWidth)) - 1);
610 hextent = getSeqPanel().seqCanvas.getWidth() / av.charWidth;
611 vextent = getSeqPanel().seqCanvas.getHeight() / av.charHeight;
618 if (vextent > height)
623 if ((hextent + x) > width)
628 if ((vextent + y) > height)
630 y = height - vextent;
643 hscroll.setValues(x, hextent, 0, width);
644 vscroll.setValues(y, vextent, 0, height);
653 public void adjustmentValueChanged(AdjustmentEvent evt)
656 int oldX = av.getStartRes();
657 int oldY = av.getStartSeq();
659 if (evt.getSource() == hscroll)
661 int x = hscroll.getValue();
663 av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av.getCharWidth())) - 1);
666 if (evt.getSource() == vscroll)
668 int offy = vscroll.getValue();
670 if (av.getWrapAlignment())
674 int rowSize = getSeqPanel().seqCanvas
675 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
676 av.setStartRes(offy * rowSize);
677 av.setEndRes((offy + 1) * rowSize);
681 // This is only called if file loaded is a jar file that
682 // was wrapped when saved and user has wrap alignment true
683 // as preference setting
684 SwingUtilities.invokeLater(new Runnable()
688 setScrollValues(av.getStartRes(), av.getStartSeq());
695 av.setStartSeq(offy);
697 + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight()));
701 if (overviewPanel != null)
703 overviewPanel.setBoxPosition();
706 int scrollX = av.startRes - oldX;
707 int scrollY = av.startSeq - oldY;
709 if (av.getWrapAlignment() || !fastPaint)
715 // Make sure we're not trying to draw a panel
716 // larger than the visible window
717 if (scrollX > av.endRes - av.startRes)
719 scrollX = av.endRes - av.startRes;
721 else if (scrollX < av.startRes - av.endRes)
723 scrollX = av.startRes - av.endRes;
726 if (scrollX != 0 || scrollY != 0)
728 getIdPanel().getIdCanvas().fastPaint(scrollY);
729 getSeqPanel().seqCanvas.fastPaint(scrollX, scrollY);
730 getScalePanel().repaint();
732 if (av.getShowAnnotation() && scrollX != 0)
734 getAnnotationPanel().fastPaint(scrollX);
741 * Repaint the alignment including the annotations and overview panels (if
744 public void paintAlignment(boolean updateOverview)
746 final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
747 av.isShowAutocalculatedAbove());
748 sorter.sort(getAlignment()
749 .getAlignmentAnnotation(),
750 av.getSortAnnotationsBy());
755 av.getStructureSelectionManager().sequenceColoursChanged(this);
757 if (overviewPanel != null)
759 overviewPanel.updateOverviewImage();
770 public void paintComponent(Graphics g)
774 Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
775 idPanelHolder.setPreferredSize(d);
776 hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
779 if (av.getWrapAlignment())
781 int maxwidth = av.getAlignment().getWidth();
783 if (av.hasHiddenColumns())
785 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
788 int canvasWidth = getSeqPanel().seqCanvas
789 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
793 / getSeqPanel().seqCanvas
794 .getWrappedCanvasWidth(getSeqPanel().seqCanvas
796 vscroll.setMaximum(max);
797 vscroll.setUnitIncrement(1);
798 vscroll.setVisibleAmount(1);
803 setScrollValues(av.getStartRes(), av.getStartSeq());
817 * @return DOCUMENT ME!
819 * @throws PrinterException
822 public int print(Graphics pg, PageFormat pf, int pi)
823 throws PrinterException
825 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
827 int pwidth = (int) pf.getImageableWidth();
828 int pheight = (int) pf.getImageableHeight();
830 if (av.getWrapAlignment())
832 return printWrappedAlignment(pg, pwidth, pheight, pi);
836 return printUnwrapped(pg, pwidth, pheight, pi);
852 * @return DOCUMENT ME!
854 * @throws PrinterException
857 public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
858 throws PrinterException
860 int idWidth = getVisibleIdWidth(false);
861 FontMetrics fm = getFontMetrics(av.getFont());
862 int scaleHeight = av.charHeight + fm.getDescent();
864 pg.setColor(Color.white);
865 pg.fillRect(0, 0, pwidth, pheight);
866 pg.setFont(av.getFont());
868 // //////////////////////////////////
869 // / How many sequences and residues can we fit on a printable page?
870 int totalRes = (pwidth - idWidth) / av.getCharWidth();
872 int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
874 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
876 // ///////////////////////////
877 // / Only print these sequences and residues on this page
880 // ///////////////////////////
881 // / Only print these sequences and residues on this page
884 // ///////////////////////////
885 // / Only print these sequences and residues on this page
888 // ///////////////////////////
889 // / Only print these sequences and residues on this page
891 startRes = (pi % pagesWide) * totalRes;
892 endRes = (startRes + totalRes) - 1;
894 if (endRes > (av.getAlignment().getWidth() - 1))
896 endRes = av.getAlignment().getWidth() - 1;
899 startSeq = (pi / pagesWide) * totalSeq;
900 endSeq = startSeq + totalSeq;
902 if (endSeq > av.getAlignment().getHeight())
904 endSeq = av.getAlignment().getHeight();
907 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
910 if (av.isShowAnnotation())
912 pagesHigh += getAnnotationPanel().adjustPanelHeight() + 3;
915 pagesHigh /= pheight;
917 if (pi >= (pagesWide * pagesHigh))
919 return Printable.NO_SUCH_PAGE;
923 pg.translate(idWidth, 0);
924 getScalePanel().drawScale(pg, startRes, endRes, pwidth - idWidth,
926 pg.translate(-idWidth, scaleHeight);
930 Color currentColor = null;
931 Color currentTextColor = null;
933 pg.setFont(getIdPanel().getIdCanvas().getIdfont());
936 for (int i = startSeq; i < endSeq; i++)
938 seq = av.getAlignment().getSequenceAt(i);
939 if ((av.getSelectionGroup() != null)
940 && av.getSelectionGroup().getSequences(null).contains(seq))
942 currentColor = Color.gray;
943 currentTextColor = Color.black;
947 currentColor = av.getSequenceColour(seq);
948 currentTextColor = Color.black;
951 pg.setColor(currentColor);
952 pg.fillRect(0, (i - startSeq) * av.charHeight, idWidth,
955 pg.setColor(currentTextColor);
958 if (av.isRightAlignIds())
960 fm = pg.getFontMetrics();
962 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
967 seq.getDisplayId(av.getShowJVSuffix()),
969 (((i - startSeq) * av.charHeight) + av.getCharHeight())
970 - (av.getCharHeight() / 5));
973 pg.setFont(av.getFont());
975 // draw main sequence panel
976 pg.translate(idWidth, 0);
977 getSeqPanel().seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
979 if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
981 // draw annotation - need to offset for current scroll position
982 int offset = -getAlabels().getScrollOffset();
983 pg.translate(0, offset);
984 pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
985 getAlabels().drawComponent(pg, idWidth);
986 pg.translate(idWidth + 3, 0);
987 getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
988 pg, -1, startRes, endRes + 1);
989 pg.translate(0, -offset);
992 return Printable.PAGE_EXISTS;
1007 * @return DOCUMENT ME!
1009 * @throws PrinterException
1012 public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
1013 int pi) throws PrinterException
1016 int annotationHeight = 0;
1017 AnnotationLabels labels = null;
1018 if (av.isShowAnnotation())
1020 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1021 labels = new AnnotationLabels(av);
1024 int hgap = av.charHeight;
1025 if (av.scaleAboveWrapped)
1027 hgap += av.charHeight;
1030 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1033 int idWidth = getVisibleIdWidth(false);
1035 int maxwidth = av.getAlignment().getWidth();
1036 if (av.hasHiddenColumns())
1038 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1041 int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
1044 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1046 pg.setColor(Color.white);
1047 pg.fillRect(0, 0, pwidth, pheight);
1048 pg.setFont(av.getFont());
1052 pg.setColor(Color.black);
1054 pg.translate(0, -pi * pheight);
1056 pg.setClip(0, pi * pheight, pwidth, pheight);
1062 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1064 pg.setFont(getIdPanel().getIdCanvas().getIdfont());
1065 SequenceI s = av.getAlignment().getSequenceAt(i);
1066 String string = s.getDisplayId(av.getShowJVSuffix());
1068 if (av.isRightAlignIds())
1070 FontMetrics fm = pg.getFontMetrics();
1071 xPos = idWidth - fm.stringWidth(string) - 4;
1073 pg.drawString(string, xPos,
1074 ((i * av.charHeight) + ypos + av.charHeight)
1075 - (av.charHeight / 5));
1079 pg.translate(-3, ypos
1080 + (av.getAlignment().getHeight() * av.charHeight));
1082 pg.setFont(av.getFont());
1083 labels.drawComponent(pg, idWidth);
1084 pg.translate(+3, -ypos
1085 - (av.getAlignment().getHeight() * av.charHeight));
1089 } while (ypos < totalHeight);
1091 pg.translate(idWidth, 0);
1093 getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1096 if ((pi * pheight) < totalHeight)
1098 return Printable.PAGE_EXISTS;
1103 return Printable.NO_SUCH_PAGE;
1108 * get current sequence ID panel width, or nominal value if panel were to be
1109 * displayed using default settings
1113 public int getVisibleIdWidth()
1115 return getVisibleIdWidth(true);
1119 * get current sequence ID panel width, or nominal value if panel were to be
1120 * displayed using default settings
1123 * indicate if the Id width for onscreen or offscreen display should
1127 public int getVisibleIdWidth(boolean onscreen)
1129 // see if rendering offscreen - check preferences and calc width accordingly
1130 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1132 return calculateIdWidth(-1).width + 4;
1134 Integer idwidth = null;
1136 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1138 return (getIdPanel().getWidth() > 0 ? getIdPanel().getWidth()
1139 : calculateIdWidth().width + 4);
1141 return idwidth.intValue() + 4;
1144 void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
1146 long progress = System.currentTimeMillis();
1147 headless = (System.getProperty("java.awt.headless") != null && System
1148 .getProperty("java.awt.headless").equals("true"));
1149 if (alignFrame != null && !headless)
1151 alignFrame.setProgressBar(MessageManager.formatMessage(
1152 "status.saving_file",
1154 { type.getLabel() }), progress);
1158 AlignmentDimension aDimension = getAlignmentDimension();
1161 jalview.util.ImageMaker im;
1162 final String imageAction, imageTitle;
1163 if (type == jalview.util.ImageMaker.TYPE.PNG)
1165 imageAction = "Create PNG image from alignment";
1168 else if (type == jalview.util.ImageMaker.TYPE.EPS)
1170 imageAction = "Create EPS file from alignment";
1171 imageTitle = alignFrame.getTitle();
1175 imageAction = "Create SVG file from alignment";
1176 imageTitle = alignFrame.getTitle();
1179 im = new jalview.util.ImageMaker(this, type, imageAction,
1180 aDimension.getWidth(), aDimension.getHeight(), file,
1182 if (av.getWrapAlignment())
1184 if (im.getGraphics() != null)
1186 printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
1187 aDimension.getHeight(), 0);
1193 if (im.getGraphics() != null)
1195 printUnwrapped(im.getGraphics(), aDimension.getWidth(),
1196 aDimension.getHeight(), 0);
1200 } catch (OutOfMemoryError err)
1203 System.out.println("########################\n" + "OUT OF MEMORY "
1204 + file + "\n" + "########################");
1205 new OOMWarning("Creating Image for " + file, err);
1206 // System.out.println("Create IMAGE: " + err);
1207 } catch (Exception ex)
1209 ex.printStackTrace();
1213 if (alignFrame != null && !headless)
1215 alignFrame.setProgressBar(MessageManager.getString("status.export_complete"), progress);
1220 public AlignmentDimension getAlignmentDimension()
1222 int maxwidth = av.getAlignment().getWidth();
1223 if (av.hasHiddenColumns())
1225 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1228 int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
1229 + getScalePanel().getHeight();
1230 int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
1232 if (av.getWrapAlignment())
1234 height = getWrappedHeight();
1237 // need to obtain default alignment width and then add in any
1238 // additional allowance for id margin
1239 // this duplicates the calculation in getWrappedHeight but adjusts for
1241 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1242 - alignFrame.getInsets().left
1243 - alignFrame.getInsets().right - getVisibleIdWidth()
1244 + getVisibleIdWidth(false);
1248 width = getSeqPanel().getWidth() + getVisibleIdWidth(false);
1252 else if (av.getShowAnnotation())
1254 height += getAnnotationPanel().adjustPanelHeight() + 3;
1256 return new AlignmentDimension(width, height);
1263 public void makeEPS(File epsFile)
1265 makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile);
1271 public void makePNG(File pngFile)
1273 makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile);
1276 public void makeSVG(File svgFile)
1278 makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile);
1280 public void makePNGImageMap(File imgMapFile, String imageName)
1282 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1283 // ////////////////////////////////////////////
1284 int idWidth = getVisibleIdWidth(false);
1285 FontMetrics fm = getFontMetrics(av.getFont());
1286 int scaleHeight = av.charHeight + fm.getDescent();
1289 // ////////////////////////////////
1290 if (imgMapFile != null)
1294 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1295 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1296 StringBuffer text = new StringBuffer();
1297 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1298 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1299 out.println("<img src=\"" + imageName
1300 + "\" border=\"0\" usemap=\"#Map\" >"
1301 + "<map name=\"Map\">");
1303 for (s = 0; s < sSize; s++)
1305 sy = s * av.charHeight + scaleHeight;
1307 SequenceI seq = av.getAlignment().getSequenceAt(s);
1308 SequenceFeature[] features = seq.getDatasetSequence()
1309 .getSequenceFeatures();
1310 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1311 for (res = 0; res < alwidth; res++)
1313 text = new StringBuffer();
1315 if (av.getAlignment().isNucleotide())
1317 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1322 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1331 String triplet = obj.toString();
1332 int alIndex = seq.findPosition(res);
1333 gSize = groups.length;
1334 for (g = 0; g < gSize; g++)
1336 if (text.length() < 1)
1338 text.append("<area shape=\"rect\" coords=\""
1339 + (idWidth + res * av.charWidth) + "," + sy + ","
1340 + (idWidth + (res + 1) * av.charWidth) + ","
1341 + (av.charHeight + sy) + "\""
1342 + " onMouseOver=\"toolTip('" + alIndex + " "
1346 if (groups[g].getStartRes() < res
1347 && groups[g].getEndRes() > res)
1349 text.append("<br><em>" + groups[g].getName() + "</em>");
1353 if (features != null)
1355 if (text.length() < 1)
1357 text.append("<area shape=\"rect\" coords=\""
1358 + (idWidth + res * av.charWidth) + "," + sy + ","
1359 + (idWidth + (res + 1) * av.charWidth) + ","
1360 + (av.charHeight + sy) + "\""
1361 + " onMouseOver=\"toolTip('" + alIndex + " "
1364 fSize = features.length;
1365 for (f = 0; f < fSize; f++)
1368 if ((features[f].getBegin() <= seq.findPosition(res))
1369 && (features[f].getEnd() >= seq.findPosition(res)))
1371 if (features[f].getType().equals("disulfide bond"))
1373 if (features[f].getBegin() == seq.findPosition(res)
1374 || features[f].getEnd() == seq
1377 text.append("<br>disulfide bond "
1378 + features[f].getBegin() + ":"
1379 + features[f].getEnd());
1384 text.append("<br>");
1385 text.append(features[f].getType());
1386 if (features[f].getDescription() != null
1387 && !features[f].getType().equals(
1388 features[f].getDescription()))
1390 text.append(" " + features[f].getDescription());
1393 if (features[f].getValue("status") != null)
1395 text.append(" (" + features[f].getValue("status")
1403 if (text.length() > 1)
1405 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1406 out.println(text.toString());
1410 out.println("</map></body></html>");
1413 } catch (Exception ex)
1415 ex.printStackTrace();
1417 } // /////////END OF IMAGE MAP
1421 int getWrappedHeight()
1423 int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
1425 if (System.getProperty("java.awt.headless") != null
1426 && System.getProperty("java.awt.headless").equals("true"))
1428 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1429 - vscroll.getPreferredSize().width
1430 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1433 int chunkWidth = getSeqPanel().seqCanvas
1434 .getWrappedCanvasWidth(seqPanelWidth);
1436 int hgap = av.charHeight;
1437 if (av.scaleAboveWrapped)
1439 hgap += av.charHeight;
1442 int annotationHeight = 0;
1443 if (av.isShowAnnotation())
1445 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1448 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1451 int maxwidth = av.getAlignment().getWidth();
1452 if (av.hasHiddenColumns())
1454 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1457 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1463 * close the panel - deregisters all listeners and nulls any references to
1466 public void closePanel()
1468 PaintRefresher.RemoveComponent(getSeqPanel().seqCanvas);
1469 PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas());
1470 PaintRefresher.RemoveComponent(this);
1473 jalview.structure.StructureSelectionManager ssm = av
1474 .getStructureSelectionManager();
1475 ssm.removeStructureViewerListener(getSeqPanel(), null);
1476 ssm.removeSelectionListener(getSeqPanel());
1477 av.setAlignment(null);
1482 if (Cache.log.isDebugEnabled())
1484 Cache.log.warn("Closing alignment panel which is already closed.");
1490 * hides or shows dynamic annotation rows based on groups and av state flags
1492 public void updateAnnotation()
1494 updateAnnotation(false, false);
1497 public void updateAnnotation(boolean applyGlobalSettings)
1499 updateAnnotation(applyGlobalSettings, false);
1502 public void updateAnnotation(boolean applyGlobalSettings,
1503 boolean preserveNewGroupSettings)
1505 av.updateGroupAnnotationSettings(applyGlobalSettings,
1506 preserveNewGroupSettings);
1507 adjustAnnotationHeight();
1511 public AlignmentI getAlignment()
1513 return av.getAlignment();
1518 public String getViewName()
1524 * Make/Unmake this alignment panel the current input focus
1528 public void setSelected(boolean b)
1532 alignFrame.setSelected(b);
1533 } catch (Exception ex)
1540 alignFrame.setDisplayedView(this);
1545 public StructureSelectionManager getStructureSelectionManager()
1547 return av.getStructureSelectionManager();
1551 public void raiseOOMWarning(String string, OutOfMemoryError error)
1553 new OOMWarning(string, error, this);
1557 public jalview.api.FeatureRenderer cloneFeatureRenderer()
1560 return new FeatureRenderer(this);
1563 public jalview.api.FeatureRenderer getFeatureRenderer()
1565 return seqPanel.seqCanvas.getFeatureRenderer();
1567 public void updateFeatureRenderer(jalview.renderer.seqfeatures.FeatureRenderer fr)
1569 fr.transferSettings(getSeqPanel().seqCanvas.getFeatureRenderer());
1572 public void updateFeatureRendererFrom(jalview.api.FeatureRenderer fr)
1574 if (getSeqPanel().seqCanvas.getFeatureRenderer() != null)
1576 getSeqPanel().seqCanvas.getFeatureRenderer().transferSettings(fr);
1580 public ScalePanel getScalePanel()
1585 public void setScalePanel(ScalePanel scalePanel)
1587 this.scalePanel = scalePanel;
1590 public SeqPanel getSeqPanel()
1595 public void setSeqPanel(SeqPanel seqPanel)
1597 this.seqPanel = seqPanel;
1600 public AnnotationPanel getAnnotationPanel()
1602 return annotationPanel;
1605 public void setAnnotationPanel(AnnotationPanel annotationPanel)
1607 this.annotationPanel = annotationPanel;
1610 public AnnotationLabels getAlabels()
1615 public void setAlabels(AnnotationLabels alabels)
1617 this.alabels = alabels;
1620 public IdPanel getIdPanel()
1625 public void setIdPanel(IdPanel idPanel)
1627 this.idPanel = idPanel;