2 * Jalview - A Sequence Alignment Editor and Viewer
\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
\r
5 * This program is free software; you can redistribute it and/or
\r
6 * modify it under the terms of the GNU General Public License
\r
7 * as published by the Free Software Foundation; either version 2
\r
8 * of the License, or (at your option) any later version.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
15 * You should have received a copy of the GNU General Public License
\r
16 * along with this program; if not, write to the Free Software
\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
\r
20 package jalview.gui;
\r
22 import jalview.datamodel.*;
\r
24 import javax.swing.*;
\r
26 import java.awt.event.*;
\r
28 import java.awt.image.*;
\r
30 public class AnnotationPanel extends JPanel implements MouseListener, MouseMotionListener, ActionListener, AdjustmentListener
\r
36 ArrayList activeRes;
\r
37 static String HELIX ="Helix";
\r
38 static String SHEET ="Sheet";
\r
39 static String LABEL ="Label";
\r
40 static String REMOVE="Remove Annotation";
\r
41 static String COLOUR="Colour";
\r
42 static Color HELIX_COLOUR = Color.red.darker();
\r
43 static Color SHEET_COLOUR = Color.green.darker().darker();
\r
46 BufferedImage image;
\r
51 boolean fastPaint = false;
\r
53 public static int GRAPH_HEIGHT = 40;
\r
57 public AnnotationPanel(AlignmentPanel ap)
\r
61 this.setLayout(null);
\r
62 addMouseListener(this);
\r
63 addMouseMotionListener(this);
\r
64 adjustPanelHeight();
\r
67 ap.annotationScroller.getVerticalScrollBar().addAdjustmentListener( this );
\r
70 public void adjustmentValueChanged(AdjustmentEvent evt)
\r
72 ap.alabels.setScrollOffset( -evt.getValue() );
\r
75 public void adjustPanelHeight()
\r
77 // setHeight of panels
\r
78 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
81 for (int i = 0; i < aa.length; i++)
\r
89 aa[i].height += av.charHeight;
\r
94 aa[i].height += GRAPH_HEIGHT;
\r
98 height += aa[i].height;
\r
101 this.setPreferredSize(new Dimension(1, height));
\r
105 public void addEditableColumn(int i)
\r
109 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
110 for(int j=0; j<aa.length; j++)
\r
118 if(activeRes==null)
\r
120 activeRes = new ArrayList();
\r
121 activeRes.add(String.valueOf(i));
\r
125 activeRes.add(String.valueOf(i));
\r
130 public void actionPerformed(ActionEvent evt)
\r
133 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
134 Annotation [] anot = aa[activeRow].annotations;
\r
136 if(evt.getActionCommand().equals(REMOVE))
\r
138 for(int i=0; i<activeRes.size(); i++)
\r
140 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
141 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
144 else if(evt.getActionCommand().equals(LABEL))
\r
146 String label = JOptionPane.showInputDialog(this, "Enter Label ", "Enter label", JOptionPane.QUESTION_MESSAGE );
\r
150 if(label.length()>0 && !aa[activeRow].hasText)
\r
151 aa[activeRow].hasText = true;
\r
153 for(int i=0; i<activeRes.size(); i++)
\r
155 int index = Integer.parseInt(activeRes.get(i).toString());
\r
156 if(anot[index]==null)
\r
157 anot[index] = new Annotation(label, "", ' ',0);
\r
158 anot[index].displayCharacter = label;
\r
161 else if(evt.getActionCommand().equals(COLOUR))
\r
163 Color col = JColorChooser.showDialog(this, "Choose foreground colour", Color.black);
\r
164 for (int i = 0; i < activeRes.size(); i++)
\r
166 int index = Integer.parseInt(activeRes.get(i).toString());
\r
167 if (anot[index] == null)
\r
168 anot[index] = new Annotation("", "", ' ', 0);
\r
169 anot[index].colour = col;
\r
172 else // HELIX OR SHEET
\r
175 String symbol = "\u03B1";
\r
176 if(evt.getActionCommand().equals(HELIX))
\r
178 else if(evt.getActionCommand().equals(SHEET))
\r
184 if(!aa[activeRow].hasIcons)
\r
185 aa[activeRow].hasIcons = true;
\r
188 String label = JOptionPane.showInputDialog("Enter a label for the structure?", symbol );
\r
192 if(label.length()>0 && !aa[activeRow].hasText)
\r
193 aa[activeRow].hasText = true;
\r
195 for(int i=0; i<activeRes.size(); i++)
\r
197 int index = Integer.parseInt(activeRes.get(i).toString());
\r
198 if (anot[index] == null)
\r
200 anot[index] = new Annotation(label, "", type, 0);
\r
203 anot[ index ].secondaryStructure = type;
\r
204 anot[ index ].displayCharacter = label;
\r
208 adjustPanelHeight();
\r
216 public void mousePressed(MouseEvent evt)
\r
218 if (SwingUtilities.isRightMouseButton(evt))
\r
220 if(activeRes==null)
\r
223 JPopupMenu pop = new JPopupMenu("Structure type");
\r
224 JMenuItem item = new JMenuItem(HELIX);
\r
225 item.addActionListener(this);
\r
227 item = new JMenuItem(SHEET);
\r
228 item.addActionListener(this);
\r
230 item = new JMenuItem(LABEL);
\r
231 item.addActionListener(this);
\r
233 item = new JMenuItem(COLOUR);
\r
234 item.addActionListener(this);
\r
236 item = new JMenuItem(REMOVE);
\r
237 item.addActionListener(this);
\r
239 pop.show(this, evt.getX(), evt.getY());
\r
244 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
250 for(int i=0; i<aa.length; i++)
\r
252 height+= aa[i].height;
\r
254 if(evt.getY()<height)
\r
256 if(!aa[i].editable)
\r
268 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
\r
270 if(evt.isControlDown() || evt.isAltDown())
\r
271 addEditableColumn(res);
\r
273 else if(evt.isShiftDown())
\r
276 if(activeRes==null)
\r
277 activeRes=new ArrayList();
\r
280 int start = Integer.parseInt( activeRes.get( activeRes.size()-1 ).toString() );
\r
288 for(int n=start; n<=end; n++)
\r
289 addEditableColumn(n);
\r
295 activeRes = new ArrayList();
\r
296 activeRes.add( String.valueOf(res) );
\r
302 public void mouseReleased(MouseEvent evt)
\r
304 public void mouseEntered(MouseEvent evt)
\r
306 public void mouseExited(MouseEvent evt)
\r
308 public void mouseDragged(MouseEvent evt)
\r
310 public void mouseMoved(MouseEvent evt)
\r
312 ToolTipManager.sharedInstance().registerComponent(this);
\r
313 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
319 for(int i=0; i<aa.length; i++)
\r
322 if( aa[i].visible )
\r
323 height += aa[i].height;
\r
325 if(evt.getY()<height)
\r
332 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
\r
333 if(row>-1 && res<aa[row].annotations.length && aa[row].annotations[res]!=null)
\r
335 this.setToolTipText(aa[row].annotations[res].description);
\r
336 StringBuffer text = new StringBuffer("Sequence position " + (res + 1) +
\r
338 aa[row].annotations[res].description);
\r
339 ap.alignFrame.statusBar.setText(text.toString());
\r
344 public void mouseClicked(MouseEvent evt) {}
\r
347 public void paintComponent(Graphics g)
\r
349 g.setColor(Color.white);
\r
350 g.fillRect(0,0,getWidth(), getHeight());
\r
354 g.drawImage(image, 0, 0, this);
\r
359 imgWidth = (av.endRes-av.startRes+1) *av.charWidth;
\r
361 image = new BufferedImage(imgWidth,
\r
362 ap.annotationPanel.getHeight(),
\r
363 BufferedImage.TYPE_INT_RGB);
\r
364 gg = (Graphics2D) image.getGraphics();
\r
365 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
\r
366 RenderingHints.VALUE_ANTIALIAS_ON);
\r
368 gg.setFont(av.getFont());
\r
369 fm = gg.getFontMetrics();
\r
371 drawComponent( gg, av.startRes, av.endRes+1);
\r
372 g.drawImage( image, 0, 0, this);
\r
376 public void fastPaint(int horizontal)
\r
378 if( horizontal == 0
\r
379 || av.alignment.getAlignmentAnnotation()==null
\r
380 || av.alignment.getAlignmentAnnotation().length<1
\r
387 gg.copyArea( 0,0, imgWidth, getHeight(), -horizontal*av.charWidth, 0 );
\r
388 int sr=av.startRes, er=av.endRes+1, transX=0;
\r
390 if(horizontal>0) // scrollbar pulled right, image to the left
\r
392 transX = (er-sr-horizontal)*av.charWidth;
\r
393 sr = er - horizontal ;
\r
395 else if(horizontal<0)
\r
397 er = sr-horizontal;
\r
401 gg.translate(transX, 0);
\r
403 drawComponent(gg, sr, er);
\r
405 gg.translate( -transX, 0 );
\r
412 public void drawComponent(Graphics2D g, int startRes, int endRes)
\r
414 g.setColor(Color.white);
\r
415 g.fillRect(0,0,(endRes-startRes) *av.charWidth, getHeight());
\r
416 if(av.alignment.getAlignmentAnnotation()==null || av.alignment.getAlignmentAnnotation().length<1)
\r
418 g.setColor(Color.white);
\r
419 g.fillRect(0,0,getWidth(), getHeight());
\r
420 g.setColor(Color.black);
\r
421 g.drawString("Alignment has no annotations",20,15);
\r
425 AlignmentAnnotation [] aa = av.alignment.getAlignmentAnnotation();
\r
428 char [] lastSS = new char[aa.length];
\r
429 int [] lastSSX= new int[aa.length] ;
\r
430 int iconOffset = av.charHeight/2;
\r
431 boolean validRes = false;
\r
434 for(int i=0; i<aa.length; i++)
\r
436 AlignmentAnnotation row = aa[i];
\r
442 // this is so that we draw the characters below the graph
\r
445 y -= av.charHeight;
\r
448 iconOffset = av.charHeight/2;
\r
452 for(j=startRes; j<endRes; j++)
\r
454 if(row.annotations.length<=j || row.annotations[j]==null)
\r
459 x = (j-startRes)*av.charWidth;
\r
465 g.setColor(Color.red);
\r
467 if(activeRes!=null)
\r
468 for (int n = 0; n < activeRes.size(); n++)
\r
470 int v = Integer.parseInt(activeRes.get(n).toString()) ;
\r
472 g.fillRect( (j-startRes) * av.charWidth, y, av.charWidth, row.height);
\r
478 if(validRes && row.annotations[j].displayCharacter.length()>0)
\r
480 int charOffset = (av.charWidth - fm.charWidth(row.annotations[j].displayCharacter.charAt(0)))/2;
\r
481 g.setColor( row.annotations[j].colour);
\r
484 if (row.annotations[0].secondaryStructure == 'H'
\r
485 || row.annotations[0].secondaryStructure == 'E')
\r
486 g.drawString(row.annotations[j].displayCharacter, x,
\r
487 y + iconOffset + 2);
\r
489 else if( (row.annotations[j].secondaryStructure=='H'
\r
490 || row.annotations[j].secondaryStructure=='E') &&
\r
491 (row.annotations[j-1]==null ||
\r
492 row.annotations[j].secondaryStructure!=row.annotations[j-1].secondaryStructure))
\r
494 g.drawString(row.annotations[j].displayCharacter, x, y + iconOffset + 2);
\r
497 g.drawString(row.annotations[j].displayCharacter, x + charOffset,
\r
498 y + iconOffset + 2);
\r
502 if(!validRes || row.annotations[j].secondaryStructure!=lastSS[i])
\r
507 g.setColor(HELIX_COLOUR);
\r
508 g.fillRoundRect(lastSSX[i], y+4 + iconOffset, x-lastSSX[i], 7, 8, 8);
\r
511 g.setColor(SHEET_COLOUR);
\r
512 g.fillRect(lastSSX[i], y + 4 + iconOffset, x-lastSSX[i]-4, 7);
\r
513 g.fillPolygon(new int[] {x - 4, x- 4, x }
\r
514 , new int[]{y+ iconOffset, y + 14+ iconOffset, y + 8+ iconOffset}, 3);
\r
519 g.setColor(Color.gray);
\r
520 g.fillRect(lastSSX[i], y+6+ iconOffset, x-lastSSX[i], 2);
\r
525 lastSS[i] = row.annotations[j].secondaryStructure;
\r
531 if (validRes && row.isGraph)
\r
533 g.setColor(new Color(0,0,180));
\r
534 int height = (int)((row.annotations[j].value / row.graphMax)*GRAPH_HEIGHT);
\r
536 if(row.windowLength>1)
\r
539 for(int i2=j- (row.windowLength/2); i2<j+(row.windowLength/2); i2++)
\r
541 if(i2<0 || i2>=av.alignment.getWidth())
\r
544 total += row.annotations[i2].value;
\r
547 total/=row.windowLength;
\r
548 height = (int)( (total / row.graphMax) *GRAPH_HEIGHT);
\r
551 g.setColor(row.annotations[j].colour);
\r
552 g.fillRect(x, y-height, av.charWidth, height );
\r
564 g.setColor(HELIX_COLOUR);
\r
565 g.fillRoundRect(lastSSX[i], y+4+ iconOffset, x - lastSSX[i], 7, 8, 8);
\r
568 g.setColor(SHEET_COLOUR);
\r
569 g.fillRect(lastSSX[i], y + 4+ iconOffset, x - lastSSX[i] - 4, 7);
\r
570 g.fillPolygon(new int[]
\r
573 {y + iconOffset, y + 14+ iconOffset, y + 7+ iconOffset}
\r
579 g.setColor(Color.gray);
\r
580 g.fillRect(lastSSX[i], y+6+ iconOffset, x-lastSSX[i], 2);
\r
585 if(row.isGraph && row.hasText)
\r
592 // used by overview window
\r
593 public void drawGraph(Graphics g, AlignmentAnnotation aa,int width, int y)
\r
595 g.setColor(Color.white);
\r
596 g.fillRect(0,0,width, y);
\r
597 g.setColor(new Color(0,0,180));
\r
599 for(int j=0; j<aa.annotations.length; j++)
\r
601 g.setColor(new Color(0, 0, 180));
\r
602 int height = (int) ( (aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT );
\r
603 g.fillRect(x, y - height, av.charWidth, height);
\r