2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
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.
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.
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
20 package jalview.appletgui;
25 import java.awt.event.*;
27 import jalview.datamodel.*;
29 public class AnnotationPanel
30 extends Panel implements AdjustmentListener
37 static String HELIX = "Helix";
38 static String SHEET = "Sheet";
39 static String LABEL = "Label";
40 static String REMOVE = "Remove Annotation";
41 static String COLOUR = "Colour";
42 static Color HELIX_COLOUR = Color.red.darker();
43 static Color SHEET_COLOUR = Color.green.darker().darker();
50 boolean fastPaint = false;
52 public static int GRAPH_HEIGHT = 40;
56 public AnnotationPanel(AlignmentPanel ap)
58 if (System.getProperty("os.name").startsWith("Mac"))
66 addMouseMotionListener(new MouseMotionAdapter()
68 public void mouseMoved(MouseEvent evt)
74 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
78 public AnnotationPanel(AlignViewport av)
84 public void adjustmentValueChanged(AdjustmentEvent evt)
86 ap.alabels.setScrollOffset( -evt.getValue());
89 public int adjustPanelHeight()
91 // setHeight of panels
92 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
98 for (int i = 0; i < aa.length; i++)
109 aa[i].height += av.charHeight;
118 aa[i].height += GRAPH_HEIGHT;
121 if (aa[i].height == 0)
125 height += aa[i].height;
133 this.setSize(getSize().width, height);
141 public void addEditableColumn(int i)
145 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
149 for (int j = 0; j < aa.length; j++)
159 if (activeRes == null)
161 activeRes = new Vector();
162 activeRes.addElement(String.valueOf(i));
166 activeRes.addElement(String.valueOf(i));
169 public void doMouseMoved(MouseEvent evt)
171 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
179 for (int i = 0; i < aa.length; i++)
184 height += aa[i].height;
187 if (evt.getY() < height)
194 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
196 if(av.hasHiddenColumns)
197 res = av.getColumnSelection().adjustForHiddenColumns(res);
199 if (row > -1 && res < aa[row].annotations.length && aa[row].annotations[res] != null)
201 StringBuffer text = new StringBuffer("Sequence position " + (res + 1) +
203 aa[row].annotations[res].description);
204 ap.alignFrame.statusBar.setText(text.toString());
208 public void update(Graphics g)
213 public void paint(Graphics g)
216 imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;
218 if (image == null || imgWidth != image.getWidth(this))
220 image = createImage(imgWidth, ap.annotationPanel.getSize().height);
221 gg = image.getGraphics();
222 gg.setFont(av.getFont());
223 fm = gg.getFontMetrics();
229 g.drawImage(image, 0, 0, this);
234 drawComponent(gg, av.startRes, av.endRes + 1);
235 g.setColor(Color.white);
236 g.fillRect(0, 0, getSize().width, getSize().height);
237 g.drawImage(image, 0, 0, this);
240 public void fastPaint(int horizontal)
243 || av.alignment.getAlignmentAnnotation() == null
244 || av.alignment.getAlignmentAnnotation().length < 1
251 gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal * av.charWidth, 0);
252 int sr = av.startRes, er = av.endRes + 1, transX = 0;
254 if (horizontal > 0) // scrollbar pulled right, image to the left
256 transX = (er - sr - horizontal) * av.charWidth;
257 sr = er - horizontal;
259 else if (horizontal < 0)
261 er = sr - horizontal;
264 gg.translate(transX, 0);
266 drawComponent(gg, sr, er);
268 gg.translate( -transX, 0);
277 * @param g DOCUMENT ME!
278 * @param startRes DOCUMENT ME!
279 * @param endRes DOCUMENT ME!
281 public void drawComponent(Graphics g, int startRes, int endRes)
283 g.setFont(av.getFont());
286 fm = g.getFontMetrics();
289 g.setColor(Color.white);
290 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
292 if ((av.alignment.getAlignmentAnnotation() == null) ||
293 (av.alignment.getAlignmentAnnotation().length < 1))
295 g.setColor(Color.white);
296 g.fillRect(0, 0, getSize().width, getSize().height);
297 g.setColor(Color.black);
298 if(av.validCharWidth)
299 g.drawString("Alignment has no annotations", 20, 15);
304 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
311 int iconOffset = av.charHeight / 2;
312 boolean validRes = false;
314 boolean [] graphGroupDrawn = new boolean[aa.length];
318 for (int i = 0; i < aa.length; i++)
320 AlignmentAnnotation row = aa[i];
332 if(row.graphGroup>-1 && graphGroupDrawn[ row.graphGroup ] )
335 // this is so that we draw the characters below the graph
346 iconOffset = av.charHeight / 2;
354 while(x < endRes-startRes)
356 if (av.hasHiddenColumns)
358 column = av.getColumnSelection().adjustForHiddenColumns(startRes+x);
359 if (column > row.annotations.length-1)
367 if ( (row.annotations.length <= column) ||
368 (row.annotations[column] == null))
378 if (av.validCharWidth && validRes &&
379 (row.annotations[column].displayCharacter.length() > 0))
381 int charOffset = (av.charWidth -
382 fm.charWidth(row.annotations[column].displayCharacter.charAt(
384 g.setColor(row.annotations[column].colour);
386 if (column == 0 || row.graph>0)
388 g.drawString(row.annotations[column].displayCharacter,
389 (x*av.charWidth)+charOffset,
393 row.annotations[column - 1] == null
394 ||(!row.annotations[column].displayCharacter.equals(
395 row.annotations[column - 1].displayCharacter)
397 (row.annotations[column].displayCharacter.length() <2 &&
398 row.annotations[column].secondaryStructure==' ')))
400 g.drawString(row.annotations[column].displayCharacter,
401 (x*av.charWidth)+charOffset,
409 (row.annotations[column].secondaryStructure != lastSS))
414 g.setColor(HELIX_COLOUR);
417 //Off by 1 offset when drawing rects and ovals
418 //to offscreen image on the MAC
419 g.fillRoundRect(lastSSX, y + 4 + iconOffset,
420 (x*av.charWidth) - lastSSX, 7, 8, 8);
424 int sCol = (lastSSX / av.charWidth) + startRes;
426 int x2 = (x*av.charWidth);
429 row.annotations[sCol-1]==null ||
430 row.annotations[sCol-1].secondaryStructure!='H')
432 g.fillArc(lastSSX, y+4+iconOffset, av.charWidth, 8, 90,180) ;
433 x1 += av.charWidth/2;
436 if(row.annotations[column]==null ||
437 row.annotations[column].secondaryStructure!='H')
439 g.fillArc((x*av.charWidth)-av.charWidth,
440 y+4+iconOffset, av.charWidth, 8, 270,180);
441 x2 -= av.charWidth/2;
444 g.fillRect(x1, y+4+iconOffset, x2-x1, 8);
448 g.setColor(SHEET_COLOUR);
449 g.fillRect(lastSSX, y + 4 + iconOffset,
450 (x*av.charWidth) - lastSSX - 4, 7);
451 g.fillPolygon(new int[] { (x*av.charWidth) - 4,
452 (x*av.charWidth) - 4,
456 y + iconOffset, y + 14 + iconOffset,
464 g.setColor(Color.gray);
465 g.fillRect(lastSSX, y + 6 + iconOffset,
466 (x*av.charWidth) - lastSSX, 2);
473 lastSS = row.annotations[column].secondaryStructure;
480 lastSSX = (x*av.charWidth);
489 if(column>=row.annotations.length)
490 column = row.annotations.length-1;
499 g.setColor(HELIX_COLOUR);
502 //Off by 1 offset when drawing rects and ovals
503 //to offscreen image on the MAC
504 g.fillRoundRect(lastSSX, y + 4 + iconOffset,
505 (x*av.charWidth) - lastSSX, 7, 8, 8);
509 int sCol = (lastSSX / av.charWidth) + startRes;
511 int x2 = (x*av.charWidth);
514 row.annotations[sCol - 1] == null ||
515 row.annotations[sCol - 1].secondaryStructure != 'H')
517 g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);
518 x1 += av.charWidth / 2;
521 if (row.annotations[column] == null ||
522 row.annotations[column].secondaryStructure != 'H')
524 g.fillArc((x*av.charWidth) - av.charWidth,
525 y + 4 + iconOffset, av.charWidth, 8, 270,
527 x2 -= av.charWidth / 2;
530 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
535 g.setColor(SHEET_COLOUR);
537 if (row.annotations[endRes] == null
538 || row.annotations[endRes].secondaryStructure != 'E')
540 g.fillRect(lastSSX, y + 4 + iconOffset,
541 (x*av.charWidth) - lastSSX - 4, 7);
542 g.fillPolygon(new int[]
543 {(x*av.charWidth) - 4,
544 (x*av.charWidth) - 4,
548 y + iconOffset, y + 14 + iconOffset,
554 g.fillRect(lastSSX, y + 4 + iconOffset,
555 (x+1) * av.charWidth - lastSSX, 7);
560 g.setColor(Color.gray);
561 if(!av.wrapAlignment || endRes==av.endRes)
562 g.fillRect(lastSSX, y + 6 + iconOffset,
563 (x*av.charWidth) - lastSSX, 2);
571 if(row.graph == AlignmentAnnotation.LINE_GRAPH )
573 if(row.graphGroup>-1 && !graphGroupDrawn[row.graphGroup])
575 float groupmax=-999999, groupmin=9999999;
576 for(int gg=0; gg<aa.length; gg++)
578 if(aa[gg].graphGroup!=row.graphGroup)
582 aa[gg].visible = false;
584 if(aa[gg].graphMax>groupmax)
585 groupmax = aa[gg].graphMax;
586 if(aa[gg].graphMin<groupmin)
587 groupmin = aa[gg].graphMin;
590 for (int gg = 0; gg < aa.length; gg++)
592 if (aa[gg].graphGroup == row.graphGroup)
594 drawLineGraph(g, aa[gg], startRes, endRes, y,
600 graphGroupDrawn[ row.graphGroup ] = true;
603 drawLineGraph(g, row, startRes, endRes,
604 y, row.graphMin, row.graphMax, row.graphHeight );
606 else if(row.graph == AlignmentAnnotation.BAR_GRAPH )
607 drawBarGraph(g, row, startRes, endRes,
608 row.graphMin, row.graphMax, y);
611 if (row.graph>0 && row.hasText)
623 public void drawLineGraph(Graphics g, AlignmentAnnotation aa,
626 float min, float max,
629 if(sRes>aa.annotations.length)
636 //Adjustment for fastpaint to left
640 eRes = Math.min(eRes, aa.annotations.length);
650 float range = max - min;
654 y2 = y - (int)((0-min / range)*graphHeight);
656 g.setColor(Color.gray);
657 g.drawLine(x-av.charWidth,y2,(eRes-sRes)*av.charWidth,y2);
659 eRes = Math.min(eRes, aa.annotations.length);
662 int aaMax = aa.annotations.length-1;
664 while( x < eRes - sRes )
667 if(av.hasHiddenColumns)
669 column = av.getColumnSelection().adjustForHiddenColumns(column);
677 if(aa.annotations[column]==null || aa.annotations[column-1]==null)
683 g.setColor(aa.annotations[column].colour);
684 y1 = y - (int) (((aa.annotations[column-1].value-min) / range) * graphHeight);
685 y2 = y - (int) (((aa.annotations[column].value-min) / range) * graphHeight);
687 g.drawLine(x*av.charWidth-av.charWidth/2, y1, x*av.charWidth+av.charWidth/2, y2);
691 if(aa.threshold!=null)
693 g.setColor(aa.threshold.colour);
695 y2 = (int)(y - ((aa.threshold.value-min) / range)*graphHeight);
696 g.drawLine(0,y2,(eRes-sRes)*av.charWidth,y2);
700 public void drawBarGraph(Graphics g, AlignmentAnnotation aa,
702 float min, float max,
705 if(sRes>aa.annotations.length)
708 eRes = Math.min(eRes, aa.annotations.length);
712 float range = max - min;
715 y2 = y - (int)((0-min / (range))*aa.graphHeight);
717 g.setColor(Color.gray);
719 g.drawLine(x,y2,(eRes-sRes)*av.charWidth,y2);
722 int aaMax = aa.annotations.length-1;
724 while( x < eRes-sRes )
727 if(av.hasHiddenColumns)
729 column = av.getColumnSelection().adjustForHiddenColumns(column);
737 if (aa.annotations[column] == null)
743 g.setColor(aa.annotations[column].colour);
744 y1 = y - (int) (((aa.annotations[column].value-min) / (range)) * aa.graphHeight);
747 g.fillRect(x*av.charWidth, y2, av.charWidth, y1-y2 );
749 g.fillRect(x*av.charWidth, y1, av.charWidth, y2-y1 );
754 if(aa.threshold!=null)
756 g.setColor(aa.threshold.colour);
757 y2 = (int)(y - ((aa.threshold.value-min) / range)*aa.graphHeight);
758 g.drawLine(0,y2,(eRes-sRes)*av.charWidth,y2);
762 // used by overview window
763 public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y, int sRes, int eRes)
765 g.setColor(Color.white);
766 g.fillRect(0, 0, width, y);
767 g.setColor(new Color(0, 0, 180));
771 for (int j = sRes; j < eRes; j++)
773 g.setColor(aa.annotations[j].colour);
775 height = (int) ((aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT);
778 g.fillRect(x, y - height, av.charWidth, height);