ec5fbd8e84176b18362e5673d76668744b61eaa8
[jalview.git] / src / jalview / appletgui / AnnotationPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 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.util.*;
23
24 import java.awt.*;
25 import java.awt.event.*;
26
27 import jalview.datamodel.*;
28
29 public class AnnotationPanel
30     extends Panel
31     implements AdjustmentListener, ActionListener, MouseListener, MouseMotionListener
32 {
33   AlignViewport av;
34   AlignmentPanel ap;
35   int activeRow = -1;
36
37   Vector activeRes;
38   static String HELIX = "Helix";
39   static String SHEET = "Sheet";
40   static String LABEL = "Label";
41   static String REMOVE = "Remove Annotation";
42   static String COLOUR = "Colour";
43   static Color HELIX_COLOUR = Color.red.darker();
44   static Color SHEET_COLOUR = Color.green.darker().darker();
45   
46   Image image;
47   Graphics gg;
48   FontMetrics fm;
49   int imgWidth = 0;
50
51   boolean fastPaint = false;
52   public static int GRAPH_HEIGHT = 40;
53
54   boolean MAC = false;
55
56   public AnnotationPanel(AlignmentPanel ap)
57   {
58     MAC = new jalview.util.Platform().isAMac();
59     this.ap = ap;
60     av = ap.av;
61     setLayout(null);
62     adjustPanelHeight();
63
64     addMouseMotionListener(this);
65
66     addMouseListener(this);
67
68
69     // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
70   }
71
72   public AnnotationPanel(AlignViewport av)
73   {
74     this.av = av;
75   }
76
77   public void adjustmentValueChanged(AdjustmentEvent evt)
78   {
79     ap.alabels.setScrollOffset( -evt.getValue());
80   }
81
82   /**
83    * DOCUMENT ME!
84    *
85    * @param evt DOCUMENT ME!
86    */
87   public void actionPerformed(ActionEvent evt)
88   {
89     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
90     Annotation[] anot = aa[activeRow].annotations;
91
92     if (anot.length < av.getColumnSelection().getMax())
93     {
94       Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
95       System.arraycopy(anot, 0, temp, 0, anot.length);
96       anot = temp;
97       aa[activeRow].annotations = anot;
98     }
99
100     String label = "";
101     if (av.colSel != null && av.colSel.size() > 0
102         && anot[av.colSel.getMin()] != null)
103       label = anot[av.getColumnSelection().getMin()].displayCharacter;
104
105
106     if (evt.getActionCommand().equals(REMOVE))
107     {
108       for (int i = 0; i < av.getColumnSelection().size(); i++)
109       {
110         anot[av.getColumnSelection().columnAt(i)] = null;
111       }
112     }
113     else if (evt.getActionCommand().equals(LABEL))
114     {
115       label = enterLabel(label, "Enter Label");
116
117       if (label == null)
118       {
119         return;
120       }
121
122       if ( (label.length() > 0) && !aa[activeRow].hasText)
123       {
124         aa[activeRow].hasText = true;
125       }
126
127       for (int i = 0; i < av.getColumnSelection().size(); i++)
128       {
129         int index = av.getColumnSelection().columnAt(i);
130
131         if(!av.colSel.isVisible(index))
132           continue;
133
134         if (anot[index] == null)
135         {
136           anot[index] = new Annotation(label, "", ' ', 0);
137         }
138
139         anot[index].displayCharacter = label;
140       }
141     }
142     else if (evt.getActionCommand().equals(COLOUR))
143     {
144       UserDefinedColours udc = new UserDefinedColours(
145           this,
146          Color.black, ap.alignFrame);
147
148       Color col = udc.getColor();
149
150       for (int i = 0; i < av.getColumnSelection().size(); i++)
151       {
152         int index = av.getColumnSelection().columnAt(i);
153
154         if(!av.colSel.isVisible(index))
155           continue;
156
157         if (anot[index] == null)
158         {
159           anot[index] = new Annotation("", "", ' ', 0);
160         }
161
162         anot[index].colour = col;
163       }
164     }
165     else // HELIX OR SHEET
166     {
167       char type = 0;
168       String symbol = "\u03B1";
169
170       if (evt.getActionCommand().equals(HELIX))
171       {
172         type = 'H';
173       }
174       else if (evt.getActionCommand().equals(SHEET))
175       {
176         type = 'E';
177         symbol = "\u03B2";
178       }
179
180       if (!aa[activeRow].hasIcons)
181       {
182         aa[activeRow].hasIcons = true;
183       }
184
185       label = enterLabel(symbol, "Enter Label");
186
187       if (label == null)
188       {
189         return;
190       }
191
192       if ( (label.length() > 0) && !aa[activeRow].hasText)
193       {
194         aa[activeRow].hasText = true;
195       }
196
197       for (int i = 0; i < av.getColumnSelection().size(); i++)
198       {
199         int index = av.getColumnSelection().columnAt(i);
200
201         if(!av.colSel.isVisible(index))
202           continue;
203
204         if (anot[index] == null)
205         {
206           anot[index] = new Annotation(label, "", type, 0);
207         }
208
209         anot[index].secondaryStructure = type;
210         anot[index].displayCharacter = label;
211       }
212     }
213
214     adjustPanelHeight();
215     repaint();
216
217     return;
218   }
219
220   String enterLabel(String text, String label)
221   {
222     EditNameDialog dialog = new EditNameDialog(text,null,label,null,
223         ap.alignFrame,"Enter Label", 400,200, true);
224
225     if(dialog.accept)
226       return dialog.getName();
227     else
228       return null;
229   }
230
231   public void mousePressed(MouseEvent evt)
232   {
233       AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
234       if (aa == null)
235       {
236         return;
237       }
238
239       int height = 0;
240       activeRow = -1;
241
242
243       for (int i = 0; i < aa.length; i++)
244       {
245         if (aa[i].visible)
246         {
247           height += aa[i].height;
248         }
249
250         if (evt.getY() < height)
251         {
252           if (aa[i].editable)
253           {
254             activeRow = i;
255           }
256
257           break;
258         }
259       }
260
261       if ( (evt.getModifiers() & InputEvent.BUTTON3_MASK) ==
262         InputEvent.BUTTON3_MASK  && activeRow != -1)
263       {
264         if (av.getColumnSelection() == null)
265         {
266           return;
267         }
268
269         PopupMenu pop = new PopupMenu("Structure type");
270         MenuItem item = new MenuItem(HELIX);
271         item.addActionListener(this);
272         pop.add(item);
273         item = new MenuItem(SHEET);
274         item.addActionListener(this);
275         pop.add(item);
276         item = new MenuItem(LABEL);
277         item.addActionListener(this);
278         pop.add(item);
279         item = new MenuItem(COLOUR);
280         item.addActionListener(this);
281         pop.add(item);
282         item = new MenuItem(REMOVE);
283         item.addActionListener(this);
284         pop.add(item);
285         ap.alignFrame.add(pop);
286         pop.show(this, evt.getX(), evt.getY());
287
288         return;
289       }
290
291       if (aa == null)
292       {
293         return;
294       }
295
296       ap.scalePanel.mousePressed(evt);
297   }
298
299   public void mouseReleased(MouseEvent evt)
300   {
301     ap.scalePanel.mouseReleased(evt);
302   }
303
304   public void mouseClicked(MouseEvent evt)
305   {}
306
307   public void mouseDragged(MouseEvent evt)
308   {
309     ap.scalePanel.mouseDragged(evt);
310   }
311
312   public void mouseMoved(MouseEvent evt)
313   {
314     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
315     if (aa == null)
316     {
317       return;
318     }
319
320     int row = -1;
321     int height = 0;
322     for (int i = 0; i < aa.length; i++)
323     {
324
325       if (aa[i].visible)
326       {
327         height += aa[i].height;
328       }
329
330       if (evt.getY() < height)
331       {
332         row = i;
333         break;
334       }
335     }
336
337     int res = evt.getX() / av.getCharWidth() + av.getStartRes();
338
339     if (av.hasHiddenColumns)
340     {
341       res = av.getColumnSelection().adjustForHiddenColumns(res);
342     }
343
344     if (row > -1 && res < aa[row].annotations.length && aa[row].annotations[res] != null)
345     {
346       StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
347       if (aa[row].annotations[res].description != null)
348       {
349         text.append("  " + aa[row].annotations[res].description);
350       }
351       ap.alignFrame.statusBar.setText(text.toString());
352     }
353   }
354   public void mouseEntered(MouseEvent evt)
355   {
356     ap.scalePanel.mouseEntered(evt);
357   }
358   public void mouseExited(MouseEvent evt)
359   {
360     ap.scalePanel.mouseExited(evt);
361   }
362
363
364   public int adjustPanelHeight()
365   {
366     // setHeight of panels
367     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
368     int height = 0;
369
370     if (aa != null)
371     {
372       for (int i = 0; i < aa.length; i++)
373       {
374         if (!aa[i].visible)
375         {
376           continue;
377         }
378
379         aa[i].height = 0;
380
381         if (aa[i].hasText)
382         {
383           aa[i].height += av.charHeight;
384         }
385
386         if (aa[i].hasIcons)
387         {
388           aa[i].height += 16;
389         }
390
391         if (aa[i].graph > 0)
392         {
393           aa[i].height += aa[i].graphHeight;
394         }
395
396         if (aa[i].height == 0)
397         {
398           aa[i].height = 20;
399         }
400
401         height += aa[i].height;
402       }
403     }
404     else
405     {
406       height = 20;
407     }
408
409     this.setSize(getSize().width, height);
410
411     repaint();
412
413     return height;
414
415   }
416
417   public void addEditableColumn(int i)
418   {
419     if (activeRow == -1)
420     {
421       AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
422       if (aa == null)
423       {
424         return;
425       }
426
427       for (int j = 0; j < aa.length; j++)
428       {
429         if (aa[j].editable)
430         {
431           activeRow = j;
432           break;
433         }
434       }
435     }
436
437     if (activeRes == null)
438     {
439       activeRes = new Vector();
440       activeRes.addElement(String.valueOf(i));
441       return;
442     }
443
444     activeRes.addElement(String.valueOf(i));
445   }
446
447
448   public void update(Graphics g)
449   {
450     paint(g);
451   }
452
453   public void paint(Graphics g)
454   {
455
456     imgWidth = getSize().width;
457     //(av.endRes - av.startRes + 1) * av.charWidth;
458
459     if (image == null || imgWidth != image.getWidth(this))
460     {
461       image = createImage(imgWidth, ap.annotationPanel.getSize().height);
462       gg = image.getGraphics();
463       gg.setFont(av.getFont());
464       fm = gg.getFontMetrics();
465       fastPaint = false;
466     }
467
468     if (fastPaint)
469     {
470       g.drawImage(image, 0, 0, this);
471       fastPaint = false;
472       return;
473     }
474
475     gg.setColor(Color.white);
476     gg.fillRect(0, 0, getSize().width, getSize().height);
477     drawComponent(gg, av.startRes, av.endRes + 1);
478
479     g.drawImage(image, 0, 0, this);
480   }
481
482   public void fastPaint(int horizontal)
483   {
484     if (horizontal == 0
485         || av.alignment.getAlignmentAnnotation() == null
486         || av.alignment.getAlignmentAnnotation().length < 1
487         )
488     {
489       repaint();
490       return;
491     }
492
493     gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal * av.charWidth, 0);
494     int sr = av.startRes, er = av.endRes + 1, transX = 0;
495
496     if (horizontal > 0) // scrollbar pulled right, image to the left
497     {
498       transX = (er - sr - horizontal) * av.charWidth;
499       sr = er - horizontal;
500     }
501     else if (horizontal < 0)
502     {
503       er = sr - horizontal;
504     }
505
506     gg.translate(transX, 0);
507
508     drawComponent(gg, sr, er);
509
510     gg.translate( -transX, 0);
511
512     fastPaint = true;
513     repaint();
514   }
515
516   /**
517    * DOCUMENT ME!
518    *
519    * @param g DOCUMENT ME!
520    * @param startRes DOCUMENT ME!
521    * @param endRes DOCUMENT ME!
522    */
523   public void drawComponent(Graphics g, int startRes, int endRes)
524   {
525     g.setFont(av.getFont());
526
527     g.setColor(Color.white);
528     g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
529
530     if (fm == null)
531     {
532       fm = g.getFontMetrics();
533     }
534
535     if ( (av.alignment.getAlignmentAnnotation() == null) ||
536         (av.alignment.getAlignmentAnnotation().length < 1))
537     {
538       g.setColor(Color.white);
539       g.fillRect(0, 0, getSize().width, getSize().height);
540       g.setColor(Color.black);
541       if (av.validCharWidth)
542       {
543         g.drawString("Alignment has no annotations", 20, 15);
544       }
545
546       return;
547     }
548
549     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
550
551     int x = 0;
552     int y = 0;
553     int column = 0;
554     char lastSS;
555     int lastSSX;
556     int iconOffset = av.charHeight / 2;
557     boolean validRes = false;
558
559     boolean[] graphGroupDrawn = new boolean[aa.length];
560
561     //\u03B2 \u03B1
562     for (int i = 0; i < aa.length; i++)
563     {
564       AlignmentAnnotation row = aa[i];
565
566       if (!row.visible)
567       {
568         continue;
569       }
570
571       lastSS = ' ';
572       lastSSX = 0;
573
574       if (row.graph > 0)
575       {
576         if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])
577         {
578           continue;
579         }
580
581         // this is so that we draw the characters below the graph
582         y += row.height;
583
584         if (row.hasText)
585         {
586           y -= av.charHeight;
587         }
588       }
589
590       if (row.hasText)
591       {
592         iconOffset = av.charHeight / 2;
593       }
594       else
595       {
596         iconOffset = 0;
597       }
598
599       x = 0;
600       while (x < endRes - startRes)
601       {
602         if (av.hasHiddenColumns)
603         {
604           column = av.getColumnSelection().adjustForHiddenColumns(startRes + x);
605           if (column > row.annotations.length - 1)
606           {
607             break;
608           }
609         }
610         else
611         {
612           column = startRes + x;
613         }
614
615         if ( (row.annotations.length <= column) ||
616             (row.annotations[column] == null))
617         {
618           validRes = false;
619         }
620         else
621         {
622           validRes = true;
623         }
624
625         if (activeRow == i)
626         {
627           g.setColor(Color.red);
628
629           if (av.getColumnSelection() != null)
630           {
631             for (int n = 0; n < av.getColumnSelection().size(); n++)
632             {
633               int v = av.getColumnSelection().columnAt(n);
634
635               if (v == column)
636               {
637                 g.fillRect(x * av.charWidth, y,
638                            av.charWidth, av.charHeight);
639               }
640             }
641           }
642         }
643
644
645
646         if (av.validCharWidth && validRes &&
647             (row.annotations[column].displayCharacter!=null && row.annotations[column].displayCharacter.length() > 0))
648         {
649           int charOffset = (av.getCentreColumnLabels()) ? ((av.charWidth -
650                   fm.charsWidth(row.annotations[column].
651                                displayCharacter.toCharArray(),0,
652                                row.annotations[column].
653                                displayCharacter.length())) / 2)
654                                : (av.charWidth - fm.charWidth(row.annotations[column].
655                                        displayCharacter.charAt(0))) / 2;
656
657           if (row.annotations[column].colour == null)
658             g.setColor(Color.black);
659           else
660             g.setColor(row.annotations[column].colour);
661
662           if (column == 0 || row.graph > 0)
663           {
664             g.drawString(row.annotations[column].displayCharacter,
665                          (x * av.charWidth) + charOffset,
666                          y + iconOffset + 3);
667           }
668           else if (
669               row.annotations[column - 1] == null
670               || (!row.annotations[column].displayCharacter.equals(
671                   row.annotations[column - 1].displayCharacter)
672                   ||
673                   (row.annotations[column].displayCharacter.length() < 2 &&
674                    row.annotations[column].secondaryStructure == ' ')))
675           {
676             g.drawString(row.annotations[column].displayCharacter,
677                          (x * av.charWidth) + charOffset,
678                          y + iconOffset + 3);
679           }
680         }
681
682         if (row.hasIcons)
683         {
684           if (!validRes ||
685               (row.annotations[column].secondaryStructure != lastSS))
686           {
687             switch (lastSS)
688             {
689               case 'H':
690                 g.setColor(HELIX_COLOUR);
691                 if (MAC)
692                 {
693                   //Off by 1 offset when drawing rects and ovals
694                   //to offscreen image on the MAC
695                   g.fillRoundRect(lastSSX, y + 4 + iconOffset,
696                                   (x * av.charWidth) - lastSSX, 7, 8, 8);
697                   break;
698                 }
699
700                 int sCol = (lastSSX / av.charWidth) + startRes;
701                 int x1 = lastSSX;
702                 int x2 = (x * av.charWidth);
703
704                 if (sCol == 0 ||
705                     row.annotations[sCol - 1] == null ||
706                     row.annotations[sCol - 1].secondaryStructure != 'H')
707                 {
708                   g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90,
709                             180);
710                   x1 += av.charWidth / 2;
711                 }
712
713                 if (row.annotations[column] == null ||
714                     row.annotations[column].secondaryStructure != 'H')
715                 {
716                   g.fillArc( (x * av.charWidth) - av.charWidth,
717                             y + 4 + iconOffset, av.charWidth, 8, 270, 180);
718                   x2 -= av.charWidth / 2;
719                 }
720
721                 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
722                 break;
723
724               case 'E':
725                 g.setColor(SHEET_COLOUR);
726                 g.fillRect(lastSSX, y + 4 + iconOffset,
727                            (x * av.charWidth) - lastSSX - 4, 7);
728                 g.fillPolygon(new int[]
729                               { (x * av.charWidth) - 4,
730                               (x * av.charWidth) - 4,
731                               (x * av.charWidth)},
732                               new int[]
733                               {
734                               y + iconOffset, y + 14 + iconOffset,
735                               y + 8 + iconOffset
736                 }, 3);
737
738                 break;
739
740               default:
741                 g.setColor(Color.gray);
742                 g.fillRect(lastSSX, y + 6 + iconOffset,
743                            (x * av.charWidth) - lastSSX, 2);
744
745                 break;
746             }
747
748             if (validRes)
749             {
750               lastSS = row.annotations[column].secondaryStructure;
751             }
752             else
753             {
754               lastSS = ' ';
755             }
756
757             lastSSX = (x * av.charWidth);
758           }
759         }
760
761         column++;
762         x++;
763       }
764
765       if (column >= row.annotations.length)
766       {
767         column = row.annotations.length - 1;
768       }
769
770       //  x ++;
771
772       if (row.hasIcons)
773       {
774         switch (lastSS)
775         {
776           case 'H':
777             g.setColor(HELIX_COLOUR);
778             if (MAC)
779             {
780               //Off by 1 offset when drawing rects and ovals
781               //to offscreen image on the MAC
782               g.fillRoundRect(lastSSX, y + 4 + iconOffset,
783                               (x * av.charWidth) - lastSSX, 7, 8, 8);
784               break;
785             }
786
787             int sCol = (lastSSX / av.charWidth) + startRes;
788             int x1 = lastSSX;
789             int x2 = (x * av.charWidth);
790
791             if (sCol == 0 ||
792                 row.annotations[sCol - 1] == null ||
793                 row.annotations[sCol - 1].secondaryStructure != 'H')
794             {
795               g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);
796               x1 += av.charWidth / 2;
797             }
798
799             if (row.annotations[column] == null ||
800                 row.annotations[column].secondaryStructure != 'H')
801             {
802               g.fillArc( (x * av.charWidth) - av.charWidth,
803                         y + 4 + iconOffset, av.charWidth, 8, 270,
804                         180);
805               x2 -= av.charWidth / 2;
806             }
807
808             g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
809
810             break;
811
812           case 'E':
813             g.setColor(SHEET_COLOUR);
814
815             if (row.annotations[endRes] == null
816                 || row.annotations[endRes].secondaryStructure != 'E')
817             {
818               g.fillRect(lastSSX, y + 4 + iconOffset,
819                          (x * av.charWidth) - lastSSX - 4, 7);
820               g.fillPolygon(new int[]
821                             { (x * av.charWidth) - 4,
822                             (x * av.charWidth) - 4,
823                             (x * av.charWidth)},
824                             new int[]
825                             {
826                             y + iconOffset, y + 14 + iconOffset,
827                             y + 7 + iconOffset
828               }, 3);
829             }
830             else
831             {
832               g.fillRect(lastSSX, y + 4 + iconOffset,
833                          x * av.charWidth - lastSSX, 7);
834             }
835             break;
836
837           default:
838             g.setColor(Color.gray);
839             if (!av.wrapAlignment || endRes == av.endRes)
840             {
841               g.fillRect(lastSSX, y + 6 + iconOffset,
842                          (x * av.charWidth) - lastSSX, 2);
843             }
844
845             break;
846         }
847       }
848
849       if (row.graph > 0)
850       {
851         if (row.graph == AlignmentAnnotation.LINE_GRAPH)
852         {
853           if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup])
854           {
855             float groupmax = -999999, groupmin = 9999999;
856             for (int gg = 0; gg < aa.length; gg++)
857             {
858               if (aa[gg].graphGroup != row.graphGroup)
859               {
860                 continue;
861               }
862
863               if (aa[gg] != row)
864               {
865                 aa[gg].visible = false;
866               }
867
868               if (aa[gg].graphMax > groupmax)
869               {
870                 groupmax = aa[gg].graphMax;
871               }
872               if (aa[gg].graphMin < groupmin)
873               {
874                 groupmin = aa[gg].graphMin;
875               }
876             }
877
878             for (int gg = 0; gg < aa.length; gg++)
879             {
880               if (aa[gg].graphGroup == row.graphGroup)
881               {
882                 drawLineGraph(g, aa[gg], startRes, endRes, y,
883                               groupmin, groupmax,
884                               row.graphHeight);
885               }
886             }
887
888             graphGroupDrawn[row.graphGroup] = true;
889           }
890           else
891           {
892             drawLineGraph(g, row, startRes, endRes,
893                           y, row.graphMin, row.graphMax, row.graphHeight);
894           }
895         }
896         else if (row.graph == AlignmentAnnotation.BAR_GRAPH)
897         {
898           drawBarGraph(g, row, startRes, endRes,
899                        row.graphMin, row.graphMax, y);
900         }
901       }
902
903       if (row.graph > 0 && row.hasText)
904       {
905         y += av.charHeight;
906       }
907
908       if (row.graph == 0)
909       {
910         y += aa[i].height;
911       }
912     }
913   }
914
915   public void drawLineGraph(Graphics g, AlignmentAnnotation aa,
916                             int sRes, int eRes,
917                             int y,
918                             float min, float max,
919                             int graphHeight)
920   {
921     if (sRes > aa.annotations.length)
922     {
923       return;
924     }
925
926     int x = 0;
927
928     //Adjustment for fastpaint to left
929     if (eRes < av.endRes)
930     {
931       eRes++;
932     }
933
934     eRes = Math.min(eRes, aa.annotations.length);
935
936     int y1 = y, y2 = y;
937     float range = max - min;
938
939     ////Draw origin
940     if (min < 0)
941     {
942       y2 = y - (int) ( (0 - min / range) * graphHeight);
943     }
944
945     g.setColor(Color.gray);
946     g.drawLine(x - av.charWidth, y2, (eRes - sRes) * av.charWidth, y2);
947
948     eRes = Math.min(eRes, aa.annotations.length);
949
950     int column;
951     int aaMax = aa.annotations.length - 1;
952
953     while (x < eRes - sRes)
954     {
955       column = sRes + x;
956       if (av.hasHiddenColumns)
957       {
958         column = av.getColumnSelection().adjustForHiddenColumns(column);
959       }
960
961       if (column > aaMax)
962       {
963         break;
964       }
965       
966       if (aa.annotations[column] == null) //  || coaa.annotations[column - 1] == null)
967       {
968         x++;
969         continue;
970       }
971
972       if (aa.annotations[column].colour == null)
973         g.setColor(Color.black);
974       else
975         g.setColor(aa.annotations[column].colour);
976       if (column==0 || aa.annotations[column-1]==null)
977       {
978         y1 = y -
979         (int) ( ( (aa.annotations[column].value - min) / range) * graphHeight);
980       } else {
981         y1 = y -
982         (int) ( ( (aa.annotations[column-1].value - min) / range) * graphHeight);        
983       }
984       y2 = y -
985           (int) ( ( (aa.annotations[column].value - min) / range) * graphHeight);
986
987       g.drawLine(x * av.charWidth - av.charWidth / 2, y1,
988                  x * av.charWidth + av.charWidth / 2, y2);
989       x++;
990     }
991
992     if (aa.threshold != null)
993     {
994       g.setColor(aa.threshold.colour);
995
996       y2 = (int) (y - ( (aa.threshold.value - min) / range) * graphHeight);
997       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);
998     }
999   }
1000
1001   public void drawBarGraph(Graphics g, AlignmentAnnotation aa,
1002                            int sRes, int eRes,
1003                            float min, float max,
1004                            int y)
1005   {
1006     if (sRes > aa.annotations.length)
1007     {
1008       return;
1009     }
1010
1011     eRes = Math.min(eRes, aa.annotations.length);
1012
1013     int x = 0, y1 = y, y2 = y;
1014
1015     float range = max - min;
1016
1017     if (min < 0)
1018     {
1019       y2 = y - (int) ( (0 - min / (range)) * aa.graphHeight);
1020     }
1021
1022     g.setColor(Color.gray);
1023
1024     g.drawLine(x, y2, (eRes - sRes) * av.charWidth, y2);
1025
1026     int column;
1027     int aaMax = aa.annotations.length - 1;
1028
1029     while (x < eRes - sRes)
1030     {
1031       column = sRes + x;
1032       if (av.hasHiddenColumns)
1033       {
1034         column = av.getColumnSelection().adjustForHiddenColumns(column);
1035       }
1036
1037       if (column > aaMax)
1038       {
1039         break;
1040       }
1041
1042       if (aa.annotations[column] == null)
1043       {
1044         x++;
1045         continue;
1046       }
1047
1048       if (aa.annotations[column].colour == null)
1049         g.setColor(Color.black);
1050       else
1051         g.setColor(aa.annotations[column].colour);
1052
1053       y1 = y -
1054           (int) ( ( (aa.annotations[column].value - min) / (range)) * aa.graphHeight);
1055
1056       if (y1 - y2 > 0)
1057       {
1058         g.fillRect(x * av.charWidth, y2, av.charWidth, y1 - y2);
1059       }
1060       else
1061       {
1062         g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1);
1063       }
1064
1065       x++;
1066
1067     }
1068     if (aa.threshold != null)
1069     {
1070       g.setColor(aa.threshold.colour);
1071       y2 = (int) (y - ( (aa.threshold.value - min) / range) * aa.graphHeight);
1072       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);
1073     }
1074   }
1075
1076   // used by overview window
1077   public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y,
1078                         int sRes, int eRes)
1079   {
1080     eRes = Math.min(eRes, aa.annotations.length);
1081     g.setColor(Color.white);
1082     g.fillRect(0, 0, width, y);
1083     g.setColor(new Color(0, 0, 180));
1084
1085     int x = 0, height;
1086
1087     for (int j = sRes; j < eRes; j++)
1088     {
1089       if (aa.annotations[j].colour == null)
1090         g.setColor(Color.black);
1091       else
1092         g.setColor(aa.annotations[j].colour);
1093
1094       height = (int) ( (aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT);
1095       if (height > y)
1096       {
1097         height = y;
1098       }
1099       g.fillRect(x, y - height, av.charWidth, height);
1100       x += av.charWidth;
1101     }
1102   }
1103 }