c74914f80f0f37e36f7ccca5ef91c258718a279d
[jalview.git] / src / jalview / appletgui / AlignmentPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.appletgui;
22
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Dimension;
26 import java.awt.FontMetrics;
27 import java.awt.Frame;
28 import java.awt.Graphics;
29 import java.awt.Panel;
30 import java.awt.Scrollbar;
31 import java.awt.event.AdjustmentEvent;
32 import java.awt.event.AdjustmentListener;
33 import java.awt.event.ComponentAdapter;
34 import java.awt.event.ComponentEvent;
35
36 import jalview.analysis.AnnotationSorter;
37 import jalview.api.AlignViewportI;
38 import jalview.api.AlignmentViewPanel;
39 import jalview.datamodel.AlignmentI;
40 import jalview.datamodel.SearchResults;
41 import jalview.datamodel.SequenceI;
42 import jalview.structure.StructureSelectionManager;
43
44 public class AlignmentPanel extends Panel implements AdjustmentListener,
45         AlignmentViewPanel
46 {
47
48   public AlignViewport av;
49
50   OverviewPanel overviewPanel;
51
52   SeqPanel seqPanel;
53
54   IdPanel idPanel;
55
56   IdwidthAdjuster idwidthAdjuster;
57
58   public AlignFrame alignFrame;
59
60   ScalePanel scalePanel;
61
62   AnnotationPanel annotationPanel;
63
64   AnnotationLabels alabels;
65
66   // this value is set false when selection area being dragged
67   boolean fastPaint = true;
68
69   public void finalize()
70   {
71     alignFrame = null;
72     av = null;
73     seqPanel = null;
74     seqPanelHolder = null;
75     sequenceHolderPanel = null;
76     scalePanel = null;
77     scalePanelHolder = null;
78     annotationPanel = null;
79     annotationPanelHolder = null;
80     annotationSpaceFillerHolder = null;
81   }
82
83   public AlignmentPanel(AlignFrame af, final AlignViewport av)
84   {
85     try
86     {
87       jbInit();
88     } catch (Exception e)
89     {
90       e.printStackTrace();
91     }
92
93     alignFrame = af;
94     this.av = av;
95     seqPanel = new SeqPanel(av, this);
96     idPanel = new IdPanel(av, this);
97     scalePanel = new ScalePanel(av, this);
98     idwidthAdjuster = new IdwidthAdjuster(this);
99     annotationPanel = new AnnotationPanel(this);
100     annotationPanelHolder.add(annotationPanel, BorderLayout.CENTER);
101
102     sequenceHolderPanel.add(annotationPanelHolder, BorderLayout.SOUTH);
103     alabels = new AnnotationLabels(this);
104
105     setAnnotationVisible(av.isShowAnnotation());
106
107     idPanelHolder.add(idPanel, BorderLayout.CENTER);
108     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
109     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
110     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
111     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
112
113     fontChanged();
114     setScrollValues(0, 0);
115
116     apvscroll.addAdjustmentListener(this);
117     hscroll.addAdjustmentListener(this);
118     vscroll.addAdjustmentListener(this);
119
120     addComponentListener(new ComponentAdapter()
121     {
122       public void componentResized(ComponentEvent evt)
123       {
124         setScrollValues(av.getStartRes(), av.getStartSeq());
125         if (getSize().height > 0
126                 && annotationPanelHolder.getSize().height > 0)
127         {
128           validateAnnotationDimensions(false);
129         }
130         repaint();
131       }
132
133     });
134
135     Dimension d = calculateIdWidth();
136     idPanel.idCanvas.setSize(d);
137
138     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);
139
140     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
141     annotationSpaceFillerHolder.setSize(d.width,
142             annotationPanel.getSize().height);
143     alabels.setSize(d.width, annotationPanel.getSize().height);
144     final AlignmentPanel ap = this;
145     av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
146     {
147       public void propertyChange(java.beans.PropertyChangeEvent evt)
148       {
149         if (evt.getPropertyName().equals("alignment"))
150         {
151           PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
152           alignmentChanged();
153         }
154       }
155     });
156   }
157
158   @Override
159   public AlignViewportI getAlignViewport()
160   {
161     return av;
162   }
163   public SequenceRenderer getSequenceRenderer()
164   {
165     return seqPanel.seqCanvas.sr;
166   }
167   @Override
168   public jalview.api.FeatureRenderer getFeatureRenderer()
169   {
170     return seqPanel.seqCanvas.fr;
171   }
172   @Override
173   public jalview.api.FeatureRenderer cloneFeatureRenderer()
174   {
175     FeatureRenderer nfr = new FeatureRenderer(av);
176     nfr.transferSettings(seqPanel.seqCanvas.fr);
177     return nfr;
178   }
179   public void alignmentChanged()
180   {
181     av.alignmentChanged(this);
182
183     if (overviewPanel != null)
184     {
185       overviewPanel.updateOverviewImage();
186     }
187
188     alignFrame.updateEditMenuBar();
189
190     repaint();
191   }
192
193   public void fontChanged()
194   {
195     // set idCanvas bufferedImage to null
196     // to prevent drawing old image
197     idPanel.idCanvas.image = null;
198     FontMetrics fm = getFontMetrics(av.getFont());
199
200     scalePanel.setSize(new Dimension(10, av.getCharHeight()
201             + fm.getDescent()));
202     idwidthAdjuster.setSize(new Dimension(10, av.getCharHeight()
203             + fm.getDescent()));
204     av.updateSequenceIdColours();
205     annotationPanel.image = null;
206     int ap = annotationPanel.adjustPanelHeight(false);
207     Dimension d = calculateIdWidth();
208     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);
209     alabels.setSize(d.width + 4, ap);
210
211     idPanel.idCanvas.setSize(d);
212     hscrollFillerPanel.setSize(d);
213
214     validateAnnotationDimensions(false);
215     annotationPanel.repaint();
216     validate();
217     repaint();
218
219     if (overviewPanel != null)
220     {
221       overviewPanel.updateOverviewImage();
222     }
223   }
224
225   public void setIdWidth(int w, int h)
226   {
227     idPanel.idCanvas.setSize(w, h);
228     idPanelHolder.setSize(w, idPanelHolder.getSize().height);
229     annotationSpaceFillerHolder.setSize(w,
230             annotationSpaceFillerHolder.getSize().height);
231     alabels.setSize(w, alabels.getSize().height);
232     validate();
233   }
234
235   Dimension calculateIdWidth()
236   {
237     if (av.nullFrame == null)
238     {
239       av.nullFrame = new Frame();
240       av.nullFrame.addNotify();
241     }
242
243     Graphics g = av.nullFrame.getGraphics();
244
245     FontMetrics fm = g.getFontMetrics(av.font);
246     AlignmentI al = av.getAlignment();
247
248     int i = 0;
249     int idWidth = 0;
250     String id;
251     while (i < al.getHeight() && al.getSequenceAt(i) != null)
252     {
253       SequenceI s = al.getSequenceAt(i);
254       id = s.getDisplayId(av.getShowJVSuffix());
255
256       if (fm.stringWidth(id) > idWidth)
257       {
258         idWidth = fm.stringWidth(id);
259       }
260       i++;
261     }
262
263     // Also check annotation label widths
264     i = 0;
265     if (al.getAlignmentAnnotation() != null)
266     {
267       fm = g.getFontMetrics(av.nullFrame.getFont());
268       while (i < al.getAlignmentAnnotation().length)
269       {
270         String label = al.getAlignmentAnnotation()[i].label;
271         if (fm.stringWidth(label) > idWidth)
272         {
273           idWidth = fm.stringWidth(label);
274         }
275         i++;
276       }
277     }
278
279     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);
280   }
281
282   /**
283    * Highlight the given results on the alignment.
284    * 
285    */
286   public void highlightSearchResults(SearchResults results)
287   {
288     scrollToPosition(results);
289     seqPanel.seqCanvas.highlightSearchResults(results);
290   }
291
292   /**
293    * scroll the view to show the position of the highlighted region in results
294    * (if any) and redraw the overview
295    * 
296    * @param results
297    * @return false if results were not found
298    */
299   public boolean scrollToPosition(SearchResults results)
300   {
301     return scrollToPosition(results, true);
302   }
303
304   /**
305    * scroll the view to show the position of the highlighted region in results
306    * (if any)
307    * 
308    * @param results
309    * @param redrawOverview
310    *          - when set, the overview will be recalculated (takes longer)
311    * @return false if results were not found
312    */
313   public boolean scrollToPosition(SearchResults results,
314           boolean redrawOverview)
315   {
316
317     // do we need to scroll the panel?
318     if (results != null && results.getSize() > 0)
319     {
320       AlignmentI alignment = av.getAlignment();
321       int seqIndex = alignment.findIndex(results);
322       if (seqIndex == -1)
323       {
324         return false;
325       }
326       SequenceI seq = alignment.getSequenceAt(seqIndex);
327       int[] r = results.getResults(seq, 0, alignment.getWidth());
328       if (r == null)
329       {
330         if (av.applet.debug)
331         {// DEBUG
332           System.out
333                   .println("DEBUG: scroll didn't happen - results not within alignment : "
334                           + seq.getStart() + "," + seq.getEnd());
335         }
336         return false;
337       }
338       if (av.applet.debug)
339       {
340         // DEBUG
341         /*
342          * System.out.println("DEBUG: scroll: start=" + r[0] +
343          * " av.getStartRes()=" + av.getStartRes() + " end=" + r[1] +
344          * " seq.end=" + seq.getEnd() + " av.getEndRes()=" + av.getEndRes() +
345          * " hextent=" + hextent);
346          */
347       }
348       int start = r[0];
349       int end = r[1];
350       if (start < 0)
351       {
352         return false;
353       }
354       if (end == seq.getEnd())
355       {
356         return false;
357       }
358       return scrollTo(start, end, seqIndex, false, redrawOverview);
359     }
360     return true;
361   }
362
363   public boolean scrollTo(int ostart, int end, int seqIndex,
364           boolean scrollToNearest, boolean redrawOverview)
365   {
366     int startv, endv, starts, ends, width;
367
368     int start = -1;
369     if (av.hasHiddenColumns())
370     {
371       start = av.getColumnSelection().findColumnPosition(ostart);
372       end = av.getColumnSelection().findColumnPosition(end);
373       if (start == end)
374       {
375         if (!scrollToNearest && !av.getColumnSelection().isVisible(ostart))
376         {
377           // don't scroll - position isn't visible
378           return false;
379         }
380       }
381     }
382     else
383     {
384       start = ostart;
385     }
386     if (!av.getWrapAlignment())
387     {
388       /*
389        * int spos=av.getStartRes(),sqpos=av.getStartSeq(); if ((startv =
390        * av.getStartRes()) >= start) { spos=start-1; // seqIn //
391        * setScrollValues(start - 1, seqIndex); } else if ((endv =
392        * av.getEndRes()) <= end) { // setScrollValues(spos=startv + 1 + end -
393        * endv, seqIndex); spos=startv + 1 + end - endv; } else if ((starts =
394        * av.getStartSeq()) > seqIndex) { setScrollValues(av.getStartRes(),
395        * seqIndex); } else if ((ends = av.getEndSeq()) <= seqIndex) {
396        * setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1); }
397        * 
398        * /*
399        */
400       if ((av.getStartRes() > end)
401               || (av.getEndRes() < start)
402               || ((av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))
403       {
404         if (start > av.getAlignment().getWidth() - hextent)
405         {
406           start = av.getAlignment().getWidth() - hextent;
407           if (start < 0)
408           {
409             start = 0;
410           }
411
412         }
413         if (seqIndex > av.getAlignment().getHeight() - vextent)
414         {
415           seqIndex = av.getAlignment().getHeight() - vextent;
416           if (seqIndex < 0)
417           {
418             seqIndex = 0;
419           }
420         }
421         // System.out.println("trying to scroll to: "+start+" "+seqIndex);
422         setScrollValues(start, seqIndex);
423       }/**/
424     }
425     else
426     {
427       scrollToWrappedVisible(start);
428     }
429     if (redrawOverview && overviewPanel != null)
430     {
431       overviewPanel.setBoxPosition();
432     }
433     paintAlignment(redrawOverview);
434     return true;
435   }
436
437   void scrollToWrappedVisible(int res)
438   {
439     int cwidth = seqPanel.seqCanvas
440             .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
441     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))
442     {
443       vscroll.setValue(res / cwidth);
444       av.startRes = vscroll.getValue() * cwidth;
445     }
446   }
447
448   public OverviewPanel getOverviewPanel()
449   {
450     return overviewPanel;
451   }
452
453   public void setOverviewPanel(OverviewPanel op)
454   {
455     overviewPanel = op;
456   }
457
458   public void setAnnotationVisible(boolean b)
459   {
460     if (!av.getWrapAlignment())
461     {
462       annotationSpaceFillerHolder.setVisible(b);
463       annotationPanelHolder.setVisible(b);
464     }
465     else
466     {
467       annotationSpaceFillerHolder.setVisible(false);
468       annotationPanelHolder.setVisible(false);
469     }
470     validate();
471     repaint();
472   }
473
474   /**
475    * automatically adjust annotation panel height for new annotation whilst
476    * ensuring the alignment is still visible.
477    */
478   public void adjustAnnotationHeight()
479   {
480     // TODO: display vertical annotation scrollbar if necessary
481     // this is called after loading new annotation onto alignment
482     if (alignFrame.getSize().height == 0)
483     {
484       System.out
485               .println("adjustAnnotationHeight frame size zero NEEDS FIXING");
486     }
487     fontChanged();
488     validateAnnotationDimensions(true);
489     apvscroll.addNotify();
490     hscroll.addNotify();
491     validate();
492     paintAlignment(true);
493   }
494
495   /**
496    * calculate the annotation dimensions and refresh slider values accordingly.
497    * need to do repaints/notifys afterwards.
498    */
499   protected void validateAnnotationDimensions(boolean adjustPanelHeight)
500   {
501     boolean modified = false;
502     int height = av.calcPanelHeight();
503     int minsize = 0;
504     if (hscroll.isVisible())
505     {
506       height += (minsize = hscroll.getPreferredSize().height);
507     }
508     if (apvscroll.isVisible())
509     {
510       minsize += apvscroll.getPreferredSize().height;
511     }
512     int mheight = height;
513     Dimension d = sequenceHolderPanel.getSize(), e = idPanel.getSize();
514     int seqandannot = d.height - scalePanelHolder.getSize().height;
515
516     if (adjustPanelHeight)
517     {
518       // NOTE: this logic is different in the application. Need a better
519       // algorithm to define behaviour
520       // sets initial preferred height
521       // try and set height according to alignment
522       float sscaling = (float) ((av.getCharHeight() * av.getAlignment()
523               .getHeight()) / (1.0 * mheight));
524       if (sscaling > 0.5)
525       {
526         // if the alignment is too big then
527         // default is 0.5 split
528         height = seqandannot / 2;
529       }
530       else
531       {
532         // otherwise just set the panel so that one row of sequence is visible
533         height = -av.getCharHeight() * 1
534                 + (int) (seqandannot * (1 - sscaling));
535       }
536     }
537     else
538     {
539       // maintain same window layout whilst updating sliders
540       height = annotationPanelHolder.getSize().height;
541     }
542
543     if (seqandannot - height < 5)
544     {
545       height = seqandannot;
546     }
547     annotationPanel.setSize(new Dimension(d.width, height));
548     alabels.setSize(new Dimension(e.width, height));
549     annotationSpaceFillerHolder.setSize(new Dimension(e.width, height));
550     annotationPanelHolder.setSize(new Dimension(d.width, height));
551     // seqPanelHolder.setSize(d.width, seqandannot - height);
552     seqPanel.seqCanvas
553             .setSize(d.width, seqPanel.seqCanvas.getSize().height);
554     int s = apvscroll.getValue();
555     if (s > mheight - height)
556     {
557       s = 0;
558     }
559     apvscroll.setValues(s, height, 0, mheight);
560     annotationPanel.setScrollOffset(apvscroll.getValue(), false);
561     alabels.setScrollOffset(apvscroll.getValue(), false);
562   }
563
564   public void setWrapAlignment(boolean wrap)
565   {
566     av.startSeq = 0;
567     av.startRes = 0;
568     scalePanelHolder.setVisible(!wrap);
569
570     hscroll.setVisible(!wrap);
571     idwidthAdjuster.setVisible(!wrap);
572
573     if (wrap)
574     {
575       annotationPanelHolder.setVisible(false);
576       annotationSpaceFillerHolder.setVisible(false);
577     }
578     else if (av.isShowAnnotation())
579     {
580       annotationPanelHolder.setVisible(true);
581       annotationSpaceFillerHolder.setVisible(true);
582     }
583
584     idSpaceFillerPanel1.setVisible(!wrap);
585
586     fontChanged(); // This is so that the scalePanel is resized correctly
587
588     validate();
589     sequenceHolderPanel.validate();
590     repaint();
591
592   }
593
594   int hextent = 0;
595
596   int vextent = 0;
597
598   // return value is true if the scroll is valid
599   public boolean scrollUp(boolean up)
600   {
601     if (up)
602     {
603       if (vscroll.getValue() < 1)
604       {
605         return false;
606       }
607       setScrollValues(hscroll.getValue(), vscroll.getValue() - 1);
608     }
609     else
610     {
611       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())
612       {
613         return false;
614       }
615       setScrollValues(hscroll.getValue(), vscroll.getValue() + 1);
616     }
617
618     repaint();
619     return true;
620   }
621
622   public boolean scrollRight(boolean right)
623   {
624     if (!right)
625     {
626       if (hscroll.getValue() < 1)
627       {
628         return false;
629       }
630       setScrollValues(hscroll.getValue() - 1, vscroll.getValue());
631     }
632     else
633     {
634       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())
635       {
636         return false;
637       }
638       setScrollValues(hscroll.getValue() + 1, vscroll.getValue());
639     }
640
641     repaint();
642     return true;
643   }
644
645   public void setScrollValues(int x, int y)
646   {
647     int width = av.getAlignment().getWidth();
648     int height = av.getAlignment().getHeight();
649
650     if (av.hasHiddenColumns())
651     {
652       width = av.getColumnSelection().findColumnPosition(width);
653     }
654     if (x < 0)
655     {
656       x = 0;
657     }
658     ;
659
660     hextent = seqPanel.seqCanvas.getSize().width / av.getCharWidth();
661     vextent = seqPanel.seqCanvas.getSize().height / av.getCharHeight();
662
663     if (hextent > width)
664     {
665       hextent = width;
666     }
667
668     if (vextent > height)
669     {
670       vextent = height;
671     }
672
673     if ((hextent + x) > width)
674     {
675       System.err.println("hextent was " + hextent + " and x was " + x);
676
677       x = width - hextent;
678     }
679
680     if ((vextent + y) > height)
681     {
682       y = height - vextent;
683     }
684
685     if (y < 0)
686     {
687       y = 0;
688     }
689
690     if (x < 0)
691     {
692       System.err.println("x was " + x);
693       x = 0;
694     }
695
696     av.setStartSeq(y);
697
698     int endSeq = y + vextent;
699     if (endSeq > av.getAlignment().getHeight())
700     {
701       endSeq = av.getAlignment().getHeight();
702     }
703
704     av.setEndSeq(endSeq);
705     av.setStartRes(x);
706     av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av
707             .getCharWidth())) - 1);
708
709     hscroll.setValues(x, hextent, 0, width);
710     vscroll.setValues(y, vextent, 0, height);
711
712     if (overviewPanel != null)
713     {
714       overviewPanel.setBoxPosition();
715     }
716     sendViewPosition();
717
718   }
719
720   public void adjustmentValueChanged(AdjustmentEvent evt)
721   {
722     int oldX = av.getStartRes();
723     int oldY = av.getStartSeq();
724
725     if (evt == null || evt.getSource() == apvscroll)
726     {
727       annotationPanel.setScrollOffset(apvscroll.getValue(), false);
728       alabels.setScrollOffset(apvscroll.getValue(), false);
729       // annotationPanel.image=null;
730       // alabels.image=null;
731       // alabels.repaint();
732       // annotationPanel.repaint();
733     }
734     if (evt == null || evt.getSource() == hscroll)
735     {
736       int x = hscroll.getValue();
737       av.setStartRes(x);
738       av.setEndRes(x + seqPanel.seqCanvas.getSize().width
739               / av.getCharWidth() - 1);
740     }
741
742     if (evt == null || evt.getSource() == vscroll)
743     {
744       int offy = vscroll.getValue();
745       if (av.getWrapAlignment())
746       {
747         int rowSize = seqPanel.seqCanvas
748                 .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
749         av.setStartRes(vscroll.getValue() * rowSize);
750         av.setEndRes((vscroll.getValue() + 1) * rowSize);
751       }
752       else
753       {
754         av.setStartSeq(offy);
755         av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
756                 / av.getCharHeight());
757       }
758     }
759
760     if (overviewPanel != null)
761     {
762       overviewPanel.setBoxPosition();
763     }
764
765     int scrollX = av.startRes - oldX;
766     int scrollY = av.startSeq - oldY;
767
768     if (av.getWrapAlignment() || !fastPaint || av.MAC)
769     {
770       repaint();
771     }
772     else
773     {
774       // Make sure we're not trying to draw a panel
775       // larger than the visible window
776       if (scrollX > av.endRes - av.startRes)
777       {
778         scrollX = av.endRes - av.startRes;
779       }
780       else if (scrollX < av.startRes - av.endRes)
781       {
782         scrollX = av.startRes - av.endRes;
783       }
784
785       idPanel.idCanvas.fastPaint(scrollY);
786       seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
787
788       scalePanel.repaint();
789       if (av.isShowAnnotation())
790       {
791         annotationPanel.fastPaint(av.getStartRes() - oldX);
792       }
793     }
794     sendViewPosition();
795
796   }
797
798   private void sendViewPosition()
799   {
800     StructureSelectionManager.getStructureSelectionManager(av.applet)
801             .sendViewPosition(this, av.startRes, av.endRes, av.startSeq,
802                     av.endSeq);
803   }
804
805   /**
806    * Repaint the alignment and annotations, and, optionally, any overview window
807    */
808   public void paintAlignment(boolean updateOverview)
809   {
810     final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
811             av.isShowAutocalculatedAbove());
812     sorter.sort(getAlignment().getAlignmentAnnotation(),
813             av.getSortAnnotationsBy());
814     repaint();
815
816     if (updateOverview)
817     {
818       jalview.structure.StructureSelectionManager
819               .getStructureSelectionManager(av.applet)
820               .sequenceColoursChanged(this);
821
822       if (overviewPanel != null)
823       {
824         overviewPanel.updateOverviewImage();
825       }
826     }
827   }
828
829   public void update(Graphics g)
830   {
831     paint(g);
832   }
833
834   public void paint(Graphics g)
835   {
836     invalidate();
837     Dimension d = idPanel.idCanvas.getSize();
838     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
839
840     if (av.getWrapAlignment())
841     {
842       int maxwidth = av.getAlignment().getWidth();
843
844       if (av.hasHiddenColumns())
845       {
846         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
847       }
848
849       int canvasWidth = seqPanel.seqCanvas
850               .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
851
852       if (canvasWidth > 0)
853       {
854         int max = maxwidth / canvasWidth;
855         vscroll.setMaximum(1 + max);
856         vscroll.setUnitIncrement(1);
857         vscroll.setVisibleAmount(1);
858       }
859     }
860     else
861     {
862       setScrollValues(av.getStartRes(), av.getStartSeq());
863     }
864
865     seqPanel.seqCanvas.repaint();
866     idPanel.idCanvas.repaint();
867     if (!av.getWrapAlignment())
868     {
869       if (av.isShowAnnotation())
870       {
871         alabels.repaint();
872         annotationPanel.repaint();
873       }
874       scalePanel.repaint();
875     }
876
877   }
878
879   protected Panel sequenceHolderPanel = new Panel();
880
881   protected Scrollbar vscroll = new Scrollbar();
882
883   protected Scrollbar hscroll = new Scrollbar();
884
885   protected Panel seqPanelHolder = new Panel();
886
887   BorderLayout borderLayout1 = new BorderLayout();
888
889   BorderLayout borderLayout3 = new BorderLayout();
890
891   protected Panel scalePanelHolder = new Panel();
892
893   protected Panel idPanelHolder = new Panel();
894
895   BorderLayout borderLayout5 = new BorderLayout();
896
897   protected Panel idSpaceFillerPanel1 = new Panel();
898
899   public Panel annotationSpaceFillerHolder = new Panel();
900
901   BorderLayout borderLayout6 = new BorderLayout();
902
903   BorderLayout borderLayout7 = new BorderLayout();
904
905   Panel hscrollHolder = new Panel();
906
907   BorderLayout borderLayout10 = new BorderLayout();
908
909   protected Panel hscrollFillerPanel = new Panel();
910
911   BorderLayout borderLayout11 = new BorderLayout();
912
913   BorderLayout borderLayout4 = new BorderLayout();
914
915   BorderLayout borderLayout2 = new BorderLayout();
916
917   Panel annotationPanelHolder = new Panel();
918
919   protected Scrollbar apvscroll = new Scrollbar();
920
921   BorderLayout borderLayout12 = new BorderLayout();
922
923   private void jbInit() throws Exception
924   {
925     // idPanelHolder.setPreferredSize(new Dimension(70, 10));
926     this.setLayout(borderLayout7);
927
928     // sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
929     sequenceHolderPanel.setLayout(borderLayout3);
930     seqPanelHolder.setLayout(borderLayout1);
931     scalePanelHolder.setBackground(Color.white);
932
933     // scalePanelHolder.setPreferredSize(new Dimension(10, 30));
934     scalePanelHolder.setLayout(borderLayout6);
935     idPanelHolder.setLayout(borderLayout5);
936     idSpaceFillerPanel1.setBackground(Color.white);
937
938     // idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));
939     idSpaceFillerPanel1.setLayout(borderLayout11);
940     annotationSpaceFillerHolder.setBackground(Color.white);
941
942     // annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));
943     annotationSpaceFillerHolder.setLayout(borderLayout4);
944     hscroll.setOrientation(Scrollbar.HORIZONTAL);
945     hscrollHolder.setLayout(borderLayout10);
946     hscrollFillerPanel.setBackground(Color.white);
947     apvscroll.setOrientation(Scrollbar.VERTICAL);
948     apvscroll.setVisible(true);
949     apvscroll.addAdjustmentListener(this);
950
951     annotationPanelHolder.setBackground(Color.white);
952     annotationPanelHolder.setLayout(borderLayout12);
953     annotationPanelHolder.add(apvscroll, BorderLayout.EAST);
954     // hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
955     hscrollHolder.setBackground(Color.white);
956
957     // annotationScroller.setPreferredSize(new Dimension(10, 80));
958     // this.setPreferredSize(new Dimension(220, 166));
959     seqPanelHolder.setBackground(Color.white);
960     idPanelHolder.setBackground(Color.white);
961     sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);
962     sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);
963     seqPanelHolder.add(vscroll, BorderLayout.EAST);
964
965     // Panel3.add(secondaryPanelHolder, BorderLayout.SOUTH);
966     this.add(idPanelHolder, BorderLayout.WEST);
967     idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);
968     idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);
969     this.add(hscrollHolder, BorderLayout.SOUTH);
970     hscrollHolder.add(hscroll, BorderLayout.CENTER);
971     hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);
972     this.add(sequenceHolderPanel, BorderLayout.CENTER);
973   }
974
975   /**
976    * hides or shows dynamic annotation rows based on groups and av state flags
977    */
978   public void updateAnnotation()
979   {
980     updateAnnotation(false);
981   }
982
983   public void updateAnnotation(boolean applyGlobalSettings)
984   {
985     updateAnnotation(applyGlobalSettings, false);
986   }
987
988   public void updateAnnotation(boolean applyGlobalSettings,
989           boolean preserveNewGroupSettings)
990   {
991     av.updateGroupAnnotationSettings(applyGlobalSettings,
992             preserveNewGroupSettings);
993     adjustAnnotationHeight();
994   }
995
996   @Override
997   public AlignmentI getAlignment()
998   {
999     return av.getAlignment();
1000   }
1001
1002   @Override
1003   public String getViewName()
1004   {
1005     return getName();
1006   }
1007
1008   @Override
1009   public StructureSelectionManager getStructureSelectionManager()
1010   {
1011     return StructureSelectionManager
1012             .getStructureSelectionManager(av.applet);
1013   }
1014
1015   @Override
1016   public void raiseOOMWarning(String string, OutOfMemoryError error)
1017   {
1018     // TODO: JAL-960
1019     System.err.println("Out of memory whilst '" + string + "'");
1020     error.printStackTrace();
1021   }
1022
1023 }