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
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
119 public void addEditableColumn(int i)
\r
121 if (activeRow == -1)
\r
123 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
125 for (int j = 0; j < aa.length; j++)
\r
127 if (aa[j].editable)
\r
136 if (activeRes == null)
\r
138 activeRes = new ArrayList();
\r
139 activeRes.add(String.valueOf(i));
\r
144 activeRes.add(String.valueOf(i));
\r
147 public void actionPerformed(ActionEvent evt)
\r
149 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
150 Annotation[] anot = aa[activeRow].annotations;
\r
152 if (evt.getActionCommand().equals(REMOVE))
\r
154 for (int i = 0; i < activeRes.size(); i++)
\r
156 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
157 anot[Integer.parseInt(activeRes.get(i).toString())] = null;
\r
160 else if (evt.getActionCommand().equals(LABEL))
\r
162 String label = JOptionPane.showInputDialog(this, "Enter Label ",
\r
164 JOptionPane.QUESTION_MESSAGE);
\r
171 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
173 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
180 if (anot[index] == null)
\r
182 anot[index] = new Annotation(label, "", ' ', 0);
\r
185 anot[index].displayCharacter = label;
\r
188 else if (evt.getActionCommand().equals(COLOUR))
\r
190 Color col = JColorChooser.showDialog(this,
\r
191 "Choose foreground colour",
\r
194 for (int i = 0; i < activeRes.size(); i++)
\r
196 int index = Integer.parseInt(activeRes.get(i).toString());
\r
198 if (anot[index] == null)
\r
200 anot[index] = new Annotation("", "", ' ', 0);
\r
203 anot[index].colour = col;
\r
206 else // HELIX OR SHEET
\r
209 String symbol = "\u03B1";
\r
211 if (evt.getActionCommand().equals(HELIX))
\r
215 else if (evt.getActionCommand().equals(SHEET))
\r
221 if (!aa[activeRow].hasIcons)
\r
223 aa[activeRow].hasIcons = true;
\r
226 String label = JOptionPane.showInputDialog(
\r
227 "Enter a label for the structure?",
\r
235 if ( (label.length() > 0) && !aa[activeRow].hasText)
\r
237 aa[activeRow].hasText = true;
\r
240 for (int i = 0; i < activeRes.size(); i++)
\r
242 int index = Integer.parseInt(activeRes.get(i).toString());
\r
244 if (anot[index] == null)
\r
246 anot[index] = new Annotation(label, "", type, 0);
\r
249 anot[index].secondaryStructure = type;
\r
250 anot[index].displayCharacter = label;
\r
254 adjustPanelHeight();
\r
261 public void mousePressed(MouseEvent evt)
\r
265 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
267 for (int i = 0; i < aa.length; i++)
\r
269 height += aa[i].height;
\r
271 if (evt.getY() < height)
\r
273 if (aa[i].editable)
\r
283 if (SwingUtilities.isRightMouseButton(evt))
\r
285 if (activeRes == null)
\r
291 JPopupMenu pop = new JPopupMenu("Structure type");
\r
292 JMenuItem item = new JMenuItem(HELIX);
\r
293 item.addActionListener(this);
\r
295 item = new JMenuItem(SHEET);
\r
296 item.addActionListener(this);
\r
298 item = new JMenuItem(LABEL);
\r
299 item.addActionListener(this);
\r
301 item = new JMenuItem(COLOUR);
\r
302 item.addActionListener(this);
\r
304 item = new JMenuItem(REMOVE);
\r
305 item.addActionListener(this);
\r
307 pop.show(this, evt.getX(), evt.getY());
\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 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
387 for (int i = 0; i < aa.length; i++)
\r
391 height += aa[i].height;
\r
394 if (evt.getY() < height)
\r
402 int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();
\r
404 if ( (row > -1) && (res < aa[row].annotations.length) &&
\r
405 (aa[row].annotations[res] != null))
\r
407 this.setToolTipText(aa[row].annotations[res].description);
\r
409 StringBuffer text = new StringBuffer("Sequence position " +
\r
411 aa[row].annotations[res].description);
\r
412 ap.alignFrame.statusBar.setText(text.toString());
\r
416 public void mouseClicked(MouseEvent evt)
\r
420 public void paintComponent(Graphics g)
\r
422 g.setColor(Color.white);
\r
423 g.fillRect(0, 0, getWidth(), getHeight());
\r
427 g.drawImage(image, 0, 0, this);
\r
433 imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;
\r
435 image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),
\r
436 BufferedImage.TYPE_INT_RGB);
\r
437 gg = (Graphics2D) image.getGraphics();
\r
438 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
\r
439 RenderingHints.VALUE_ANTIALIAS_ON);
\r
441 gg.setFont(av.getFont());
\r
442 fm = gg.getFontMetrics();
\r
444 drawComponent(gg, av.startRes, av.endRes + 1);
\r
445 g.drawImage(image, 0, 0, this);
\r
448 public void fastPaint(int horizontal)
\r
450 if ( (horizontal == 0) ||
\r
451 (av.alignment.getAlignmentAnnotation() == null) ||
\r
452 (av.alignment.getAlignmentAnnotation().length < 1))
\r
459 gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);
\r
461 int sr = av.startRes;
\r
462 int er = av.endRes + 1;
\r
465 if (horizontal > 0) // scrollbar pulled right, image to the left
\r
467 transX = (er - sr - horizontal) * av.charWidth;
\r
468 sr = er - horizontal;
\r
470 else if (horizontal < 0)
\r
472 er = sr - horizontal;
\r
475 gg.translate(transX, 0);
\r
477 drawComponent(gg, sr, er);
\r
479 gg.translate( -transX, 0);
\r
485 public void drawComponent(Graphics2D g, int startRes, int endRes)
\r
487 g.setColor(Color.white);
\r
488 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());
\r
490 if ( (av.alignment.getAlignmentAnnotation() == null) ||
\r
491 (av.alignment.getAlignmentAnnotation().length < 1))
\r
493 g.setColor(Color.white);
\r
494 g.fillRect(0, 0, getWidth(), getHeight());
\r
495 g.setColor(Color.black);
\r
496 g.drawString("Alignment has no annotations", 20, 15);
\r
501 AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
\r
506 char[] lastSS = new char[aa.length];
\r
507 int[] lastSSX = new int[aa.length];
\r
508 int iconOffset = av.charHeight / 2;
\r
509 boolean validRes = false;
\r
512 for (int i = 0; i < aa.length; i++)
\r
514 AlignmentAnnotation row = aa[i];
\r
523 // this is so that we draw the characters below the graph
\r
528 y -= av.charHeight;
\r
534 iconOffset = av.charHeight / 2;
\r
541 for (j = startRes; j < endRes; j++)
\r
543 if ( (row.annotations.length <= j) ||
\r
544 (row.annotations[j] == null))
\r
553 x = (j - startRes) * av.charWidth;
\r
555 if (activeRow == i)
\r
557 g.setColor(Color.red);
\r
559 if (activeRes != null)
\r
561 for (int n = 0; n < activeRes.size(); n++)
\r
563 int v = Integer.parseInt(activeRes.get(n).toString());
\r
567 g.fillRect( (j - startRes) * av.charWidth, y,
\r
568 av.charWidth, row.height);
\r
575 (row.annotations[j].displayCharacter.length() > 0))
\r
577 int charOffset = (av.charWidth -
\r
578 fm.charWidth(row.annotations[j].displayCharacter.
\r
581 g.setColor(row.annotations[j].colour);
\r
585 if ( (row.annotations[0].secondaryStructure == 'H') ||
\r
586 (row.annotations[0].secondaryStructure == 'E'))
\r
588 g.drawString(row.annotations[j].displayCharacter,
\r
589 x, y + iconOffset + 2);
\r
592 else if ( ( (row.annotations[j].secondaryStructure == 'H') ||
\r
593 (row.annotations[j].secondaryStructure == 'E')) &&
\r
594 ( (row.annotations[j - 1] == null) ||
\r
595 (row.annotations[j].secondaryStructure != row.annotations[j -
\r
596 1].secondaryStructure)))
\r
598 g.drawString(row.annotations[j].displayCharacter, x,
\r
599 y + iconOffset + 2);
\r
604 g.drawString(row.annotations[j].displayCharacter,
\r
605 x + charOffset, y + iconOffset + 2);
\r
612 (row.annotations[j].secondaryStructure != lastSS[i]))
\r
617 g.setColor(HELIX_COLOUR);
\r
618 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
619 x - lastSSX[i], 7, 8, 8);
\r
624 g.setColor(SHEET_COLOUR);
\r
625 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
626 x - lastSSX[i] - 4, 7);
\r
627 g.fillPolygon(new int[]
\r
631 y + iconOffset, y + 14 + iconOffset,
\r
641 g.setColor(Color.gray);
\r
642 g.fillRect(lastSSX[i], y + 6 + iconOffset,
\r
643 x - lastSSX[i], 2);
\r
650 lastSS[i] = row.annotations[j].secondaryStructure;
\r
661 if (validRes && row.isGraph)
\r
663 g.setColor(new Color(0, 0, 180));
\r
665 int height = (int) ( (row.annotations[j].value / row.graphMax) *
\r
668 if (row.windowLength > 1)
\r
672 for (int i2 = j - (row.windowLength / 2);
\r
673 i2 < (j + (row.windowLength / 2)); i2++)
\r
675 if ( (i2 < 0) || (i2 >= av.alignment.getWidth()))
\r
680 total += row.annotations[i2].value;
\r
683 total /= row.windowLength;
\r
684 height = (int) ( (total / row.graphMax) * GRAPH_HEIGHT);
\r
687 g.setColor(row.annotations[j].colour);
\r
688 g.fillRect(x, y - height, av.charWidth, height);
\r
699 g.setColor(HELIX_COLOUR);
\r
700 g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,
\r
701 x - lastSSX[i], 7, 8, 8);
\r
706 g.setColor(SHEET_COLOUR);
\r
707 g.fillRect(lastSSX[i], y + 4 + iconOffset,
\r
708 x - lastSSX[i] - 4, 7);
\r
709 g.fillPolygon(new int[]
\r
713 y + iconOffset, y + 14 + iconOffset,
\r
723 g.setColor(Color.gray);
\r
724 g.fillRect(lastSSX[i], y + 6 + iconOffset, x - lastSSX[i], 2);
\r
730 if (row.isGraph && row.hasText)
\r
732 y += av.charHeight;
\r
742 // used by overview window
\r
743 public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y)
\r
745 g.setColor(Color.white);
\r
746 g.fillRect(0, 0, width, y);
\r
747 g.setColor(new Color(0, 0, 180));
\r
751 for (int j = 0; j < aa.annotations.length; j++)
\r
753 g.setColor(new Color(0, 0, 180));
\r
755 int height = (int) ( (aa.annotations[j].value / aa.graphMax) *
\r
757 g.fillRect(x, y - height, av.charWidth, height);
\r