Change order of repaint if wrapped
[jalview.git] / src / jalview / appletgui / 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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.awt.*;\r
23 import java.awt.event.*;\r
24 \r
25 import jalview.datamodel.*;\r
26 \r
27 public class AlignmentPanel extends Panel implements AdjustmentListener\r
28 {\r
29 \r
30   AlignViewport av;\r
31   OverviewPanel overviewPanel;\r
32   SeqPanel seqPanel;\r
33   IdPanel idPanel;\r
34   IdwidthAdjuster idwidthAdjuster;\r
35   public AlignFrame alignFrame;\r
36   ScalePanel scalePanel;\r
37   AnnotationPanel annotationPanel;\r
38   AnnotationLabels alabels;\r
39 \r
40   // this value is set false when selection area being dragged\r
41   boolean fastPaint = true;\r
42 \r
43   boolean MAC = false;\r
44 \r
45   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
46   {\r
47     this.addKeyListener(new KeyAdapter()\r
48     {\r
49       public void keyPressed(KeyEvent ke)\r
50       {\r
51         System.out.println("Align Panel "+ke);\r
52       }\r
53     });\r
54 \r
55     try\r
56     {\r
57       jbInit();\r
58     }\r
59     catch (Exception e)\r
60     {\r
61       e.printStackTrace();\r
62     }\r
63 \r
64     if(System.getProperty("os.name").startsWith("Mac"))\r
65       MAC = true;\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     scalePanel = new ScalePanel(av, this);\r
72     idwidthAdjuster = new IdwidthAdjuster(this);\r
73     annotationPanel = new AnnotationPanel(this);\r
74     alabels = new AnnotationLabels(this);\r
75 \r
76     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
77     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
78     annotationScroller.add(annotationPanel);\r
79     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
80     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
81     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
82 \r
83     fontChanged();\r
84     setScrollValues(0, 0);\r
85 \r
86     hscroll.addAdjustmentListener(this);\r
87     vscroll.addAdjustmentListener(this);\r
88 \r
89     addComponentListener(new ComponentAdapter()\r
90     {\r
91       public void componentResized(ComponentEvent evt)\r
92       {\r
93         setScrollValues(av.getStartRes(), av.getStartSeq());\r
94         repaint();\r
95       }\r
96     });\r
97 \r
98     Dimension d = calculateIdWidth();\r
99     idPanel.idCanvas.setSize(d);\r
100 \r
101     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);\r
102     annotationScroller.setSize(annotationPanel.getSize());\r
103 \r
104     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
105     annotationSpaceFillerHolder.setSize(d.width,\r
106                                         annotationPanel.getSize().height);\r
107     alabels.setSize(d.width, annotationPanel.getSize().height);\r
108 \r
109   }\r
110 \r
111 \r
112   public void fontChanged()\r
113   {\r
114     // set idCanvas bufferedImage to null\r
115     // to prevent drawing old image\r
116     FontMetrics fm = getFontMetrics(av.getFont());\r
117 \r
118     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
119     idwidthAdjuster.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
120 \r
121     annotationPanel.adjustPanelHeight();\r
122     annotationPanel.repaint();\r
123     Dimension d = calculateIdWidth();\r
124     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);\r
125     idPanel.idCanvas.setSize(d);\r
126     hscrollFillerPanel.setSize(d);\r
127 \r
128     alignFrame.pack();\r
129 \r
130     if(overviewPanel!=null)\r
131           overviewPanel.updateOverviewImage();\r
132   }\r
133 \r
134   public void setIdWidth(int w, int h)\r
135   {\r
136     idPanel.idCanvas.setSize(w, h);\r
137     idPanelHolder.setSize(w, idPanelHolder.getSize().height);\r
138     alabels.setSize(w, alabels.getSize().height);\r
139     validate();\r
140   }\r
141 \r
142   Dimension calculateIdWidth()\r
143   {\r
144     Frame frame = new Frame();\r
145     frame.addNotify();\r
146     Graphics g = frame.getGraphics();\r
147     if (g == null)\r
148     {\r
149       Frame f = new Frame();\r
150       f.addNotify();\r
151       g = f.getGraphics();\r
152     }\r
153 \r
154     FontMetrics fm = g.getFontMetrics(av.font);\r
155     AlignmentI al = av.getAlignment();\r
156 \r
157     int i = 0;\r
158     int idWidth = 0;\r
159     String id;\r
160     while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
161     {\r
162       SequenceI s = al.getSequenceAt(i);\r
163       id = s.getDisplayId(av.getShowJVSuffix());\r
164 \r
165       if (fm.stringWidth(id) > idWidth)\r
166       {\r
167         idWidth = fm.stringWidth(id);\r
168       }\r
169       i++;\r
170     }\r
171 \r
172     // Also check annotation label widths\r
173     i = 0;\r
174     if (al.getAlignmentAnnotation() != null)\r
175     {\r
176       fm = g.getFontMetrics(frame.getFont());\r
177       while (i < al.getAlignmentAnnotation().length)\r
178       {\r
179         String label = al.getAlignmentAnnotation()[i].label;\r
180         if (fm.stringWidth(label) > idWidth)\r
181         {\r
182           idWidth = fm.stringWidth(label);\r
183         }\r
184         i++;\r
185       }\r
186     }\r
187 \r
188     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);\r
189   }\r
190 \r
191   public void highlightSearchResults(int[] results)\r
192   {\r
193     seqPanel.seqCanvas.highlightSearchResults(results);\r
194 \r
195     // do we need to scroll the panel?\r
196     if (results != null)\r
197     {\r
198       SequenceI seq = av.alignment.getSequenceAt(results[0]);\r
199       int start = seq.findIndex(results[1]) - 1;\r
200       int end = seq.findIndex(results[2]) - 1;\r
201       if (av.getStartRes() > start\r
202           || av.getEndRes() < end\r
203           || (av.getStartSeq() > results[0]\r
204               || av.getEndSeq() < results[0]))\r
205       {\r
206         setScrollValues(start, results[0]);\r
207       }\r
208     }\r
209 \r
210   }\r
211 \r
212   public OverviewPanel getOverviewPanel()\r
213   {\r
214     return overviewPanel;\r
215   }\r
216 \r
217   public void setOverviewPanel(OverviewPanel op)\r
218   {\r
219     overviewPanel = op;\r
220   }\r
221 \r
222   public void setAnnotationVisible(boolean b)\r
223   {\r
224     if (!av.wrapAlignment)\r
225     {\r
226       annotationSpaceFillerHolder.setVisible(b);\r
227       annotationScroller.setVisible(b);\r
228     }\r
229     validate();\r
230     repaint();\r
231   }\r
232 \r
233   public void setWrapAlignment(boolean wrap)\r
234   {\r
235     av.startSeq = 0;\r
236     scalePanelHolder.setVisible(!wrap);\r
237     hscroll.setVisible(!wrap);\r
238     idwidthAdjuster.setVisible(!wrap);\r
239 \r
240     if (wrap)\r
241     {\r
242       annotationScroller.setVisible(false);\r
243       annotationSpaceFillerHolder.setVisible(false);\r
244     }\r
245     else if (av.showAnnotation)\r
246     {\r
247       annotationScroller.setVisible(true);\r
248       annotationSpaceFillerHolder.setVisible(true);\r
249     }\r
250 \r
251     idSpaceFillerPanel1.setVisible(!wrap);\r
252 \r
253     validate();\r
254     repaint();\r
255 \r
256   }\r
257 \r
258 \r
259   int hextent = 0;\r
260   int vextent = 0;\r
261 \r
262   // return value is true if the scroll is valid\r
263   public boolean scrollUp(boolean up)\r
264   {\r
265     if (up)\r
266     {\r
267       if (vscroll.getValue() < 1)\r
268       {\r
269         return false;\r
270       }\r
271       fastPaint = false;\r
272       vscroll.setValue(vscroll.getValue() - 1);\r
273     }\r
274     else\r
275     {\r
276       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())\r
277       {\r
278         return false;\r
279       }\r
280       fastPaint = false;\r
281       vscroll.setValue(vscroll.getValue() + 1);\r
282     }\r
283     fastPaint = true;\r
284     return true;\r
285   }\r
286 \r
287   public boolean scrollRight(boolean right)\r
288   {\r
289 \r
290     if (right)\r
291     {\r
292       if (hscroll.getValue() < 1)\r
293       {\r
294         return false;\r
295       }\r
296       fastPaint = false;\r
297       hscroll.setValue(hscroll.getValue() - 1);\r
298     }\r
299     else\r
300     {\r
301       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
302       {\r
303         return false;\r
304       }\r
305       fastPaint = false;\r
306       hscroll.setValue(hscroll.getValue() + 1);\r
307     }\r
308     fastPaint = true;\r
309     return true;\r
310   }\r
311 \r
312   public void setScrollValues(int x, int y)\r
313   {\r
314 \r
315     av.setStartRes(x);\r
316     av.setStartSeq(y);\r
317     av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() - 1);\r
318 \r
319     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;\r
320     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;\r
321 \r
322     if (hextent > av.alignment.getWidth())\r
323     {\r
324       hextent = av.alignment.getWidth();\r
325     }\r
326     if (vextent > av.alignment.getHeight())\r
327     {\r
328       vextent = av.alignment.getHeight();\r
329     }\r
330 \r
331     if (hextent + x > av.getAlignment().getWidth())\r
332     {\r
333       x = av.getAlignment().getWidth() - hextent;\r
334     }\r
335 \r
336     if (vextent + y > av.getAlignment().getHeight())\r
337     {\r
338       y = av.getAlignment().getHeight() - vextent;\r
339     }\r
340 \r
341     if (y < 0)\r
342     {\r
343       y = 0;\r
344     }\r
345 \r
346     if (x < 0)\r
347     {\r
348       x = 0;\r
349     }\r
350 \r
351     int endSeq = y + vextent;\r
352     if (endSeq > av.alignment.getHeight())\r
353     {\r
354       endSeq = av.alignment.getHeight();\r
355     }\r
356 \r
357     av.setEndSeq(endSeq);\r
358     hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());\r
359     vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());\r
360 \r
361   }\r
362 \r
363   public void adjustmentValueChanged(AdjustmentEvent evt)\r
364   {\r
365     int oldX = av.getStartRes();\r
366     int oldY = av.getStartSeq();\r
367 \r
368     if (evt.getSource() == hscroll)\r
369     {\r
370       int x = hscroll.getValue();\r
371       av.setStartRes(x);\r
372       av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() -\r
373                    1);\r
374     }\r
375 \r
376     if (evt.getSource() == vscroll)\r
377     {\r
378       int offy = vscroll.getValue();\r
379       if (av.getWrapAlignment())\r
380       {\r
381         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
382             seqCanvas.getSize().width);\r
383         av.setStartRes(vscroll.getValue() * rowSize);\r
384         av.setEndRes( (vscroll.getValue() + 1) * rowSize);\r
385       }\r
386       else\r
387       {\r
388         av.setStartSeq(offy);\r
389         av.setEndSeq(offy +\r
390                      seqPanel.seqCanvas.getSize().height / av.getCharHeight());\r
391       }\r
392     }\r
393 \r
394     if (overviewPanel != null)\r
395     {\r
396       overviewPanel.setBoxPosition();\r
397     }\r
398 \r
399     if (av.getWrapAlignment() || !fastPaint || MAC)\r
400     {\r
401       repaint();\r
402     }\r
403     else\r
404     {\r
405       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
406       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
407                                    av.getStartSeq() - oldY);\r
408 \r
409       scalePanel.repaint();\r
410       if (av.getShowAnnotation())\r
411       {\r
412         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
413       }\r
414     }\r
415 \r
416   }\r
417 \r
418   public void update(Graphics g)\r
419   {\r
420     paint(g);\r
421   }\r
422 \r
423   public void paint(Graphics g)\r
424   {\r
425     Dimension d = idPanel.idCanvas.getSize();\r
426     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
427     annotationSpaceFillerHolder.setSize(d.width,\r
428                                         annotationPanel.getSize().height);\r
429 \r
430     alabels.setSize(d.width, annotationPanel.getSize().height);\r
431 \r
432     if (av.getWrapAlignment())\r
433     {\r
434       int max = av.alignment.getWidth() /\r
435           seqPanel.seqCanvas.\r
436           getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width) +1;\r
437       vscroll.setMaximum(max);\r
438       vscroll.setUnitIncrement(1);\r
439       vscroll.setVisibleAmount(1);\r
440     }\r
441     else\r
442     {\r
443       setScrollValues(av.getStartRes(), av.getStartSeq());\r
444     }\r
445 \r
446     alabels.repaint();\r
447 \r
448     seqPanel.seqCanvas.repaint();\r
449     scalePanel.repaint();\r
450     annotationPanel.repaint();\r
451     idPanel.idCanvas.repaint();\r
452 \r
453     if (getBounds() == g.getClipBounds())\r
454     {\r
455       if (overviewPanel != null)\r
456         overviewPanel.updateOverviewImage();\r
457     }\r
458 \r
459   }\r
460 \r
461   protected Panel sequenceHolderPanel = new Panel();\r
462   protected Scrollbar vscroll = new Scrollbar();\r
463   protected Scrollbar hscroll = new Scrollbar();\r
464   protected Panel seqPanelHolder = new Panel();\r
465   BorderLayout borderLayout1 = new BorderLayout();\r
466   BorderLayout borderLayout3 = new BorderLayout();\r
467   protected Panel scalePanelHolder = new Panel();\r
468   protected Panel idPanelHolder = new Panel();\r
469   BorderLayout borderLayout5 = new BorderLayout();\r
470   protected Panel idSpaceFillerPanel1 = new Panel();\r
471   public Panel annotationSpaceFillerHolder = new Panel();\r
472   BorderLayout borderLayout6 = new BorderLayout();\r
473   BorderLayout borderLayout7 = new BorderLayout();\r
474   Panel hscrollHolder = new Panel();\r
475   BorderLayout borderLayout10 = new BorderLayout();\r
476   protected Panel hscrollFillerPanel = new Panel();\r
477   BorderLayout borderLayout11 = new BorderLayout();\r
478   public Panel annotationScroller = new Panel();\r
479   BorderLayout borderLayout4 = new BorderLayout();\r
480   BorderLayout borderLayout2 = new BorderLayout();\r
481 \r
482   private void jbInit() throws Exception {\r
483       //  idPanelHolder.setPreferredSize(new Dimension(70, 10));\r
484       this.setLayout(borderLayout7);\r
485 \r
486       //   sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));\r
487       sequenceHolderPanel.setLayout(borderLayout3);\r
488       seqPanelHolder.setLayout(borderLayout1);\r
489       scalePanelHolder.setBackground(Color.white);\r
490 \r
491       // scalePanelHolder.setPreferredSize(new Dimension(10, 30));\r
492       scalePanelHolder.setLayout(borderLayout6);\r
493       idPanelHolder.setLayout(borderLayout5);\r
494       idSpaceFillerPanel1.setBackground(Color.white);\r
495 \r
496       //  idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));\r
497       idSpaceFillerPanel1.setLayout(borderLayout11);\r
498       annotationSpaceFillerHolder.setBackground(Color.white);\r
499 \r
500       //  annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));\r
501       annotationSpaceFillerHolder.setLayout(borderLayout4);\r
502       hscroll.setOrientation(Scrollbar.HORIZONTAL);\r
503       hscrollHolder.setLayout(borderLayout10);\r
504       hscrollFillerPanel.setBackground(Color.white);\r
505 \r
506       //  hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));\r
507       hscrollHolder.setBackground(Color.white);\r
508 \r
509       //    annotationScroller.setPreferredSize(new Dimension(10, 80));\r
510       //  this.setPreferredSize(new Dimension(220, 166));\r
511       seqPanelHolder.setBackground(Color.white);\r
512       idPanelHolder.setBackground(Color.white);\r
513       annotationScroller.setLayout(borderLayout2);\r
514       sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);\r
515       sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);\r
516       seqPanelHolder.add(vscroll, BorderLayout.EAST);\r
517       sequenceHolderPanel.add(annotationScroller, BorderLayout.SOUTH);\r
518 \r
519       //  Panel3.add(secondaryPanelHolder,  BorderLayout.SOUTH);\r
520       this.add(idPanelHolder, BorderLayout.WEST);\r
521       idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);\r
522       idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);\r
523       this.add(hscrollHolder, BorderLayout.SOUTH);\r
524       hscrollHolder.add(hscroll, BorderLayout.CENTER);\r
525       hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);\r
526       this.add(sequenceHolderPanel, BorderLayout.CENTER);\r
527   }\r
528 \r
529 }\r