2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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.*;
25 import jalview.datamodel.*;
26 import jalview.renderer.AnnotationRenderer;
27 import jalview.renderer.AwtRenderPanelI;
28 import jalview.util.MessageManager;
30 public class AnnotationPanel extends Panel implements AwtRenderPanelI,
31 AdjustmentListener, ActionListener, MouseListener,
42 final String HELIX = "Helix";
44 final String SHEET = "Sheet";
47 * For RNA secondary structure "stems" aka helices
49 final String STEM = "RNA Helix";
51 final String LABEL = "Label";
53 final String REMOVE = "Remove Annotation";
55 final String COLOUR = "Colour";
57 final Color HELIX_COLOUR = Color.red.darker();
59 final Color SHEET_COLOUR = Color.green.darker().darker();
69 boolean fastPaint = false;
71 // Used For mouse Dragging and resizing graphs
72 int graphStretch = -1;
74 int graphStretchY = -1;
76 boolean mouseDragging = false;
78 public static int GRAPH_HEIGHT = 40;
82 public final AnnotationRenderer renderer;
84 public AnnotationPanel(AlignmentPanel ap)
86 MAC = new jalview.util.Platform().isAMac();
90 int height = adjustPanelHeight();
91 ap.apvscroll.setValues(0, getSize().height, 0, height);
93 addMouseMotionListener(this);
95 addMouseListener(this);
97 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
98 renderer = new AnnotationRenderer();
101 public AnnotationPanel(AlignViewport av)
104 renderer = new AnnotationRenderer();
108 public void adjustmentValueChanged(AdjustmentEvent evt)
119 public void actionPerformed(ActionEvent evt)
121 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
126 Annotation[] anot = aa[activeRow].annotations;
128 if (anot.length < av.getColumnSelection().getMax())
130 Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
131 System.arraycopy(anot, 0, temp, 0, anot.length);
133 aa[activeRow].annotations = anot;
137 if (av.getColumnSelection() != null
138 && av.getColumnSelection().size() > 0
139 && anot[av.getColumnSelection().getMin()] != null)
140 label = anot[av.getColumnSelection().getMin()].displayCharacter;
142 if (evt.getActionCommand().equals(REMOVE))
144 for (int i = 0; i < av.getColumnSelection().size(); i++)
146 anot[av.getColumnSelection().columnAt(i)] = null;
149 else if (evt.getActionCommand().equals(LABEL))
151 label = enterLabel(label, "Enter Label");
158 if ((label.length() > 0) && !aa[activeRow].hasText)
160 aa[activeRow].hasText = true;
163 for (int i = 0; i < av.getColumnSelection().size(); i++)
165 int index = av.getColumnSelection().columnAt(i);
167 if (!av.getColumnSelection().isVisible(index))
170 if (anot[index] == null)
172 anot[index] = new Annotation(label, "", ' ', 0);
175 anot[index].displayCharacter = label;
178 else if (evt.getActionCommand().equals(COLOUR))
180 UserDefinedColours udc = new UserDefinedColours(this, Color.black,
183 Color col = udc.getColor();
185 for (int i = 0; i < av.getColumnSelection().size(); i++)
187 int index = av.getColumnSelection().columnAt(i);
189 if (!av.getColumnSelection().isVisible(index))
192 if (anot[index] == null)
194 anot[index] = new Annotation("", "", ' ', 0);
197 anot[index].colour = col;
204 String symbol = "\u03B1";
206 if (evt.getActionCommand().equals(HELIX))
210 else if (evt.getActionCommand().equals(SHEET))
216 // Added by LML to color stems
217 else if (evt.getActionCommand().equals(STEM))
223 if (!aa[activeRow].hasIcons)
225 aa[activeRow].hasIcons = true;
228 label = enterLabel(symbol, "Enter Label");
235 if ((label.length() > 0) && !aa[activeRow].hasText)
237 aa[activeRow].hasText = true;
240 for (int i = 0; i < av.getColumnSelection().size(); i++)
242 int index = av.getColumnSelection().columnAt(i);
244 if (!av.getColumnSelection().isVisible(index))
247 if (anot[index] == null)
249 anot[index] = new Annotation(label, "", type, 0);
252 anot[index].secondaryStructure = type;
253 anot[index].displayCharacter = label;
257 av.getAlignment().validateAnnotation(aa[activeRow]);
259 ap.alignmentChanged();
266 String enterLabel(String text, String label)
268 EditNameDialog dialog = new EditNameDialog(text, null, label, null,
269 ap.alignFrame, "Enter Label", 400, 200, true);
272 return dialog.getName();
278 public void mousePressed(MouseEvent evt)
280 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
286 int height = -scrollOffset;
289 for (int i = 0; i < aa.length; i++)
293 height += aa[i].height;
296 if (evt.getY() < height)
302 else if (aa[i].graph > 0)
306 graphStretchY = evt.getY();
313 if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
316 if (av.getColumnSelection() == null)
321 PopupMenu pop = new PopupMenu(MessageManager.getString("label.structure_type"));
324 * Just display the needed structure options
326 if (av.getAlignment().isNucleotide() == true)
328 item = new MenuItem(STEM);
329 item.addActionListener(this);
334 item = new MenuItem(HELIX);
335 item.addActionListener(this);
337 item = new MenuItem(SHEET);
338 item.addActionListener(this);
341 item = new MenuItem(LABEL);
342 item.addActionListener(this);
344 item = new MenuItem(COLOUR);
345 item.addActionListener(this);
347 item = new MenuItem(REMOVE);
348 item.addActionListener(this);
350 ap.alignFrame.add(pop);
351 pop.show(this, evt.getX(), evt.getY());
361 ap.scalePanel.mousePressed(evt);
365 public void mouseReleased(MouseEvent evt)
369 mouseDragging = false;
373 needValidating = false;
375 ap.scalePanel.mouseReleased(evt);
379 public void mouseClicked(MouseEvent evt)
383 boolean needValidating = false;
386 public void mouseDragged(MouseEvent evt)
388 if (graphStretch > -1)
390 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
392 if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
394 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
396 graphStretchY = evt.getY();
397 av.calcPanelHeight();
398 needValidating = true;
399 ap.paintAlignment(true);
403 ap.scalePanel.mouseDragged(evt);
408 public void mouseMoved(MouseEvent evt)
410 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
417 int height = -scrollOffset;
418 for (int i = 0; i < aa.length; i++)
423 height += aa[i].height;
426 if (evt.getY() < height)
433 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
435 if (av.hasHiddenColumns())
437 res = av.getColumnSelection().adjustForHiddenColumns(res);
440 if (row > -1 && res < aa[row].annotations.length
441 && aa[row].annotations[res] != null)
443 StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
444 if (aa[row].annotations[res].description != null)
446 text.append(" " + aa[row].annotations[res].description);
448 ap.alignFrame.statusBar.setText(text.toString());
453 public void mouseEntered(MouseEvent evt)
455 ap.scalePanel.mouseEntered(evt);
459 public void mouseExited(MouseEvent evt)
461 ap.scalePanel.mouseExited(evt);
464 public int adjustPanelHeight()
466 return adjustPanelHeight(true);
469 public int adjustPanelHeight(boolean repaint)
471 int height = av.calcPanelHeight();
472 this.setSize(new Dimension(getSize().width, height));
481 * calculate the height for visible annotation, revalidating bounds where
482 * necessary ABSTRACT GUI METHOD
484 * @return total height of annotation
487 public void addEditableColumn(int i)
491 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
497 for (int j = 0; j < aa.length; j++)
507 if (activeRes == null)
509 activeRes = new Vector();
510 activeRes.addElement(String.valueOf(i));
514 activeRes.addElement(String.valueOf(i));
518 public void update(Graphics g)
524 public void paint(Graphics g)
526 Dimension d = getSize();
528 // (av.endRes - av.startRes + 1) * av.charWidth;
529 if (imgWidth < 1 || d.height < 1)
533 if (image == null || imgWidth != image.getWidth(this)
534 || d.height != image.getHeight(this))
536 image = createImage(imgWidth, d.height);
537 gg = image.getGraphics();
538 gg.setFont(av.getFont());
539 fm = gg.getFontMetrics();
545 g.drawImage(image, 0, 0, this);
550 gg.setColor(Color.white);
551 gg.fillRect(0, 0, getSize().width, getSize().height);
552 drawComponent(gg, av.startRes, av.endRes + 1);
554 g.drawImage(image, 0, 0, this);
557 public void fastPaint(int horizontal)
560 || av.getAlignment().getAlignmentAnnotation() == null
561 || av.getAlignment().getAlignmentAnnotation().length < 1)
567 gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal
569 int sr = av.startRes, er = av.endRes + 1, transX = 0;
571 if (horizontal > 0) // scrollbar pulled right, image to the left
573 transX = (er - sr - horizontal) * av.charWidth;
574 sr = er - horizontal;
576 else if (horizontal < 0)
578 er = sr - horizontal;
581 gg.translate(transX, 0);
583 drawComponent(gg, sr, er);
585 gg.translate(-transX, 0);
601 public void drawComponent(Graphics g, int startRes, int endRes)
603 Font ofont = av.getFont();
606 g.setColor(Color.white);
607 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
611 fm = g.getFontMetrics();
614 if ((av.getAlignment().getAlignmentAnnotation() == null)
615 || (av.getAlignment().getAlignmentAnnotation().length < 1))
617 g.setColor(Color.white);
618 g.fillRect(0, 0, getSize().width, getSize().height);
619 g.setColor(Color.black);
620 if (av.validCharWidth)
622 g.drawString(MessageManager.getString("label.alignment_has_no_annotations"), 20, 15);
627 g.translate(0, -scrollOffset);
628 renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
629 g.translate(0, +scrollOffset);
632 int scrollOffset = 0;
634 public void setScrollOffset(int value)
636 scrollOffset = value;
641 public FontMetrics getFontMetrics()
647 public Image getFadedImage()
653 public int getFadedImageWidth()
657 private int[] bounds = new int[2];
659 public int[] getVisibleVRange()
661 if (ap!=null && ap.alabels!=null)
663 int sOffset=-ap.alabels.scrollOffset;
664 int visHeight = sOffset+ap.annotationPanelHolder.getHeight();
665 bounds[0] = sOffset; bounds[1]=visHeight;