Use paintAlignment
[jalview.git] / src / jalview / gui / AlignmentPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import java.beans.*;\r
22 import java.io.*;\r
23 \r
24 import java.awt.*;\r
25 import java.awt.event.*;\r
26 import java.awt.print.*;\r
27 import javax.swing.*;\r
28 \r
29 import jalview.datamodel.*;\r
30 import jalview.jbgui.*;\r
31 import jalview.schemes.*;\r
32 \r
33 /**\r
34  * DOCUMENT ME!\r
35  *\r
36  * @author $author$\r
37  * @version $Revision$\r
38  */\r
39 public class AlignmentPanel\r
40     extends GAlignmentPanel implements AdjustmentListener, Printable\r
41 {\r
42   public AlignViewport av;\r
43   OverviewPanel overviewPanel;\r
44   SeqPanel seqPanel;\r
45   IdPanel idPanel;\r
46   IdwidthAdjuster idwidthAdjuster;\r
47 \r
48   /** DOCUMENT ME!! */\r
49   public AlignFrame alignFrame;\r
50   ScalePanel scalePanel;\r
51   AnnotationPanel annotationPanel;\r
52   AnnotationLabels alabels;\r
53 \r
54   // this value is set false when selection area being dragged\r
55   boolean fastPaint = true;\r
56   int hextent = 0;\r
57   int vextent = 0;\r
58 \r
59   /**\r
60    * Creates a new AlignmentPanel object.\r
61    *\r
62    * @param af DOCUMENT ME!\r
63    * @param av DOCUMENT ME!\r
64    */\r
65   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
66   {\r
67     alignFrame = af;\r
68     this.av = av;\r
69     seqPanel = new SeqPanel(av, this);\r
70     idPanel = new IdPanel(av, this);\r
71 \r
72     scalePanel = new ScalePanel(av, this);\r
73 \r
74     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
75     idwidthAdjuster = new IdwidthAdjuster(this);\r
76     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
77 \r
78     annotationPanel = new AnnotationPanel(this);\r
79     alabels = new AnnotationLabels(this);\r
80 \r
81     annotationScroller.setViewportView(annotationPanel);\r
82     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
83 \r
84     fontChanged();\r
85 \r
86     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
87     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
88 \r
89     setScrollValues(0, 0);\r
90 \r
91     setAnnotationVisible(av.getShowAnnotation());\r
92 \r
93     hscroll.addAdjustmentListener(this);\r
94     vscroll.addAdjustmentListener(this);\r
95 \r
96     final AlignmentPanel ap = this;\r
97     av.addPropertyChangeListener(new PropertyChangeListener()\r
98     {\r
99       public void propertyChange(PropertyChangeEvent evt)\r
100       {\r
101         if (evt.getPropertyName().equals("alignment"))\r
102         {\r
103           PaintRefresher.Refresh(ap,\r
104                                  av.getSequenceSetId(),\r
105                                  true,\r
106                                  true);\r
107           alignmentChanged();\r
108         }\r
109       }\r
110     });\r
111 \r
112     adjustAnnotationHeight();\r
113 \r
114   }\r
115 \r
116   public void alignmentChanged()\r
117   {\r
118     av.alignmentChanged(this);\r
119 \r
120     if (overviewPanel != null)\r
121     {\r
122       overviewPanel.updateOverviewImage();\r
123     }\r
124 \r
125     alignFrame.updateEditMenuBar();\r
126 \r
127     repaint();\r
128   }\r
129 \r
130   /**\r
131    * DOCUMENT ME!\r
132    */\r
133   public void fontChanged()\r
134   {\r
135     // set idCanvas bufferedImage to null\r
136     // to prevent drawing old image\r
137     FontMetrics fm = getFontMetrics(av.getFont());\r
138 \r
139     scalePanelHolder.setPreferredSize(new Dimension(10,\r
140         av.charHeight + fm.getDescent()));\r
141     idSpaceFillerPanel1.setPreferredSize(new Dimension(10,\r
142         av.charHeight + fm.getDescent()));\r
143 \r
144     idPanel.idCanvas.gg = null;\r
145     seqPanel.seqCanvas.img = null;\r
146     annotationPanel.adjustPanelHeight();\r
147 \r
148     Dimension d = calculateIdWidth();\r
149     d.setSize(d.width + 4, d.height);\r
150     idPanel.idCanvas.setPreferredSize(d);\r
151     hscrollFillerPanel.setPreferredSize(d);\r
152 \r
153     if (overviewPanel != null)\r
154     {\r
155       overviewPanel.setBoxPosition();\r
156     }\r
157 \r
158     repaint();\r
159   }\r
160 \r
161   /**\r
162    * DOCUMENT ME!\r
163    *\r
164    * @return DOCUMENT ME!\r
165    */\r
166   public Dimension calculateIdWidth()\r
167   {\r
168     Container c = new Container();\r
169 \r
170     FontMetrics fm = c.getFontMetrics(\r
171         new Font(av.font.getName(), Font.ITALIC, av.font.getSize()));\r
172 \r
173     AlignmentI al = av.getAlignment();\r
174 \r
175     int i = 0;\r
176     int idWidth = 0;\r
177     String id;\r
178 \r
179     while ( (i < al.getHeight()) && (al.getSequenceAt(i) != null))\r
180     {\r
181       SequenceI s = al.getSequenceAt(i);\r
182 \r
183       id = s.getDisplayId(av.getShowJVSuffix());\r
184 \r
185       if (fm.stringWidth(id) > idWidth)\r
186       {\r
187         idWidth = fm.stringWidth(id);\r
188       }\r
189 \r
190       i++;\r
191     }\r
192 \r
193     // Also check annotation label widths\r
194     i = 0;\r
195 \r
196     if (al.getAlignmentAnnotation() != null)\r
197     {\r
198       fm = c.getFontMetrics(alabels.getFont());\r
199 \r
200       while (i < al.getAlignmentAnnotation().length)\r
201       {\r
202         String label = al.getAlignmentAnnotation()[i].label;\r
203 \r
204         if (fm.stringWidth(label) > idWidth)\r
205         {\r
206           idWidth = fm.stringWidth(label);\r
207         }\r
208 \r
209         i++;\r
210       }\r
211     }\r
212 \r
213     return new Dimension(idWidth, 12);\r
214   }\r
215 \r
216   /**\r
217    * DOCUMENT ME!\r
218    *\r
219    * @param results DOCUMENT ME!\r
220    */\r
221   public void highlightSearchResults(SearchResults results)\r
222   {\r
223     seqPanel.seqCanvas.highlightSearchResults(results);\r
224 \r
225     // do we need to scroll the panel?\r
226     if (results != null)\r
227     {\r
228       SequenceI seq = results.getResultSequence(0);\r
229       int seqIndex = av.alignment.findIndex(seq);\r
230       int start = seq.findIndex(results.getResultStart(0)) - 1;\r
231       int end = seq.findIndex(results.getResultEnd(0)) - 1;\r
232 \r
233       if (!av.wrapAlignment)\r
234       {\r
235         if ( (av.getStartRes() > end) || (av.getEndRes() < start) ||\r
236             ( (av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))\r
237         {\r
238           setScrollValues(start, seqIndex);\r
239         }\r
240       }\r
241       else\r
242       {\r
243         scrollToWrappedVisible(start);\r
244       }\r
245     }\r
246   }\r
247 \r
248   void scrollToWrappedVisible(int res)\r
249   {\r
250     int cwidth = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.\r
251         getWidth());\r
252     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))\r
253     {\r
254       vscroll.setValue(res / cwidth);\r
255       av.startRes = vscroll.getValue() * cwidth;\r
256     }\r
257   }\r
258 \r
259   /**\r
260    * DOCUMENT ME!\r
261    *\r
262    * @return DOCUMENT ME!\r
263    */\r
264   public OverviewPanel getOverviewPanel()\r
265   {\r
266     return overviewPanel;\r
267   }\r
268 \r
269   /**\r
270    * DOCUMENT ME!\r
271    *\r
272    * @param op DOCUMENT ME!\r
273    */\r
274   public void setOverviewPanel(OverviewPanel op)\r
275   {\r
276     overviewPanel = op;\r
277   }\r
278 \r
279   /**\r
280    * DOCUMENT ME!\r
281    *\r
282    * @param b DOCUMENT ME!\r
283    */\r
284   public void setAnnotationVisible(boolean b)\r
285   {\r
286     if (!av.wrapAlignment)\r
287     {\r
288       annotationSpaceFillerHolder.setVisible(b);\r
289       annotationScroller.setVisible(b);\r
290     }\r
291     repaint();\r
292   }\r
293 \r
294   public void adjustAnnotationHeight()\r
295   {\r
296     if (alignFrame.getHeight() == 0)\r
297     {\r
298       System.out.println("NEEDS FIXING");\r
299     }\r
300 \r
301     int height = annotationPanel.adjustPanelHeight();\r
302 \r
303     if (height > alignFrame.getHeight() / 2)\r
304     {\r
305       height = alignFrame.getHeight() / 2;\r
306     }\r
307 \r
308     annotationScroller.setPreferredSize(\r
309         new Dimension(annotationScroller.getWidth(),\r
310                       height));\r
311 \r
312     annotationSpaceFillerHolder.setPreferredSize(new Dimension(\r
313         annotationSpaceFillerHolder.getWidth(),\r
314         height));\r
315 \r
316     repaint();\r
317   }\r
318 \r
319   /**\r
320    * DOCUMENT ME!\r
321    *\r
322    * @param wrap DOCUMENT ME!\r
323    */\r
324   public void setWrapAlignment(boolean wrap)\r
325   {\r
326     av.startSeq = 0;\r
327     scalePanelHolder.setVisible(!wrap);\r
328     hscroll.setVisible(!wrap);\r
329     idwidthAdjuster.setVisible(!wrap);\r
330 \r
331     if (wrap)\r
332     {\r
333       annotationScroller.setVisible(false);\r
334       annotationSpaceFillerHolder.setVisible(false);\r
335     }\r
336     else if (av.showAnnotation)\r
337     {\r
338       annotationScroller.setVisible(true);\r
339       annotationSpaceFillerHolder.setVisible(true);\r
340     }\r
341 \r
342     idSpaceFillerPanel1.setVisible(!wrap);\r
343 \r
344     repaint();\r
345   }\r
346 \r
347   // return value is true if the scroll is valid\r
348   public boolean scrollUp(boolean up)\r
349   {\r
350     if (up)\r
351     {\r
352       if (vscroll.getValue() < 1)\r
353       {\r
354         return false;\r
355       }\r
356 \r
357       fastPaint = false;\r
358       vscroll.setValue(vscroll.getValue() - 1);\r
359     }\r
360     else\r
361     {\r
362       if ( (vextent + vscroll.getValue()) >= av.getAlignment().getHeight())\r
363       {\r
364         return false;\r
365       }\r
366 \r
367       fastPaint = false;\r
368       vscroll.setValue(vscroll.getValue() + 1);\r
369     }\r
370 \r
371     fastPaint = true;\r
372 \r
373     return true;\r
374   }\r
375 \r
376   /**\r
377    * DOCUMENT ME!\r
378    *\r
379    * @param right DOCUMENT ME!\r
380    *\r
381    * @return DOCUMENT ME!\r
382    */\r
383   public boolean scrollRight(boolean right)\r
384   {\r
385     if (!right)\r
386     {\r
387       if (hscroll.getValue() < 1)\r
388       {\r
389         return false;\r
390       }\r
391 \r
392       fastPaint = false;\r
393       hscroll.setValue(hscroll.getValue() - 1);\r
394     }\r
395     else\r
396     {\r
397       if ( (hextent + hscroll.getValue()) >= av.getAlignment().getWidth())\r
398       {\r
399         return false;\r
400       }\r
401 \r
402       fastPaint = false;\r
403       hscroll.setValue(hscroll.getValue() + 1);\r
404     }\r
405 \r
406     fastPaint = true;\r
407 \r
408     return true;\r
409   }\r
410 \r
411   /**\r
412    * DOCUMENT ME!\r
413    *\r
414    * @param x DOCUMENT ME!\r
415    * @param y DOCUMENT ME!\r
416    */\r
417   public void setScrollValues(int x, int y)\r
418   {\r
419 \r
420     int width = av.alignment.getWidth();\r
421     int height = av.alignment.getHeight();\r
422 \r
423     if (av.hasHiddenColumns)\r
424     {\r
425       width = av.getColumnSelection().findColumnPosition(width);\r
426     }\r
427 \r
428     av.setEndRes( (x + (seqPanel.seqCanvas.getWidth() / av.charWidth)) - 1);\r
429 \r
430     hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;\r
431     vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;\r
432 \r
433     if (hextent > width)\r
434     {\r
435       hextent = width;\r
436     }\r
437 \r
438     if (vextent > height)\r
439     {\r
440       vextent = height;\r
441     }\r
442 \r
443     if ( (hextent + x) > width)\r
444     {\r
445       x = width - hextent;\r
446     }\r
447 \r
448     if ( (vextent + y) > height)\r
449     {\r
450       y = height - vextent;\r
451     }\r
452 \r
453     if (y < 0)\r
454     {\r
455       y = 0;\r
456     }\r
457 \r
458     if (x < 0)\r
459     {\r
460       x = 0;\r
461     }\r
462 \r
463     hscroll.setValues(x, hextent, 0, width);\r
464     vscroll.setValues(y, vextent, 0, height);\r
465   }\r
466 \r
467   /**\r
468    * DOCUMENT ME!\r
469    *\r
470    * @param evt DOCUMENT ME!\r
471    */\r
472   public void adjustmentValueChanged(AdjustmentEvent evt)\r
473   {\r
474 \r
475     int oldX = av.getStartRes();\r
476     int oldY = av.getStartSeq();\r
477 \r
478     if (evt.getSource() == hscroll)\r
479     {\r
480       int x = hscroll.getValue();\r
481       av.setStartRes(x);\r
482       av.setEndRes( (x +\r
483                      (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);\r
484     }\r
485 \r
486     if (evt.getSource() == vscroll)\r
487     {\r
488       int offy = vscroll.getValue();\r
489 \r
490       if (av.getWrapAlignment())\r
491       {\r
492         if (offy > -1)\r
493         {\r
494           int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
495               seqCanvas.getWidth());\r
496           av.setStartRes(offy * rowSize);\r
497           av.setEndRes( (offy + 1) * rowSize);\r
498         }\r
499         else\r
500         {\r
501           //This is only called if file loaded is a jar file that\r
502           //was wrapped when saved and user has wrap alignment true\r
503           //as preference setting\r
504           SwingUtilities.invokeLater(new Runnable()\r
505           {\r
506             public void run()\r
507             {\r
508               setScrollValues(av.getStartRes(), av.getStartSeq());\r
509             }\r
510           });\r
511         }\r
512       }\r
513       else\r
514       {\r
515         av.setStartSeq(offy);\r
516         av.setEndSeq(offy +\r
517                      (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));\r
518       }\r
519     }\r
520 \r
521     if (overviewPanel != null)\r
522     {\r
523       overviewPanel.setBoxPosition();\r
524     }\r
525 \r
526     int scrollX = av.startRes - oldX;\r
527     int scrollY = av.startSeq - oldY;\r
528 \r
529     if (av.getWrapAlignment() || !fastPaint)\r
530     {\r
531       repaint();\r
532     }\r
533     else\r
534     {\r
535       // Make sure we're not trying to draw a panel\r
536       // larger than the visible window\r
537       if (scrollX > av.endRes - av.startRes)\r
538       {\r
539         scrollX = av.endRes - av.startRes;\r
540       }\r
541       else if (scrollX < av.startRes - av.endRes)\r
542       {\r
543         scrollX = av.startRes - av.endRes;\r
544       }\r
545 \r
546       if (scrollX != 0 || scrollY != 0)\r
547       {\r
548         idPanel.idCanvas.fastPaint(scrollY);\r
549         seqPanel.seqCanvas.fastPaint(scrollX,\r
550                                      scrollY);\r
551         scalePanel.repaint();\r
552 \r
553         if (av.getShowAnnotation())\r
554         {\r
555           annotationPanel.fastPaint(scrollX);\r
556         }\r
557       }\r
558     }\r
559   }\r
560 \r
561   public void paintAlignment(boolean updateOverview)\r
562   {\r
563     repaint();\r
564 \r
565     if(updateOverview)\r
566     {\r
567       jalview.structure.StructureSelectionManager.getStructureSelectionManager()\r
568           .sequenceColoursChanged(this);\r
569 \r
570       if (overviewPanel != null)\r
571       {\r
572         overviewPanel.updateOverviewImage();\r
573       }\r
574     }\r
575   }\r
576 \r
577   /**\r
578    * DOCUMENT ME!\r
579    *\r
580    * @param g DOCUMENT ME!\r
581    */\r
582   public void paintComponent(Graphics g)\r
583   {\r
584     invalidate();\r
585 \r
586     Dimension d = idPanel.idCanvas.getPreferredSize();\r
587     idPanelHolder.setPreferredSize(d);\r
588     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));\r
589     validate();\r
590 \r
591     if (av.getWrapAlignment())\r
592     {\r
593       int maxwidth = av.alignment.getWidth();\r
594 \r
595       if (av.hasHiddenColumns)\r
596       {\r
597         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
598       }\r
599 \r
600       int canvasWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
601           seqCanvas.getWidth());\r
602       if (canvasWidth > 0)\r
603       {\r
604         int max = maxwidth /\r
605             seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.\r
606             getWidth()) +\r
607             1;\r
608         vscroll.setMaximum(max);\r
609         vscroll.setUnitIncrement(1);\r
610         vscroll.setVisibleAmount(1);\r
611       }\r
612     }\r
613     else\r
614     {\r
615       setScrollValues(av.getStartRes(), av.getStartSeq());\r
616     }\r
617   }\r
618 \r
619   /**\r
620    * DOCUMENT ME!\r
621    *\r
622    * @param pg DOCUMENT ME!\r
623    * @param pf DOCUMENT ME!\r
624    * @param pi DOCUMENT ME!\r
625    *\r
626    * @return DOCUMENT ME!\r
627    *\r
628    * @throws PrinterException DOCUMENT ME!\r
629    */\r
630   public int print(Graphics pg, PageFormat pf, int pi)\r
631       throws PrinterException\r
632   {\r
633     pg.translate( (int) pf.getImageableX(), (int) pf.getImageableY());\r
634 \r
635     int pwidth = (int) pf.getImageableWidth();\r
636     int pheight = (int) pf.getImageableHeight();\r
637 \r
638     if (av.getWrapAlignment())\r
639     {\r
640       return printWrappedAlignment(pg, pwidth, pheight, pi);\r
641     }\r
642     else\r
643     {\r
644       return printUnwrapped(pg, pwidth, pheight, pi);\r
645     }\r
646   }\r
647 \r
648   /**\r
649    * DOCUMENT ME!\r
650    *\r
651    * @param pg DOCUMENT ME!\r
652    * @param pwidth DOCUMENT ME!\r
653    * @param pheight DOCUMENT ME!\r
654    * @param pi DOCUMENT ME!\r
655    *\r
656    * @return DOCUMENT ME!\r
657    *\r
658    * @throws PrinterException DOCUMENT ME!\r
659    */\r
660   public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)\r
661       throws PrinterException\r
662   {\r
663     int idWidth = getVisibleIdWidth();\r
664     FontMetrics fm = getFontMetrics(av.getFont());\r
665     int scaleHeight = av.charHeight + fm.getDescent();\r
666 \r
667     pg.setColor(Color.white);\r
668     pg.fillRect(0, 0, pwidth, pheight);\r
669     pg.setFont(av.getFont());\r
670 \r
671     ////////////////////////////////////\r
672     /// How many sequences and residues can we fit on a printable page?\r
673     int totalRes = (pwidth - idWidth) / av.getCharWidth();\r
674 \r
675     int totalSeq = (int) ( (pheight - scaleHeight) / av.getCharHeight()) -\r
676         1;\r
677 \r
678     int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;\r
679 \r
680     /////////////////////////////\r
681     /// Only print these sequences and residues on this page\r
682     int startRes;\r
683 \r
684     /////////////////////////////\r
685     /// Only print these sequences and residues on this page\r
686     int endRes;\r
687 \r
688     /////////////////////////////\r
689     /// Only print these sequences and residues on this page\r
690     int startSeq;\r
691 \r
692     /////////////////////////////\r
693     /// Only print these sequences and residues on this page\r
694     int endSeq;\r
695     startRes = (pi % pagesWide) * totalRes;\r
696     endRes = (startRes + totalRes) - 1;\r
697 \r
698     if (endRes > (av.getAlignment().getWidth() - 1))\r
699     {\r
700       endRes = av.getAlignment().getWidth() - 1;\r
701     }\r
702 \r
703     startSeq = (pi / pagesWide) * totalSeq;\r
704     endSeq = startSeq + totalSeq;\r
705 \r
706     if (endSeq > av.getAlignment().getHeight())\r
707     {\r
708       endSeq = av.getAlignment().getHeight();\r
709     }\r
710 \r
711     int pagesHigh = ( (av.alignment.getHeight() / totalSeq) + 1) * pheight;\r
712 \r
713     if (av.showAnnotation)\r
714     {\r
715       pagesHigh += annotationPanel.adjustPanelHeight() + 3;\r
716     }\r
717 \r
718     pagesHigh /= pheight;\r
719 \r
720     if (pi >= (pagesWide * pagesHigh))\r
721     {\r
722       return Printable.NO_SUCH_PAGE;\r
723     }\r
724 \r
725     //draw Scale\r
726     pg.translate(idWidth, 0);\r
727     scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth, scaleHeight);\r
728     pg.translate( -idWidth, scaleHeight);\r
729 \r
730     ////////////////\r
731     // Draw the ids\r
732     Color currentColor = null;\r
733     Color currentTextColor = null;\r
734 \r
735     pg.setFont(idPanel.idCanvas.idfont);\r
736 \r
737     SequenceI seq;\r
738     for (int i = startSeq; i < endSeq; i++)\r
739     {\r
740       seq = av.getAlignment().getSequenceAt(i);\r
741       if ( (av.getSelectionGroup() != null) &&\r
742           av.getSelectionGroup().getSequences(null).contains(seq))\r
743       {\r
744         currentColor = Color.gray;\r
745         currentTextColor = Color.black;\r
746       }\r
747       else\r
748       {\r
749         currentColor = av.getSequenceColour(seq);\r
750         currentTextColor = Color.black;\r
751       }\r
752 \r
753       pg.setColor(currentColor);\r
754       pg.fillRect(0, (i - startSeq) * av.charHeight, idWidth,\r
755                   av.getCharHeight());\r
756 \r
757       pg.setColor(currentTextColor);\r
758 \r
759       int xPos = 0;\r
760       if (av.rightAlignIds)\r
761       {\r
762         fm = pg.getFontMetrics();\r
763         xPos = idWidth - fm.stringWidth(\r
764             seq.getDisplayId(av.getShowJVSuffix())\r
765             ) - 4;\r
766       }\r
767 \r
768       pg.drawString(seq.getDisplayId(av.getShowJVSuffix()),\r
769                     xPos,\r
770                     ( ( (i - startSeq) * av.charHeight) + av.getCharHeight()) -\r
771                     (av.getCharHeight() / 5));\r
772     }\r
773 \r
774     pg.setFont(av.getFont());\r
775 \r
776     // draw main sequence panel\r
777     pg.translate(idWidth, 0);\r
778     seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);\r
779 \r
780     if (av.showAnnotation && (endSeq == av.alignment.getHeight()))\r
781     {\r
782       pg.translate( -idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);\r
783       alabels.drawComponent( (Graphics2D) pg, idWidth);\r
784       pg.translate(idWidth + 3, 0);\r
785       annotationPanel.drawComponent( (Graphics2D) pg, startRes, endRes +\r
786                                     1);\r
787     }\r
788 \r
789     return Printable.PAGE_EXISTS;\r
790   }\r
791 \r
792   /**\r
793    * DOCUMENT ME!\r
794    *\r
795    * @param pg DOCUMENT ME!\r
796    * @param pwidth DOCUMENT ME!\r
797    * @param pheight DOCUMENT ME!\r
798    * @param pi DOCUMENT ME!\r
799    *\r
800    * @return DOCUMENT ME!\r
801    *\r
802    * @throws PrinterException DOCUMENT ME!\r
803    */\r
804   public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,\r
805                                    int pi)\r
806       throws PrinterException\r
807   {\r
808 \r
809     int annotationHeight = 0;\r
810     AnnotationLabels labels = null;\r
811     if (av.showAnnotation)\r
812     {\r
813       annotationHeight = annotationPanel.adjustPanelHeight();\r
814       labels = new AnnotationLabels(av);\r
815     }\r
816 \r
817     int hgap = av.charHeight;\r
818     if (av.scaleAboveWrapped)\r
819     {\r
820       hgap += av.charHeight;\r
821     }\r
822 \r
823     int cHeight = av.getAlignment().getHeight() * av.charHeight\r
824         + hgap\r
825         + annotationHeight;\r
826 \r
827     int idWidth = getVisibleIdWidth();\r
828 \r
829     int maxwidth = av.alignment.getWidth();\r
830     if (av.hasHiddenColumns)\r
831     {\r
832       maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
833     }\r
834 \r
835     int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth -\r
836         idWidth);\r
837 \r
838     int totalHeight = cHeight * (maxwidth / resWidth + 1);\r
839 \r
840     pg.setColor(Color.white);\r
841     pg.fillRect(0, 0, pwidth, pheight);\r
842     pg.setFont(av.getFont());\r
843 \r
844     ////////////////\r
845     // Draw the ids\r
846     pg.setColor(Color.black);\r
847 \r
848     pg.translate(0, -pi * pheight);\r
849 \r
850     pg.setClip(0, pi * pheight, pwidth, pheight);\r
851 \r
852     int ypos = hgap;\r
853 \r
854     do\r
855     {\r
856       for (int i = 0; i < av.alignment.getHeight(); i++)\r
857       {\r
858         pg.setFont(idPanel.idCanvas.idfont);\r
859         SequenceI s = av.alignment.getSequenceAt(i);\r
860         String string = s.getDisplayId(av.getShowJVSuffix());\r
861         int xPos = 0;\r
862         if (av.rightAlignIds)\r
863         {\r
864           FontMetrics fm = pg.getFontMetrics();\r
865           xPos = idWidth - fm.stringWidth(string) - 4;\r
866         }\r
867         pg.drawString(string, xPos,\r
868                       ( (i * av.charHeight) + ypos + av.charHeight) -\r
869                       (av.charHeight / 5));\r
870       }\r
871       if (labels != null)\r
872       {\r
873         pg.translate( -3,\r
874                      ypos +\r
875                      (av.getAlignment().getHeight() * av.charHeight));\r
876 \r
877         pg.setFont(av.getFont());\r
878         labels.drawComponent(pg, idWidth);\r
879         pg.translate( +3,\r
880                      -ypos -\r
881                      (av.getAlignment().getHeight() * av.charHeight));\r
882       }\r
883 \r
884       ypos += cHeight;\r
885     }\r
886     while (ypos < totalHeight);\r
887 \r
888     pg.translate(idWidth, 0);\r
889 \r
890     seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight, 0);\r
891 \r
892     if ( (pi * pheight) < totalHeight)\r
893     {\r
894       return Printable.PAGE_EXISTS;\r
895 \r
896     }\r
897     else\r
898     {\r
899       return Printable.NO_SUCH_PAGE;\r
900     }\r
901   }\r
902 \r
903   int getVisibleIdWidth()\r
904   {\r
905     return\r
906         idPanel.getWidth() > 0 ? idPanel.getWidth() :\r
907         calculateIdWidth().width + 4;\r
908   }\r
909 \r
910   void makeAlignmentImage(int type, File file)\r
911   {\r
912     int maxwidth = av.alignment.getWidth();\r
913     if (av.hasHiddenColumns)\r
914     {\r
915       maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);\r
916     }\r
917 \r
918     int height = ( (av.alignment.getHeight() + 1) * av.charHeight) + 30;\r
919     int width = getVisibleIdWidth() + (maxwidth * av.charWidth);\r
920 \r
921     if (av.getWrapAlignment())\r
922     {\r
923       height = getWrappedHeight();\r
924       if (System.getProperty("java.awt.headless") != null\r
925           && System.getProperty("java.awt.headless").equals("true"))\r
926       {\r
927         width = alignFrame.getWidth()\r
928             - vscroll.getPreferredSize().width\r
929             - alignFrame.getInsets().left\r
930             - alignFrame.getInsets().right;\r
931       }\r
932       else\r
933       {\r
934         width = seqPanel.getWidth() + getVisibleIdWidth();\r
935       }\r
936 \r
937     }\r
938     else if (av.getShowAnnotation())\r
939     {\r
940       height += annotationPanel.adjustPanelHeight() + 3;\r
941     }\r
942 \r
943     try\r
944     {\r
945 \r
946       jalview.util.ImageMaker im;\r
947       if (type == jalview.util.ImageMaker.PNG)\r
948       {\r
949         im = new jalview.util.ImageMaker(this,\r
950                                          jalview.util.ImageMaker.PNG,\r
951                                          "Create PNG image from alignment",\r
952                                          width, height, file, null);\r
953       }\r
954       else\r
955       {\r
956         im = new jalview.util.ImageMaker(this,\r
957                                          jalview.util.ImageMaker.EPS,\r
958                                          "Create EPS file from alignment",\r
959                                          width, height, file,\r
960                                          alignFrame.getTitle());\r
961       }\r
962 \r
963       if (av.getWrapAlignment())\r
964       {\r
965         if (im.getGraphics() != null)\r
966         {\r
967           printWrappedAlignment(im.getGraphics(), width, height, 0);\r
968           im.writeImage();\r
969         }\r
970       }\r
971       else\r
972       {\r
973         if (im.getGraphics() != null)\r
974         {\r
975           printUnwrapped(im.getGraphics(), width, height, 0);\r
976           im.writeImage();\r
977         }\r
978       }\r
979     }\r
980     catch (OutOfMemoryError err)\r
981     {\r
982       System.out.println("########################\n"\r
983                          + "OUT OF MEMORY " + file + "\n"\r
984                          + "########################");\r
985 \r
986       JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
987                                             "Out of Memory Creating Image!!"\r
988                                             +\r
989                                             "\nSee help files for increasing Java Virtual Machine memory."\r
990                                             , "Out of memory",\r
991                                             JOptionPane.WARNING_MESSAGE);\r
992       System.out.println("Create IMAGE: " + err);\r
993       System.gc();\r
994 \r
995     }\r
996     catch (Exception ex)\r
997     {\r
998       ex.printStackTrace();\r
999     }\r
1000   }\r
1001 \r
1002   /**\r
1003    * DOCUMENT ME!\r
1004    */\r
1005   public void makeEPS(File epsFile)\r
1006   {\r
1007     makeAlignmentImage(jalview.util.ImageMaker.EPS, epsFile);\r
1008   }\r
1009 \r
1010   /**\r
1011    * DOCUMENT ME!\r
1012    */\r
1013   public void makePNG(File pngFile)\r
1014   {\r
1015     makeAlignmentImage(jalview.util.ImageMaker.PNG, pngFile);\r
1016   }\r
1017 \r
1018   public void makePNGImageMap(File imgMapFile, String imageName)\r
1019   {\r
1020     ///////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS\r
1021     //////////////////////////////////////////////\r
1022     int idWidth = getVisibleIdWidth();\r
1023     FontMetrics fm = getFontMetrics(av.getFont());\r
1024     int scaleHeight = av.charHeight + fm.getDescent();\r
1025 \r
1026     // Gen image map\r
1027     //////////////////////////////////\r
1028     if (imgMapFile != null)\r
1029     {\r
1030       try\r
1031       {\r
1032         int s, sSize = av.alignment.getHeight(),\r
1033             res, alwidth = av.alignment.getWidth(), g, gSize, f, fSize, sy;\r
1034         StringBuffer text = new StringBuffer();\r
1035         PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));\r
1036         out.println(jalview.io.HTMLOutput.getImageMapHTML());\r
1037         out.println("<img src=\"" + imageName +\r
1038                     "\" border=\"0\" usemap=\"#Map\" >"\r
1039                     + "<map name=\"Map\">");\r
1040 \r
1041         for (s = 0; s < sSize; s++)\r
1042         {\r
1043           sy = s * av.charHeight + scaleHeight;\r
1044 \r
1045           SequenceI seq = av.alignment.getSequenceAt(s);\r
1046           SequenceFeature[] features = seq.getDatasetSequence().\r
1047               getSequenceFeatures();\r
1048           SequenceGroup[] groups = av.alignment.findAllGroups(seq);\r
1049           for (res = 0; res < alwidth; res++)\r
1050           {\r
1051             text = new StringBuffer();\r
1052             Object obj = null;\r
1053             if (av.alignment.isNucleotide())\r
1054             {\r
1055               obj = ResidueProperties.nucleotideName.get(seq.getCharAt(res) +\r
1056                   "");\r
1057             }\r
1058             else\r
1059             {\r
1060               obj = ResidueProperties.aa2Triplet.get(\r
1061                   seq.getCharAt(res) + "");\r
1062             }\r
1063 \r
1064             if (obj == null)\r
1065             {\r
1066               continue;\r
1067             }\r
1068 \r
1069             String triplet = obj.toString();\r
1070             int alIndex = seq.findPosition(res);\r
1071             gSize = groups.length;\r
1072             for (g = 0; g < gSize; g++)\r
1073             {\r
1074               if (text.length() < 1)\r
1075               {\r
1076                 text.append("<area shape=\"rect\" coords=\""\r
1077                             + (idWidth + res * av.charWidth) + ","\r
1078                             + sy + ","\r
1079                             + (idWidth + (res + 1) * av.charWidth) + ","\r
1080                             + (av.charHeight + sy) + "\""\r
1081                             + " onMouseOver=\"toolTip('"\r
1082                             + alIndex + " " + triplet);\r
1083               }\r
1084 \r
1085               if (groups[g].getStartRes() < res && groups[g].getEndRes() > res)\r
1086               {\r
1087                 text.append("<br><em>" + groups[g].getName() + "</em>");\r
1088               }\r
1089             }\r
1090 \r
1091             if (features != null)\r
1092             {\r
1093               if (text.length() < 1)\r
1094               {\r
1095                 text.append("<area shape=\"rect\" coords=\""\r
1096                             + (idWidth + res * av.charWidth) + ","\r
1097                             + sy + ","\r
1098                             + (idWidth + (res + 1) * av.charWidth) + ","\r
1099                             + (av.charHeight + sy) + "\""\r
1100                             + " onMouseOver=\"toolTip('"\r
1101                             + alIndex + " " + triplet);\r
1102               }\r
1103               fSize = features.length;\r
1104               for (f = 0; f < fSize; f++)\r
1105               {\r
1106 \r
1107                 if ( (features[f].getBegin() <= seq.findPosition(res)) &&\r
1108                     (features[f].getEnd() >= seq.findPosition(res)))\r
1109                 {\r
1110                   if (features[f].getType().equals("disulfide bond"))\r
1111                   {\r
1112                     if (features[f].getBegin() == seq.findPosition(res)\r
1113                         || features[f].getEnd() == seq.findPosition(res))\r
1114                     {\r
1115                       text.append("<br>disulfide bond " + features[f].getBegin() +\r
1116                                   ":" +\r
1117                                   features[f].getEnd());\r
1118                     }\r
1119                   }\r
1120                   else\r
1121                   {\r
1122                     text.append("<br>");\r
1123                     text.append(features[f].getType());\r
1124                     if (features[f].getDescription() != null &&\r
1125                         !features[f].\r
1126                         getType().equals(features[f].getDescription()))\r
1127                     {\r
1128                       text.append(" " + features[f].getDescription());\r
1129                     }\r
1130 \r
1131                     if (features[f].getValue("status") != null)\r
1132                     {\r
1133                       text.append(" (" + features[f].getValue("status") + ")");\r
1134                     }\r
1135                   }\r
1136                 }\r
1137 \r
1138               }\r
1139             }\r
1140             if (text.length() > 1)\r
1141             {\r
1142               text.append("')\"; onMouseOut=\"toolTip()\";  href=\"#\">");\r
1143               out.println(text.toString());\r
1144             }\r
1145           }\r
1146         }\r
1147         out.println("</map></body></html>");\r
1148         out.close();\r
1149 \r
1150       }\r
1151       catch (Exception ex)\r
1152       {\r
1153         ex.printStackTrace();\r
1154       }\r
1155     } ///////////END OF IMAGE MAP\r
1156 \r
1157   }\r
1158 \r
1159   int getWrappedHeight()\r
1160   {\r
1161     int seqPanelWidth = seqPanel.seqCanvas.getWidth();\r
1162 \r
1163     if (System.getProperty("java.awt.headless") != null\r
1164         && System.getProperty("java.awt.headless").equals("true"))\r
1165     {\r
1166       seqPanelWidth = alignFrame.getWidth()\r
1167           - getVisibleIdWidth()\r
1168           - vscroll.getPreferredSize().width\r
1169           - alignFrame.getInsets().left\r
1170           - alignFrame.getInsets().right;\r
1171     }\r
1172 \r
1173     int chunkWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(\r
1174         seqPanelWidth\r
1175         );\r
1176 \r
1177     int hgap = av.charHeight;\r
1178     if (av.scaleAboveWrapped)\r
1179     {\r
1180       hgap += av.charHeight;\r
1181     }\r
1182 \r
1183     int annotationHeight = 0;\r
1184     if (av.showAnnotation)\r
1185     {\r
1186       annotationHeight = annotationPanel.adjustPanelHeight();\r
1187     }\r
1188 \r
1189     int cHeight = av.getAlignment().getHeight() * av.charHeight\r
1190         + hgap\r
1191         + annotationHeight;\r
1192 \r
1193     int maxwidth = av.alignment.getWidth();\r
1194     if (av.hasHiddenColumns)\r
1195     {\r
1196       maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
1197     }\r
1198 \r
1199     int height = ( (maxwidth / chunkWidth) + 1) * cHeight;\r
1200 \r
1201     return height;\r
1202   }\r
1203 }\r