3 import jalview.datamodel.*;
\r
5 import javax.swing.*;
\r
7 import java.awt.event.*;
\r
9 import java.awt.image.*;
\r
11 public class AnnotationPanel extends JPanel implements MouseListener, MouseMotionListener, ActionListener, AdjustmentListener
\r
17 ArrayList activeRes;
\r
18 static String HELIX ="Helix";
\r
19 static String SHEET ="Sheet";
\r
20 static String LABEL ="Label";
\r
21 static String REMOVE="Remove Annotation";
\r
22 static String COLOUR="Colour";
\r
23 static Color HELIX_COLOUR = Color.red.darker();
\r
24 static Color SHEET_COLOUR = Color.green.darker().darker();
\r
27 BufferedImage image;
\r
32 boolean fastPaint = false;
\r
34 public static int GRAPH_HEIGHT = 40;
\r
38 public AnnotationPanel(AlignmentPanel ap)
\r
42 this.setLayout(null);
\r
43 addMouseListener(this);
\r
44 addMouseMotionListener(this);
\r
45 adjustPanelHeight();
\r
48 ap.annotationScroller.getVerticalScrollBar().addAdjustmentListener( this );
\r
51 public void adjustmentValueChanged(AdjustmentEvent evt)
\r
53 ap.alabels.setScrollOffset( -evt.getValue() );
\r
56 public void adjustPanelHeight()
\r
58 // setHeight of panels
\r
59 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
62 for (int i = 0; i < aa.length; i++)
\r
70 aa[i].height += av.charHeight;
\r
75 aa[i].height += GRAPH_HEIGHT;
\r
79 height += aa[i].height;
\r
82 this.setPreferredSize(new Dimension(1, height));
\r
86 public void addEditableColumn(int i)
\r
90 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
91 for(int j=0; j<aa.length; j++)
\r
101 activeRes = new ArrayList();
\r
102 activeRes.add(String.valueOf(i));
\r
106 activeRes.add(String.valueOf(i));
\r
111 public void actionPerformed(ActionEvent evt)
\r
114 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
115 Annotation [] anot = aa[activeRow].annotations;
\r
117 if(evt.getActionCommand().equals(REMOVE))
\r
119 for(int i=0; i<activeRes.size(); i++)
\r
121 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
122 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
125 else if(evt.getActionCommand().equals(LABEL))
\r
127 String label = JOptionPane.showInputDialog(this, "Enter Label ", "Enter label", JOptionPane.QUESTION_MESSAGE );
\r
131 if(label.length()>0 && !aa[activeRow].hasText)
\r
132 aa[activeRow].hasText = true;
\r
134 for(int i=0; i<activeRes.size(); i++)
\r
136 int index = Integer.parseInt(activeRes.get(i).toString());
\r
137 if(anot[index]==null)
\r
138 anot[index] = new Annotation(label, "", ' ',0);
\r
139 anot[index].displayCharacter = label;
\r
142 else if(evt.getActionCommand().equals(COLOUR))
\r
144 Color col = JColorChooser.showDialog(this, "Choose foreground colour", Color.black);
\r
145 for (int i = 0; i < activeRes.size(); i++)
\r
147 int index = Integer.parseInt(activeRes.get(i).toString());
\r
148 if (anot[index] == null)
\r
149 anot[index] = new Annotation("", "", ' ', 0);
\r
150 anot[index].colour = col;
\r
153 else // HELIX OR SHEET
\r
156 String symbol = "\u03B1";
\r
157 if(evt.getActionCommand().equals(HELIX))
\r
159 else if(evt.getActionCommand().equals(SHEET))
\r
165 if(!aa[activeRow].hasIcons)
\r
166 aa[activeRow].hasIcons = true;
\r
169 String label = JOptionPane.showInputDialog("Enter a label for the structure?", symbol );
\r
173 if(label.length()>0 && !aa[activeRow].hasText)
\r
174 aa[activeRow].hasText = true;
\r
176 for(int i=0; i<activeRes.size(); i++)
\r
178 int index = Integer.parseInt(activeRes.get(i).toString());
\r
179 if (anot[index] == null)
\r
181 anot[index] = new Annotation(label, "", type, 0);
\r
184 anot[ index ].secondaryStructure = type;
\r
185 anot[ index ].displayCharacter = label;
\r
189 adjustPanelHeight();
\r
197 public void mousePressed(MouseEvent evt)
\r
199 if (SwingUtilities.isRightMouseButton(evt))
\r
201 if(activeRes==null)
\r
204 JPopupMenu pop = new JPopupMenu("Structure type");
\r
205 JMenuItem item = new JMenuItem(HELIX);
\r
206 item.addActionListener(this);
\r
208 item = new JMenuItem(SHEET);
\r
209 item.addActionListener(this);
\r
211 item = new JMenuItem(LABEL);
\r
212 item.addActionListener(this);
\r
214 item = new JMenuItem(COLOUR);
\r
215 item.addActionListener(this);
\r
217 item = new JMenuItem(REMOVE);
\r
218 item.addActionListener(this);
\r
220 pop.show(this, evt.getX(), evt.getY());
\r
225 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
231 for(int i=0; i<aa.length; i++)
\r
233 height+= aa[i].height;
\r
235 if(evt.getY()<height)
\r
237 if(!aa[i].editable)
\r
249 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
\r
251 if(evt.isControlDown() || evt.isAltDown())
\r
252 addEditableColumn(res);
\r
254 else if(evt.isShiftDown())
\r
257 if(activeRes==null)
\r
258 activeRes=new ArrayList();
\r
261 int start = Integer.parseInt( activeRes.get( activeRes.size()-1 ).toString() );
\r
269 for(int n=start; n<=end; n++)
\r
270 addEditableColumn(n);
\r
276 activeRes = new ArrayList();
\r
277 activeRes.add( String.valueOf(res) );
\r
283 public void mouseReleased(MouseEvent evt)
\r
285 public void mouseEntered(MouseEvent evt)
\r
287 public void mouseExited(MouseEvent evt)
\r
289 public void mouseDragged(MouseEvent evt)
\r
291 public void mouseMoved(MouseEvent evt)
\r
293 ToolTipManager.sharedInstance().registerComponent(this);
\r
294 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
300 for(int i=0; i<aa.length; i++)
\r
303 if( aa[i].visible )
\r
304 height += aa[i].height;
\r
306 if(evt.getY()<height)
\r
313 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
\r
314 if(row>-1 && res<aa[row].annotations.length && aa[row].annotations[res]!=null)
\r
316 this.setToolTipText(aa[row].annotations[res].description);
\r
317 StringBuffer text = new StringBuffer("Sequence position " + (res + 1) +
\r
319 aa[row].annotations[res].description);
\r
320 ap.alignFrame.statusBar.setText(text.toString());
\r
325 public void mouseClicked(MouseEvent evt) {}
\r
328 public void paintComponent(Graphics g)
\r
330 g.setColor(Color.white);
\r
331 g.fillRect(0,0,getWidth(), getHeight());
\r
335 g.drawImage(image, 0, 0, this);
\r
340 imgWidth = (av.endRes-av.startRes+1) *av.charWidth;
\r
342 image = new BufferedImage(imgWidth,
\r
343 ap.annotationPanel.getHeight(),
\r
344 BufferedImage.TYPE_INT_RGB);
\r
345 gg = (Graphics2D) image.getGraphics();
\r
346 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
\r
347 RenderingHints.VALUE_ANTIALIAS_ON);
\r
348 fm = gg.getFontMetrics();
\r
349 gg.setFont(av.getFont());
\r
351 drawComponent( gg, av.startRes, av.endRes+1);
\r
352 g.drawImage( image, 0, 0, this);
\r
356 public void fastPaint(int horizontal)
\r
358 if( horizontal == 0
\r
359 || av.alignment.getAlignmentAnnotation()==null
\r
360 || av.alignment.getAlignmentAnnotation().length<1
\r
367 gg.copyArea( 0,0, imgWidth, getHeight(), -horizontal*av.charWidth, 0 );
\r
368 int sr=av.startRes, er=av.endRes+1, transX=0;
\r
370 if(horizontal>0) // scrollbar pulled right, image to the left
\r
372 transX = (er-sr-horizontal)*av.charWidth;
\r
373 sr = er - horizontal ;
\r
375 else if(horizontal<0)
\r
377 er = sr-horizontal;
\r
381 gg.translate(transX, 0);
\r
383 drawComponent(gg, sr, er);
\r
385 gg.translate( -transX, 0 );
\r
392 public void drawComponent(Graphics2D g, int startRes, int endRes)
\r
394 g.setColor(Color.white);
\r
395 g.fillRect(0,0,(endRes-startRes) *av.charWidth, getHeight());
\r
396 if(av.alignment.getAlignmentAnnotation()==null || av.alignment.getAlignmentAnnotation().length<1)
\r
398 g.setColor(Color.white);
\r
399 g.fillRect(0,0,getWidth(), getHeight());
\r
400 g.setColor(Color.black);
\r
401 g.drawString("Alignment has no annotations",20,15);
\r
405 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
408 char [] lastSS = new char[aa.length];
\r
409 int [] lastSSX= new int[aa.length] ;
\r
410 int iconOffset = av.charHeight/2;
\r
411 boolean validRes = false;
\r
414 for(int i=0; i<aa.length; i++)
\r
416 AlignmentAnnotation row = aa[i];
\r
422 // this is so that we draw the characters below the graph
\r
425 y -= av.charHeight;
\r
428 iconOffset = av.charHeight/2;
\r
432 for(j=startRes; j<endRes; j++)
\r
434 validRes = row.annotations[j]==null?false:true;
\r
436 x = (j-startRes)*av.charWidth;
\r
442 g.setColor(Color.red);
\r
444 if(activeRes!=null)
\r
445 for (int n = 0; n < activeRes.size(); n++)
\r
447 int v = Integer.parseInt(activeRes.get(n).toString()) ;
\r
449 g.fillRect( (j-startRes) * av.charWidth, y, av.charWidth, row.height);
\r
455 if(validRes && row.annotations[j].displayCharacter.length()>0)
\r
457 int charOffset = (av.charWidth -
\r
458 fm.charWidth(row.annotations[j].displayCharacter.
\r
460 g.setColor( row.annotations[j].colour);
\r
463 if (row.annotations[0].secondaryStructure == 'H'
\r
464 || row.annotations[0].secondaryStructure == 'E')
\r
465 g.drawString(row.annotations[j].displayCharacter, x,
\r
466 y + iconOffset + 2);
\r
468 else if( (row.annotations[j].secondaryStructure=='H'
\r
469 || row.annotations[j].secondaryStructure=='E') &&
\r
470 (row.annotations[j-1]==null ||
\r
471 row.annotations[j].secondaryStructure!=row.annotations[j-1].secondaryStructure))
\r
473 g.drawString(row.annotations[j].displayCharacter, x, y + iconOffset + 2);
\r
476 g.drawString(row.annotations[j].displayCharacter, x + charOffset,
\r
477 y + iconOffset + 2);
\r
481 if(!validRes || row.annotations[j].secondaryStructure!=lastSS[i])
\r
486 g.setColor(HELIX_COLOUR);
\r
487 g.fillRoundRect(lastSSX[i], y+4 + iconOffset, x-lastSSX[i], 7, 8, 8);
\r
490 g.setColor(SHEET_COLOUR);
\r
491 g.fillRect(lastSSX[i], y + 4 + iconOffset, x-lastSSX[i]-4, 7);
\r
492 g.fillPolygon(new int[] {x - 4, x- 4, x }
\r
493 , new int[]{y+ iconOffset, y + 14+ iconOffset, y + 8+ iconOffset}, 3);
\r
498 g.setColor(Color.gray);
\r
499 g.fillRect(lastSSX[i], y+6+ iconOffset, x-lastSSX[i], 2);
\r
504 lastSS[i] = row.annotations[j].secondaryStructure;
\r
510 if (validRes && row.isGraph)
\r
512 g.setColor(new Color(0,0,180));
\r
513 int height = (int)((row.annotations[j].value / row.graphMax)*GRAPH_HEIGHT);
\r
515 if(row.windowLength>1)
\r
518 for(int i2=j- (row.windowLength/2); i2<j+(row.windowLength/2); i2++)
\r
520 if(i2<0 || i2>=av.alignment.getWidth())
\r
523 total += row.annotations[i2].value;
\r
526 total/=row.windowLength;
\r
527 height = (int)( (total / row.graphMax) *GRAPH_HEIGHT);
\r
530 g.setColor(row.annotations[j].colour);
\r
531 g.fillRect(x, y-height, av.charWidth, height );
\r
543 g.setColor(HELIX_COLOUR);
\r
544 g.fillRoundRect(lastSSX[i], y+4+ iconOffset, x - lastSSX[i], 7, 8, 8);
\r
547 g.setColor(SHEET_COLOUR);
\r
548 g.fillRect(lastSSX[i], y + 4+ iconOffset, x - lastSSX[i] - 4, 7);
\r
549 g.fillPolygon(new int[]
\r
552 {y + iconOffset, y + 14+ iconOffset, y + 7+ iconOffset}
\r
558 g.setColor(Color.gray);
\r
559 g.fillRect(lastSSX[i], y+6+ iconOffset, x-lastSSX[i], 2);
\r
564 if(row.isGraph && row.hasText)
\r
571 // used by overview window
\r
572 public void drawGraph(Graphics g, AlignmentAnnotation aa,int width, int y)
\r
574 g.setColor(Color.white);
\r
575 g.fillRect(0,0,width, y);
\r
576 g.setColor(new Color(0,0,180));
\r
578 for(int j=0; j<aa.annotations.length; j++)
\r
580 g.setColor(new Color(0, 0, 180));
\r
581 int height = (int) ( (aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT );
\r
582 g.fillRect(x, y - height, av.charWidth, height);
\r