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;
37 import jalview.util.MessageManager;
43 * @version $Revision: 1.161 $
45 public class AlignmentPanel extends GAlignmentPanel implements
46 AdjustmentListener, Printable, AlignmentViewPanel
48 public AlignViewport av;
50 OverviewPanel overviewPanel;
56 IdwidthAdjuster idwidthAdjuster;
59 public AlignFrame alignFrame;
61 ScalePanel scalePanel;
63 AnnotationPanel annotationPanel;
65 AnnotationLabels alabels;
67 // this value is set false when selection area being dragged
68 boolean fastPaint = true;
75 * Creates a new AlignmentPanel object.
82 public AlignmentPanel(AlignFrame af, final AlignViewport av)
86 seqPanel = new SeqPanel(av, this);
87 idPanel = new IdPanel(av, this);
89 scalePanel = new ScalePanel(av, this);
91 idPanelHolder.add(idPanel, BorderLayout.CENTER);
92 idwidthAdjuster = new IdwidthAdjuster(this);
93 idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
95 annotationPanel = new AnnotationPanel(this);
96 alabels = new AnnotationLabels(this);
98 annotationScroller.setViewportView(annotationPanel);
99 annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
101 scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
102 seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
104 setScrollValues(0, 0);
106 setAnnotationVisible(av.getShowAnnotation());
108 hscroll.addAdjustmentListener(this);
109 vscroll.addAdjustmentListener(this);
111 final AlignmentPanel ap = this;
112 av.addPropertyChangeListener(new PropertyChangeListener()
114 public void propertyChange(PropertyChangeEvent evt)
116 if (evt.getPropertyName().equals("alignment"))
118 PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
124 adjustAnnotationHeight();
128 public void alignmentChanged()
130 av.alignmentChanged(this);
132 alignFrame.updateEditMenuBar();
134 paintAlignment(true);
141 public void fontChanged()
143 // set idCanvas bufferedImage to null
144 // to prevent drawing old image
145 FontMetrics fm = getFontMetrics(av.getFont());
147 scalePanelHolder.setPreferredSize(new Dimension(10, av.charHeight
149 idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight
152 idPanel.idCanvas.gg = null;
153 seqPanel.seqCanvas.img = null;
154 annotationPanel.adjustPanelHeight();
156 Dimension d = calculateIdWidth();
157 d.setSize(d.width + 4, d.height);
158 idPanel.idCanvas.setPreferredSize(d);
159 hscrollFillerPanel.setPreferredSize(d);
161 if (overviewPanel != null)
163 overviewPanel.setBoxPosition();
170 * Calculate the width of the alignment labels based on the displayed names
171 * and any bounds on label width set in preferences.
173 * @return Dimension giving the maximum width of the alignment label panel
174 * that should be used.
176 public Dimension calculateIdWidth()
178 // calculate sensible default width when no preference is available
180 int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
181 int maxwidth = Math.max(20,
182 Math.min(afwidth - 200, (int) 2 * afwidth / 3));
183 return calculateIdWidth(maxwidth);
187 * Calculate the width of the alignment labels based on the displayed names
188 * and any bounds on label width set in preferences.
191 * -1 or maximum width allowed for IdWidth
192 * @return Dimension giving the maximum width of the alignment label panel
193 * that should be used.
195 public Dimension calculateIdWidth(int maxwidth)
197 Container c = new Container();
199 FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(),
200 Font.ITALIC, av.font.getSize()));
202 AlignmentI al = av.getAlignment();
207 while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
209 SequenceI s = al.getSequenceAt(i);
211 id = s.getDisplayId(av.getShowJVSuffix());
213 if (fm.stringWidth(id) > idWidth)
215 idWidth = fm.stringWidth(id);
221 // Also check annotation label widths
224 if (al.getAlignmentAnnotation() != null)
226 fm = c.getFontMetrics(alabels.getFont());
228 while (i < al.getAlignmentAnnotation().length)
230 String label = al.getAlignmentAnnotation()[i].label;
232 if (fm.stringWidth(label) > idWidth)
234 idWidth = fm.stringWidth(label);
241 return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth,
246 * Highlight the given results on the alignment.
249 public void highlightSearchResults(SearchResults results)
251 scrollToPosition(results);
252 seqPanel.seqCanvas.highlightSearchResults(results);
256 * scroll the view to show the position of the highlighted region in results
257 * (if any) and redraw the overview
261 public boolean scrollToPosition(SearchResults results)
263 return scrollToPosition(results, true);
267 * scroll the view to show the position of the highlighted region in results
271 * @param redrawOverview
272 * - when set, the overview will be recalculated (takes longer)
273 * @return false if results were not found
275 public boolean scrollToPosition(SearchResults results,
276 boolean redrawOverview)
278 int startv, endv, starts, ends, width;
279 // TODO: properly locate search results in view when large numbers of hidden
280 // columns exist before highlighted region
281 // do we need to scroll the panel?
282 // TODO: tons of nullpointereexceptions raised here.
283 if (results != null && results.getSize() > 0 && av != null
284 && av.getAlignment() != null)
286 int seqIndex = av.getAlignment().findIndex(results);
291 SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
293 int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
300 // System.err.println("Seq : "+seqIndex+" Scroll to "+start+","+end); //
306 if (end == seq.getEnd())
310 if (av.hasHiddenColumns())
312 start = av.getColumnSelection().findColumnPosition(start);
313 end = av.getColumnSelection().findColumnPosition(end);
316 if (!av.getColumnSelection().isVisible(r[0]))
318 // don't scroll - position isn't visible
323 if (!av.wrapAlignment)
325 if ((startv = av.getStartRes()) >= start)
327 setScrollValues(start - 1, seqIndex);
329 else if ((endv = av.getEndRes()) <= end)
331 setScrollValues(startv + 1 + end - endv, seqIndex);
333 else if ((starts = av.getStartSeq()) > seqIndex)
335 setScrollValues(av.getStartRes(), seqIndex);
337 else if ((ends = av.getEndSeq()) <= seqIndex)
339 setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
344 scrollToWrappedVisible(start);
347 if (redrawOverview && overviewPanel != null)
349 overviewPanel.setBoxPosition();
351 paintAlignment(redrawOverview);
355 void scrollToWrappedVisible(int res)
357 int cwidth = seqPanel.seqCanvas
358 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
359 if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
361 vscroll.setValue((res / cwidth));
362 av.startRes = vscroll.getValue() * cwidth;
370 * @return DOCUMENT ME!
372 public OverviewPanel getOverviewPanel()
374 return overviewPanel;
383 public void setOverviewPanel(OverviewPanel op)
391 * Hide or show annotation panel
394 public void setAnnotationVisible(boolean b)
396 if (!av.wrapAlignment)
398 annotationSpaceFillerHolder.setVisible(b);
399 annotationScroller.setVisible(b);
405 * automatically adjust annotation panel height for new annotation whilst
406 * ensuring the alignment is still visible.
408 public void adjustAnnotationHeight()
410 // TODO: display vertical annotation scrollbar if necessary
411 // this is called after loading new annotation onto alignment
412 if (alignFrame.getHeight() == 0)
414 System.out.println("NEEDS FIXING");
416 validateAnnotationDimensions(true);
418 paintAlignment(true);
422 * calculate the annotation dimensions and refresh slider values accordingly.
423 * need to do repaints/notifys afterwards.
425 protected void validateAnnotationDimensions(boolean adjustPanelHeight)
427 int height = annotationPanel.adjustPanelHeight();
429 int theight = av.getCharHeight()
430 * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0
431 : av.getAlignment().getHiddenSequences().getSize()));
432 float sscaling = (float) (theight / (1.0 * theight + height));
433 float ascaling = (float) (height * 1.0 / alignFrame.getHeight());
434 int rheight = alignFrame.getHeight() - height - av.getCharHeight();
435 if (adjustPanelHeight)
437 // NOTE: this logic is different in the applet. Need a better algorithm to
439 // try and set height according to alignment
440 if (ascaling > 0 && sscaling < 0.5)
442 // if the alignment is too big then
443 // default is 0.5 split
444 height = alignFrame.getHeight() / 2;
448 // if space for more than one sequence row left when annotation is fully
449 // displayed then set height to annotation height
450 // otherwise, leave at least two lines of sequence shown.
451 height = (rheight > av.getCharHeight()) ? height
452 : (-av.getCharHeight() * 3 + (int) (alignFrame.getHeight() * (1 - sscaling)));
457 // maintain same window layout whilst updating sliders
458 height = annotationScroller.getSize().height;
462 annotationScroller.setPreferredSize(new Dimension(annotationScroller
463 .getWidth(), height));
465 annotationSpaceFillerHolder.setPreferredSize(new Dimension(
466 annotationSpaceFillerHolder.getWidth(), height));
467 annotationScroller.validate();// repaint();
468 annotationScroller.addNotify();
477 public void setWrapAlignment(boolean wrap)
480 scalePanelHolder.setVisible(!wrap);
481 hscroll.setVisible(!wrap);
482 idwidthAdjuster.setVisible(!wrap);
486 annotationScroller.setVisible(false);
487 annotationSpaceFillerHolder.setVisible(false);
489 else if (av.showAnnotation)
491 annotationScroller.setVisible(true);
492 annotationSpaceFillerHolder.setVisible(true);
495 idSpaceFillerPanel1.setVisible(!wrap);
500 // return value is true if the scroll is valid
501 public boolean scrollUp(boolean up)
505 if (vscroll.getValue() < 1)
511 vscroll.setValue(vscroll.getValue() - 1);
515 if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())
521 vscroll.setValue(vscroll.getValue() + 1);
535 * @return DOCUMENT ME!
537 public boolean scrollRight(boolean right)
541 if (hscroll.getValue() < 1)
547 hscroll.setValue(hscroll.getValue() - 1);
551 if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())
557 hscroll.setValue(hscroll.getValue() + 1);
566 * Adjust row/column scrollers to show a visible position in the alignment.
569 * visible column to scroll to DOCUMENT ME!
571 * visible row to scroll to
574 public void setScrollValues(int x, int y)
576 // System.err.println("Scroll to "+x+","+y);
577 if (av == null || av.getAlignment() == null)
581 int width = av.getAlignment().getWidth();
582 int height = av.getAlignment().getHeight();
584 if (av.hasHiddenColumns())
586 width = av.getColumnSelection().findColumnPosition(width);
589 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.charWidth)) - 1);
591 hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;
592 vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;
599 if (vextent > height)
604 if ((hextent + x) > width)
609 if ((vextent + y) > height)
611 y = height - vextent;
624 hscroll.setValues(x, hextent, 0, width);
625 vscroll.setValues(y, vextent, 0, height);
634 public void adjustmentValueChanged(AdjustmentEvent evt)
637 int oldX = av.getStartRes();
638 int oldY = av.getStartSeq();
640 if (evt.getSource() == hscroll)
642 int x = hscroll.getValue();
644 av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);
647 if (evt.getSource() == vscroll)
649 int offy = vscroll.getValue();
651 if (av.getWrapAlignment())
655 int rowSize = seqPanel.seqCanvas
656 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
657 av.setStartRes(offy * rowSize);
658 av.setEndRes((offy + 1) * rowSize);
662 // This is only called if file loaded is a jar file that
663 // was wrapped when saved and user has wrap alignment true
664 // as preference setting
665 SwingUtilities.invokeLater(new Runnable()
669 setScrollValues(av.getStartRes(), av.getStartSeq());
676 av.setStartSeq(offy);
678 + (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));
682 if (overviewPanel != null)
684 overviewPanel.setBoxPosition();
687 int scrollX = av.startRes - oldX;
688 int scrollY = av.startSeq - oldY;
690 if (av.getWrapAlignment() || !fastPaint)
696 // Make sure we're not trying to draw a panel
697 // larger than the visible window
698 if (scrollX > av.endRes - av.startRes)
700 scrollX = av.endRes - av.startRes;
702 else if (scrollX < av.startRes - av.endRes)
704 scrollX = av.startRes - av.endRes;
707 if (scrollX != 0 || scrollY != 0)
709 idPanel.idCanvas.fastPaint(scrollY);
710 seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
711 scalePanel.repaint();
713 if (av.getShowAnnotation() && scrollX != 0)
715 annotationPanel.fastPaint(scrollX);
721 public void paintAlignment(boolean updateOverview)
727 av.getStructureSelectionManager().sequenceColoursChanged(this);
729 if (overviewPanel != null)
731 overviewPanel.updateOverviewImage();
742 public void paintComponent(Graphics g)
746 Dimension d = idPanel.idCanvas.getPreferredSize();
747 idPanelHolder.setPreferredSize(d);
748 hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
751 if (av.getWrapAlignment())
753 int maxwidth = av.getAlignment().getWidth();
755 if (av.hasHiddenColumns())
757 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
760 int canvasWidth = seqPanel.seqCanvas
761 .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
766 .getWrappedCanvasWidth(seqPanel.seqCanvas
768 vscroll.setMaximum(max);
769 vscroll.setUnitIncrement(1);
770 vscroll.setVisibleAmount(1);
775 setScrollValues(av.getStartRes(), av.getStartSeq());
789 * @return DOCUMENT ME!
791 * @throws PrinterException
794 public int print(Graphics pg, PageFormat pf, int pi)
795 throws PrinterException
797 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
799 int pwidth = (int) pf.getImageableWidth();
800 int pheight = (int) pf.getImageableHeight();
802 if (av.getWrapAlignment())
804 return printWrappedAlignment(pg, pwidth, pheight, pi);
808 return printUnwrapped(pg, pwidth, pheight, pi);
824 * @return DOCUMENT ME!
826 * @throws PrinterException
829 public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)
830 throws PrinterException
832 int idWidth = getVisibleIdWidth(false);
833 FontMetrics fm = getFontMetrics(av.getFont());
834 int scaleHeight = av.charHeight + fm.getDescent();
836 pg.setColor(Color.white);
837 pg.fillRect(0, 0, pwidth, pheight);
838 pg.setFont(av.getFont());
840 // //////////////////////////////////
841 // / How many sequences and residues can we fit on a printable page?
842 int totalRes = (pwidth - idWidth) / av.getCharWidth();
844 int totalSeq = (int) ((pheight - scaleHeight) / av.getCharHeight()) - 1;
846 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
848 // ///////////////////////////
849 // / Only print these sequences and residues on this page
852 // ///////////////////////////
853 // / Only print these sequences and residues on this page
856 // ///////////////////////////
857 // / Only print these sequences and residues on this page
860 // ///////////////////////////
861 // / Only print these sequences and residues on this page
863 startRes = (pi % pagesWide) * totalRes;
864 endRes = (startRes + totalRes) - 1;
866 if (endRes > (av.getAlignment().getWidth() - 1))
868 endRes = av.getAlignment().getWidth() - 1;
871 startSeq = (pi / pagesWide) * totalSeq;
872 endSeq = startSeq + totalSeq;
874 if (endSeq > av.getAlignment().getHeight())
876 endSeq = av.getAlignment().getHeight();
879 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
882 if (av.showAnnotation)
884 pagesHigh += annotationPanel.adjustPanelHeight() + 3;
887 pagesHigh /= pheight;
889 if (pi >= (pagesWide * pagesHigh))
891 return Printable.NO_SUCH_PAGE;
895 pg.translate(idWidth, 0);
896 scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth,
898 pg.translate(-idWidth, scaleHeight);
902 Color currentColor = null;
903 Color currentTextColor = null;
905 pg.setFont(idPanel.idCanvas.idfont);
908 for (int i = startSeq; i < endSeq; i++)
910 seq = av.getAlignment().getSequenceAt(i);
911 if ((av.getSelectionGroup() != null)
912 && av.getSelectionGroup().getSequences(null).contains(seq))
914 currentColor = Color.gray;
915 currentTextColor = Color.black;
919 currentColor = av.getSequenceColour(seq);
920 currentTextColor = Color.black;
923 pg.setColor(currentColor);
924 pg.fillRect(0, (i - startSeq) * av.charHeight, idWidth,
927 pg.setColor(currentTextColor);
930 if (av.rightAlignIds)
932 fm = pg.getFontMetrics();
934 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
939 seq.getDisplayId(av.getShowJVSuffix()),
941 (((i - startSeq) * av.charHeight) + av.getCharHeight())
942 - (av.getCharHeight() / 5));
945 pg.setFont(av.getFont());
947 // draw main sequence panel
948 pg.translate(idWidth, 0);
949 seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
951 if (av.showAnnotation && (endSeq == av.getAlignment().getHeight()))
953 // draw annotation - need to offset for current scroll position
954 int offset = -alabels.scrollOffset;
955 pg.translate(0, offset);
956 pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
957 alabels.drawComponent((Graphics2D) pg, idWidth);
958 pg.translate(idWidth + 3, 0);
959 annotationPanel.renderer.drawComponent(annotationPanel, av,
960 (Graphics2D) pg, -1, startRes, endRes + 1);
961 pg.translate(0, -offset);
964 return Printable.PAGE_EXISTS;
979 * @return DOCUMENT ME!
981 * @throws PrinterException
984 public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,
985 int pi) throws PrinterException
988 int annotationHeight = 0;
989 AnnotationLabels labels = null;
990 if (av.showAnnotation)
992 annotationHeight = annotationPanel.adjustPanelHeight();
993 labels = new AnnotationLabels(av);
996 int hgap = av.charHeight;
997 if (av.scaleAboveWrapped)
999 hgap += av.charHeight;
1002 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1005 int idWidth = getVisibleIdWidth(false);
1007 int maxwidth = av.getAlignment().getWidth();
1008 if (av.hasHiddenColumns())
1010 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1013 int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth
1016 int totalHeight = cHeight * (maxwidth / resWidth + 1);
1018 pg.setColor(Color.white);
1019 pg.fillRect(0, 0, pwidth, pheight);
1020 pg.setFont(av.getFont());
1024 pg.setColor(Color.black);
1026 pg.translate(0, -pi * pheight);
1028 pg.setClip(0, pi * pheight, pwidth, pheight);
1034 for (int i = 0; i < av.getAlignment().getHeight(); i++)
1036 pg.setFont(idPanel.idCanvas.idfont);
1037 SequenceI s = av.getAlignment().getSequenceAt(i);
1038 String string = s.getDisplayId(av.getShowJVSuffix());
1040 if (av.rightAlignIds)
1042 FontMetrics fm = pg.getFontMetrics();
1043 xPos = idWidth - fm.stringWidth(string) - 4;
1045 pg.drawString(string, xPos,
1046 ((i * av.charHeight) + ypos + av.charHeight)
1047 - (av.charHeight / 5));
1051 pg.translate(-3, ypos
1052 + (av.getAlignment().getHeight() * av.charHeight));
1054 pg.setFont(av.getFont());
1055 labels.drawComponent(pg, idWidth);
1056 pg.translate(+3, -ypos
1057 - (av.getAlignment().getHeight() * av.charHeight));
1061 } while (ypos < totalHeight);
1063 pg.translate(idWidth, 0);
1065 seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
1068 if ((pi * pheight) < totalHeight)
1070 return Printable.PAGE_EXISTS;
1075 return Printable.NO_SUCH_PAGE;
1080 * get current sequence ID panel width, or nominal value if panel were to be
1081 * displayed using default settings
1085 int getVisibleIdWidth()
1087 return getVisibleIdWidth(true);
1091 * get current sequence ID panel width, or nominal value if panel were to be
1092 * displayed using default settings
1095 * indicate if the Id width for onscreen or offscreen display should
1099 int getVisibleIdWidth(boolean onscreen)
1101 // see if rendering offscreen - check preferences and calc width accordingly
1102 if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
1104 return calculateIdWidth(-1).width + 4;
1106 Integer idwidth = null;
1108 || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
1110 return (idPanel.getWidth() > 0 ? idPanel.getWidth()
1111 : calculateIdWidth().width + 4);
1113 return idwidth.intValue() + 4;
1116 void makeAlignmentImage(int type, File file)
1118 long progress = System.currentTimeMillis();
1119 boolean headless = (System.getProperty("java.awt.headless") != null && System
1120 .getProperty("java.awt.headless").equals("true"));
1121 if (alignFrame != null && !headless)
1123 alignFrame.setProgressBar(MessageManager.formatMessage("status.saving_file", new String[]{(type == jalview.util.ImageMaker.PNG ? MessageManager.getString("label.png_image") : MessageManager.getString("label.eps_file"))}), progress);
1127 int maxwidth = av.getAlignment().getWidth();
1128 if (av.hasHiddenColumns())
1130 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
1133 int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
1134 + scalePanel.getHeight();
1135 int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
1137 if (av.getWrapAlignment())
1139 height = getWrappedHeight();
1142 // need to obtain default alignment width and then add in any
1143 // additional allowance for id margin
1144 // this duplicates the calculation in getWrappedHeight but adjusts for
1146 width = alignFrame.getWidth() - vscroll.getPreferredSize().width
1147 - alignFrame.getInsets().left
1148 - alignFrame.getInsets().right - getVisibleIdWidth()
1149 + getVisibleIdWidth(false);
1153 width = seqPanel.getWidth() + getVisibleIdWidth(false);
1157 else if (av.getShowAnnotation())
1159 height += annotationPanel.adjustPanelHeight() + 3;
1165 jalview.util.ImageMaker im;
1166 final String imageAction, imageTitle;
1167 if (type == jalview.util.ImageMaker.PNG)
1169 imageAction = "Create PNG image from alignment";
1174 imageAction = "Create EPS file from alignment";
1175 imageTitle = alignFrame.getTitle();
1177 im = new jalview.util.ImageMaker(this, type, imageAction, width,
1178 height, file, imageTitle);
1179 if (av.getWrapAlignment())
1181 if (im.getGraphics() != null)
1183 printWrappedAlignment(im.getGraphics(), width, height, 0);
1189 if (im.getGraphics() != null)
1191 printUnwrapped(im.getGraphics(), width, height, 0);
1195 } catch (OutOfMemoryError err)
1198 System.out.println("########################\n" + "OUT OF MEMORY "
1199 + file + "\n" + "########################");
1200 new OOMWarning("Creating Image for " + file, err);
1201 // System.out.println("Create IMAGE: " + err);
1202 } catch (Exception ex)
1204 ex.printStackTrace();
1208 if (alignFrame != null && !headless)
1210 alignFrame.setProgressBar(MessageManager.getString("status.export_complete"), progress);
1218 public void makeEPS(File epsFile)
1220 makeAlignmentImage(jalview.util.ImageMaker.EPS, epsFile);
1226 public void makePNG(File pngFile)
1228 makeAlignmentImage(jalview.util.ImageMaker.PNG, pngFile);
1231 public void makePNGImageMap(File imgMapFile, String imageName)
1233 // /////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS
1234 // ////////////////////////////////////////////
1235 int idWidth = getVisibleIdWidth(false);
1236 FontMetrics fm = getFontMetrics(av.getFont());
1237 int scaleHeight = av.charHeight + fm.getDescent();
1240 // ////////////////////////////////
1241 if (imgMapFile != null)
1245 int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
1246 .getAlignment().getWidth(), g, gSize, f, fSize, sy;
1247 StringBuffer text = new StringBuffer();
1248 PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
1249 out.println(jalview.io.HTMLOutput.getImageMapHTML());
1250 out.println("<img src=\"" + imageName
1251 + "\" border=\"0\" usemap=\"#Map\" >"
1252 + "<map name=\"Map\">");
1254 for (s = 0; s < sSize; s++)
1256 sy = s * av.charHeight + scaleHeight;
1258 SequenceI seq = av.getAlignment().getSequenceAt(s);
1259 SequenceFeature[] features = seq.getDatasetSequence()
1260 .getSequenceFeatures();
1261 SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
1262 for (res = 0; res < alwidth; res++)
1264 text = new StringBuffer();
1266 if (av.getAlignment().isNucleotide())
1268 obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res)
1273 obj = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
1282 String triplet = obj.toString();
1283 int alIndex = seq.findPosition(res);
1284 gSize = groups.length;
1285 for (g = 0; g < gSize; g++)
1287 if (text.length() < 1)
1289 text.append("<area shape=\"rect\" coords=\""
1290 + (idWidth + res * av.charWidth) + "," + sy + ","
1291 + (idWidth + (res + 1) * av.charWidth) + ","
1292 + (av.charHeight + sy) + "\""
1293 + " onMouseOver=\"toolTip('" + alIndex + " "
1297 if (groups[g].getStartRes() < res
1298 && groups[g].getEndRes() > res)
1300 text.append("<br><em>" + groups[g].getName() + "</em>");
1304 if (features != null)
1306 if (text.length() < 1)
1308 text.append("<area shape=\"rect\" coords=\""
1309 + (idWidth + res * av.charWidth) + "," + sy + ","
1310 + (idWidth + (res + 1) * av.charWidth) + ","
1311 + (av.charHeight + sy) + "\""
1312 + " onMouseOver=\"toolTip('" + alIndex + " "
1315 fSize = features.length;
1316 for (f = 0; f < fSize; f++)
1319 if ((features[f].getBegin() <= seq.findPosition(res))
1320 && (features[f].getEnd() >= seq.findPosition(res)))
1322 if (features[f].getType().equals("disulfide bond"))
1324 if (features[f].getBegin() == seq.findPosition(res)
1325 || features[f].getEnd() == seq
1328 text.append("<br>disulfide bond "
1329 + features[f].getBegin() + ":"
1330 + features[f].getEnd());
1335 text.append("<br>");
1336 text.append(features[f].getType());
1337 if (features[f].getDescription() != null
1338 && !features[f].getType().equals(
1339 features[f].getDescription()))
1341 text.append(" " + features[f].getDescription());
1344 if (features[f].getValue("status") != null)
1346 text.append(" (" + features[f].getValue("status")
1354 if (text.length() > 1)
1356 text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">");
1357 out.println(text.toString());
1361 out.println("</map></body></html>");
1364 } catch (Exception ex)
1366 ex.printStackTrace();
1368 } // /////////END OF IMAGE MAP
1372 int getWrappedHeight()
1374 int seqPanelWidth = seqPanel.seqCanvas.getWidth();
1376 if (System.getProperty("java.awt.headless") != null
1377 && System.getProperty("java.awt.headless").equals("true"))
1379 seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
1380 - vscroll.getPreferredSize().width
1381 - alignFrame.getInsets().left - alignFrame.getInsets().right;
1384 int chunkWidth = seqPanel.seqCanvas
1385 .getWrappedCanvasWidth(seqPanelWidth);
1387 int hgap = av.charHeight;
1388 if (av.scaleAboveWrapped)
1390 hgap += av.charHeight;
1393 int annotationHeight = 0;
1394 if (av.showAnnotation)
1396 annotationHeight = annotationPanel.adjustPanelHeight();
1399 int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
1402 int maxwidth = av.getAlignment().getWidth();
1403 if (av.hasHiddenColumns())
1405 maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
1408 int height = ((maxwidth / chunkWidth) + 1) * cHeight;
1414 * close the panel - deregisters all listeners and nulls any references to
1417 public void closePanel()
1419 PaintRefresher.RemoveComponent(seqPanel.seqCanvas);
1420 PaintRefresher.RemoveComponent(idPanel.idCanvas);
1421 PaintRefresher.RemoveComponent(this);
1424 jalview.structure.StructureSelectionManager ssm = av
1425 .getStructureSelectionManager();
1426 ssm.removeStructureViewerListener(seqPanel, null);
1427 ssm.removeSelectionListener(seqPanel);
1428 av.setAlignment(null);
1433 if (Cache.log.isDebugEnabled())
1435 Cache.log.warn("Closing alignment panel which is already closed.");
1441 * hides or shows dynamic annotation rows based on groups and av state flags
1443 public void updateAnnotation()
1445 updateAnnotation(false, false);
1448 public void updateAnnotation(boolean applyGlobalSettings)
1450 updateAnnotation(applyGlobalSettings, false);
1453 public void updateAnnotation(boolean applyGlobalSettings,
1454 boolean preserveNewGroupSettings)
1456 av.updateGroupAnnotationSettings(applyGlobalSettings,
1457 preserveNewGroupSettings);
1458 adjustAnnotationHeight();
1462 public AlignmentI getAlignment()
1464 return av.getAlignment();
1468 * get the name for this view
1472 public String getViewName()
1478 * Make/Unmake this alignment panel the current input focus
1482 public void setSelected(boolean b)
1486 alignFrame.setSelected(b);
1487 } catch (Exception ex)
1494 alignFrame.setDisplayedView(this);
1499 public StructureSelectionManager getStructureSelectionManager()
1501 return av.getStructureSelectionManager();
1505 public void raiseOOMWarning(String string, OutOfMemoryError error)
1507 new OOMWarning(string, error, this);
1510 public FeatureRenderer cloneFeatureRenderer()
1513 return new FeatureRenderer(this);
1516 public void updateFeatureRenderer(FeatureRenderer fr)
1518 fr.transferSettings(seqPanel.seqCanvas.getFeatureRenderer());
1521 public void updateFeatureRendererFrom(FeatureRenderer fr)
1523 if (seqPanel.seqCanvas.getFeatureRenderer() != null)
1525 seqPanel.seqCanvas.getFeatureRenderer().transferSettings(fr);