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
1019 int annotationHeight = 0;
1020 AnnotationLabels labels = null;
1021 if (av.isShowAnnotation())
1023 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1024 labels = new AnnotationLabels(av);
1027 int hgap = av.getCharHeight();
1028 if (av.getScaleAboveWrapped())
1030 hgap += av.getCharHeight();
1033 int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap
1036 int idWidth = getVisibleIdWidth(false);
1038 int maxwidth = av.getAlignment().getWidth();
1039 if (av.hasHiddenColumns())
1041 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1044 int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
1047 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1049 pg.setColor(Color.white);
1050 pg.fillRect(0, 0, pwidth, pheight);
1051 pg.setFont(av.getFont());
1055 pg.setColor(Color.black);
1057 pg.translate(0, -pi * pheight);
1059 pg.setClip(0, pi * pheight, pwidth, pheight);
1065 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1067 pg.setFont(getIdPanel().getIdCanvas().getIdfont());
1068 SequenceI s = av.getAlignment().getSequenceAt(i);
1069 String string = s.getDisplayId(av.getShowJVSuffix());
1071 if (av.isRightAlignIds())
1073 FontMetrics fm = pg.getFontMetrics();
1074 xPos = idWidth - fm.stringWidth(string) - 4;
1076 pg.drawString(string, xPos,
1077 ((i * av.getCharHeight()) + ypos + av.getCharHeight())
1078 - (av.getCharHeight() / 5));
1082 pg.translate(-3, ypos
1083 + (av.getAlignment().getHeight() * av.getCharHeight()));
1085 pg.setFont(av.getFont());
1086 labels.drawComponent(pg, idWidth);
1087 pg.translate(+3, -ypos
1088 - (av.getAlignment().getHeight() * av
1093 } while (ypos < totalHeight);
1095 pg.translate(idWidth, 0);
1097 getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1100 if ((pi * pheight) < totalHeight)
1102 return Printable.PAGE_EXISTS;
1107 return Printable.NO_SUCH_PAGE;
1112 * get current sequence ID panel width, or nominal value if panel were to be
1113 * displayed using default settings
1117 public int getVisibleIdWidth()
1119 return getVisibleIdWidth(true);
1123 * get current sequence ID panel width, or nominal value if panel were to be
1124 * displayed using default settings
1127 * indicate if the Id width for onscreen or offscreen display should
1131 public int getVisibleIdWidth(boolean onscreen)
1133 // see if rendering offscreen - check preferences and calc width accordingly
1134 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1136 return calculateIdWidth(-1).width + 4;
1138 Integer idwidth = null;
1140 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1142 return (getIdPanel().getWidth() > 0 ? getIdPanel().getWidth()
1143 : calculateIdWidth().width + 4);
1145 return idwidth.intValue() + 4;
1148 void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
1150 long progress = System.currentTimeMillis();
1151 headless = (System.getProperty("java.awt.headless") != null && System
1152 .getProperty("java.awt.headless").equals("true"));
1153 if (alignFrame != null && !headless)
1155 alignFrame.setProgressBar(MessageManager.formatMessage(
1156 "status.saving_file",
1158 { type.getLabel() }), progress);
1162 AlignmentDimension aDimension = getAlignmentDimension();
1165 jalview.util.ImageMaker im;
1166 final String imageAction, imageTitle;
1167 if (type == jalview.util.ImageMaker.TYPE.PNG)
1169 imageAction = "Create PNG image from alignment";
1172 else if (type == jalview.util.ImageMaker.TYPE.EPS)
1174 imageAction = "Create EPS file from alignment";
1175 imageTitle = alignFrame.getTitle();
1179 imageAction = "Create SVG file from alignment";
1180 imageTitle = alignFrame.getTitle();
1183 im = new jalview.util.ImageMaker(this, type, imageAction,
1184 aDimension.getWidth(), aDimension.getHeight(), file,
1186 if (av.getWrapAlignment())
1188 if (im.getGraphics() != null)
1190 printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
1191 aDimension.getHeight(), 0);
1197 if (im.getGraphics() != null)
1199 printUnwrapped(im.getGraphics(), aDimension.getWidth(),
1200 aDimension.getHeight(), 0);
1204 } catch (OutOfMemoryError err)
1207 System.out.println("########################\n" + "OUT OF MEMORY "
1208 + file + "\n" + "########################");
1209 new OOMWarning("Creating Image for " + file, err);
1210 // System.out.println("Create IMAGE: " + err);
1211 } catch (Exception ex)
1213 ex.printStackTrace();
1217 if (alignFrame != null && !headless)
1219 alignFrame.setProgressBar(MessageManager.getString("status.export_complete"), progress);
1224 public AlignmentDimension getAlignmentDimension()
1226 int maxwidth = av.getAlignment().getWidth();
1227 if (av.hasHiddenColumns())
1229 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1232 int height = ((av.getAlignment().getHeight() + 1) * av.getCharHeight())
1233 + getScalePanel().getHeight();
1234 int width = getVisibleIdWidth(false) + (maxwidth * av.getCharWidth());
1236 if (av.getWrapAlignment())
1238 height = getWrappedHeight();
1241 // need to obtain default alignment width and then add in any
1242 // additional allowance for id margin
1243 // this duplicates the calculation in getWrappedHeight but adjusts for
1245 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1246 - alignFrame.getInsets().left
1247 - alignFrame.getInsets().right - getVisibleIdWidth()
1248 + getVisibleIdWidth(false);
1252 width = getSeqPanel().getWidth() + getVisibleIdWidth(false);
1256 else if (av.isShowAnnotation())
1258 height += getAnnotationPanel().adjustPanelHeight() + 3;
1260 return new AlignmentDimension(width, height);
1267 public void makeEPS(File epsFile)
1269 makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile);
1275 public void makePNG(File pngFile)
1277 makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile);
1280 public void makeSVG(File svgFile)
1282 makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile);
1284 public void makePNGImageMap(File imgMapFile, String imageName)
1286 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1287 // ////////////////////////////////////////////
1288 int idWidth = getVisibleIdWidth(false);
1289 FontMetrics fm = getFontMetrics(av.getFont());
1290 int scaleHeight = av.getCharHeight() + fm.getDescent();
1293 // ////////////////////////////////
1294 if (imgMapFile != null)
1298 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1299 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1300 StringBuffer text = new StringBuffer();
1301 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1302 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1303 out.println("<img src=\"" + imageName
1304 + "\" border=\"0\" usemap=\"#Map\" >"
1305 + "<map name=\"Map\">");
1307 for (s = 0; s < sSize; s++)
1309 sy = s * av.getCharHeight() + scaleHeight;
1311 SequenceI seq = av.getAlignment().getSequenceAt(s);
1312 SequenceFeature[] features = seq.getDatasetSequence()
1313 .getSequenceFeatures();
1314 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1315 for (res = 0; res < alwidth; res++)
1317 text = new StringBuffer();
1319 if (av.getAlignment().isNucleotide())
1321 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1326 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1335 String triplet = obj.toString();
1336 int alIndex = seq.findPosition(res);
1337 gSize = groups.length;
1338 for (g = 0; g < gSize; g++)
1340 if (text.length() < 1)
1342 text.append("<area shape=\"rect\" coords=\""
1343 + (idWidth + res * av.getCharWidth()) + "," + sy
1344 + "," + (idWidth + (res + 1) * av.getCharWidth())
1346 + (av.getCharHeight() + sy) + "\""
1347 + " onMouseOver=\"toolTip('" + alIndex + " "
1351 if (groups[g].getStartRes() < res
1352 && groups[g].getEndRes() > res)
1354 text.append("<br><em>" + groups[g].getName() + "</em>");
1358 if (features != null)
1360 if (text.length() < 1)
1362 text.append("<area shape=\"rect\" coords=\""
1363 + (idWidth + res * av.getCharWidth()) + "," + sy
1364 + "," + (idWidth + (res + 1) * av.getCharWidth())
1366 + (av.getCharHeight() + sy) + "\""
1367 + " onMouseOver=\"toolTip('" + alIndex + " "
1370 fSize = features.length;
1371 for (f = 0; f < fSize; f++)
1374 if ((features[f].getBegin() <= seq.findPosition(res))
1375 && (features[f].getEnd() >= seq.findPosition(res)))
1377 if (features[f].getType().equals("disulfide bond"))
1379 if (features[f].getBegin() == seq.findPosition(res)
1380 || features[f].getEnd() == seq
1383 text.append("<br>disulfide bond "
1384 + features[f].getBegin() + ":"
1385 + features[f].getEnd());
1390 text.append("<br>");
1391 text.append(features[f].getType());
1392 if (features[f].getDescription() != null
1393 && !features[f].getType().equals(
1394 features[f].getDescription()))
1396 text.append(" " + features[f].getDescription());
1399 if (features[f].getValue("status") != null)
1401 text.append(" (" + features[f].getValue("status")
1409 if (text.length() > 1)
1411 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1412 out.println(text.toString());
1416 out.println("</map></body></html>");
1419 } catch (Exception ex)
1421 ex.printStackTrace();
1423 } // /////////END OF IMAGE MAP
1427 int getWrappedHeight()
1429 int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
1431 if (System.getProperty("java.awt.headless") != null
1432 && System.getProperty("java.awt.headless").equals("true"))
1434 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1435 - vscroll.getPreferredSize().width
1436 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1439 int chunkWidth = getSeqPanel().seqCanvas
1440 .getWrappedCanvasWidth(seqPanelWidth);
1442 int hgap = av.getCharHeight();
1443 if (av.getScaleAboveWrapped())
1445 hgap += av.getCharHeight();
1448 int annotationHeight = 0;
1449 if (av.isShowAnnotation())
1451 annotationHeight = getAnnotationPanel().adjustPanelHeight();
1454 int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap
1457 int maxwidth = av.getAlignment().getWidth();
1458 if (av.hasHiddenColumns())
1460 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1463 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1469 * close the panel - deregisters all listeners and nulls any references to
1472 public void closePanel()
1474 PaintRefresher.RemoveComponent(getSeqPanel().seqCanvas);
1475 PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas());
1476 PaintRefresher.RemoveComponent(this);
1479 jalview.structure.StructureSelectionManager ssm = av
1480 .getStructureSelectionManager();
1481 ssm.removeStructureViewerListener(getSeqPanel(), null);
1482 ssm.removeSelectionListener(getSeqPanel());
1483 av.setAlignment(null);
1488 if (Cache.log.isDebugEnabled())
1490 Cache.log.warn("Closing alignment panel which is already closed.");
1496 * hides or shows dynamic annotation rows based on groups and av state flags
1498 public void updateAnnotation()
1500 updateAnnotation(false, false);
1503 public void updateAnnotation(boolean applyGlobalSettings)
1505 updateAnnotation(applyGlobalSettings, false);
1508 public void updateAnnotation(boolean applyGlobalSettings,
1509 boolean preserveNewGroupSettings)
1511 av.updateGroupAnnotationSettings(applyGlobalSettings,
1512 preserveNewGroupSettings);
1513 adjustAnnotationHeight();
1517 public AlignmentI getAlignment()
1519 return av.getAlignment();
1524 public String getViewName()
1530 * Make/Unmake this alignment panel the current input focus
1534 public void setSelected(boolean b)
1538 alignFrame.setSelected(b);
1539 } catch (Exception ex)
1546 alignFrame.setDisplayedView(this);
1551 public StructureSelectionManager getStructureSelectionManager()
1553 return av.getStructureSelectionManager();
1557 public void raiseOOMWarning(String string, OutOfMemoryError error)
1559 new OOMWarning(string, error, this);
1563 public jalview.api.FeatureRenderer cloneFeatureRenderer()
1566 return new FeatureRenderer(this);
1569 public jalview.api.FeatureRenderer getFeatureRenderer()
1571 return seqPanel.seqCanvas.getFeatureRenderer();
1573 public void updateFeatureRenderer(jalview.renderer.seqfeatures.FeatureRenderer fr)
1575 fr.transferSettings(getSeqPanel().seqCanvas.getFeatureRenderer());
1578 public void updateFeatureRendererFrom(jalview.api.FeatureRenderer fr)
1580 if (getSeqPanel().seqCanvas.getFeatureRenderer() != null)
1582 getSeqPanel().seqCanvas.getFeatureRenderer().transferSettings(fr);
1586 public ScalePanel getScalePanel()
1591 public void setScalePanel(ScalePanel scalePanel)
1593 this.scalePanel = scalePanel;
1596 public SeqPanel getSeqPanel()
1601 public void setSeqPanel(SeqPanel seqPanel)
1603 this.seqPanel = seqPanel;
1606 public AnnotationPanel getAnnotationPanel()
1608 return annotationPanel;
1611 public void setAnnotationPanel(AnnotationPanel annotationPanel)
1613 this.annotationPanel = annotationPanel;
1616 public AnnotationLabels getAlabels()
1621 public void setAlabels(AnnotationLabels alabels)
1623 this.alabels = alabels;
1626 public IdPanel getIdPanel()
1631 public void setIdPanel(IdPanel idPanel)
1633 this.idPanel = idPanel;