2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
18 package jalview.appletgui;
23 import java.awt.event.*;
24 import java.awt.image.BufferedImage;
26 import jalview.datamodel.*;
27 import jalview.renderer.AnnotationRenderer;
28 import jalview.renderer.AwtRenderPanelI;
30 public class AnnotationPanel extends Panel implements AwtRenderPanelI, AdjustmentListener,
31 ActionListener, MouseListener, MouseMotionListener
41 final String HELIX = "Helix";
43 final String SHEET = "Sheet";
46 * For RNA secondary structure "stems" aka helices
48 final String STEM = "RNA Helix";
50 final String LABEL = "Label";
52 final String REMOVE = "Remove Annotation";
54 final String COLOUR = "Colour";
56 final Color HELIX_COLOUR = Color.red.darker();
58 final Color SHEET_COLOUR = Color.green.darker().darker();
68 boolean fastPaint = false;
70 // Used For mouse Dragging and resizing graphs
71 int graphStretch = -1;
73 int graphStretchY = -1;
75 boolean mouseDragging = false;
77 public static int GRAPH_HEIGHT = 40;
81 public final AnnotationRenderer renderer;
83 public AnnotationPanel(AlignmentPanel ap)
85 MAC = new jalview.util.Platform().isAMac();
89 int height = adjustPanelHeight();
90 ap.apvscroll.setValues(0, getSize().height, 0, height);
92 addMouseMotionListener(this);
94 addMouseListener(this);
96 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
97 renderer = new AnnotationRenderer();
100 public AnnotationPanel(AlignViewport av)
103 renderer = new AnnotationRenderer();
107 public void adjustmentValueChanged(AdjustmentEvent evt)
118 public void actionPerformed(ActionEvent evt)
120 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
125 Annotation[] anot = aa[activeRow].annotations;
127 if (anot.length < av.getColumnSelection().getMax())
129 Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
130 System.arraycopy(anot, 0, temp, 0, anot.length);
132 aa[activeRow].annotations = anot;
136 if (av.getColumnSelection() != null && av.getColumnSelection().size() > 0
137 && anot[av.getColumnSelection().getMin()] != null)
138 label = anot[av.getColumnSelection().getMin()].displayCharacter;
140 if (evt.getActionCommand().equals(REMOVE))
142 for (int i = 0; i < av.getColumnSelection().size(); i++)
144 anot[av.getColumnSelection().columnAt(i)] = null;
147 else if (evt.getActionCommand().equals(LABEL))
149 label = enterLabel(label, "Enter Label");
156 if ((label.length() > 0) && !aa[activeRow].hasText)
158 aa[activeRow].hasText = true;
161 for (int i = 0; i < av.getColumnSelection().size(); i++)
163 int index = av.getColumnSelection().columnAt(i);
165 if (!av.getColumnSelection().isVisible(index))
168 if (anot[index] == null)
170 anot[index] = new Annotation(label, "", ' ', 0);
173 anot[index].displayCharacter = label;
176 else if (evt.getActionCommand().equals(COLOUR))
178 UserDefinedColours udc = new UserDefinedColours(this, Color.black,
181 Color col = udc.getColor();
183 for (int i = 0; i < av.getColumnSelection().size(); i++)
185 int index = av.getColumnSelection().columnAt(i);
187 if (!av.getColumnSelection().isVisible(index))
190 if (anot[index] == null)
192 anot[index] = new Annotation("", "", ' ', 0);
195 anot[index].colour = col;
202 String symbol = "\u03B1";
204 if (evt.getActionCommand().equals(HELIX))
208 else if (evt.getActionCommand().equals(SHEET))
214 // Added by LML to color stems
215 else if (evt.getActionCommand().equals(STEM))
221 if (!aa[activeRow].hasIcons)
223 aa[activeRow].hasIcons = true;
226 label = enterLabel(symbol, "Enter Label");
233 if ((label.length() > 0) && !aa[activeRow].hasText)
235 aa[activeRow].hasText = true;
238 for (int i = 0; i < av.getColumnSelection().size(); i++)
240 int index = av.getColumnSelection().columnAt(i);
242 if (!av.getColumnSelection().isVisible(index))
245 if (anot[index] == null)
247 anot[index] = new Annotation(label, "", type, 0);
250 anot[index].secondaryStructure = type;
251 anot[index].displayCharacter = label;
255 aa[activeRow].validateRangeAndDisplay();
258 ap.alignmentChanged();
264 String enterLabel(String text, String label)
266 EditNameDialog dialog = new EditNameDialog(text, null, label, null,
267 ap.alignFrame, "Enter Label", 400, 200, true);
270 return dialog.getName();
276 public void mousePressed(MouseEvent evt)
278 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
284 int height = -scrollOffset;
287 for (int i = 0; i < aa.length; i++)
291 height += aa[i].height;
294 if (evt.getY() < height)
300 else if (aa[i].graph > 0)
304 graphStretchY = evt.getY();
311 if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
314 if (av.getColumnSelection() == null)
319 PopupMenu pop = new PopupMenu("Structure type");
322 * Just display the needed structure options
324 if (av.getAlignment().isNucleotide() == true)
326 item = new MenuItem(STEM);
327 item.addActionListener(this);
330 item = new MenuItem(HELIX);
331 item.addActionListener(this);
333 item = new MenuItem(SHEET);
334 item.addActionListener(this);
337 item = new MenuItem(LABEL);
338 item.addActionListener(this);
340 item = new MenuItem(COLOUR);
341 item.addActionListener(this);
343 item = new MenuItem(REMOVE);
344 item.addActionListener(this);
346 ap.alignFrame.add(pop);
347 pop.show(this, evt.getX(), evt.getY());
357 ap.scalePanel.mousePressed(evt);
361 public void mouseReleased(MouseEvent evt)
365 mouseDragging = false;
369 needValidating = false;
371 ap.scalePanel.mouseReleased(evt);
375 public void mouseClicked(MouseEvent evt)
379 boolean needValidating = false;
382 public void mouseDragged(MouseEvent evt)
384 if (graphStretch > -1)
386 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
388 if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
390 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
392 graphStretchY = evt.getY();
394 needValidating = true;
395 ap.paintAlignment(true);
399 ap.scalePanel.mouseDragged(evt);
404 public void mouseMoved(MouseEvent evt)
406 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
413 int height = -scrollOffset;
414 for (int i = 0; i < aa.length; i++)
419 height += aa[i].height;
422 if (evt.getY() < height)
429 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
431 if (av.hasHiddenColumns())
433 res = av.getColumnSelection().adjustForHiddenColumns(res);
436 if (row > -1 && res < aa[row].annotations.length
437 && aa[row].annotations[res] != null)
439 StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
440 if (aa[row].annotations[res].description != null)
442 text.append(" " + aa[row].annotations[res].description);
444 ap.alignFrame.statusBar.setText(text.toString());
449 public void mouseEntered(MouseEvent evt)
451 ap.scalePanel.mouseEntered(evt);
455 public void mouseExited(MouseEvent evt)
457 ap.scalePanel.mouseExited(evt);
460 public int adjustPanelHeight()
462 return adjustPanelHeight(true);
465 public int adjustPanelHeight(boolean repaint)
467 int height = calcPanelHeight();
468 this.setSize(new Dimension(getSize().width, height));
476 * calculate the height for visible annotation, revalidating bounds where necessary
477 * ABSTRACT GUI METHOD
478 * @return total height of annotation
480 public int calcPanelHeight()
482 // setHeight of panels
483 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
488 for (int i = 0; i < aa.length; i++)
499 aa[i].height += av.charHeight;
509 aa[i].height += aa[i].graphHeight;
512 if (aa[i].height == 0)
517 height += aa[i].height;
529 public void addEditableColumn(int i)
533 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
539 for (int j = 0; j < aa.length; j++)
549 if (activeRes == null)
551 activeRes = new Vector();
552 activeRes.addElement(String.valueOf(i));
556 activeRes.addElement(String.valueOf(i));
560 public void update(Graphics g)
566 public void paint(Graphics g)
568 Dimension d = getSize();
570 // (av.endRes - av.startRes + 1) * av.charWidth;
571 if (imgWidth<1 || d.height<1)
575 if (image == null || imgWidth != image.getWidth(this) || d.height != image.getHeight(this))
577 image = createImage(imgWidth, d.height);
578 gg = image.getGraphics();
579 gg.setFont(av.getFont());
580 fm = gg.getFontMetrics();
586 g.drawImage(image, 0, 0, this);
591 gg.setColor(Color.white);
592 gg.fillRect(0, 0, getSize().width, getSize().height);
593 drawComponent(gg, av.startRes, av.endRes + 1);
595 g.drawImage(image, 0, 0, this);
598 public void fastPaint(int horizontal)
600 if (horizontal == 0 || av.getAlignment().getAlignmentAnnotation() == null
601 || av.getAlignment().getAlignmentAnnotation().length < 1)
607 gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal
609 int sr = av.startRes, er = av.endRes + 1, transX = 0;
611 if (horizontal > 0) // scrollbar pulled right, image to the left
613 transX = (er - sr - horizontal) * av.charWidth;
614 sr = er - horizontal;
616 else if (horizontal < 0)
618 er = sr - horizontal;
621 gg.translate(transX, 0);
623 drawComponent(gg, sr, er);
625 gg.translate(-transX, 0);
641 public void drawComponent(Graphics g, int startRes, int endRes)
643 Font ofont = av.getFont();
646 g.setColor(Color.white);
647 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
651 fm = g.getFontMetrics();
654 if ((av.getAlignment().getAlignmentAnnotation() == null)
655 || (av.getAlignment().getAlignmentAnnotation().length < 1))
657 g.setColor(Color.white);
658 g.fillRect(0, 0, getSize().width, getSize().height);
659 g.setColor(Color.black);
660 if (av.validCharWidth)
662 g.drawString("Alignment has no annotations", 20, 15);
667 g.translate(0, -scrollOffset);
668 renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
669 g.translate(0, +scrollOffset);
672 int scrollOffset = 0;
674 public void setScrollOffset(int value)
676 scrollOffset = value;
681 public FontMetrics getFontMetrics()
687 public Image getFadedImage()
693 public int getFadedImageWidth()