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.isShowAnnotation());
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.getCharHeight()
168 idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av
172 getIdPanel().getIdCanvas().gg = null;
173 getSeqPanel().seqCanvas.img = null;
174 getAnnotationPanel().adjustPanelHeight();
176 Dimension d = calculateIdWidth();
177 d.setSize(d.width + 4, d.height);
178 getIdPanel().getIdCanvas().setPreferredSize(d);
179 hscrollFillerPanel.setPreferredSize(d);
181 if (overviewPanel != null)
183 overviewPanel.setBoxPosition();
190 * Calculate the width of the alignment labels based on the displayed names
191 * and any bounds on label width set in preferences.
193 * @return Dimension giving the maximum width of the alignment label panel
194 * that should be used.
196 public Dimension calculateIdWidth()
198 // calculate sensible default width when no preference is available
200 int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
201 int maxwidth = Math.max(20,
202 Math.min(afwidth - 200, 2 * afwidth / 3));
203 return calculateIdWidth(maxwidth);
207 * Calculate the width of the alignment labels based on the displayed names
208 * and any bounds on label width set in preferences.
211 * -1 or maximum width allowed for IdWidth
212 * @return Dimension giving the maximum width of the alignment label panel
213 * that should be used.
215 public Dimension calculateIdWidth(int maxwidth)
217 Container c = new Container();
219 FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
220 Font.ITALIC, av.font.getSize()));
222 AlignmentI al = av.getAlignment();
227 while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
229 SequenceI s = al.getSequenceAt(i);
231 id = s.getDisplayId(av.getShowJVSuffix());
233 if (fm.stringWidth(id) > idWidth)
235 idWidth = fm.stringWidth(id);
241 // Also check annotation label widths
244 if (al.getAlignmentAnnotation() != null)
246 fm = c.getFontMetrics(getAlabels().getFont());
248 while (i < al.getAlignmentAnnotation().length)
250 String label = al.getAlignmentAnnotation()[i].label;
252 if (fm.stringWidth(label) > idWidth)
254 idWidth = fm.stringWidth(label);
261 return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
266 * Highlight the given results on the alignment.
269 public void highlightSearchResults(SearchResults results)
271 scrollToPosition(results);
272 getSeqPanel().seqCanvas.highlightSearchResults(results);
276 * scroll the view to show the position of the highlighted region in results
277 * (if any) and redraw the overview
281 public boolean scrollToPosition(SearchResults results)
283 return scrollToPosition(results, true);
287 * scroll the view to show the position of the highlighted region in results
291 * @param redrawOverview
292 * - when set, the overview will be recalculated (takes longer)
293 * @return false if results were not found
295 public boolean scrollToPosition(SearchResults results,
296 boolean redrawOverview)
298 int startv, endv, starts, ends, width;
299 // TODO: properly locate search results in view when large numbers of hidden
300 // columns exist before highlighted region
301 // do we need to scroll the panel?
302 // TODO: tons of nullpointereexceptions raised here.
303 if (results != null && results.getSize() > 0 && av != null
304 && av.getAlignment() != null)
306 int seqIndex = av.getAlignment().findIndex(results);
311 SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
313 int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
320 // System.err.println("Seq : "+seqIndex+" Scroll to "+start+","+end); //
326 if (end == seq.getEnd())
330 if (av.hasHiddenColumns())
332 start = av.getColumnSelection().findColumnPosition(start);
333 end = av.getColumnSelection().findColumnPosition(end);
336 if (!av.getColumnSelection().isVisible(r[0]))
338 // don't scroll - position isn't visible
343 if (!av.getWrapAlignment())
345 if ((startv = av.getStartRes()) >= start)
347 setScrollValues(start - 1, seqIndex);
349 else if ((endv = av.getEndRes()) <= end)
351 setScrollValues(startv + 1 + end - endv, seqIndex);
353 else if ((starts = av.getStartSeq()) > seqIndex)
355 setScrollValues(av.getStartRes(), seqIndex);
357 else if ((ends = av.getEndSeq()) <= seqIndex)
359 setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
364 scrollToWrappedVisible(start);
367 if (redrawOverview && overviewPanel != null)
369 overviewPanel.setBoxPosition();
371 paintAlignment(redrawOverview);
375 void scrollToWrappedVisible(int res)
377 int cwidth = getSeqPanel().seqCanvas
378 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
379 if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
381 vscroll.setValue((res / cwidth));
382 av.startRes = vscroll.getValue() * cwidth;
390 * @return DOCUMENT ME!
392 public OverviewPanel getOverviewPanel()
394 return overviewPanel;
403 public void setOverviewPanel(OverviewPanel op)
411 * Hide or show annotation panel
414 public void setAnnotationVisible(boolean b)
416 if (!av.getWrapAlignment())
418 annotationSpaceFillerHolder.setVisible(b);
419 annotationScroller.setVisible(b);
425 * automatically adjust annotation panel height for new annotation whilst
426 * ensuring the alignment is still visible.
428 public void adjustAnnotationHeight()
430 // TODO: display vertical annotation scrollbar if necessary
431 // this is called after loading new annotation onto alignment
432 if (alignFrame.getHeight() == 0)
434 System.out.println("NEEDS FIXING");
436 validateAnnotationDimensions(true);
438 paintAlignment(true);
442 * calculate the annotation dimensions and refresh slider values accordingly.
443 * need to do repaints/notifys afterwards.
445 protected void validateAnnotationDimensions(boolean adjustPanelHeight)
447 int height = getAnnotationPanel().adjustPanelHeight();
449 int theight = av.getCharHeight()
450 * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0
451 : av.getAlignment().getHiddenSequences().getSize()));
452 float sscaling = (float) (theight / (1.0 * theight + height));
453 float ascaling = (float) (height * 1.0 / alignFrame.getHeight());
454 int rheight = alignFrame.getHeight() - height - av.getCharHeight();
455 if (adjustPanelHeight)
457 // NOTE: this logic is different in the applet. Need a better algorithm to
459 // try and set height according to alignment
460 if (ascaling > 0 && sscaling < 0.5)
462 // if the alignment is too big then
463 // default is 0.5 split
464 height = alignFrame.getHeight() / 2;
468 // if space for more than one sequence row left when annotation is fully
469 // displayed then set height to annotation height
470 // otherwise, leave at least two lines of sequence shown.
471 height = (rheight > av.getCharHeight()) ? height
472 : (-av.getCharHeight() * 3 + (int) (alignFrame.getHeight() * (1 - sscaling)));
477 // maintain same window layout whilst updating sliders
478 height = annotationScroller.getSize().height;
482 annotationScroller.setPreferredSize(new Dimension(annotationScroller
483 .getWidth(), height));
485 annotationSpaceFillerHolder.setPreferredSize(new Dimension(
486 annotationSpaceFillerHolder.getWidth(), height));
487 annotationScroller.validate();// repaint();
488 annotationScroller.addNotify();
497 public void setWrapAlignment(boolean wrap)
500 scalePanelHolder.setVisible(!wrap);
501 hscroll.setVisible(!wrap);
502 idwidthAdjuster.setVisible(!wrap);
506 annotationScroller.setVisible(false);
507 annotationSpaceFillerHolder.setVisible(false);
509 else if (av.isShowAnnotation())
511 annotationScroller.setVisible(true);
512 annotationSpaceFillerHolder.setVisible(true);
515 idSpaceFillerPanel1.setVisible(!wrap);
520 // return value is true if the scroll is valid
521 public boolean scrollUp(boolean up)
525 if (vscroll.getValue() < 1)
531 vscroll.setValue(vscroll.getValue() - 1);
535 if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())
541 vscroll.setValue(vscroll.getValue() + 1);
555 * @return DOCUMENT ME!
557 public boolean scrollRight(boolean right)
561 if (hscroll.getValue() < 1)
567 hscroll.setValue(hscroll.getValue() - 1);
571 if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())
577 hscroll.setValue(hscroll.getValue() + 1);
586 * Adjust row/column scrollers to show a visible position in the alignment.
589 * visible column to scroll to DOCUMENT ME!
591 * visible row to scroll to
594 public void setScrollValues(int x, int y)
596 // System.err.println("Scroll to "+x+","+y);
597 if (av == null || av.getAlignment() == null)
601 int width = av.getAlignment().getWidth();
602 int height = av.getAlignment().getHeight();
604 if (av.hasHiddenColumns())
606 width = av.getColumnSelection().findColumnPosition(width);
609 av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av
610 .getCharWidth())) - 1);
612 hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
613 vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
620 if (vextent > height)
625 if ((hextent + x) > width)
630 if ((vextent + y) > height)
632 y = height - vextent;
645 hscroll.setValues(x, hextent, 0, width);
646 vscroll.setValues(y, vextent, 0, height);
655 public void adjustmentValueChanged(AdjustmentEvent evt)
658 int oldX = av.getStartRes();
659 int oldY = av.getStartSeq();
661 if (evt.getSource() == hscroll)
663 int x = hscroll.getValue();
665 av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av.getCharWidth())) - 1);
668 if (evt.getSource() == vscroll)
670 int offy = vscroll.getValue();
672 if (av.getWrapAlignment())
676 int rowSize = getSeqPanel().seqCanvas
677 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
678 av.setStartRes(offy * rowSize);
679 av.setEndRes((offy + 1) * rowSize);
683 // This is only called if file loaded is a jar file that
684 // was wrapped when saved and user has wrap alignment true
685 // as preference setting
686 SwingUtilities.invokeLater(new Runnable()
690 setScrollValues(av.getStartRes(), av.getStartSeq());
697 av.setStartSeq(offy);
699 + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight()));
703 if (overviewPanel != null)
705 overviewPanel.setBoxPosition();
708 int scrollX = av.startRes - oldX;
709 int scrollY = av.startSeq - oldY;
711 if (av.getWrapAlignment() || !fastPaint)
717 // Make sure we're not trying to draw a panel
718 // larger than the visible window
719 if (scrollX > av.endRes - av.startRes)
721 scrollX = av.endRes - av.startRes;
723 else if (scrollX < av.startRes - av.endRes)
725 scrollX = av.startRes - av.endRes;
728 if (scrollX != 0 || scrollY != 0)
730 getIdPanel().getIdCanvas().fastPaint(scrollY);
731 getSeqPanel().seqCanvas.fastPaint(scrollX, scrollY);
732 getScalePanel().repaint();
734 if (av.isShowAnnotation() && scrollX != 0)
736 getAnnotationPanel().fastPaint(scrollX);
743 * Repaint the alignment including the annotations and overview panels (if
746 public void paintAlignment(boolean updateOverview)
748 final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
749 av.isShowAutocalculatedAbove());
750 sorter.sort(getAlignment()
751 .getAlignmentAnnotation(),
752 av.getSortAnnotationsBy());
757 av.getStructureSelectionManager().sequenceColoursChanged(this);
759 if (overviewPanel != null)
761 overviewPanel.updateOverviewImage();
772 public void paintComponent(Graphics g)
776 Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
777 idPanelHolder.setPreferredSize(d);
778 hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
781 if (av.getWrapAlignment())
783 int maxwidth = av.getAlignment().getWidth();
785 if (av.hasHiddenColumns())
787 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
790 int canvasWidth = getSeqPanel().seqCanvas
791 .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
795 / getSeqPanel().seqCanvas
796 .getWrappedCanvasWidth(getSeqPanel().seqCanvas
798 vscroll.setMaximum(max);
799 vscroll.setUnitIncrement(1);
800 vscroll.setVisibleAmount(1);
805 setScrollValues(av.getStartRes(), av.getStartSeq());
819 * @return DOCUMENT ME!
821 * @throws PrinterException
824 public int print(Graphics pg, PageFormat pf, int pi)
825 throws PrinterException
827 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
829 int pwidth = (int) pf.getImageableWidth();
830 int pheight = (int) pf.getImageableHeight();
832 if (av.getWrapAlignment())
834 return printWrappedAlignment(pg, pwidth, pheight, pi);
838 return printUnwrapped(pg, pwidth, pheight, pi);
854 * @return DOCUMENT ME!
856 * @throws PrinterException
859 public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
860 throws PrinterException
862 int idWidth = getVisibleIdWidth(false);
863 FontMetrics fm = getFontMetrics(av.getFont());
864 int scaleHeight = av.getCharHeight() + fm.getDescent();
866 pg.setColor(Color.white);
867 pg.fillRect(0, 0, pwidth, pheight);
868 pg.setFont(av.getFont());
870 // //////////////////////////////////
871 // / How many sequences and residues can we fit on a printable page?
872 int totalRes = (pwidth - idWidth) / av.getCharWidth();
874 int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
876 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
878 // ///////////////////////////
879 // / Only print these sequences and residues on this page
882 // ///////////////////////////
883 // / Only print these sequences and residues on this page
886 // ///////////////////////////
887 // / Only print these sequences and residues on this page
890 // ///////////////////////////
891 // / Only print these sequences and residues on this page
893 startRes = (pi % pagesWide) * totalRes;
894 endRes = (startRes + totalRes) - 1;
896 if (endRes > (av.getAlignment().getWidth() - 1))
898 endRes = av.getAlignment().getWidth() - 1;
901 startSeq = (pi / pagesWide) * totalSeq;
902 endSeq = startSeq + totalSeq;
904 if (endSeq > av.getAlignment().getHeight())
906 endSeq = av.getAlignment().getHeight();
909 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
912 if (av.isShowAnnotation())
914 pagesHigh += getAnnotationPanel().adjustPanelHeight() + 3;
917 pagesHigh /= pheight;
919 if (pi >= (pagesWide * pagesHigh))
921 return Printable.NO_SUCH_PAGE;
925 pg.translate(idWidth, 0);
926 getScalePanel().drawScale(pg, startRes, endRes, pwidth - idWidth,
928 pg.translate(-idWidth, scaleHeight);
932 Color currentColor = null;
933 Color currentTextColor = null;
935 pg.setFont(getIdPanel().getIdCanvas().getIdfont());
938 for (int i = startSeq; i < endSeq; i++)
940 seq = av.getAlignment().getSequenceAt(i);
941 if ((av.getSelectionGroup() != null)
942 && av.getSelectionGroup().getSequences(null).contains(seq))
944 currentColor = Color.gray;
945 currentTextColor = Color.black;
949 currentColor = av.getSequenceColour(seq);
950 currentTextColor = Color.black;
953 pg.setColor(currentColor);
954 pg.fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
957 pg.setColor(currentTextColor);
960 if (av.isRightAlignIds())
962 fm = pg.getFontMetrics();
964 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
969 seq.getDisplayId(av.getShowJVSuffix()),
971 (((i - startSeq) * av.getCharHeight()) + av.getCharHeight())
972 - (av.getCharHeight() / 5));
975 pg.setFont(av.getFont());
977 // draw main sequence panel
978 pg.translate(idWidth, 0);
979 getSeqPanel().seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
981 if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
983 // draw annotation - need to offset for current scroll position
984 int offset = -getAlabels().getScrollOffset();
985 pg.translate(0, offset);
986 pg.translate(-idWidth - 3, (endSeq - startSeq) * av.getCharHeight()
988 getAlabels().drawComponent(pg, idWidth);
989 pg.translate(idWidth + 3, 0);
990 getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
991 pg, -1, startRes, endRes + 1);
992 pg.translate(0, -offset);
995 return Printable.PAGE_EXISTS;
1010 * @return DOCUMENT ME!
1012 * @throws PrinterException
1015 public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
1016 int pi) throws PrinterException
1018 int annotationHeight = 0;
1019 AnnotationLabels labels = null;
1020 if (av.isShowAnnotation())
1022 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1023 labels = new AnnotationLabels(av);
1026 int hgap = av.getCharHeight();
1027 if (av.getScaleAboveWrapped())
1029 hgap += av.getCharHeight();
1032 int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap
1035 int idWidth = getVisibleIdWidth(false);
1037 int maxwidth = av.getAlignment().getWidth();
1038 if (av.hasHiddenColumns())
1040 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1043 int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
1046 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1048 pg.setColor(Color.white);
1049 pg.fillRect(0, 0, pwidth, pheight);
1050 pg.setFont(av.getFont());
1054 pg.setColor(Color.black);
1056 pg.translate(0, -pi * pheight);
1058 pg.setClip(0, pi * pheight, pwidth, pheight);
1064 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1066 pg.setFont(getIdPanel().getIdCanvas().getIdfont());
1067 SequenceI s = av.getAlignment().getSequenceAt(i);
1068 String string = s.getDisplayId(av.getShowJVSuffix());
1070 if (av.isRightAlignIds())
1072 FontMetrics fm = pg.getFontMetrics();
1073 xPos = idWidth - fm.stringWidth(string) - 4;
1075 pg.drawString(string, xPos,
1076 ((i * av.getCharHeight()) + ypos + av.getCharHeight())
1077 - (av.getCharHeight() / 5));
1081 pg.translate(-3, ypos
1082 + (av.getAlignment().getHeight() * av.getCharHeight()));
1084 pg.setFont(av.getFont());
1085 labels.drawComponent(pg, idWidth);
1086 pg.translate(+3, -ypos
1087 - (av.getAlignment().getHeight() * av
1092 } while (ypos < totalHeight);
1094 pg.translate(idWidth, 0);
1096 getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1099 if ((pi * pheight) < totalHeight)
1101 return Printable.PAGE_EXISTS;
1106 return Printable.NO_SUCH_PAGE;
1111 * get current sequence ID panel width, or nominal value if panel were to be
1112 * displayed using default settings
1116 public int getVisibleIdWidth()
1118 return getVisibleIdWidth(true);
1122 * get current sequence ID panel width, or nominal value if panel were to be
1123 * displayed using default settings
1126 * indicate if the Id width for onscreen or offscreen display should
1130 public int getVisibleIdWidth(boolean onscreen)
1132 // see if rendering offscreen - check preferences and calc width accordingly
1133 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1135 return calculateIdWidth(-1).width + 4;
1137 Integer idwidth = null;
1139 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1141 return (getIdPanel().getWidth() > 0 ? getIdPanel().getWidth()
1142 : calculateIdWidth().width + 4);
1144 return idwidth.intValue() + 4;
1147 void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
1149 long progress = System.currentTimeMillis();
1150 headless = (System.getProperty("java.awt.headless") != null && System
1151 .getProperty("java.awt.headless").equals("true"));
1152 if (alignFrame != null && !headless)
1154 alignFrame.setProgressBar(MessageManager.formatMessage(
1155 "status.saving_file",
1157 { type.getLabel() }), progress);
1161 AlignmentDimension aDimension = getAlignmentDimension();
1164 jalview.util.ImageMaker im;
1165 final String imageAction, imageTitle;
1166 if (type == jalview.util.ImageMaker.TYPE.PNG)
1168 imageAction = "Create PNG image from alignment";
1171 else if (type == jalview.util.ImageMaker.TYPE.EPS)
1173 imageAction = "Create EPS file from alignment";
1174 imageTitle = alignFrame.getTitle();
1178 imageAction = "Create SVG file from alignment";
1179 imageTitle = alignFrame.getTitle();
1182 im = new jalview.util.ImageMaker(this, type, imageAction,
1183 aDimension.getWidth(), aDimension.getHeight(), file,
1185 if (av.getWrapAlignment())
1187 if (im.getGraphics() != null)
1189 printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
1190 aDimension.getHeight(), 0);
1196 if (im.getGraphics() != null)
1198 printUnwrapped(im.getGraphics(), aDimension.getWidth(),
1199 aDimension.getHeight(), 0);
1203 } catch (OutOfMemoryError err)
1206 System.out.println("########################\n" + "OUT OF MEMORY "
1207 + file + "\n" + "########################");
1208 new OOMWarning("Creating Image for " + file, err);
1209 // System.out.println("Create IMAGE: " + err);
1210 } catch (Exception ex)
1212 ex.printStackTrace();
1216 if (alignFrame != null && !headless)
1218 alignFrame.setProgressBar(MessageManager.getString("status.export_complete"), progress);
1223 public AlignmentDimension getAlignmentDimension()
1225 int maxwidth = av.getAlignment().getWidth();
1226 if (av.hasHiddenColumns())
1228 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1231 int height = ((av.getAlignment().getHeight() + 1) * av.getCharHeight())
1232 + getScalePanel().getHeight();
1233 int width = getVisibleIdWidth(false) + (maxwidth * av.getCharWidth());
1235 if (av.getWrapAlignment())
1237 height = getWrappedHeight();
1240 // need to obtain default alignment width and then add in any
1241 // additional allowance for id margin
1242 // this duplicates the calculation in getWrappedHeight but adjusts for
1244 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1245 - alignFrame.getInsets().left
1246 - alignFrame.getInsets().right - getVisibleIdWidth()
1247 + getVisibleIdWidth(false);
1251 width = getSeqPanel().getWidth() + getVisibleIdWidth(false);
1255 else if (av.isShowAnnotation())
1257 height += getAnnotationPanel().adjustPanelHeight() + 3;
1259 return new AlignmentDimension(width, height);
1266 public void makeEPS(File epsFile)
1268 makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile);
1274 public void makePNG(File pngFile)
1276 makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile);
1279 public void makeSVG(File svgFile)
1281 makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile);
1283 public void makePNGImageMap(File imgMapFile, String imageName)
1285 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1286 // ////////////////////////////////////////////
1287 int idWidth = getVisibleIdWidth(false);
1288 FontMetrics fm = getFontMetrics(av.getFont());
1289 int scaleHeight = av.getCharHeight() + fm.getDescent();
1292 // ////////////////////////////////
1293 if (imgMapFile != null)
1297 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1298 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1299 StringBuffer text = new StringBuffer();
1300 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1301 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1302 out.println("<img src=\"" + imageName
1303 + "\" border=\"0\" usemap=\"#Map\" >"
1304 + "<map name=\"Map\">");
1306 for (s = 0; s < sSize; s++)
1308 sy = s * av.getCharHeight() + scaleHeight;
1310 SequenceI seq = av.getAlignment().getSequenceAt(s);
1311 SequenceFeature[] features = seq.getDatasetSequence()
1312 .getSequenceFeatures();
1313 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1314 for (res = 0; res < alwidth; res++)
1316 text = new StringBuffer();
1318 if (av.getAlignment().isNucleotide())
1320 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1325 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1334 String triplet = obj.toString();
1335 int alIndex = seq.findPosition(res);
1336 gSize = groups.length;
1337 for (g = 0; g < gSize; g++)
1339 if (text.length() < 1)
1341 text.append("<area shape=\"rect\" coords=\""
1342 + (idWidth + res * av.getCharWidth()) + "," + sy
1343 + "," + (idWidth + (res + 1) * av.getCharWidth())
1345 + (av.getCharHeight() + sy) + "\""
1346 + " onMouseOver=\"toolTip('" + alIndex + " "
1350 if (groups[g].getStartRes() < res
1351 && groups[g].getEndRes() > res)
1353 text.append("<br><em>" + groups[g].getName() + "</em>");
1357 if (features != null)
1359 if (text.length() < 1)
1361 text.append("<area shape=\"rect\" coords=\""
1362 + (idWidth + res * av.getCharWidth()) + "," + sy
1363 + "," + (idWidth + (res + 1) * av.getCharWidth())
1365 + (av.getCharHeight() + sy) + "\""
1366 + " onMouseOver=\"toolTip('" + alIndex + " "
1369 fSize = features.length;
1370 for (f = 0; f < fSize; f++)
1373 if ((features[f].getBegin() <= seq.findPosition(res))
1374 && (features[f].getEnd() >= seq.findPosition(res)))
1376 if (features[f].getType().equals("disulfide bond"))
1378 if (features[f].getBegin() == seq.findPosition(res)
1379 || features[f].getEnd() == seq
1382 text.append("<br>disulfide bond "
1383 + features[f].getBegin() + ":"
1384 + features[f].getEnd());
1389 text.append("<br>");
1390 text.append(features[f].getType());
1391 if (features[f].getDescription() != null
1392 && !features[f].getType().equals(
1393 features[f].getDescription()))
1395 text.append(" " + features[f].getDescription());
1398 if (features[f].getValue("status") != null)
1400 text.append(" (" + features[f].getValue("status")
1408 if (text.length() > 1)
1410 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1411 out.println(text.toString());
1415 out.println("</map></body></html>");
1418 } catch (Exception ex)
1420 ex.printStackTrace();
1422 } // /////////END OF IMAGE MAP
1426 int getWrappedHeight()
1428 int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
1430 if (System.getProperty("java.awt.headless") != null
1431 && System.getProperty("java.awt.headless").equals("true"))
1433 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1434 - vscroll.getPreferredSize().width
1435 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1438 int chunkWidth = getSeqPanel().seqCanvas
1439 .getWrappedCanvasWidth(seqPanelWidth);
1441 int hgap = av.getCharHeight();
1442 if (av.getScaleAboveWrapped())
1444 hgap += av.getCharHeight();
1447 int annotationHeight = 0;
1448 if (av.isShowAnnotation())
1450 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1453 int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap
1456 int maxwidth = av.getAlignment().getWidth();
1457 if (av.hasHiddenColumns())
1459 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1462 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1468 * close the panel - deregisters all listeners and nulls any references to
1471 public void closePanel()
1473 PaintRefresher.RemoveComponent(getSeqPanel().seqCanvas);
1474 PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas());
1475 PaintRefresher.RemoveComponent(this);
1478 jalview.structure.StructureSelectionManager ssm = av
1479 .getStructureSelectionManager();
1480 ssm.removeStructureViewerListener(getSeqPanel(), null);
1481 ssm.removeSelectionListener(getSeqPanel());
1482 av.setAlignment(null);
1487 if (Cache.log.isDebugEnabled())
1489 Cache.log.warn("Closing alignment panel which is already closed.");
1495 * hides or shows dynamic annotation rows based on groups and av state flags
1497 public void updateAnnotation()
1499 updateAnnotation(false, false);
1502 public void updateAnnotation(boolean applyGlobalSettings)
1504 updateAnnotation(applyGlobalSettings, false);
1507 public void updateAnnotation(boolean applyGlobalSettings,
1508 boolean preserveNewGroupSettings)
1510 av.updateGroupAnnotationSettings(applyGlobalSettings,
1511 preserveNewGroupSettings);
1512 adjustAnnotationHeight();
1516 public AlignmentI getAlignment()
1518 return av.getAlignment();
1523 public String getViewName()
1529 * Make/Unmake this alignment panel the current input focus
1533 public void setSelected(boolean b)
1537 alignFrame.setSelected(b);
1538 } catch (Exception ex)
1545 alignFrame.setDisplayedView(this);
1550 public StructureSelectionManager getStructureSelectionManager()
1552 return av.getStructureSelectionManager();
1556 public void raiseOOMWarning(String string, OutOfMemoryError error)
1558 new OOMWarning(string, error, this);
1562 public jalview.api.FeatureRenderer cloneFeatureRenderer()
1565 return new FeatureRenderer(this);
1568 public jalview.api.FeatureRenderer getFeatureRenderer()
1570 return seqPanel.seqCanvas.getFeatureRenderer();
1572 public void updateFeatureRenderer(jalview.renderer.seqfeatures.FeatureRenderer fr)
1574 fr.transferSettings(getSeqPanel().seqCanvas.getFeatureRenderer());
1577 public void updateFeatureRendererFrom(jalview.api.FeatureRenderer fr)
1579 if (getSeqPanel().seqCanvas.getFeatureRenderer() != null)
1581 getSeqPanel().seqCanvas.getFeatureRenderer().transferSettings(fr);
1585 public ScalePanel getScalePanel()
1590 public void setScalePanel(ScalePanel scalePanel)
1592 this.scalePanel = scalePanel;
1595 public SeqPanel getSeqPanel()
1600 public void setSeqPanel(SeqPanel seqPanel)
1602 this.seqPanel = seqPanel;
1605 public AnnotationPanel getAnnotationPanel()
1607 return annotationPanel;
1610 public void setAnnotationPanel(AnnotationPanel annotationPanel)
1612 this.annotationPanel = annotationPanel;
1615 public AnnotationLabels getAlabels()
1620 public void setAlabels(AnnotationLabels alabels)
1622 this.alabels = alabels;
1625 public IdPanel getIdPanel()
1630 public void setIdPanel(IdPanel idPanel)
1632 this.idPanel = idPanel;