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