2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.appletgui;
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.Annotation;
25 import jalview.renderer.AnnotationRenderer;
26 import jalview.renderer.AwtRenderPanelI;
27 import jalview.util.MessageManager;
29 import java.awt.Color;
30 import java.awt.Dimension;
32 import java.awt.FontMetrics;
33 import java.awt.Graphics;
34 import java.awt.Image;
35 import java.awt.MenuItem;
36 import java.awt.Panel;
37 import java.awt.PopupMenu;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.AdjustmentEvent;
41 import java.awt.event.AdjustmentListener;
42 import java.awt.event.InputEvent;
43 import java.awt.event.MouseEvent;
44 import java.awt.event.MouseListener;
45 import java.awt.event.MouseMotionListener;
47 public class AnnotationPanel extends Panel implements AwtRenderPanelI,
48 AdjustmentListener, ActionListener, MouseListener,
57 final String HELIX = "Helix";
59 final String SHEET = "Sheet";
62 * For RNA secondary structure "stems" aka helices
64 final String STEM = "RNA Helix";
66 final String LABEL = "Label";
68 final String REMOVE = "Remove Annotation";
70 final String COLOUR = "Colour";
72 final Color HELIX_COLOUR = Color.red.darker();
74 final Color SHEET_COLOUR = Color.green.darker().darker();
84 boolean fastPaint = false;
86 // Used For mouse Dragging and resizing graphs
87 int graphStretch = -1;
89 int graphStretchY = -1;
91 boolean mouseDragging = false;
93 public static int GRAPH_HEIGHT = 40;
97 public final AnnotationRenderer renderer;
99 public AnnotationPanel(AlignmentPanel ap)
101 MAC = new jalview.util.Platform().isAMac();
105 int height = adjustPanelHeight();
106 ap.apvscroll.setValues(0, getSize().height, 0, height);
108 addMouseMotionListener(this);
110 addMouseListener(this);
112 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
113 renderer = new AnnotationRenderer();
116 public AnnotationPanel(AlignViewport av)
119 renderer = new AnnotationRenderer();
123 public void adjustmentValueChanged(AdjustmentEvent evt)
134 public void actionPerformed(ActionEvent evt)
136 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
141 Annotation[] anot = aa[activeRow].annotations;
143 if (anot.length < av.getColumnSelection().getMax())
145 Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
146 System.arraycopy(anot, 0, temp, 0, anot.length);
148 aa[activeRow].annotations = anot;
152 if (av.getColumnSelection() != null
153 && av.getColumnSelection().size() > 0
154 && anot[av.getColumnSelection().getMin()] != null)
156 label = anot[av.getColumnSelection().getMin()].displayCharacter;
159 if (evt.getActionCommand().equals(REMOVE))
161 for (int i = 0; i < av.getColumnSelection().size(); i++)
163 anot[av.getColumnSelection().columnAt(i)] = null;
166 else if (evt.getActionCommand().equals(LABEL))
168 label = enterLabel(label, "Enter Label");
175 if ((label.length() > 0) && !aa[activeRow].hasText)
177 aa[activeRow].hasText = true;
180 for (int i = 0; i < av.getColumnSelection().size(); i++)
182 int index = av.getColumnSelection().columnAt(i);
184 if (!av.getColumnSelection().isVisible(index))
189 if (anot[index] == null)
191 anot[index] = new Annotation(label, "", ' ', 0);
194 anot[index].displayCharacter = label;
197 else if (evt.getActionCommand().equals(COLOUR))
199 UserDefinedColours udc = new UserDefinedColours(this, Color.black,
202 Color col = udc.getColor();
204 for (int i = 0; i < av.getColumnSelection().size(); i++)
206 int index = av.getColumnSelection().columnAt(i);
208 if (!av.getColumnSelection().isVisible(index))
213 if (anot[index] == null)
215 anot[index] = new Annotation("", "", ' ', 0);
218 anot[index].colour = col;
225 String symbol = "\u03B1";
227 if (evt.getActionCommand().equals(HELIX))
231 else if (evt.getActionCommand().equals(SHEET))
237 // Added by LML to color stems
238 else if (evt.getActionCommand().equals(STEM))
244 if (!aa[activeRow].hasIcons)
246 aa[activeRow].hasIcons = true;
249 label = enterLabel(symbol, "Enter Label");
256 if ((label.length() > 0) && !aa[activeRow].hasText)
258 aa[activeRow].hasText = true;
259 if (evt.getActionCommand().equals(STEM))
261 aa[activeRow].showAllColLabels = true;
265 for (int i = 0; i < av.getColumnSelection().size(); i++)
267 int index = av.getColumnSelection().columnAt(i);
269 if (!av.getColumnSelection().isVisible(index))
274 if (anot[index] == null)
276 anot[index] = new Annotation(label, "", type, 0);
279 anot[index].secondaryStructure = type != 'S' ? type : label
280 .length() == 0 ? ' ' : label.charAt(0);
281 anot[index].displayCharacter = label;
285 av.getAlignment().validateAnnotation(aa[activeRow]);
287 ap.alignmentChanged();
294 String enterLabel(String text, String label)
296 EditNameDialog dialog = new EditNameDialog(text, null, label, null,
297 ap.alignFrame, "Enter Label", 400, 200, true);
301 return dialog.getName();
310 public void mousePressed(MouseEvent evt)
312 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
318 int height = -scrollOffset;
321 for (int i = 0; i < aa.length; i++)
325 height += aa[i].height;
328 if (evt.getY() < height)
334 else if (aa[i].graph > 0)
338 graphStretchY = evt.getY();
345 if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
348 if (av.getColumnSelection() == null)
353 PopupMenu pop = new PopupMenu(
354 MessageManager.getString("label.structure_type"));
357 * Just display the needed structure options
359 if (av.getAlignment().isNucleotide() == true)
361 item = new MenuItem(STEM);
362 item.addActionListener(this);
367 item = new MenuItem(HELIX);
368 item.addActionListener(this);
370 item = new MenuItem(SHEET);
371 item.addActionListener(this);
374 item = new MenuItem(LABEL);
375 item.addActionListener(this);
377 item = new MenuItem(COLOUR);
378 item.addActionListener(this);
380 item = new MenuItem(REMOVE);
381 item.addActionListener(this);
383 ap.alignFrame.add(pop);
384 pop.show(this, evt.getX(), evt.getY());
389 ap.scalePanel.mousePressed(evt);
393 public void mouseReleased(MouseEvent evt)
397 mouseDragging = false;
401 needValidating = false;
403 ap.scalePanel.mouseReleased(evt);
407 public void mouseClicked(MouseEvent evt)
411 boolean needValidating = false;
414 public void mouseDragged(MouseEvent evt)
416 if (graphStretch > -1)
418 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
420 if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
422 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
424 graphStretchY = evt.getY();
425 av.calcPanelHeight();
426 needValidating = true;
427 ap.paintAlignment(true);
431 ap.scalePanel.mouseDragged(evt);
436 public void mouseMoved(MouseEvent evt)
438 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
445 int height = -scrollOffset;
446 for (int i = 0; i < aa.length; i++)
451 height += aa[i].height;
454 if (evt.getY() < height)
461 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
463 if (av.hasHiddenColumns())
465 res = av.getColumnSelection().adjustForHiddenColumns(res);
468 if (row > -1 && res < aa[row].annotations.length
469 && aa[row].annotations[res] != null)
471 StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
472 if (aa[row].annotations[res].description != null)
474 text.append(" " + aa[row].annotations[res].description);
476 ap.alignFrame.statusBar.setText(text.toString());
481 public void mouseEntered(MouseEvent evt)
483 ap.scalePanel.mouseEntered(evt);
487 public void mouseExited(MouseEvent evt)
489 ap.scalePanel.mouseExited(evt);
492 public int adjustPanelHeight()
494 return adjustPanelHeight(true);
497 public int adjustPanelHeight(boolean repaint)
499 int height = av.calcPanelHeight();
500 this.setSize(new Dimension(getSize().width, height));
509 * calculate the height for visible annotation, revalidating bounds where
510 * necessary ABSTRACT GUI METHOD
512 * @return total height of annotation
515 public void addEditableColumn(int i)
519 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
525 for (int j = 0; j < aa.length; j++)
537 public void update(Graphics g)
543 public void paint(Graphics g)
545 Dimension d = getSize();
547 // (av.endRes - av.startRes + 1) * av.charWidth;
548 if (imgWidth < 1 || d.height < 1)
552 if (image == null || imgWidth != image.getWidth(this)
553 || d.height != image.getHeight(this))
555 image = createImage(imgWidth, d.height);
556 gg = image.getGraphics();
557 gg.setFont(av.getFont());
558 fm = gg.getFontMetrics();
564 g.drawImage(image, 0, 0, this);
569 gg.setColor(Color.white);
570 gg.fillRect(0, 0, getSize().width, getSize().height);
571 drawComponent(gg, av.startRes, av.endRes + 1);
573 g.drawImage(image, 0, 0, this);
576 public void fastPaint(int horizontal)
579 || av.getAlignment().getAlignmentAnnotation() == null
580 || av.getAlignment().getAlignmentAnnotation().length < 1)
586 gg.copyArea(0, 0, imgWidth, getSize().height,
587 -horizontal * av.getCharWidth(), 0);
588 int sr = av.startRes, er = av.endRes + 1, transX = 0;
590 if (horizontal > 0) // scrollbar pulled right, image to the left
592 transX = (er - sr - horizontal) * av.getCharWidth();
593 sr = er - horizontal;
595 else if (horizontal < 0)
597 er = sr - horizontal;
600 gg.translate(transX, 0);
602 drawComponent(gg, sr, er);
604 gg.translate(-transX, 0);
620 public void drawComponent(Graphics g, int startRes, int endRes)
622 Font ofont = av.getFont();
625 g.setColor(Color.white);
626 g.fillRect(0, 0, (endRes - startRes) * av.getCharWidth(),
631 fm = g.getFontMetrics();
634 if ((av.getAlignment().getAlignmentAnnotation() == null)
635 || (av.getAlignment().getAlignmentAnnotation().length < 1))
637 g.setColor(Color.white);
638 g.fillRect(0, 0, getSize().width, getSize().height);
639 g.setColor(Color.black);
640 if (av.validCharWidth)
642 g.drawString(MessageManager
643 .getString("label.alignment_has_no_annotations"), 20, 15);
648 g.translate(0, -scrollOffset);
649 renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
650 g.translate(0, +scrollOffset);
653 int scrollOffset = 0;
655 public void setScrollOffset(int value, boolean repaint)
657 scrollOffset = value;
665 public FontMetrics getFontMetrics()
671 public Image getFadedImage()
677 public int getFadedImageWidth()
682 private int[] bounds = new int[2];
685 public int[] getVisibleVRange()
687 if (ap != null && ap.alabels != null)
689 int sOffset = -ap.alabels.scrollOffset;
690 int visHeight = sOffset + ap.annotationPanelHolder.getHeight();
692 bounds[1] = visHeight;