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.schemes.ResidueProperties;
33 import jalview.structure.StructureSelectionManager;
34 import jalview.util.MessageManager;
36 import java.awt.BorderLayout;
37 import java.awt.Color;
38 import java.awt.Container;
39 import java.awt.Dimension;
41 import java.awt.FontMetrics;
42 import java.awt.Graphics;
43 import java.awt.event.AdjustmentEvent;
44 import java.awt.event.AdjustmentListener;
45 import java.awt.print.PageFormat;
46 import java.awt.print.Printable;
47 import java.awt.print.PrinterException;
48 import java.beans.PropertyChangeEvent;
49 import java.beans.PropertyChangeListener;
51 import java.io.FileWriter;
52 import java.io.PrintWriter;
54 import javax.swing.SwingUtilities;
60 * @version $Revision: 1.161 $
62 public class AlignmentPanel extends GAlignmentPanel implements
63 AdjustmentListener, Printable, AlignmentViewPanel
65 public AlignViewport av;
67 OverviewPanel overviewPanel;
73 IdwidthAdjuster idwidthAdjuster;
76 public AlignFrame alignFrame;
78 ScalePanel scalePanel;
80 AnnotationPanel annotationPanel;
82 AnnotationLabels alabels;
84 // this value is set false when selection area being dragged
85 boolean fastPaint = true;
92 * Creates a new AlignmentPanel object.
97 public AlignmentPanel(AlignFrame af, final AlignViewport av)
101 seqPanel = new SeqPanel(av, this);
102 idPanel = new IdPanel(av, this);
104 scalePanel = new ScalePanel(av, this);
106 idPanelHolder.add(idPanel, BorderLayout.CENTER);
107 idwidthAdjuster = new IdwidthAdjuster(this);
108 idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
110 annotationPanel = new AnnotationPanel(this);
111 alabels = new AnnotationLabels(this);
113 annotationScroller.setViewportView(annotationPanel);
114 annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
116 scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
117 seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
119 setScrollValues(0, 0);
121 setAnnotationVisible(av.getShowAnnotation());
123 hscroll.addAdjustmentListener(this);
124 vscroll.addAdjustmentListener(this);
126 final AlignmentPanel ap = this;
127 av.addPropertyChangeListener(new PropertyChangeListener()
129 public void propertyChange(PropertyChangeEvent evt)
131 if (evt.getPropertyName().equals("alignment"))
133 PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
139 adjustAnnotationHeight();
143 public void alignmentChanged()
145 av.alignmentChanged(this);
147 alignFrame.updateEditMenuBar();
149 paintAlignment(true);
156 public void fontChanged()
158 // set idCanvas bufferedImage to null
159 // to prevent drawing old image
160 FontMetrics fm = getFontMetrics(av.getFont());
162 scalePanelHolder.setPreferredSize(new Dimension(10, av.charHeight
164 idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight
167 idPanel.idCanvas.gg = null;
168 seqPanel.seqCanvas.img = null;
169 annotationPanel.adjustPanelHeight();
171 Dimension d = calculateIdWidth();
172 d.setSize(d.width + 4, d.height);
173 idPanel.idCanvas.setPreferredSize(d);
174 hscrollFillerPanel.setPreferredSize(d);
176 if (overviewPanel != null)
178 overviewPanel.setBoxPosition();
185 * Calculate the width of the alignment labels based on the displayed names
186 * and any bounds on label width set in preferences.
188 * @return Dimension giving the maximum width of the alignment label panel
189 * that should be used.
191 public Dimension calculateIdWidth()
193 // calculate sensible default width when no preference is available
195 int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
196 int maxwidth = Math.max(20,
197 Math.min(afwidth - 200, 2 * afwidth / 3));
198 return calculateIdWidth(maxwidth);
202 * Calculate the width of the alignment labels based on the displayed names
203 * and any bounds on label width set in preferences.
206 * -1 or maximum width allowed for IdWidth
207 * @return Dimension giving the maximum width of the alignment label panel
208 * that should be used.
210 public Dimension calculateIdWidth(int maxwidth)
212 Container c = new Container();
214 FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
215 Font.ITALIC, av.font.getSize()));
217 AlignmentI al = av.getAlignment();
222 while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
224 SequenceI s = al.getSequenceAt(i);
226 id = s.getDisplayId(av.getShowJVSuffix());
228 if (fm.stringWidth(id) > idWidth)
230 idWidth = fm.stringWidth(id);
236 // Also check annotation label widths
239 if (al.getAlignmentAnnotation() != null)
241 fm = c.getFontMetrics(alabels.getFont());
243 while (i < al.getAlignmentAnnotation().length)
245 String label = al.getAlignmentAnnotation()[i].label;
247 if (fm.stringWidth(label) > idWidth)
249 idWidth = fm.stringWidth(label);
256 return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
261 * Highlight the given results on the alignment.
264 public void highlightSearchResults(SearchResults results)
266 scrollToPosition(results);
267 seqPanel.seqCanvas.highlightSearchResults(results);
271 * scroll the view to show the position of the highlighted region in results
272 * (if any) and redraw the overview
276 public boolean scrollToPosition(SearchResults results)
278 return scrollToPosition(results, true);
282 * scroll the view to show the position of the highlighted region in results
286 * @param redrawOverview
287 * - when set, the overview will be recalculated (takes longer)
288 * @return false if results were not found
290 public boolean scrollToPosition(SearchResults results,
291 boolean redrawOverview)
293 int startv, endv, starts, ends, width;
294 // TODO: properly locate search results in view when large numbers of hidden
295 // columns exist before highlighted region
296 // do we need to scroll the panel?
297 // TODO: tons of nullpointereexceptions raised here.
298 if (results != null && results.getSize() > 0 && av != null
299 && av.getAlignment() != null)
301 int seqIndex = av.getAlignment().findIndex(results);
306 SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
308 int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
315 // System.err.println("Seq : "+seqIndex+" Scroll to "+start+","+end); //
321 if (end == seq.getEnd())
325 if (av.hasHiddenColumns())
327 start = av.getColumnSelection().findColumnPosition(start);
328 end = av.getColumnSelection().findColumnPosition(end);
331 if (!av.getColumnSelection().isVisible(r[0]))
333 // don't scroll - position isn't visible
338 if (!av.wrapAlignment)
340 if ((startv = av.getStartRes()) >= start)
342 setScrollValues(start - 1, seqIndex);
344 else if ((endv = av.getEndRes()) <= end)
346 setScrollValues(startv + 1 + end - endv, seqIndex);
348 else if ((starts = av.getStartSeq()) > seqIndex)
350 setScrollValues(av.getStartRes(), seqIndex);
352 else if ((ends = av.getEndSeq()) <= seqIndex)
354 setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
359 scrollToWrappedVisible(start);
362 if (redrawOverview && overviewPanel != null)
364 overviewPanel.setBoxPosition();
366 paintAlignment(redrawOverview);
370 void scrollToWrappedVisible(int res)
372 int cwidth = seqPanel.seqCanvas
373 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
374 if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
376 vscroll.setValue((res / cwidth));
377 av.startRes = vscroll.getValue() * cwidth;
385 * @return DOCUMENT ME!
387 public OverviewPanel getOverviewPanel()
389 return overviewPanel;
398 public void setOverviewPanel(OverviewPanel op)
406 * Hide or show annotation panel
409 public void setAnnotationVisible(boolean b)
411 if (!av.wrapAlignment)
413 annotationSpaceFillerHolder.setVisible(b);
414 annotationScroller.setVisible(b);
420 * automatically adjust annotation panel height for new annotation whilst
421 * ensuring the alignment is still visible.
423 public void adjustAnnotationHeight()
425 // TODO: display vertical annotation scrollbar if necessary
426 // this is called after loading new annotation onto alignment
427 if (alignFrame.getHeight() == 0)
429 System.out.println("NEEDS FIXING");
431 validateAnnotationDimensions(true);
433 paintAlignment(true);
437 * calculate the annotation dimensions and refresh slider values accordingly.
438 * need to do repaints/notifys afterwards.
440 protected void validateAnnotationDimensions(boolean adjustPanelHeight)
442 int height = annotationPanel.adjustPanelHeight();
444 int theight = av.getCharHeight()
445 * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0
446 : av.getAlignment().getHiddenSequences().getSize()));
447 float sscaling = (float) (theight / (1.0 * theight + height));
448 float ascaling = (float) (height * 1.0 / alignFrame.getHeight());
449 int rheight = alignFrame.getHeight() - height - av.getCharHeight();
450 if (adjustPanelHeight)
452 // NOTE: this logic is different in the applet. Need a better algorithm to
454 // try and set height according to alignment
455 if (ascaling > 0 && sscaling < 0.5)
457 // if the alignment is too big then
458 // default is 0.5 split
459 height = alignFrame.getHeight() / 2;
463 // if space for more than one sequence row left when annotation is fully
464 // displayed then set height to annotation height
465 // otherwise, leave at least two lines of sequence shown.
466 height = (rheight > av.getCharHeight()) ? height
467 : (-av.getCharHeight() * 3 + (int) (alignFrame.getHeight() * (1 - sscaling)));
472 // maintain same window layout whilst updating sliders
473 height = annotationScroller.getSize().height;
477 annotationScroller.setPreferredSize(new Dimension(annotationScroller
478 .getWidth(), height));
480 annotationSpaceFillerHolder.setPreferredSize(new Dimension(
481 annotationSpaceFillerHolder.getWidth(), height));
482 annotationScroller.validate();// repaint();
483 annotationScroller.addNotify();
492 public void setWrapAlignment(boolean wrap)
495 scalePanelHolder.setVisible(!wrap);
496 hscroll.setVisible(!wrap);
497 idwidthAdjuster.setVisible(!wrap);
501 annotationScroller.setVisible(false);
502 annotationSpaceFillerHolder.setVisible(false);
504 else if (av.showAnnotation)
506 annotationScroller.setVisible(true);
507 annotationSpaceFillerHolder.setVisible(true);
510 idSpaceFillerPanel1.setVisible(!wrap);
515 // return value is true if the scroll is valid
516 public boolean scrollUp(boolean up)
520 if (vscroll.getValue() < 1)
526 vscroll.setValue(vscroll.getValue() - 1);
530 if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())
536 vscroll.setValue(vscroll.getValue() + 1);
550 * @return DOCUMENT ME!
552 public boolean scrollRight(boolean right)
556 if (hscroll.getValue() < 1)
562 hscroll.setValue(hscroll.getValue() - 1);
566 if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())
572 hscroll.setValue(hscroll.getValue() + 1);
581 * Adjust row/column scrollers to show a visible position in the alignment.
584 * visible column to scroll to DOCUMENT ME!
586 * visible row to scroll to
589 public void setScrollValues(int x, int y)
591 // System.err.println("Scroll to "+x+","+y);
592 if (av == null || av.getAlignment() == null)
596 int width = av.getAlignment().getWidth();
597 int height = av.getAlignment().getHeight();
599 if (av.hasHiddenColumns())
601 width = av.getColumnSelection().findColumnPosition(width);
604 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.charWidth)) - 1);
606 hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;
607 vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;
614 if (vextent > height)
619 if ((hextent + x) > width)
624 if ((vextent + y) > height)
626 y = height - vextent;
639 hscroll.setValues(x, hextent, 0, width);
640 vscroll.setValues(y, vextent, 0, height);
649 public void adjustmentValueChanged(AdjustmentEvent evt)
651 int oldX = av.getStartRes();
652 int oldY = av.getStartSeq();
654 if (evt.getSource() == hscroll)
656 int x = hscroll.getValue();
658 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);
661 if (evt.getSource() == vscroll)
663 int offy = vscroll.getValue();
665 if (av.getWrapAlignment())
669 int rowSize = seqPanel.seqCanvas
670 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
671 av.setStartRes(offy * rowSize);
672 av.setEndRes((offy + 1) * rowSize);
676 // This is only called if file loaded is a jar file that
677 // was wrapped when saved and user has wrap alignment true
678 // as preference setting
679 SwingUtilities.invokeLater(new Runnable()
683 setScrollValues(av.getStartRes(), av.getStartSeq());
690 av.setStartSeq(offy);
692 + (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));
696 if (overviewPanel != null)
698 overviewPanel.setBoxPosition();
701 int scrollX = av.startRes - oldX;
702 int scrollY = av.startSeq - oldY;
704 if (av.getWrapAlignment() || !fastPaint)
710 // Make sure we're not trying to draw a panel
711 // larger than the visible window
712 if (scrollX > av.endRes - av.startRes)
714 scrollX = av.endRes - av.startRes;
716 else if (scrollX < av.startRes - av.endRes)
718 scrollX = av.startRes - av.endRes;
721 if (scrollX != 0 || scrollY != 0)
723 idPanel.idCanvas.fastPaint(scrollY);
724 seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
725 scalePanel.repaint();
727 if (av.getShowAnnotation() && scrollX != 0)
729 annotationPanel.fastPaint(scrollX);
736 * Repaint the alignment including the annotations and overview panels (if
739 public void paintAlignment(boolean updateOverview)
741 final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
742 av.isShowAutocalculatedAbove());
743 sorter.sort(getAlignment()
744 .getAlignmentAnnotation(),
745 av.getSortAnnotationsBy());
750 av.getStructureSelectionManager().sequenceColoursChanged(this);
752 if (overviewPanel != null)
754 overviewPanel.updateOverviewImage();
765 public void paintComponent(Graphics g)
769 Dimension d = idPanel.idCanvas.getPreferredSize();
770 idPanelHolder.setPreferredSize(d);
771 hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
774 if (av.getWrapAlignment())
776 int maxwidth = av.getAlignment().getWidth();
778 if (av.hasHiddenColumns())
780 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
783 int canvasWidth = seqPanel.seqCanvas
784 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
789 .getWrappedCanvasWidth(seqPanel.seqCanvas
791 vscroll.setMaximum(max);
792 vscroll.setUnitIncrement(1);
793 vscroll.setVisibleAmount(1);
798 setScrollValues(av.getStartRes(), av.getStartSeq());
812 * @return DOCUMENT ME!
814 * @throws PrinterException
817 public int print(Graphics pg, PageFormat pf, int pi)
818 throws PrinterException
820 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
822 int pwidth = (int) pf.getImageableWidth();
823 int pheight = (int) pf.getImageableHeight();
825 if (av.getWrapAlignment())
827 return printWrappedAlignment(pg, pwidth, pheight, pi);
831 return printUnwrapped(pg, pwidth, pheight, pi);
847 * @return DOCUMENT ME!
849 * @throws PrinterException
852 public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
853 throws PrinterException
855 int idWidth = getVisibleIdWidth(false);
856 FontMetrics fm = getFontMetrics(av.getFont());
857 int scaleHeight = av.charHeight + fm.getDescent();
859 pg.setColor(Color.white);
860 pg.fillRect(0, 0, pwidth, pheight);
861 pg.setFont(av.getFont());
863 // //////////////////////////////////
864 // / How many sequences and residues can we fit on a printable page?
865 int totalRes = (pwidth - idWidth) / av.getCharWidth();
867 int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
869 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
871 // ///////////////////////////
872 // / Only print these sequences and residues on this page
875 // ///////////////////////////
876 // / Only print these sequences and residues on this page
879 // ///////////////////////////
880 // / Only print these sequences and residues on this page
883 // ///////////////////////////
884 // / Only print these sequences and residues on this page
886 startRes = (pi % pagesWide) * totalRes;
887 endRes = (startRes + totalRes) - 1;
889 if (endRes > (av.getAlignment().getWidth() - 1))
891 endRes = av.getAlignment().getWidth() - 1;
894 startSeq = (pi / pagesWide) * totalSeq;
895 endSeq = startSeq + totalSeq;
897 if (endSeq > av.getAlignment().getHeight())
899 endSeq = av.getAlignment().getHeight();
902 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
905 if (av.showAnnotation)
907 pagesHigh += annotationPanel.adjustPanelHeight() + 3;
910 pagesHigh /= pheight;
912 if (pi >= (pagesWide * pagesHigh))
914 return Printable.NO_SUCH_PAGE;
918 pg.translate(idWidth, 0);
919 scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth,
921 pg.translate(-idWidth, scaleHeight);
925 Color currentColor = null;
926 Color currentTextColor = null;
928 pg.setFont(idPanel.idCanvas.idfont);
931 for (int i = startSeq; i < endSeq; i++)
933 seq = av.getAlignment().getSequenceAt(i);
934 if ((av.getSelectionGroup() != null)
935 && av.getSelectionGroup().getSequences(null).contains(seq))
937 currentColor = Color.gray;
938 currentTextColor = Color.black;
942 currentColor = av.getSequenceColour(seq);
943 currentTextColor = Color.black;
946 pg.setColor(currentColor);
947 pg.fillRect(0, (i - startSeq) * av.charHeight, idWidth,
950 pg.setColor(currentTextColor);
953 if (av.rightAlignIds)
955 fm = pg.getFontMetrics();
957 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
962 seq.getDisplayId(av.getShowJVSuffix()),
964 (((i - startSeq) * av.charHeight) + av.getCharHeight())
965 - (av.getCharHeight() / 5));
968 pg.setFont(av.getFont());
970 // draw main sequence panel
971 pg.translate(idWidth, 0);
972 seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
974 if (av.showAnnotation && (endSeq == av.getAlignment().getHeight()))
976 // draw annotation - need to offset for current scroll position
977 int offset = -alabels.scrollOffset;
978 pg.translate(0, offset);
979 pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
980 alabels.drawComponent(pg, idWidth);
981 pg.translate(idWidth + 3, 0);
982 annotationPanel.renderer.drawComponent(annotationPanel, av,
983 pg, -1, startRes, endRes + 1);
984 pg.translate(0, -offset);
987 return Printable.PAGE_EXISTS;
1002 * @return DOCUMENT ME!
1004 * @throws PrinterException
1007 public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
1008 int pi) throws PrinterException
1011 int annotationHeight = 0;
1012 AnnotationLabels labels = null;
1013 if (av.showAnnotation)
1015 annotationHeight = annotationPanel.adjustPanelHeight();
1016 labels = new AnnotationLabels(av);
1019 int hgap = av.charHeight;
1020 if (av.scaleAboveWrapped)
1022 hgap += av.charHeight;
1025 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1028 int idWidth = getVisibleIdWidth(false);
1030 int maxwidth = av.getAlignment().getWidth();
1031 if (av.hasHiddenColumns())
1033 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1036 int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth
1039 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1041 pg.setColor(Color.white);
1042 pg.fillRect(0, 0, pwidth, pheight);
1043 pg.setFont(av.getFont());
1047 pg.setColor(Color.black);
1049 pg.translate(0, -pi * pheight);
1051 pg.setClip(0, pi * pheight, pwidth, pheight);
1057 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1059 pg.setFont(idPanel.idCanvas.idfont);
1060 SequenceI s = av.getAlignment().getSequenceAt(i);
1061 String string = s.getDisplayId(av.getShowJVSuffix());
1063 if (av.rightAlignIds)
1065 FontMetrics fm = pg.getFontMetrics();
1066 xPos = idWidth - fm.stringWidth(string) - 4;
1068 pg.drawString(string, xPos,
1069 ((i * av.charHeight) + ypos + av.charHeight)
1070 - (av.charHeight / 5));
1074 pg.translate(-3, ypos
1075 + (av.getAlignment().getHeight() * av.charHeight));
1077 pg.setFont(av.getFont());
1078 labels.drawComponent(pg, idWidth);
1079 pg.translate(+3, -ypos
1080 - (av.getAlignment().getHeight() * av.charHeight));
1084 } while (ypos < totalHeight);
1086 pg.translate(idWidth, 0);
1088 seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1091 if ((pi * pheight) < totalHeight)
1093 return Printable.PAGE_EXISTS;
1098 return Printable.NO_SUCH_PAGE;
1103 * get current sequence ID panel width, or nominal value if panel were to be
1104 * displayed using default settings
1108 int getVisibleIdWidth()
1110 return getVisibleIdWidth(true);
1114 * get current sequence ID panel width, or nominal value if panel were to be
1115 * displayed using default settings
1118 * indicate if the Id width for onscreen or offscreen display should
1122 int getVisibleIdWidth(boolean onscreen)
1124 // see if rendering offscreen - check preferences and calc width accordingly
1125 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1127 return calculateIdWidth(-1).width + 4;
1129 Integer idwidth = null;
1131 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1133 return (idPanel.getWidth() > 0 ? idPanel.getWidth()
1134 : calculateIdWidth().width + 4);
1136 return idwidth.intValue() + 4;
1139 void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
1141 long progress = System.currentTimeMillis();
1142 boolean headless = (System.getProperty("java.awt.headless") != null && System
1143 .getProperty("java.awt.headless").equals("true"));
1144 if (alignFrame != null && !headless)
1146 alignFrame.setProgressBar(MessageManager.formatMessage(
1147 "status.saving_file", new Object[]
1148 { type.getLabel() }), progress);
1152 int maxwidth = av.getAlignment().getWidth();
1153 if (av.hasHiddenColumns())
1155 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1158 int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
1159 + scalePanel.getHeight();
1160 int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
1162 if (av.getWrapAlignment())
1164 height = getWrappedHeight();
1167 // need to obtain default alignment width and then add in any
1168 // additional allowance for id margin
1169 // this duplicates the calculation in getWrappedHeight but adjusts for
1171 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1172 - alignFrame.getInsets().left
1173 - alignFrame.getInsets().right - getVisibleIdWidth()
1174 + getVisibleIdWidth(false);
1178 width = seqPanel.getWidth() + getVisibleIdWidth(false);
1182 else if (av.getShowAnnotation())
1184 height += annotationPanel.adjustPanelHeight() + 3;
1190 jalview.util.ImageMaker im;
1191 final String imageAction, imageTitle;
1192 if (type == jalview.util.ImageMaker.TYPE.PNG)
1194 imageAction = "Create PNG image from alignment";
1197 else if (type == jalview.util.ImageMaker.TYPE.EPS)
1199 imageAction = "Create EPS file from alignment";
1200 imageTitle = alignFrame.getTitle();
1204 imageAction = "Create SVG file from alignment";
1205 imageTitle = alignFrame.getTitle();
1208 im = new jalview.util.ImageMaker(this, type, imageAction, width,
1209 height, file, imageTitle);
1210 if (av.getWrapAlignment())
1212 if (im.getGraphics() != null)
1214 printWrappedAlignment(im.getGraphics(), width, height, 0);
1220 if (im.getGraphics() != null)
1222 printUnwrapped(im.getGraphics(), width, height, 0);
1226 } catch (OutOfMemoryError err)
1229 System.out.println("########################\n" + "OUT OF MEMORY "
1230 + file + "\n" + "########################");
1231 new OOMWarning("Creating Image for " + file, err);
1232 // System.out.println("Create IMAGE: " + err);
1233 } catch (Exception ex)
1235 ex.printStackTrace();
1239 if (alignFrame != null && !headless)
1241 alignFrame.setProgressBar(MessageManager.getString("status.export_complete"), progress);
1249 public void makeEPS(File epsFile)
1251 makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile);
1257 public void makePNG(File pngFile)
1259 makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile);
1262 public void makeSVG(File svgFile)
1264 makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile);
1266 public void makePNGImageMap(File imgMapFile, String imageName)
1268 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1269 // ////////////////////////////////////////////
1270 int idWidth = getVisibleIdWidth(false);
1271 FontMetrics fm = getFontMetrics(av.getFont());
1272 int scaleHeight = av.charHeight + fm.getDescent();
1275 // ////////////////////////////////
1276 if (imgMapFile != null)
1280 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1281 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1282 StringBuffer text = new StringBuffer();
1283 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1284 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1285 out.println("<img src=\"" + imageName
1286 + "\" border=\"0\" usemap=\"#Map\" >"
1287 + "<map name=\"Map\">");
1289 for (s = 0; s < sSize; s++)
1291 sy = s * av.charHeight + scaleHeight;
1293 SequenceI seq = av.getAlignment().getSequenceAt(s);
1294 SequenceFeature[] features = seq.getDatasetSequence()
1295 .getSequenceFeatures();
1296 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1297 for (res = 0; res < alwidth; res++)
1299 text = new StringBuffer();
1301 if (av.getAlignment().isNucleotide())
1303 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1308 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1317 String triplet = obj.toString();
1318 int alIndex = seq.findPosition(res);
1319 gSize = groups.length;
1320 for (g = 0; g < gSize; g++)
1322 if (text.length() < 1)
1324 text.append("<area shape=\"rect\" coords=\""
1325 + (idWidth + res * av.charWidth) + "," + sy + ","
1326 + (idWidth + (res + 1) * av.charWidth) + ","
1327 + (av.charHeight + sy) + "\""
1328 + " onMouseOver=\"toolTip('" + alIndex + " "
1332 if (groups[g].getStartRes() < res
1333 && groups[g].getEndRes() > res)
1335 text.append("<br><em>" + groups[g].getName() + "</em>");
1339 if (features != null)
1341 if (text.length() < 1)
1343 text.append("<area shape=\"rect\" coords=\""
1344 + (idWidth + res * av.charWidth) + "," + sy + ","
1345 + (idWidth + (res + 1) * av.charWidth) + ","
1346 + (av.charHeight + sy) + "\""
1347 + " onMouseOver=\"toolTip('" + alIndex + " "
1350 fSize = features.length;
1351 for (f = 0; f < fSize; f++)
1354 if ((features[f].getBegin() <= seq.findPosition(res))
1355 && (features[f].getEnd() >= seq.findPosition(res)))
1357 if (features[f].getType().equals("disulfide bond"))
1359 if (features[f].getBegin() == seq.findPosition(res)
1360 || features[f].getEnd() == seq
1363 text.append("<br>disulfide bond "
1364 + features[f].getBegin() + ":"
1365 + features[f].getEnd());
1370 text.append("<br>");
1371 text.append(features[f].getType());
1372 if (features[f].getDescription() != null
1373 && !features[f].getType().equals(
1374 features[f].getDescription()))
1376 text.append(" " + features[f].getDescription());
1379 if (features[f].getValue("status") != null)
1381 text.append(" (" + features[f].getValue("status")
1389 if (text.length() > 1)
1391 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1392 out.println(text.toString());
1396 out.println("</map></body></html>");
1399 } catch (Exception ex)
1401 ex.printStackTrace();
1403 } // /////////END OF IMAGE MAP
1407 int getWrappedHeight()
1409 int seqPanelWidth = seqPanel.seqCanvas.getWidth();
1411 if (System.getProperty("java.awt.headless") != null
1412 && System.getProperty("java.awt.headless").equals("true"))
1414 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1415 - vscroll.getPreferredSize().width
1416 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1419 int chunkWidth = seqPanel.seqCanvas
1420 .getWrappedCanvasWidth(seqPanelWidth);
1422 int hgap = av.charHeight;
1423 if (av.scaleAboveWrapped)
1425 hgap += av.charHeight;
1428 int annotationHeight = 0;
1429 if (av.showAnnotation)
1431 annotationHeight = annotationPanel.adjustPanelHeight();
1434 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1437 int maxwidth = av.getAlignment().getWidth();
1438 if (av.hasHiddenColumns())
1440 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1443 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1449 * close the panel - deregisters all listeners and nulls any references to
1452 public void closePanel()
1454 PaintRefresher.RemoveComponent(seqPanel.seqCanvas);
1455 PaintRefresher.RemoveComponent(idPanel.idCanvas);
1456 PaintRefresher.RemoveComponent(this);
1459 jalview.structure.StructureSelectionManager ssm = av
1460 .getStructureSelectionManager();
1461 ssm.removeStructureViewerListener(seqPanel, null);
1462 ssm.removeSelectionListener(seqPanel);
1463 ssm.removeEditListener(av);
1464 av.setAlignment(null);
1469 if (Cache.log.isDebugEnabled())
1471 Cache.log.warn("Closing alignment panel which is already closed.");
1477 * hides or shows dynamic annotation rows based on groups and av state flags
1479 public void updateAnnotation()
1481 updateAnnotation(false, false);
1484 public void updateAnnotation(boolean applyGlobalSettings)
1486 updateAnnotation(applyGlobalSettings, false);
1489 public void updateAnnotation(boolean applyGlobalSettings,
1490 boolean preserveNewGroupSettings)
1492 av.updateGroupAnnotationSettings(applyGlobalSettings,
1493 preserveNewGroupSettings);
1494 adjustAnnotationHeight();
1498 public AlignmentI getAlignment()
1500 return av.getAlignment();
1505 public String getViewName()
1511 * Make/Unmake this alignment panel the current input focus
1515 public void setSelected(boolean b)
1519 alignFrame.setSelected(b);
1520 } catch (Exception ex)
1527 alignFrame.setDisplayedView(this);
1532 public StructureSelectionManager getStructureSelectionManager()
1534 return av.getStructureSelectionManager();
1538 public void raiseOOMWarning(String string, OutOfMemoryError error)
1540 new OOMWarning(string, error, this);
1543 public FeatureRenderer cloneFeatureRenderer()
1546 return new FeatureRenderer(this);
1549 public void updateFeatureRenderer(FeatureRenderer fr)
1551 fr.transferSettings(seqPanel.seqCanvas.getFeatureRenderer());
1554 public void updateFeatureRendererFrom(FeatureRenderer fr)
1556 if (seqPanel.seqCanvas.getFeatureRenderer() != null)
1558 seqPanel.seqCanvas.getFeatureRenderer().transferSettings(fr);