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
19 package jalview.gui;
\r
24 import java.awt.event.*;
\r
25 import java.awt.image.*;
\r
26 import javax.swing.*;
\r
28 import jalview.datamodel.*;
\r
30 public class AnnotationPanel
\r
31 extends JPanel implements MouseListener,
\r
32 MouseMotionListener, ActionListener, AdjustmentListener
\r
34 static String HELIX = "Helix";
\r
35 static String SHEET = "Sheet";
\r
36 static String LABEL = "Label";
\r
37 static String REMOVE = "Remove Annotation";
\r
38 static String COLOUR = "Colour";
\r
39 static Color HELIX_COLOUR = Color.red.darker();
\r
40 static Color SHEET_COLOUR = Color.green.darker().darker();
\r
42 public static int GRAPH_HEIGHT = 40;
\r
47 BufferedImage image;
\r
51 boolean fastPaint = false;
\r
53 public AnnotationPanel(AlignmentPanel ap)
\r
55 ToolTipManager.sharedInstance().registerComponent(this);
\r
56 ToolTipManager.sharedInstance().setInitialDelay(0);
\r
57 ToolTipManager.sharedInstance().setDismissDelay(10000);
\r
60 this.setLayout(null);
\r
61 addMouseListener(this);
\r
62 addMouseMotionListener(this);
\r
63 ap.annotationScroller.getVerticalScrollBar().addAdjustmentListener(this);
\r
66 public void adjustmentValueChanged(AdjustmentEvent evt)
\r
68 ap.alabels.setScrollOffset( -evt.getValue());
\r
71 public void adjustPanelHeight()
\r
73 // setHeight of panels
\r
74 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
79 for (int i = 0; i < aa.length; i++)
\r
90 aa[i].height += av.charHeight;
\r
100 aa[i].height += GRAPH_HEIGHT;
\r
103 if (aa[i].height == 0)
\r
108 height += aa[i].height;
\r
116 this.setPreferredSize(new Dimension(1, height));
\r
120 public void removeEditableColumn(int col)
\r
122 if (activeRow == -1)
\r
124 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
126 for (int j = 0; j < aa.length; j++)
\r
128 if (aa[j].editable)
\r
136 if (activeRes != null && activeRes.contains(String.valueOf(col)))
\r
138 activeRes.removeElement(String.valueOf(col));
\r
144 public void addEditableColumn(int col)
\r
146 if (activeRow == -1)
\r
148 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
150 for (int j = 0; j < aa.length; j++)
\r
152 if (aa[j].editable)
\r
160 if (activeRes == null)
\r
161 activeRes = new Vector();
\r
163 if (!activeRes.contains(String.valueOf(col)))
\r
164 activeRes.addElement(String.valueOf(col));
\r
169 public void actionPerformed(ActionEvent evt)
\r
171 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
172 Annotation[] anot = aa[activeRow].annotations;
\r
174 if (evt.getActionCommand().equals(REMOVE))
\r
176 for (int i = 0; i < activeRes.size(); i++)
\r
178 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
179 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
182 else if (evt.getActionCommand().equals(LABEL))
\r
184 String label = JOptionPane.showInputDialog(this, "Enter Label ",
\r
186 JOptionPane.QUESTION_MESSAGE);
\r
191 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
193 aa[activeRow].hasText = true;
\r
196 for (int i = 0; i < activeRes.size(); i++)
\r
198 int index = Integer.parseInt(activeRes.get(i).toString());
\r
200 if (anot[index] == null)
\r
202 anot[index] = new Annotation(label, "", ' ', 0);
\r
204 anot[index].displayCharacter = label;
\r
207 else if (evt.getActionCommand().equals(COLOUR))
\r
209 Color col = JColorChooser.showDialog(this,
\r
210 "Choose foreground colour",
\r
213 for (int i = 0; i < activeRes.size(); i++)
\r
215 int index = Integer.parseInt(activeRes.get(i).toString());
\r
217 if (anot[index] == null)
\r
219 anot[index] = new Annotation("", "", ' ', 0);
\r
222 anot[index].colour = col;
\r
225 else // HELIX OR SHEET
\r
228 String symbol = "\u03B1";
\r
230 if (evt.getActionCommand().equals(HELIX))
\r
234 else if (evt.getActionCommand().equals(SHEET))
\r
240 if (!aa[activeRow].hasIcons)
\r
242 aa[activeRow].hasIcons = true;
\r
245 String label = JOptionPane.showInputDialog(
\r
246 "Enter a label for the structure?",
\r
252 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
254 aa[activeRow].hasText = true;
\r
257 for (int i = 0; i < activeRes.size(); i++)
\r
259 int index = Integer.parseInt(activeRes.get(i).toString());
\r
261 if (anot[index] == null)
\r
263 anot[index] = new Annotation(label, "", type, 0);
\r
266 anot[index].secondaryStructure = type;
\r
267 anot[index].displayCharacter = label;
\r
271 adjustPanelHeight();
\r
278 public void mousePressed(MouseEvent evt)
\r
282 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
284 for (int i = 0; i < aa.length; i++)
\r
286 height += aa[i].height;
\r
288 if (evt.getY() < height)
\r
290 if (aa[i].editable)
\r
300 if (SwingUtilities.isRightMouseButton(evt))
\r
302 if (activeRes == null)
\r
308 JPopupMenu pop = new JPopupMenu("Structure type");
\r
309 JMenuItem item = new JMenuItem(HELIX);
\r
310 item.addActionListener(this);
\r
312 item = new JMenuItem(SHEET);
\r
313 item.addActionListener(this);
\r
315 item = new JMenuItem(LABEL);
\r
316 item.addActionListener(this);
\r
318 item = new JMenuItem(COLOUR);
\r
319 item.addActionListener(this);
\r
321 item = new JMenuItem(REMOVE);
\r
322 item.addActionListener(this);
\r
324 pop.show(this, evt.getX(), evt.getY());
\r
336 int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
\r
338 if (evt.isControlDown() || evt.isAltDown())
\r
340 addEditableColumn(res);
\r
342 else if (evt.isShiftDown())
\r
344 if (activeRes == null)
\r
346 activeRes = new Vector();
\r
350 int start = Integer.parseInt(activeRes.get(activeRes.size() -
\r
361 for (int n = start; n <= end; n++)
\r
363 addEditableColumn(n);
\r
369 activeRes = new Vector();
\r
370 activeRes.addElement(String.valueOf(res));
\r
376 public void mouseReleased(MouseEvent evt)
\r
380 public void mouseEntered(MouseEvent evt)
\r
384 public void mouseExited(MouseEvent evt)
\r
388 public void mouseDragged(MouseEvent evt)
\r
392 public void mouseMoved(MouseEvent evt)
\r
394 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
404 for (int i = 0; i < aa.length; i++)
\r
408 height += aa[i].height;
\r
411 if (evt.getY() < height)
\r
419 int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
\r
421 if ( (row > -1) && (res < aa[row].annotations.length) &&
\r
422 (aa[row].annotations[res] != null))
\r
424 this.setToolTipText(aa[row].annotations[res].description);
\r
426 StringBuffer text = new StringBuffer("Sequence position " +
\r
428 aa[row].annotations[res].description);
\r
429 ap.alignFrame.statusBar.setText(text.toString());
\r
433 public void mouseClicked(MouseEvent evt)
\r
437 public void paintComponent(Graphics g)
\r
439 g.setColor(Color.white);
\r
440 g.fillRect(0, 0, getWidth(), getHeight());
\r
444 g.drawImage(image, 0, 0, this);
\r
450 imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;
\r
452 image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),
\r
453 BufferedImage.TYPE_INT_RGB);
\r
454 gg = (Graphics2D) image.getGraphics();
\r
455 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
\r
456 RenderingHints.VALUE_ANTIALIAS_ON);
\r
458 gg.setFont(av.getFont());
\r
459 fm = gg.getFontMetrics();
\r
461 drawComponent(gg, av.startRes, av.endRes + 1);
\r
462 g.drawImage(image, 0, 0, this);
\r
465 public void fastPaint(int horizontal)
\r
467 if ( (horizontal == 0) ||
\r
468 (av.alignment.getAlignmentAnnotation() == null) ||
\r
469 (av.alignment.getAlignmentAnnotation().length < 1))
\r
476 gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);
\r
478 int sr = av.startRes;
\r
479 int er = av.endRes + 1;
\r
482 if (horizontal > 0) // scrollbar pulled right, image to the left
\r
484 transX = (er - sr - horizontal) * av.charWidth;
\r
485 sr = er - horizontal;
\r
487 else if (horizontal < 0)
\r
489 er = sr - horizontal;
\r
492 gg.translate(transX, 0);
\r
494 drawComponent(gg, sr, er);
\r
496 gg.translate( -transX, 0);
\r
502 public void drawComponent(Graphics2D g, int startRes, int endRes)
\r
504 g.setColor(Color.white);
\r
505 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());
\r
507 if ( (av.alignment.getAlignmentAnnotation() == null) ||
\r
508 (av.alignment.getAlignmentAnnotation().length < 1))
\r
510 g.setColor(Color.white);
\r
511 g.fillRect(0, 0, getWidth(), getHeight());
\r
512 g.setColor(Color.black);
\r
513 g.drawString("Alignment has no annotations", 20, 15);
\r
518 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
523 char[] lastSS = new char[aa.length];
\r
524 int[] lastSSX = new int[aa.length];
\r
525 int iconOffset = av.charHeight / 2;
\r
526 boolean validRes = false;
\r
529 for (int i = 0; i < aa.length; i++)
\r
531 AlignmentAnnotation row = aa[i];
\r
540 // this is so that we draw the characters below the graph
\r
545 y -= av.charHeight;
\r
551 iconOffset = av.charHeight / 2;
\r
558 for (j = startRes; j < endRes; j++)
\r
560 if ( (row.annotations.length <= j) ||
\r
561 (row.annotations[j] == null))
\r
570 x = (j - startRes) * av.charWidth;
\r
572 if (activeRow == i)
\r
574 g.setColor(Color.red);
\r
576 if (activeRes != null)
\r
578 for (int n = 0; n < activeRes.size(); n++)
\r
580 int v = Integer.parseInt(activeRes.get(n).toString());
\r
584 g.fillRect( (j - startRes) * av.charWidth, y,
\r
585 av.charWidth, row.height);
\r
592 (row.annotations[j].displayCharacter.length() > 0))
\r
594 int charOffset = (av.charWidth -
\r
595 fm.charWidth(row.annotations[j].displayCharacter.
\r
598 g.setColor(row.annotations[j].colour);
\r
602 g.drawString(row.annotations[j].displayCharacter,
\r
603 x, y + iconOffset + 2);
\r
606 ( (row.annotations[j - 1] == null) ||
\r
607 (row.annotations[j].displayCharacter != row.annotations[j -
\r
608 1].displayCharacter)))
\r
610 g.drawString(row.annotations[j].displayCharacter, x,
\r
611 y + iconOffset + 2);
\r
619 (row.annotations[j].secondaryStructure != lastSS[i]))
\r
624 g.setColor(HELIX_COLOUR);
\r
625 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
626 x - lastSSX[i], 7, 8, 8);
\r
631 g.setColor(SHEET_COLOUR);
\r
632 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
633 x - lastSSX[i] - 4, 7);
\r
634 g.fillPolygon(new int[]
\r
638 y + iconOffset, y + 14 + iconOffset,
\r
648 g.setColor(Color.gray);
\r
649 g.fillRect(lastSSX[i], y + 6 + iconOffset,
\r
650 x - lastSSX[i], 2);
\r
657 lastSS[i] = row.annotations[j].secondaryStructure;
\r
668 if (validRes && row.isGraph)
\r
670 g.setColor(new Color(0, 0, 180));
\r
672 int height = (int) ( (row.annotations[j].value / row.graphMax) *
\r
675 if (row.windowLength > 1)
\r
679 for (int i2 = j - (row.windowLength / 2);
\r
680 i2 < (j + (row.windowLength / 2)); i2++)
\r
682 if ( (i2 < 0) || (i2 >= av.alignment.getWidth()))
\r
687 total += row.annotations[i2].value;
\r
690 total /= row.windowLength;
\r
691 height = (int) ( (total / row.graphMax) * GRAPH_HEIGHT);
\r
694 g.setColor(row.annotations[j].colour);
\r
695 g.fillRect(x, y - height, av.charWidth, height);
\r
706 g.setColor(HELIX_COLOUR);
\r
707 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
708 x - lastSSX[i], 7, 8, 8);
\r
713 g.setColor(SHEET_COLOUR);
\r
714 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
715 x - lastSSX[i] - 4, 7);
\r
716 g.fillPolygon(new int[]
\r
720 y + iconOffset, y + 14 + iconOffset,
\r
730 g.setColor(Color.gray);
\r
731 g.fillRect(lastSSX[i], y + 6 + iconOffset, x - lastSSX[i], 2);
\r
737 if (row.isGraph && row.hasText)
\r
739 y += av.charHeight;
\r
749 // used by overview window
\r
750 public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y)
\r
752 g.setColor(Color.white);
\r
753 g.fillRect(0, 0, width, y);
\r
754 g.setColor(new Color(0, 0, 180));
\r
758 for (int j = 0; j < aa.annotations.length; j++)
\r
760 g.setColor(new Color(0, 0, 180));
\r
762 int height = (int) ( (aa.annotations[j].value / aa.graphMax) *
\r
764 g.fillRect(x, y - height, av.charWidth, height);
\r