GPL license added
[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 jalview.jbappletgui.GAlignmentPanel;\r
23 import jalview.schemes.*;\r
24 import jalview.analysis.*;\r
25 import jalview.datamodel.*;\r
26 import java.awt.*;\r
27 import java.awt.event.*;\r
28 \r
29 public class AlignmentPanel extends GAlignmentPanel implements AdjustmentListener\r
30 {\r
31 \r
32   AlignViewport     av;\r
33   OverviewPanel overviewPanel;\r
34   SeqPanel   seqPanel;\r
35   IdPanel    idPanel;\r
36   IdwidthAdjuster idwidthAdjuster;\r
37   public AlignFrame alignFrame;\r
38   ScalePanel scalePanel;\r
39   AnnotationPanel annotationPanel;\r
40   AnnotationLabels alabels;\r
41 \r
42   // this value is set false when selection area being dragged\r
43   boolean fastPaint = true;\r
44 \r
45   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
46   {\r
47     alignFrame = af;\r
48     this.av         = av;\r
49     seqPanel        = new SeqPanel  (av, this);\r
50     idPanel         = new IdPanel   (av, this);\r
51     scalePanel      = new ScalePanel(av, this);\r
52     idwidthAdjuster = new IdwidthAdjuster(this);\r
53     annotationPanel = new AnnotationPanel(this);\r
54     alabels         = new AnnotationLabels(this);\r
55 \r
56 \r
57     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
58     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
59     annotationScroller.add(annotationPanel);\r
60     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
61     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
62     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
63 \r
64     fontChanged();\r
65     setScrollValues(0, 0);\r
66 \r
67     hscroll.addAdjustmentListener(this);\r
68     vscroll.addAdjustmentListener(this);\r
69 \r
70    seqPanel.seqCanvas.addKeyListener( new MyKeyAdapter() );\r
71    idPanel.idCanvas.addKeyListener( new MyKeyAdapter() );\r
72 \r
73    addComponentListener(new ComponentAdapter()\r
74      {\r
75        public void componentResized(ComponentEvent evt)\r
76        {\r
77          setScrollValues(av.getStartRes(), av.getStartSeq());\r
78          repaint();\r
79        }\r
80      });\r
81 \r
82      Dimension d = calculateIdWidth();\r
83      idPanel.idCanvas.setSize(d);\r
84 \r
85      hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);\r
86      annotationScroller.setSize(annotationPanel.getSize());\r
87 \r
88      idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
89      annotationSpaceFillerHolder.setSize(d.width,annotationPanel.getSize().height);\r
90      alabels.setSize(d.width,annotationPanel.getSize().height);\r
91 \r
92   }\r
93 \r
94   class MyKeyAdapter extends KeyAdapter\r
95   {\r
96      public void keyPressed(KeyEvent evt)\r
97      {\r
98        // System.out.println(evt.getKeyCode()); log.\r
99        switch(evt.getKeyCode())\r
100        {\r
101          case  27: // escape key\r
102            av.setSelectionGroup(null);\r
103            alignFrame.alignPanel.repaint();\r
104            break;\r
105          case KeyEvent.VK_X:\r
106            if(evt.isControlDown())\r
107            alignFrame.cut_actionPerformed(null);\r
108            break;\r
109          case KeyEvent.VK_C:\r
110          if(evt.isControlDown())\r
111            alignFrame.copy_actionPerformed(null);\r
112            break;\r
113          case KeyEvent.VK_V:\r
114           if(evt.isControlDown())\r
115            alignFrame.paste(true);\r
116            break;\r
117          case KeyEvent.VK_A:\r
118          if(evt.isControlDown())\r
119            alignFrame.selectAllSequenceMenuItem_actionPerformed(null);\r
120            break;\r
121         case KeyEvent.VK_DOWN:\r
122           alignFrame.moveSelectedSequences(false);\r
123           break;\r
124         case KeyEvent.VK_UP:\r
125           alignFrame.moveSelectedSequences(true);\r
126           break;\r
127         case KeyEvent.VK_F:\r
128          if(evt.isControlDown())\r
129           alignFrame.findMenuItem_actionPerformed(null);\r
130           break;\r
131        }\r
132      }\r
133   }\r
134 \r
135   public void fontChanged()\r
136   {\r
137     // set idCanvas bufferedImage to null\r
138     // to prevent drawing old image\r
139     FontMetrics fm = getFontMetrics(av.getFont());\r
140 \r
141     scalePanel.setSize(new Dimension(10, av.charHeight+fm.getDescent()));\r
142     idwidthAdjuster.setSize(new Dimension(10, av.charHeight+fm.getDescent()));\r
143 \r
144     annotationPanel.adjustPanelHeight();\r
145     annotationPanel.repaint();\r
146     Dimension d = calculateIdWidth();\r
147     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);\r
148     idPanel.idCanvas.setSize(d);\r
149     hscrollFillerPanel.setSize(d);\r
150 \r
151     alignFrame.pack();\r
152   }\r
153 \r
154   public void setIdWidth(int w, int h)\r
155   {\r
156     idPanel.idCanvas.setSize(w,h);\r
157     idPanelHolder.setSize(w,idPanelHolder.getSize().height);\r
158     alabels.setSize(w,alabels.getSize().height);\r
159     validate();\r
160   }\r
161   Dimension calculateIdWidth()\r
162   {\r
163     Frame frame = new Frame();\r
164     frame.addNotify();\r
165     Graphics g = frame.getGraphics();\r
166     if(g==null)\r
167     {\r
168       Frame f = new Frame();\r
169       f.addNotify();\r
170       g = f.getGraphics();\r
171     }\r
172 \r
173     FontMetrics fm = g.getFontMetrics(av.font);\r
174     AlignmentI al = av.getAlignment();\r
175 \r
176        int i   = 0;\r
177        int idWidth = 0;\r
178        String id;\r
179        while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
180        {\r
181          SequenceI s   = al.getSequenceAt(i);\r
182          if(av.getShowFullId())\r
183            id   = s.getDisplayId();\r
184          else\r
185            id = s.getName();\r
186 \r
187          if (fm.stringWidth(id) > idWidth)\r
188            idWidth = fm.stringWidth(id);\r
189          i++;\r
190        }\r
191 \r
192        // Also check annotation label widths\r
193        i=0;\r
194        if(al.getAlignmentAnnotation()!=null)\r
195        {\r
196          fm = g.getFontMetrics(frame.getFont());\r
197          while (i < al.getAlignmentAnnotation().length)\r
198          {\r
199            String label = al.getAlignmentAnnotation()[i].label;\r
200            if (fm.stringWidth(label) > idWidth)\r
201              idWidth = fm.stringWidth(label);\r
202            i++;\r
203          }\r
204        }\r
205 \r
206        return new Dimension(idWidth, idPanel.idCanvas.getSize().height);\r
207   }\r
208 \r
209 \r
210  public void highlightSearchResults(int [] results)\r
211  {\r
212    seqPanel.seqCanvas.highlightSearchResults( results );\r
213 \r
214    // do we need to scroll the panel?\r
215    if(results!=null)\r
216     {\r
217       SequenceI seq = av.alignment.getSequenceAt(results[0]);\r
218       int start = seq.findIndex( results[1] )-1;\r
219       int end = seq.findIndex( results[2] )-1;\r
220       if( av.getStartRes() > start\r
221           || av.getEndRes() < end\r
222           || (av.getStartSeq() > results[0]\r
223           || av.getEndSeq() < results[0]))\r
224         setScrollValues(start, results[0]);\r
225     }\r
226 \r
227  }\r
228 \r
229 \r
230  public OverviewPanel getOverviewPanel()\r
231  {\r
232    return overviewPanel;\r
233  }\r
234 \r
235  public void setOverviewPanel(OverviewPanel op)\r
236  {\r
237    overviewPanel = op;\r
238  }\r
239 \r
240 \r
241   public void setAnnotationVisible(boolean b)\r
242   {\r
243     annotationSpaceFillerHolder.setVisible(b);\r
244     annotationScroller.setVisible(b);\r
245     validate();\r
246     repaint();\r
247   }\r
248 \r
249 \r
250   public void setWrapAlignment(boolean wrap)\r
251   {\r
252     scalePanelHolder.setVisible(!wrap);\r
253     hscroll.setVisible(!wrap);\r
254     idwidthAdjuster.setVisible(!wrap);\r
255 \r
256     av.setShowAnnotation(!wrap);\r
257     annotationScroller.setVisible(!wrap);\r
258     annotationSpaceFillerHolder.setVisible(!wrap);\r
259     idSpaceFillerPanel1.setVisible(!wrap);\r
260 \r
261     validate();\r
262     repaint();\r
263 \r
264   }\r
265 \r
266 \r
267   public void setColourScheme()\r
268   {\r
269     ColourSchemeI cs = av.getGlobalColourScheme();\r
270 \r
271     if(av.getConservationSelected())\r
272     {\r
273 \r
274        Alignment al = (Alignment)av.getAlignment();\r
275        Conservation c = new Conservation("All",\r
276                             ResidueProperties.propHash, 3, al.getSequences(), 0,\r
277                             al.getWidth() );\r
278 \r
279        c.calculate();\r
280        c.verdict(false, av.ConsPercGaps);\r
281        ConservationColourScheme ccs = new ConservationColourScheme(c, cs);\r
282 \r
283        av.setGlobalColourScheme( ccs );\r
284 \r
285     }\r
286 \r
287     repaint();\r
288   }\r
289 \r
290 \r
291   int hextent = 0;\r
292   int vextent = 0;\r
293 \r
294   // return value is true if the scroll is valid\r
295   public boolean scrollUp(boolean up)\r
296   {\r
297     if(up)\r
298     {\r
299       if(vscroll.getValue()<1)\r
300         return false;\r
301       fastPaint  = false;\r
302       vscroll.setValue(vscroll.getValue() - 1);\r
303     }\r
304     else\r
305     {\r
306      if(vextent+vscroll.getValue() >= av.getAlignment().getHeight())\r
307        return false;\r
308       fastPaint  = false;\r
309       vscroll.setValue(vscroll.getValue() + 1);\r
310     }\r
311     fastPaint = true;\r
312     return true;\r
313   }\r
314 \r
315   public boolean scrollRight(boolean right)\r
316   {\r
317 \r
318     if (right)\r
319     {\r
320       if (hscroll.getValue() < 1)\r
321         return false;\r
322       fastPaint = false;\r
323       hscroll.setValue(hscroll.getValue() - 1);\r
324     }\r
325     else\r
326     {\r
327       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
328         return false;\r
329       fastPaint = false;\r
330       hscroll.setValue(hscroll.getValue() + 1);\r
331     }\r
332     fastPaint = true;\r
333     return true;\r
334   }\r
335 \r
336 \r
337   public void setScrollValues(int x, int y)\r
338   {\r
339 \r
340     av.setStartRes(x);\r
341     av.setStartSeq(y);\r
342     av.setEndRes(x + seqPanel.seqCanvas.getSize().width/av.getCharWidth()-1);\r
343 \r
344     hextent = seqPanel.seqCanvas.getSize().width/av.charWidth;\r
345     vextent = seqPanel.seqCanvas.getSize().height/av.charHeight;\r
346 \r
347     if(hextent > av.alignment.getWidth())\r
348       hextent = av.alignment.getWidth();\r
349     if(vextent > av.alignment.getHeight())\r
350       vextent = av.alignment.getHeight();\r
351 \r
352     if(hextent+x  >  av.getAlignment().getWidth())\r
353       x =  av.getAlignment().getWidth()- hextent;\r
354 \r
355     if(vextent+y > av.getAlignment().getHeight())\r
356       y = av.getAlignment().getHeight() - vextent;\r
357 \r
358     if(y<0)\r
359       y = 0;\r
360 \r
361     if(x<0)\r
362       x=0;\r
363 \r
364 \r
365     int endSeq = y + vextent;\r
366     if(endSeq>av.alignment.getHeight())\r
367       endSeq = av.alignment.getHeight();\r
368 \r
369 \r
370     av.setEndSeq( endSeq );\r
371     hscroll.setValues(x,hextent,0,av.getAlignment().getWidth());\r
372     vscroll.setValues(y,vextent,0,av.getAlignment().getHeight() );\r
373 \r
374   }\r
375 \r
376 \r
377   public void adjustmentValueChanged(AdjustmentEvent evt)\r
378   {\r
379     int oldX = av.getStartRes();\r
380     int oldY = av.getStartSeq();\r
381 \r
382     if (evt.getSource() == hscroll)\r
383     {\r
384       int x = hscroll.getValue();\r
385       av.setStartRes(x);\r
386       av.setEndRes(x + seqPanel.seqCanvas.getSize().width/av.getCharWidth()-1);\r
387     }\r
388 \r
389     if (evt.getSource() == vscroll)\r
390     {\r
391       int offy = vscroll.getValue();\r
392       if (av.getWrapAlignment())\r
393       {\r
394         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);\r
395         av.setStartRes( vscroll.getValue() * rowSize );\r
396         av.setEndRes( (vscroll.getValue()+1) * rowSize );\r
397       }\r
398       else\r
399       {\r
400         av.setStartSeq(offy);\r
401         av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height / av.getCharHeight());\r
402       }\r
403     }\r
404 \r
405     if(overviewPanel!=null)\r
406       overviewPanel.setBoxPosition();\r
407 \r
408     if(av.getWrapAlignment() || !fastPaint)\r
409       repaint();\r
410     else\r
411     {\r
412       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
413       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
414                                    av.getStartSeq() - oldY);\r
415 \r
416       scalePanel.repaint();\r
417       if (av.getShowAnnotation())\r
418         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
419     }\r
420 \r
421   }\r
422 \r
423   public void update(Graphics g)\r
424   {\r
425     paint (g);\r
426   }\r
427 \r
428 \r
429   public void paint(Graphics g)\r
430   {\r
431     Dimension d = idPanel.idCanvas.getSize();\r
432     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
433     annotationSpaceFillerHolder.setSize(d.width,annotationPanel.getSize().height);\r
434     alabels.setSize(d.width,annotationPanel.getSize().height);\r
435 \r
436     alabels.repaint();\r
437     idPanel.idCanvas.repaint();\r
438     seqPanel.seqCanvas.repaint();\r
439     scalePanel.repaint();\r
440     annotationPanel.repaint();\r
441 \r
442 \r
443     if (av.getWrapAlignment())\r
444     {\r
445       int max = av.alignment.getWidth() / seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);\r
446       vscroll.setMaximum(max);\r
447       vscroll.setUnitIncrement(1);\r
448       vscroll.setVisibleAmount(1);\r
449     }\r
450     else\r
451     {\r
452       setScrollValues(av.getStartRes(), av.getStartSeq());\r
453     }\r
454 \r
455 \r
456 \r
457   }\r
458 }\r