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.
27 import java.awt.event.*;
28 import java.awt.print.*;
31 import jalview.api.AlignmentViewPanel;
32 import jalview.bin.Cache;
33 import jalview.datamodel.*;
34 import jalview.jbgui.*;
35 import jalview.schemes.*;
36 import jalview.structure.StructureSelectionManager;
42 * @version $Revision: 1.161 $
44 public class AlignmentPanel extends GAlignmentPanel implements
45 AdjustmentListener, Printable, AlignmentViewPanel
47 public AlignViewport av;
49 OverviewPanel overviewPanel;
55 IdwidthAdjuster idwidthAdjuster;
58 public AlignFrame alignFrame;
60 ScalePanel scalePanel;
62 AnnotationPanel annotationPanel;
64 AnnotationLabels alabels;
66 // this value is set false when selection area being dragged
67 boolean fastPaint = true;
74 * Creates a new AlignmentPanel object.
81 public AlignmentPanel(AlignFrame af, final AlignViewport av)
85 seqPanel = new SeqPanel(av, this);
86 idPanel = new IdPanel(av, this);
88 scalePanel = new ScalePanel(av, this);
90 idPanelHolder.add(idPanel, BorderLayout.CENTER);
91 idwidthAdjuster = new IdwidthAdjuster(this);
92 idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
94 annotationPanel = new AnnotationPanel(this);
95 alabels = new AnnotationLabels(this);
97 annotationScroller.setViewportView(annotationPanel);
98 annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
100 scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
101 seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
103 setScrollValues(0, 0);
105 setAnnotationVisible(av.getShowAnnotation());
107 hscroll.addAdjustmentListener(this);
108 vscroll.addAdjustmentListener(this);
110 final AlignmentPanel ap = this;
111 av.addPropertyChangeListener(new PropertyChangeListener()
113 public void propertyChange(PropertyChangeEvent evt)
115 if (evt.getPropertyName().equals("alignment"))
117 PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
123 adjustAnnotationHeight();
127 public void alignmentChanged()
129 av.alignmentChanged(this);
131 alignFrame.updateEditMenuBar();
133 paintAlignment(true);
140 public void fontChanged()
142 // set idCanvas bufferedImage to null
143 // to prevent drawing old image
144 FontMetrics fm = getFontMetrics(av.getFont());
146 scalePanelHolder.setPreferredSize(new Dimension(10, av.charHeight
148 idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight
151 idPanel.idCanvas.gg = null;
152 seqPanel.seqCanvas.img = null;
153 annotationPanel.adjustPanelHeight();
155 Dimension d = calculateIdWidth();
156 d.setSize(d.width + 4, d.height);
157 idPanel.idCanvas.setPreferredSize(d);
158 hscrollFillerPanel.setPreferredSize(d);
160 if (overviewPanel != null)
162 overviewPanel.setBoxPosition();
169 * Calculate the width of the alignment labels based on the displayed names
170 * and any bounds on label width set in preferences.
172 * @return Dimension giving the maximum width of the alignment label panel
173 * that should be used.
175 public Dimension calculateIdWidth()
177 // calculate sensible default width when no preference is available
179 int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
180 int maxwidth = Math.max(20,
181 Math.min(afwidth - 200, (int) 2 * afwidth / 3));
182 return calculateIdWidth(maxwidth);
186 * Calculate the width of the alignment labels based on the displayed names
187 * and any bounds on label width set in preferences.
190 * -1 or maximum width allowed for IdWidth
191 * @return Dimension giving the maximum width of the alignment label panel
192 * that should be used.
194 public Dimension calculateIdWidth(int maxwidth)
196 Container c = new Container();
198 FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
199 Font.ITALIC, av.font.getSize()));
201 AlignmentI al = av.getAlignment();
206 while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
208 SequenceI s = al.getSequenceAt(i);
210 id = s.getDisplayId(av.getShowJVSuffix());
212 if (fm.stringWidth(id) > idWidth)
214 idWidth = fm.stringWidth(id);
220 // Also check annotation label widths
223 if (al.getAlignmentAnnotation() != null)
225 fm = c.getFontMetrics(alabels.getFont());
227 while (i < al.getAlignmentAnnotation().length)
229 String label = al.getAlignmentAnnotation()[i].label;
231 if (fm.stringWidth(label) > idWidth)
233 idWidth = fm.stringWidth(label);
240 return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
245 * Highlight the given results on the alignment.
248 public void highlightSearchResults(SearchResults results)
250 scrollToPosition(results);
251 seqPanel.seqCanvas.highlightSearchResults(results);
255 * scroll the view to show the position of the highlighted region in results
256 * (if any) and redraw the overview
260 public boolean scrollToPosition(SearchResults results)
262 return scrollToPosition(results, true);
266 * scroll the view to show the position of the highlighted region in results
270 * @param redrawOverview
271 * - when set, the overview will be recalculated (takes longer)
272 * @return false if results were not found
274 public boolean scrollToPosition(SearchResults results,
275 boolean redrawOverview)
277 int startv, endv, starts, ends, width;
278 // TODO: properly locate search results in view when large numbers of hidden
279 // columns exist before highlighted region
280 // do we need to scroll the panel?
281 // TODO: tons of nullpointereexceptions raised here.
282 if (results != null && results.getSize() > 0 && av != null
283 && av.getAlignment() != null)
285 int seqIndex = av.getAlignment().findIndex(results);
290 SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
292 int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
299 // System.err.println("Seq : "+seqIndex+" Scroll to "+start+","+end); //
305 if (end == seq.getEnd())
309 if (av.hasHiddenColumns())
311 start = av.getColumnSelection().findColumnPosition(start);
312 end = av.getColumnSelection().findColumnPosition(end);
315 if (!av.getColumnSelection().isVisible(r[0]))
317 // don't scroll - position isn't visible
322 if (!av.wrapAlignment)
324 if ((startv = av.getStartRes()) >= start)
326 setScrollValues(start - 1, seqIndex);
328 else if ((endv = av.getEndRes()) <= end)
330 setScrollValues(startv + 1 + end - endv, seqIndex);
332 else if ((starts = av.getStartSeq()) > seqIndex)
334 setScrollValues(av.getStartRes(), seqIndex);
336 else if ((ends = av.getEndSeq()) <= seqIndex)
338 setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
343 scrollToWrappedVisible(start);
346 if (redrawOverview && overviewPanel != null)
348 overviewPanel.setBoxPosition();
350 paintAlignment(redrawOverview);
354 void scrollToWrappedVisible(int res)
356 int cwidth = seqPanel.seqCanvas
357 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
358 if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
360 vscroll.setValue((res / cwidth));
361 av.startRes = vscroll.getValue() * cwidth;
369 * @return DOCUMENT ME!
371 public OverviewPanel getOverviewPanel()
373 return overviewPanel;
382 public void setOverviewPanel(OverviewPanel op)
390 * Hide or show annotation panel
393 public void setAnnotationVisible(boolean b)
395 if (!av.wrapAlignment)
397 annotationSpaceFillerHolder.setVisible(b);
398 annotationScroller.setVisible(b);
404 * automatically adjust annotation panel height for new annotation whilst
405 * ensuring the alignment is still visible.
407 public void adjustAnnotationHeight()
409 // TODO: display vertical annotation scrollbar if necessary
410 // this is called after loading new annotation onto alignment
411 if (alignFrame.getHeight() == 0)
413 System.out.println("NEEDS FIXING");
415 validateAnnotationDimensions(true);
417 paintAlignment(true);
421 * calculate the annotation dimensions and refresh slider values accordingly.
422 * need to do repaints/notifys afterwards.
424 protected void validateAnnotationDimensions(boolean adjustPanelHeight)
426 int height = annotationPanel.adjustPanelHeight();
428 int theight = av.getCharHeight() * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0 : av.getAlignment().getHiddenSequences().getSize()));
429 float sscaling = (float) (theight/(1.0*theight+height));
430 float ascaling=(float)(height*1.0/alignFrame.getHeight());
431 int rheight = alignFrame.getHeight() - height - av.getCharHeight();
432 if (adjustPanelHeight)
434 // NOTE: this logic is different in the applet. Need a better algorithm to define behaviour
435 // try and set height according to alignment
436 if (ascaling>0 && sscaling < 0.5)
438 // if the alignment is too big then
439 // default is 0.5 split
440 height = alignFrame.getHeight() / 2;
444 // if space for more than one sequence row left when annotation is fully displayed then set height to annotation height
445 // otherwise, leave at least two lines of sequence shown.
446 height = (rheight>av.getCharHeight()) ? height : (-av.getCharHeight() * 3
447 + (int) (alignFrame.getHeight() * (1 - sscaling)));
452 // maintain same window layout whilst updating sliders
453 height = annotationScroller.getSize().height;
457 annotationScroller.setPreferredSize(new Dimension(annotationScroller
458 .getWidth(), height));
460 annotationSpaceFillerHolder.setPreferredSize(new Dimension(
461 annotationSpaceFillerHolder.getWidth(), height));
462 annotationScroller.validate();// repaint();
463 annotationScroller.addNotify();
472 public void setWrapAlignment(boolean wrap)
475 scalePanelHolder.setVisible(!wrap);
476 hscroll.setVisible(!wrap);
477 idwidthAdjuster.setVisible(!wrap);
481 annotationScroller.setVisible(false);
482 annotationSpaceFillerHolder.setVisible(false);
484 else if (av.showAnnotation)
486 annotationScroller.setVisible(true);
487 annotationSpaceFillerHolder.setVisible(true);
490 idSpaceFillerPanel1.setVisible(!wrap);
495 // return value is true if the scroll is valid
496 public boolean scrollUp(boolean up)
500 if (vscroll.getValue() < 1)
506 vscroll.setValue(vscroll.getValue() - 1);
510 if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())
516 vscroll.setValue(vscroll.getValue() + 1);
530 * @return DOCUMENT ME!
532 public boolean scrollRight(boolean right)
536 if (hscroll.getValue() < 1)
542 hscroll.setValue(hscroll.getValue() - 1);
546 if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())
552 hscroll.setValue(hscroll.getValue() + 1);
561 * Adjust row/column scrollers to show a visible position in the alignment.
564 * visible column to scroll to DOCUMENT ME!
566 * visible row to scroll to
569 public void setScrollValues(int x, int y)
571 // System.err.println("Scroll to "+x+","+y);
572 if (av == null || av.getAlignment() == null)
576 int width = av.getAlignment().getWidth();
577 int height = av.getAlignment().getHeight();
579 if (av.hasHiddenColumns())
581 width = av.getColumnSelection().findColumnPosition(width);
584 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.charWidth)) - 1);
586 hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;
587 vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;
594 if (vextent > height)
599 if ((hextent + x) > width)
604 if ((vextent + y) > height)
606 y = height - vextent;
619 hscroll.setValues(x, hextent, 0, width);
620 vscroll.setValues(y, vextent, 0, height);
629 public void adjustmentValueChanged(AdjustmentEvent evt)
632 int oldX = av.getStartRes();
633 int oldY = av.getStartSeq();
635 if (evt.getSource() == hscroll)
637 int x = hscroll.getValue();
639 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);
642 if (evt.getSource() == vscroll)
644 int offy = vscroll.getValue();
646 if (av.getWrapAlignment())
650 int rowSize = seqPanel.seqCanvas
651 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
652 av.setStartRes(offy * rowSize);
653 av.setEndRes((offy + 1) * rowSize);
657 // This is only called if file loaded is a jar file that
658 // was wrapped when saved and user has wrap alignment true
659 // as preference setting
660 SwingUtilities.invokeLater(new Runnable()
664 setScrollValues(av.getStartRes(), av.getStartSeq());
671 av.setStartSeq(offy);
673 + (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));
677 if (overviewPanel != null)
679 overviewPanel.setBoxPosition();
682 int scrollX = av.startRes - oldX;
683 int scrollY = av.startSeq - oldY;
685 if (av.getWrapAlignment() || !fastPaint)
691 // Make sure we're not trying to draw a panel
692 // larger than the visible window
693 if (scrollX > av.endRes - av.startRes)
695 scrollX = av.endRes - av.startRes;
697 else if (scrollX < av.startRes - av.endRes)
699 scrollX = av.startRes - av.endRes;
702 if (scrollX != 0 || scrollY != 0)
704 idPanel.idCanvas.fastPaint(scrollY);
705 seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
706 scalePanel.repaint();
708 if (av.getShowAnnotation() && scrollX!=0)
710 annotationPanel.fastPaint(scrollX);
716 public void paintAlignment(boolean updateOverview)
722 av.getStructureSelectionManager().sequenceColoursChanged(this);
724 if (overviewPanel != null)
726 overviewPanel.updateOverviewImage();
737 public void paintComponent(Graphics g)
741 Dimension d = idPanel.idCanvas.getPreferredSize();
742 idPanelHolder.setPreferredSize(d);
743 hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
746 if (av.getWrapAlignment())
748 int maxwidth = av.getAlignment().getWidth();
750 if (av.hasHiddenColumns())
752 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
755 int canvasWidth = seqPanel.seqCanvas
756 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
761 .getWrappedCanvasWidth(seqPanel.seqCanvas
763 vscroll.setMaximum(max);
764 vscroll.setUnitIncrement(1);
765 vscroll.setVisibleAmount(1);
770 setScrollValues(av.getStartRes(), av.getStartSeq());
784 * @return DOCUMENT ME!
786 * @throws PrinterException
789 public int print(Graphics pg, PageFormat pf, int pi)
790 throws PrinterException
792 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
794 int pwidth = (int) pf.getImageableWidth();
795 int pheight = (int) pf.getImageableHeight();
797 if (av.getWrapAlignment())
799 return printWrappedAlignment(pg, pwidth, pheight, pi);
803 return printUnwrapped(pg, pwidth, pheight, pi);
819 * @return DOCUMENT ME!
821 * @throws PrinterException
824 public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
825 throws PrinterException
827 int idWidth = getVisibleIdWidth(false);
828 FontMetrics fm = getFontMetrics(av.getFont());
829 int scaleHeight = av.charHeight + fm.getDescent();
831 pg.setColor(Color.white);
832 pg.fillRect(0, 0, pwidth, pheight);
833 pg.setFont(av.getFont());
835 // //////////////////////////////////
836 // / How many sequences and residues can we fit on a printable page?
837 int totalRes = (pwidth - idWidth) / av.getCharWidth();
839 int totalSeq = (int) ((pheight - scaleHeight) / av.getCharHeight()) - 1;
841 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
843 // ///////////////////////////
844 // / Only print these sequences and residues on this page
847 // ///////////////////////////
848 // / Only print these sequences and residues on this page
851 // ///////////////////////////
852 // / Only print these sequences and residues on this page
855 // ///////////////////////////
856 // / Only print these sequences and residues on this page
858 startRes = (pi % pagesWide) * totalRes;
859 endRes = (startRes + totalRes) - 1;
861 if (endRes > (av.getAlignment().getWidth() - 1))
863 endRes = av.getAlignment().getWidth() - 1;
866 startSeq = (pi / pagesWide) * totalSeq;
867 endSeq = startSeq + totalSeq;
869 if (endSeq > av.getAlignment().getHeight())
871 endSeq = av.getAlignment().getHeight();
874 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
877 if (av.showAnnotation)
879 pagesHigh += annotationPanel.adjustPanelHeight() + 3;
882 pagesHigh /= pheight;
884 if (pi >= (pagesWide * pagesHigh))
886 return Printable.NO_SUCH_PAGE;
890 pg.translate(idWidth, 0);
891 scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth,
893 pg.translate(-idWidth, scaleHeight);
897 Color currentColor = null;
898 Color currentTextColor = null;
900 pg.setFont(idPanel.idCanvas.idfont);
903 for (int i = startSeq; i < endSeq; i++)
905 seq = av.getAlignment().getSequenceAt(i);
906 if ((av.getSelectionGroup() != null)
907 && av.getSelectionGroup().getSequences(null).contains(seq))
909 currentColor = Color.gray;
910 currentTextColor = Color.black;
914 currentColor = av.getSequenceColour(seq);
915 currentTextColor = Color.black;
918 pg.setColor(currentColor);
919 pg.fillRect(0, (i - startSeq) * av.charHeight, idWidth,
922 pg.setColor(currentTextColor);
925 if (av.rightAlignIds)
927 fm = pg.getFontMetrics();
929 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
934 seq.getDisplayId(av.getShowJVSuffix()),
936 (((i - startSeq) * av.charHeight) + av.getCharHeight())
937 - (av.getCharHeight() / 5));
940 pg.setFont(av.getFont());
942 // draw main sequence panel
943 pg.translate(idWidth, 0);
944 seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
946 if (av.showAnnotation && (endSeq == av.getAlignment().getHeight()))
948 // draw annotation - need to offset for current scroll position
949 int offset = -alabels.scrollOffset;
950 pg.translate(0, offset);
951 pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
952 alabels.drawComponent((Graphics2D) pg, idWidth);
953 pg.translate(idWidth + 3, 0);
954 annotationPanel.renderer.drawComponent(annotationPanel, av,
955 (Graphics2D) pg, -1, startRes, endRes + 1);
956 pg.translate(0, -offset);
959 return Printable.PAGE_EXISTS;
974 * @return DOCUMENT ME!
976 * @throws PrinterException
979 public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
980 int pi) throws PrinterException
983 int annotationHeight = 0;
984 AnnotationLabels labels = null;
985 if (av.showAnnotation)
987 annotationHeight = annotationPanel.adjustPanelHeight();
988 labels = new AnnotationLabels(av);
991 int hgap = av.charHeight;
992 if (av.scaleAboveWrapped)
994 hgap += av.charHeight;
997 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1000 int idWidth = getVisibleIdWidth(false);
1002 int maxwidth = av.getAlignment().getWidth();
1003 if (av.hasHiddenColumns())
1005 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1008 int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth
1011 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1013 pg.setColor(Color.white);
1014 pg.fillRect(0, 0, pwidth, pheight);
1015 pg.setFont(av.getFont());
1019 pg.setColor(Color.black);
1021 pg.translate(0, -pi * pheight);
1023 pg.setClip(0, pi * pheight, pwidth, pheight);
1029 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1031 pg.setFont(idPanel.idCanvas.idfont);
1032 SequenceI s = av.getAlignment().getSequenceAt(i);
1033 String string = s.getDisplayId(av.getShowJVSuffix());
1035 if (av.rightAlignIds)
1037 FontMetrics fm = pg.getFontMetrics();
1038 xPos = idWidth - fm.stringWidth(string) - 4;
1040 pg.drawString(string, xPos,
1041 ((i * av.charHeight) + ypos + av.charHeight)
1042 - (av.charHeight / 5));
1046 pg.translate(-3, ypos
1047 + (av.getAlignment().getHeight() * av.charHeight));
1049 pg.setFont(av.getFont());
1050 labels.drawComponent(pg, idWidth);
1051 pg.translate(+3, -ypos
1052 - (av.getAlignment().getHeight() * av.charHeight));
1056 } while (ypos < totalHeight);
1058 pg.translate(idWidth, 0);
1060 seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1063 if ((pi * pheight) < totalHeight)
1065 return Printable.PAGE_EXISTS;
1070 return Printable.NO_SUCH_PAGE;
1075 * get current sequence ID panel width, or nominal value if panel were to be
1076 * displayed using default settings
1080 int getVisibleIdWidth()
1082 return getVisibleIdWidth(true);
1086 * get current sequence ID panel width, or nominal value if panel were to be
1087 * displayed using default settings
1090 * indicate if the Id width for onscreen or offscreen display should
1094 int getVisibleIdWidth(boolean onscreen)
1096 // see if rendering offscreen - check preferences and calc width accordingly
1097 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1099 return calculateIdWidth(-1).width + 4;
1101 Integer idwidth = null;
1103 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1105 return (idPanel.getWidth() > 0 ? idPanel.getWidth()
1106 : calculateIdWidth().width + 4);
1108 return idwidth.intValue() + 4;
1111 void makeAlignmentImage(int type, File file)
1113 long progress = System.currentTimeMillis();
1114 boolean headless = (System.getProperty("java.awt.headless") != null
1115 && System.getProperty("java.awt.headless").equals("true"));
1116 if (alignFrame != null && !headless)
1118 alignFrame.setProgressBar("Saving "
1119 + (type == jalview.util.ImageMaker.PNG ? "PNG image"
1120 : "EPS file"), progress);
1124 int maxwidth = av.getAlignment().getWidth();
1125 if (av.hasHiddenColumns())
1127 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1130 int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
1131 + scalePanel.getHeight();
1132 int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
1134 if (av.getWrapAlignment())
1136 height = getWrappedHeight();
1139 // need to obtain default alignment width and then add in any
1140 // additional allowance for id margin
1141 // this duplicates the calculation in getWrappedHeight but adjusts for
1143 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1144 - alignFrame.getInsets().left
1145 - alignFrame.getInsets().right - getVisibleIdWidth()
1146 + getVisibleIdWidth(false);
1150 width = seqPanel.getWidth() + getVisibleIdWidth(false);
1154 else if (av.getShowAnnotation())
1156 height += annotationPanel.adjustPanelHeight() + 3;
1162 jalview.util.ImageMaker im;
1163 final String imageAction, imageTitle;
1164 if (type == jalview.util.ImageMaker.PNG)
1166 imageAction = "Create PNG image from alignment";
1171 imageAction = "Create EPS file from alignment";
1172 imageTitle = alignFrame.getTitle();
1174 im = new jalview.util.ImageMaker(this, type, imageAction, width,
1175 height, file, imageTitle);
1176 if (av.getWrapAlignment())
1178 if (im.getGraphics() != null)
1180 printWrappedAlignment(im.getGraphics(), width, height, 0);
1186 if (im.getGraphics() != null)
1188 printUnwrapped(im.getGraphics(), width, height, 0);
1192 } catch (OutOfMemoryError err)
1195 System.out.println("########################\n" + "OUT OF MEMORY "
1196 + file + "\n" + "########################");
1197 new OOMWarning("Creating Image for " + file, err);
1198 // System.out.println("Create IMAGE: " + err);
1199 } catch (Exception ex)
1201 ex.printStackTrace();
1205 if (alignFrame != null && !headless)
1207 alignFrame.setProgressBar("Export complete.", progress);
1215 public void makeEPS(File epsFile)
1217 makeAlignmentImage(jalview.util.ImageMaker.EPS, epsFile);
1223 public void makePNG(File pngFile)
1225 makeAlignmentImage(jalview.util.ImageMaker.PNG, pngFile);
1228 public void makePNGImageMap(File imgMapFile, String imageName)
1230 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1231 // ////////////////////////////////////////////
1232 int idWidth = getVisibleIdWidth(false);
1233 FontMetrics fm = getFontMetrics(av.getFont());
1234 int scaleHeight = av.charHeight + fm.getDescent();
1237 // ////////////////////////////////
1238 if (imgMapFile != null)
1242 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1243 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1244 StringBuffer text = new StringBuffer();
1245 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1246 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1247 out.println("<img src=\"" + imageName
1248 + "\" border=\"0\" usemap=\"#Map\" >"
1249 + "<map name=\"Map\">");
1251 for (s = 0; s < sSize; s++)
1253 sy = s * av.charHeight + scaleHeight;
1255 SequenceI seq = av.getAlignment().getSequenceAt(s);
1256 SequenceFeature[] features = seq.getDatasetSequence()
1257 .getSequenceFeatures();
1258 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1259 for (res = 0; res < alwidth; res++)
1261 text = new StringBuffer();
1263 if (av.getAlignment().isNucleotide())
1265 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1270 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1279 String triplet = obj.toString();
1280 int alIndex = seq.findPosition(res);
1281 gSize = groups.length;
1282 for (g = 0; g < gSize; g++)
1284 if (text.length() < 1)
1286 text.append("<area shape=\"rect\" coords=\""
1287 + (idWidth + res * av.charWidth) + "," + sy + ","
1288 + (idWidth + (res + 1) * av.charWidth) + ","
1289 + (av.charHeight + sy) + "\""
1290 + " onMouseOver=\"toolTip('" + alIndex + " "
1294 if (groups[g].getStartRes() < res
1295 && groups[g].getEndRes() > res)
1297 text.append("<br><em>" + groups[g].getName() + "</em>");
1301 if (features != null)
1303 if (text.length() < 1)
1305 text.append("<area shape=\"rect\" coords=\""
1306 + (idWidth + res * av.charWidth) + "," + sy + ","
1307 + (idWidth + (res + 1) * av.charWidth) + ","
1308 + (av.charHeight + sy) + "\""
1309 + " onMouseOver=\"toolTip('" + alIndex + " "
1312 fSize = features.length;
1313 for (f = 0; f < fSize; f++)
1316 if ((features[f].getBegin() <= seq.findPosition(res))
1317 && (features[f].getEnd() >= seq.findPosition(res)))
1319 if (features[f].getType().equals("disulfide bond"))
1321 if (features[f].getBegin() == seq.findPosition(res)
1322 || features[f].getEnd() == seq
1325 text.append("<br>disulfide bond "
1326 + features[f].getBegin() + ":"
1327 + features[f].getEnd());
1332 text.append("<br>");
1333 text.append(features[f].getType());
1334 if (features[f].getDescription() != null
1335 && !features[f].getType().equals(
1336 features[f].getDescription()))
1338 text.append(" " + features[f].getDescription());
1341 if (features[f].getValue("status") != null)
1343 text.append(" (" + features[f].getValue("status")
1351 if (text.length() > 1)
1353 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1354 out.println(text.toString());
1358 out.println("</map></body></html>");
1361 } catch (Exception ex)
1363 ex.printStackTrace();
1365 } // /////////END OF IMAGE MAP
1369 int getWrappedHeight()
1371 int seqPanelWidth = seqPanel.seqCanvas.getWidth();
1373 if (System.getProperty("java.awt.headless") != null
1374 && System.getProperty("java.awt.headless").equals("true"))
1376 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1377 - vscroll.getPreferredSize().width
1378 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1381 int chunkWidth = seqPanel.seqCanvas
1382 .getWrappedCanvasWidth(seqPanelWidth);
1384 int hgap = av.charHeight;
1385 if (av.scaleAboveWrapped)
1387 hgap += av.charHeight;
1390 int annotationHeight = 0;
1391 if (av.showAnnotation)
1393 annotationHeight = annotationPanel.adjustPanelHeight();
1396 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1399 int maxwidth = av.getAlignment().getWidth();
1400 if (av.hasHiddenColumns())
1402 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1405 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1411 * close the panel - deregisters all listeners and nulls any references to
1414 public void closePanel()
1416 PaintRefresher.RemoveComponent(seqPanel.seqCanvas);
1417 PaintRefresher.RemoveComponent(idPanel.idCanvas);
1418 PaintRefresher.RemoveComponent(this);
1421 jalview.structure.StructureSelectionManager ssm = av
1422 .getStructureSelectionManager();
1423 ssm.removeStructureViewerListener(seqPanel, null);
1424 ssm.removeSelectionListener(seqPanel);
1425 av.setAlignment(null);
1430 if (Cache.log.isDebugEnabled())
1432 Cache.log.warn("Closing alignment panel which is already closed.");
1438 * hides or shows dynamic annotation rows based on groups and av state flags
1440 public void updateAnnotation()
1442 updateAnnotation(false, false);
1445 public void updateAnnotation(boolean applyGlobalSettings)
1447 updateAnnotation(applyGlobalSettings, false);
1450 public void updateAnnotation(boolean applyGlobalSettings,
1451 boolean preserveNewGroupSettings)
1453 av.updateGroupAnnotationSettings(applyGlobalSettings,
1454 preserveNewGroupSettings);
1455 adjustAnnotationHeight();
1459 public AlignmentI getAlignment()
1461 return av.getAlignment();
1465 * get the name for this view
1469 public String getViewName()
1475 * Make/Unmake this alignment panel the current input focus
1479 public void setSelected(boolean b)
1483 alignFrame.setSelected(b);
1484 } catch (Exception ex)
1491 alignFrame.setDisplayedView(this);
1496 public StructureSelectionManager getStructureSelectionManager()
1498 return av.getStructureSelectionManager();
1502 public void raiseOOMWarning(String string, OutOfMemoryError error)
1504 new OOMWarning(string, error, this);
1507 public FeatureRenderer cloneFeatureRenderer()
1510 return new FeatureRenderer(this);
1513 public void updateFeatureRenderer(FeatureRenderer fr)
1515 fr.transferSettings(seqPanel.seqCanvas.getFeatureRenderer());
1518 public void updateFeatureRendererFrom(FeatureRenderer fr)
1520 if (seqPanel.seqCanvas.getFeatureRenderer() != null)
1522 seqPanel.seqCanvas.getFeatureRenderer().transferSettings(fr);