updated to jalview 2.1 and begun ArchiveClient/VamsasClient/VamsasStore updates.
[jalview.git] / src / jalview / appletgui / AlignmentPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19
20 package jalview.appletgui;
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import jalview.datamodel.*;
26
27 public class AlignmentPanel extends Panel implements AdjustmentListener
28 {
29
30   AlignViewport av;
31   OverviewPanel overviewPanel;
32   SeqPanel seqPanel;
33   IdPanel idPanel;
34   IdwidthAdjuster idwidthAdjuster;
35   public AlignFrame alignFrame;
36   ScalePanel scalePanel;
37   AnnotationPanel annotationPanel;
38   AnnotationLabels alabels;
39
40   // this value is set false when selection area being dragged
41   boolean fastPaint = true;
42
43
44
45   public AlignmentPanel(AlignFrame af, final AlignViewport av)
46   {
47     try
48     {
49       jbInit();
50     }
51     catch (Exception e)
52     {
53       e.printStackTrace();
54     }
55
56
57     alignFrame = af;
58     this.av = av;
59     seqPanel = new SeqPanel(av, this);
60     idPanel = new IdPanel(av, this);
61     scalePanel = new ScalePanel(av, this);
62     idwidthAdjuster = new IdwidthAdjuster(this);
63     annotationPanel = new AnnotationPanel(this);
64
65     sequenceHolderPanel.add(annotationPanel, BorderLayout.SOUTH);
66
67     alabels = new AnnotationLabels(this);
68
69     setAnnotationVisible(av.showAnnotation);
70
71     idPanelHolder.add(idPanel, BorderLayout.CENTER);
72     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
73     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
74     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
75     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
76
77     fontChanged();
78     setScrollValues(0, 0);
79
80     hscroll.addAdjustmentListener(this);
81     vscroll.addAdjustmentListener(this);
82
83     addComponentListener(new ComponentAdapter()
84     {
85       public void componentResized(ComponentEvent evt)
86       {
87         setScrollValues(av.getStartRes(), av.getStartSeq());
88         repaint();
89       }
90     });
91
92     Dimension d = calculateIdWidth();
93     idPanel.idCanvas.setSize(d);
94
95     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);
96
97     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
98     annotationSpaceFillerHolder.setSize(d.width,
99                                         annotationPanel.getSize().height);
100     alabels.setSize(d.width, annotationPanel.getSize().height);
101
102   }
103
104
105   public void fontChanged()
106   {
107     // set idCanvas bufferedImage to null
108     // to prevent drawing old image
109     idPanel.idCanvas.image = null;
110     FontMetrics fm = getFontMetrics(av.getFont());
111
112     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));
113     idwidthAdjuster.setSize(new Dimension(10, av.charHeight + fm.getDescent()));
114
115     annotationPanel.image = null;
116     int ap = annotationPanel.adjustPanelHeight();
117     annotationPanel.repaint();
118     Dimension d = calculateIdWidth();
119     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);
120     alabels.setSize(d.width+4, ap );
121     idPanel.idCanvas.setSize(d);
122     hscrollFillerPanel.setSize(d);
123
124     validate();
125     repaint();
126
127     if(overviewPanel!=null)
128           overviewPanel.updateOverviewImage();
129   }
130
131   public void setIdWidth(int w, int h)
132   {
133     idPanel.idCanvas.setSize(w, h);
134     idPanelHolder.setSize(w, idPanelHolder.getSize().height);
135     alabels.setSize(w, alabels.getSize().height);
136     validate();
137   }
138
139   Dimension calculateIdWidth()
140   {
141     if (av.nullFrame == null)
142     {
143       av.nullFrame = new Frame();
144       av.nullFrame.addNotify();
145     }
146
147     Graphics g = av.nullFrame.getGraphics();
148
149     FontMetrics fm = g.getFontMetrics(av.font);
150     AlignmentI al = av.getAlignment();
151
152     int i = 0;
153     int idWidth = 0;
154     String id;
155     while (i < al.getHeight() && al.getSequenceAt(i) != null)
156     {
157       SequenceI s = al.getSequenceAt(i);
158       id = s.getDisplayId(av.getShowJVSuffix());
159
160       if (fm.stringWidth(id) > idWidth)
161       {
162         idWidth = fm.stringWidth(id);
163       }
164       i++;
165     }
166
167     // Also check annotation label widths
168     i = 0;
169     if (al.getAlignmentAnnotation() != null)
170     {
171       fm = g.getFontMetrics(av.nullFrame.getFont());
172       while (i < al.getAlignmentAnnotation().length)
173       {
174         String label = al.getAlignmentAnnotation()[i].label;
175         if (fm.stringWidth(label) > idWidth)
176         {
177           idWidth = fm.stringWidth(label);
178         }
179         i++;
180       }
181     }
182
183     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);
184   }
185
186   public void highlightSearchResults(SearchResults results)
187   {
188     seqPanel.seqCanvas.highlightSearchResults(results);
189
190    // do we need to scroll the panel?
191     if (results != null)
192     {
193       SequenceI seq = results.getResultSequence(0);
194       int seqIndex = av.alignment.findIndex(seq);
195       int start = seq.findIndex(results.getResultStart(0)) - 1;
196       int end = seq.findIndex(results.getResultEnd(0)) - 1;
197
198         if(!av.wrapAlignment)
199         {
200           if ( (av.getStartRes() > end)  || (av.getEndRes() < start) ||
201              ( (av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))
202           {
203             if (start > av.alignment.getWidth() - hextent)
204             {
205               start = av.alignment.getWidth() - hextent;
206               if (start < 0)
207                 start = 0;
208             }
209             if (seqIndex > av.alignment.getHeight() - vextent)
210             {
211               seqIndex = av.alignment.getHeight() - vextent;
212               if (seqIndex < 0)
213                 seqIndex = 0;
214             }
215             setScrollValues(start, seqIndex);
216           }
217         }
218         else
219         {
220           scrollToWrappedVisible(start);
221         }
222     }
223
224     repaint();
225   }
226
227   void scrollToWrappedVisible(int res)
228   {
229     int cwidth = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
230     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))
231     {
232       vscroll.setValue(res / cwidth);
233       av.startRes = vscroll.getValue() * cwidth;
234     }
235   }
236
237
238   public OverviewPanel getOverviewPanel()
239   {
240     return overviewPanel;
241   }
242
243   public void setOverviewPanel(OverviewPanel op)
244   {
245     overviewPanel = op;
246   }
247
248   public void setAnnotationVisible(boolean b)
249   {
250     if (!av.wrapAlignment)
251     {
252       annotationSpaceFillerHolder.setVisible(b);
253       annotationPanel.setVisible(b);
254     }
255     validate();
256     repaint();
257   }
258
259   public void setWrapAlignment(boolean wrap)
260   {
261     av.startSeq = 0;
262     scalePanelHolder.setVisible(!wrap);
263
264
265     hscroll.setVisible(!wrap);
266     idwidthAdjuster.setVisible(!wrap);
267
268     if (wrap)
269     {
270       annotationPanel.setVisible(false);
271       annotationSpaceFillerHolder.setVisible(false);
272     }
273     else if (av.showAnnotation)
274     {
275       annotationPanel.setVisible(true);
276       annotationSpaceFillerHolder.setVisible(true);
277     }
278
279
280     idSpaceFillerPanel1.setVisible(!wrap);
281
282     fontChanged();//This is so that the scalePanel is resized correctly
283
284     validate();
285     repaint();
286
287   }
288
289
290   int hextent = 0;
291   int vextent = 0;
292
293   // return value is true if the scroll is valid
294   public boolean scrollUp(boolean up)
295   {
296     if (up)
297     {
298       if (vscroll.getValue() < 1)
299       {
300         return false;
301       }
302       setScrollValues(hscroll.getValue(), vscroll.getValue()-1);
303     }
304     else
305     {
306       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())
307       {
308         return false;
309       }
310       setScrollValues(hscroll.getValue(), vscroll.getValue()+1);
311     }
312
313     repaint();
314     return true;
315   }
316
317   public boolean scrollRight(boolean right)
318   {
319     if (!right)
320     {
321       if (hscroll.getValue() < 1)
322       {
323         return false;
324       }
325       setScrollValues(hscroll.getValue()-1, vscroll.getValue());
326     }
327     else
328     {
329       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())
330       {
331         return false;
332       }
333       setScrollValues(hscroll.getValue()+1, vscroll.getValue());
334     }
335
336     repaint();
337     return true;
338   }
339
340   public void setScrollValues(int x, int y)
341   {
342     int width = av.alignment.getWidth();
343     int height = av.alignment.getHeight();
344
345     if(av.hasHiddenColumns)
346      width = av.getColumnSelection().findColumnPosition(width);
347
348     av.setStartRes(x);
349     av.setStartSeq(y);
350
351     av.setEndRes( (x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) -1);
352
353     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;
354     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;
355
356     if (hextent > width)
357     {
358       hextent = width;
359     }
360
361     if (vextent > height)
362     {
363       vextent = height;
364     }
365
366     if ( (hextent + x) > width)
367     {
368       x = width - hextent;
369     }
370
371     if ( (vextent + y) > height)
372     {
373       y = height - vextent;
374     }
375
376     if (y < 0)
377     {
378       y = 0;
379     }
380
381     if (x < 0)
382     {
383       x = 0;
384     }
385
386     int endSeq = y + vextent;
387     if (endSeq > av.alignment.getHeight())
388     {
389       endSeq = av.alignment.getHeight();
390     }
391
392     av.setEndSeq(endSeq);
393     hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());
394     vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());
395
396     if(overviewPanel!=null)
397           overviewPanel.setBoxPosition();
398
399   }
400
401   public void adjustmentValueChanged(AdjustmentEvent evt)
402   {
403     int oldX = av.getStartRes();
404     int oldY = av.getStartSeq();
405
406
407     if (evt==null || evt.getSource() == hscroll)
408     {
409       int x = hscroll.getValue();
410       av.setStartRes(x);
411       av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() -
412                    1);
413     }
414
415
416     if (evt==null || evt.getSource() == vscroll)
417     {
418       int offy = vscroll.getValue();
419       if (av.getWrapAlignment())
420       {
421         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.
422             seqCanvas.getSize().width);
423         av.setStartRes(vscroll.getValue() * rowSize);
424         av.setEndRes( (vscroll.getValue() + 1) * rowSize);
425       }
426       else
427       {
428         av.setStartSeq(offy);
429         av.setEndSeq(offy +
430                      seqPanel.seqCanvas.getSize().height / av.getCharHeight());
431       }
432     }
433
434     if (overviewPanel != null)
435     {
436       overviewPanel.setBoxPosition();
437     }
438
439     int scrollX = av.startRes - oldX;
440     int scrollY = av.startSeq - oldY;
441
442     if (av.getWrapAlignment() || !fastPaint || av.MAC)
443     {
444       repaint();
445     }
446     else
447     {
448       // Make sure we're not trying to draw a panel
449       // larger than the visible window
450       if(scrollX>av.endRes-av.startRes)
451       {
452         scrollX = av.endRes - av.startRes;
453       }
454       else if(scrollX<av.startRes-av.endRes)
455         scrollX = av.startRes - av.endRes;
456
457       idPanel.idCanvas.fastPaint(scrollY);
458       seqPanel.seqCanvas.fastPaint(scrollX,
459                                    scrollY);
460
461       scalePanel.repaint();
462       if (av.getShowAnnotation())
463       {
464         annotationPanel.fastPaint(av.getStartRes() - oldX);
465       }
466     }
467
468   }
469
470   public void update(Graphics g)
471   {
472     paint(g);
473   }
474
475   public void paint(Graphics g)
476   {
477     invalidate();
478     Dimension d = idPanel.idCanvas.getSize();
479     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
480     annotationSpaceFillerHolder.setSize(d.width,
481                                         annotationPanel.getSize().height);
482
483     alabels.setSize(d.width, annotationPanel.getSize().height);
484
485     if (av.getWrapAlignment())
486     {
487       int maxwidth = av.alignment.getWidth();
488
489       if (av.hasHiddenColumns)
490         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
491
492       int max = maxwidth /
493           seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width) +
494           1;
495
496       vscroll.setMaximum(max);
497       vscroll.setUnitIncrement(1);
498       vscroll.setVisibleAmount(1);
499     }
500     else
501     {
502       setScrollValues(av.getStartRes(), av.getStartSeq());
503     }
504
505     alabels.repaint();
506
507     seqPanel.seqCanvas.repaint();
508     scalePanel.repaint();
509     annotationPanel.repaint();
510     idPanel.idCanvas.repaint();
511
512     if (getBounds() == g.getClipBounds())
513     {
514       if (overviewPanel != null)
515         overviewPanel.updateOverviewImage();
516     }
517
518   }
519
520   protected Panel sequenceHolderPanel = new Panel();
521   protected Scrollbar vscroll = new Scrollbar();
522   protected Scrollbar hscroll = new Scrollbar();
523   protected Panel seqPanelHolder = new Panel();
524   BorderLayout borderLayout1 = new BorderLayout();
525   BorderLayout borderLayout3 = new BorderLayout();
526   protected Panel scalePanelHolder = new Panel();
527   protected Panel idPanelHolder = new Panel();
528   BorderLayout borderLayout5 = new BorderLayout();
529   protected Panel idSpaceFillerPanel1 = new Panel();
530   public Panel annotationSpaceFillerHolder = new Panel();
531   BorderLayout borderLayout6 = new BorderLayout();
532   BorderLayout borderLayout7 = new BorderLayout();
533   Panel hscrollHolder = new Panel();
534   BorderLayout borderLayout10 = new BorderLayout();
535   protected Panel hscrollFillerPanel = new Panel();
536   BorderLayout borderLayout11 = new BorderLayout();
537   BorderLayout borderLayout4 = new BorderLayout();
538   BorderLayout borderLayout2 = new BorderLayout();
539
540   private void jbInit() throws Exception {
541       //  idPanelHolder.setPreferredSize(new Dimension(70, 10));
542       this.setLayout(borderLayout7);
543
544       //   sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
545       sequenceHolderPanel.setLayout(borderLayout3);
546       seqPanelHolder.setLayout(borderLayout1);
547       scalePanelHolder.setBackground(Color.white);
548
549       // scalePanelHolder.setPreferredSize(new Dimension(10, 30));
550       scalePanelHolder.setLayout(borderLayout6);
551       idPanelHolder.setLayout(borderLayout5);
552       idSpaceFillerPanel1.setBackground(Color.white);
553
554       //  idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));
555       idSpaceFillerPanel1.setLayout(borderLayout11);
556       annotationSpaceFillerHolder.setBackground(Color.white);
557
558       //  annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));
559       annotationSpaceFillerHolder.setLayout(borderLayout4);
560       hscroll.setOrientation(Scrollbar.HORIZONTAL);
561       hscrollHolder.setLayout(borderLayout10);
562       hscrollFillerPanel.setBackground(Color.white);
563
564       //  hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
565       hscrollHolder.setBackground(Color.white);
566
567       //    annotationScroller.setPreferredSize(new Dimension(10, 80));
568       //  this.setPreferredSize(new Dimension(220, 166));
569       seqPanelHolder.setBackground(Color.white);
570       idPanelHolder.setBackground(Color.white);
571       sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);
572       sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);
573       seqPanelHolder.add(vscroll, BorderLayout.EAST);
574
575       //  Panel3.add(secondaryPanelHolder,  BorderLayout.SOUTH);
576       this.add(idPanelHolder, BorderLayout.WEST);
577       idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);
578       idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);
579       this.add(hscrollHolder, BorderLayout.SOUTH);
580       hscrollHolder.add(hscroll, BorderLayout.CENTER);
581       hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);
582       this.add(sequenceHolderPanel, BorderLayout.CENTER);
583   }
584
585 }