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
46 ArrayList activeRes;
\r
47 BufferedImage image;
\r
51 boolean fastPaint = false;
\r
53 public AnnotationPanel(AlignmentPanel ap)
\r
57 this.setLayout(null);
\r
58 addMouseListener(this);
\r
59 addMouseMotionListener(this);
\r
60 adjustPanelHeight();
\r
62 ap.annotationScroller.getVerticalScrollBar().addAdjustmentListener(this);
\r
65 public void adjustmentValueChanged(AdjustmentEvent evt)
\r
67 ap.alabels.setScrollOffset( -evt.getValue());
\r
70 public void adjustPanelHeight()
\r
72 // setHeight of panels
\r
73 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
78 for (int i = 0; i < aa.length; i++)
\r
89 aa[i].height += av.charHeight;
\r
99 aa[i].height += GRAPH_HEIGHT;
\r
102 if (aa[i].height == 0)
\r
107 height += aa[i].height;
\r
115 this.setPreferredSize(new Dimension(1, height));
\r
118 public void addEditableColumn(int i)
\r
120 if (activeRow == -1)
\r
122 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
124 for (int j = 0; j < aa.length; j++)
\r
126 if (aa[j].editable)
\r
135 if (activeRes == null)
\r
137 activeRes = new ArrayList();
\r
138 activeRes.add(String.valueOf(i));
\r
143 activeRes.add(String.valueOf(i));
\r
146 public void actionPerformed(ActionEvent evt)
\r
148 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
149 Annotation[] anot = aa[activeRow].annotations;
\r
151 if (evt.getActionCommand().equals(REMOVE))
\r
153 for (int i = 0; i < activeRes.size(); i++)
\r
155 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
156 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
159 else if (evt.getActionCommand().equals(LABEL))
\r
161 String label = JOptionPane.showInputDialog(this, "Enter Label ",
\r
163 JOptionPane.QUESTION_MESSAGE);
\r
170 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
172 aa[activeRow].hasText = true;
\r
175 for (int i = 0; i < activeRes.size(); i++)
\r
177 int index = Integer.parseInt(activeRes.get(i).toString());
\r
179 if (anot[index] == null)
\r
181 anot[index] = new Annotation(label, "", ' ', 0);
\r
184 anot[index].displayCharacter = label;
\r
187 else if (evt.getActionCommand().equals(COLOUR))
\r
189 Color col = JColorChooser.showDialog(this,
\r
190 "Choose foreground colour",
\r
193 for (int i = 0; i < activeRes.size(); i++)
\r
195 int index = Integer.parseInt(activeRes.get(i).toString());
\r
197 if (anot[index] == null)
\r
199 anot[index] = new Annotation("", "", ' ', 0);
\r
202 anot[index].colour = col;
\r
205 else // HELIX OR SHEET
\r
208 String symbol = "\u03B1";
\r
210 if (evt.getActionCommand().equals(HELIX))
\r
214 else if (evt.getActionCommand().equals(SHEET))
\r
220 if (!aa[activeRow].hasIcons)
\r
222 aa[activeRow].hasIcons = true;
\r
225 String label = JOptionPane.showInputDialog(
\r
226 "Enter a label for the structure?",
\r
234 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
236 aa[activeRow].hasText = true;
\r
239 for (int i = 0; i < activeRes.size(); i++)
\r
241 int index = Integer.parseInt(activeRes.get(i).toString());
\r
243 if (anot[index] == null)
\r
245 anot[index] = new Annotation(label, "", type, 0);
\r
248 anot[index].secondaryStructure = type;
\r
249 anot[index].displayCharacter = label;
\r
253 adjustPanelHeight();
\r
260 public void mousePressed(MouseEvent evt)
\r
262 if (SwingUtilities.isRightMouseButton(evt))
\r
264 if (activeRes == null)
\r
269 JPopupMenu pop = new JPopupMenu("Structure type");
\r
270 JMenuItem item = new JMenuItem(HELIX);
\r
271 item.addActionListener(this);
\r
273 item = new JMenuItem(SHEET);
\r
274 item.addActionListener(this);
\r
276 item = new JMenuItem(LABEL);
\r
277 item.addActionListener(this);
\r
279 item = new JMenuItem(COLOUR);
\r
280 item.addActionListener(this);
\r
282 item = new JMenuItem(REMOVE);
\r
283 item.addActionListener(this);
\r
285 pop.show(this, evt.getX(), evt.getY());
\r
290 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
300 for (int i = 0; i < aa.length; i++)
\r
302 height += aa[i].height;
\r
304 if (evt.getY() < height)
\r
306 if (!aa[i].editable)
\r
319 int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
\r
321 if (evt.isControlDown() || evt.isAltDown())
\r
323 addEditableColumn(res);
\r
325 else if (evt.isShiftDown())
\r
327 if (activeRes == null)
\r
329 activeRes = new ArrayList();
\r
333 int start = Integer.parseInt(activeRes.get(activeRes.size() -
\r
344 for (int n = start; n <= end; n++)
\r
346 addEditableColumn(n);
\r
352 activeRes = new ArrayList();
\r
353 activeRes.add(String.valueOf(res));
\r
359 public void mouseReleased(MouseEvent evt)
\r
363 public void mouseEntered(MouseEvent evt)
\r
367 public void mouseExited(MouseEvent evt)
\r
371 public void mouseDragged(MouseEvent evt)
\r
375 public void mouseMoved(MouseEvent evt)
\r
377 ToolTipManager.sharedInstance().registerComponent(this);
\r
379 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
389 for (int i = 0; i < aa.length; i++)
\r
393 height += aa[i].height;
\r
396 if (evt.getY() < height)
\r
404 int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
\r
406 if ( (row > -1) && (res < aa[row].annotations.length) &&
\r
407 (aa[row].annotations[res] != null))
\r
409 this.setToolTipText(aa[row].annotations[res].description);
\r
411 StringBuffer text = new StringBuffer("Sequence position " +
\r
413 aa[row].annotations[res].description);
\r
414 ap.alignFrame.statusBar.setText(text.toString());
\r
418 public void mouseClicked(MouseEvent evt)
\r
422 public void paintComponent(Graphics g)
\r
424 g.setColor(Color.white);
\r
425 g.fillRect(0, 0, getWidth(), getHeight());
\r
429 g.drawImage(image, 0, 0, this);
\r
435 imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;
\r
437 image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),
\r
438 BufferedImage.TYPE_INT_RGB);
\r
439 gg = (Graphics2D) image.getGraphics();
\r
440 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
\r
441 RenderingHints.VALUE_ANTIALIAS_ON);
\r
443 gg.setFont(av.getFont());
\r
444 fm = gg.getFontMetrics();
\r
446 drawComponent(gg, av.startRes, av.endRes + 1);
\r
447 g.drawImage(image, 0, 0, this);
\r
450 public void fastPaint(int horizontal)
\r
452 if ( (horizontal == 0) ||
\r
453 (av.alignment.getAlignmentAnnotation() == null) ||
\r
454 (av.alignment.getAlignmentAnnotation().length < 1))
\r
461 gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);
\r
463 int sr = av.startRes;
\r
464 int er = av.endRes + 1;
\r
467 if (horizontal > 0) // scrollbar pulled right, image to the left
\r
469 transX = (er - sr - horizontal) * av.charWidth;
\r
470 sr = er - horizontal;
\r
472 else if (horizontal < 0)
\r
474 er = sr - horizontal;
\r
477 gg.translate(transX, 0);
\r
479 drawComponent(gg, sr, er);
\r
481 gg.translate( -transX, 0);
\r
487 public void drawComponent(Graphics2D g, int startRes, int endRes)
\r
489 g.setColor(Color.white);
\r
490 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());
\r
492 if ( (av.alignment.getAlignmentAnnotation() == null) ||
\r
493 (av.alignment.getAlignmentAnnotation().length < 1))
\r
495 g.setColor(Color.white);
\r
496 g.fillRect(0, 0, getWidth(), getHeight());
\r
497 g.setColor(Color.black);
\r
498 g.drawString("Alignment has no annotations", 20, 15);
\r
503 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
508 char[] lastSS = new char[aa.length];
\r
509 int[] lastSSX = new int[aa.length];
\r
510 int iconOffset = av.charHeight / 2;
\r
511 boolean validRes = false;
\r
514 for (int i = 0; i < aa.length; i++)
\r
516 AlignmentAnnotation row = aa[i];
\r
525 // this is so that we draw the characters below the graph
\r
530 y -= av.charHeight;
\r
536 iconOffset = av.charHeight / 2;
\r
543 for (j = startRes; j < endRes; j++)
\r
545 if ( (row.annotations.length <= j) ||
\r
546 (row.annotations[j] == null))
\r
555 x = (j - startRes) * av.charWidth;
\r
557 if (activeRow == i)
\r
559 g.setColor(Color.red);
\r
561 if (activeRes != null)
\r
563 for (int n = 0; n < activeRes.size(); n++)
\r
565 int v = Integer.parseInt(activeRes.get(n).toString());
\r
569 g.fillRect( (j - startRes) * av.charWidth, y,
\r
570 av.charWidth, row.height);
\r
577 (row.annotations[j].displayCharacter.length() > 0))
\r
579 int charOffset = (av.charWidth -
\r
580 fm.charWidth(row.annotations[j].displayCharacter.
\r
583 g.setColor(row.annotations[j].colour);
\r
587 if ( (row.annotations[0].secondaryStructure == 'H') ||
\r
588 (row.annotations[0].secondaryStructure == 'E'))
\r
590 g.drawString(row.annotations[j].displayCharacter,
\r
591 x, y + iconOffset + 2);
\r
594 else if ( ( (row.annotations[j].secondaryStructure == 'H') ||
\r
595 (row.annotations[j].secondaryStructure == 'E')) &&
\r
596 ( (row.annotations[j - 1] == null) ||
\r
597 (row.annotations[j].secondaryStructure != row.annotations[j -
\r
598 1].secondaryStructure)))
\r
600 g.drawString(row.annotations[j].displayCharacter, x,
\r
601 y + iconOffset + 2);
\r
606 g.drawString(row.annotations[j].displayCharacter,
\r
607 x + charOffset, y + iconOffset + 2);
\r
614 (row.annotations[j].secondaryStructure != lastSS[i]))
\r
619 g.setColor(HELIX_COLOUR);
\r
620 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
621 x - lastSSX[i], 7, 8, 8);
\r
626 g.setColor(SHEET_COLOUR);
\r
627 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
628 x - lastSSX[i] - 4, 7);
\r
629 g.fillPolygon(new int[]
\r
633 y + iconOffset, y + 14 + iconOffset,
\r
643 g.setColor(Color.gray);
\r
644 g.fillRect(lastSSX[i], y + 6 + iconOffset,
\r
645 x - lastSSX[i], 2);
\r
652 lastSS[i] = row.annotations[j].secondaryStructure;
\r
663 if (validRes && row.isGraph)
\r
665 g.setColor(new Color(0, 0, 180));
\r
667 int height = (int) ( (row.annotations[j].value / row.graphMax) *
\r
670 if (row.windowLength > 1)
\r
674 for (int i2 = j - (row.windowLength / 2);
\r
675 i2 < (j + (row.windowLength / 2)); i2++)
\r
677 if ( (i2 < 0) || (i2 >= av.alignment.getWidth()))
\r
682 total += row.annotations[i2].value;
\r
685 total /= row.windowLength;
\r
686 height = (int) ( (total / row.graphMax) * GRAPH_HEIGHT);
\r
689 g.setColor(row.annotations[j].colour);
\r
690 g.fillRect(x, y - height, av.charWidth, height);
\r
701 g.setColor(HELIX_COLOUR);
\r
702 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
703 x - lastSSX[i], 7, 8, 8);
\r
708 g.setColor(SHEET_COLOUR);
\r
709 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
710 x - lastSSX[i] - 4, 7);
\r
711 g.fillPolygon(new int[]
\r
715 y + iconOffset, y + 14 + iconOffset,
\r
725 g.setColor(Color.gray);
\r
726 g.fillRect(lastSSX[i], y + 6 + iconOffset, x - lastSSX[i], 2);
\r
732 if (row.isGraph && row.hasText)
\r
734 y += av.charHeight;
\r
744 // used by overview window
\r
745 public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y)
\r
747 g.setColor(Color.white);
\r
748 g.fillRect(0, 0, width, y);
\r
749 g.setColor(new Color(0, 0, 180));
\r
753 for (int j = 0; j < aa.annotations.length; j++)
\r
755 g.setColor(new Color(0, 0, 180));
\r
757 int height = (int) ( (aa.annotations[j].value / aa.graphMax) *
\r
759 g.fillRect(x, y - height, av.charWidth, height);
\r