2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 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;
26 import java.awt.event.*;
28 import jalview.datamodel.*;
29 import jalview.renderer.AnnotationRenderer;
30 import jalview.renderer.AwtRenderPanelI;
31 import jalview.util.MessageManager;
33 public class AnnotationPanel extends Panel implements AwtRenderPanelI,
34 AdjustmentListener, ActionListener, MouseListener,
45 final String HELIX = "Helix";
47 final String SHEET = "Sheet";
50 * For RNA secondary structure "stems" aka helices
52 final String STEM = "RNA Helix";
54 final String LABEL = "Label";
56 final String REMOVE = "Remove Annotation";
58 final String COLOUR = "Colour";
60 final Color HELIX_COLOUR = Color.red.darker();
62 final Color SHEET_COLOUR = Color.green.darker().darker();
72 boolean fastPaint = false;
74 // Used For mouse Dragging and resizing graphs
75 int graphStretch = -1;
77 int graphStretchY = -1;
79 boolean mouseDragging = false;
81 public static int GRAPH_HEIGHT = 40;
85 public final AnnotationRenderer renderer;
87 public AnnotationPanel(AlignmentPanel ap)
89 MAC = new jalview.util.Platform().isAMac();
93 int height = adjustPanelHeight();
94 ap.apvscroll.setValues(0, getSize().height, 0, height);
96 addMouseMotionListener(this);
98 addMouseListener(this);
100 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
101 renderer = new AnnotationRenderer();
104 public AnnotationPanel(AlignViewport av)
107 renderer = new AnnotationRenderer();
111 public void adjustmentValueChanged(AdjustmentEvent evt)
122 public void actionPerformed(ActionEvent evt)
124 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
129 Annotation[] anot = aa[activeRow].annotations;
131 if (anot.length < av.getColumnSelection().getMax())
133 Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
134 System.arraycopy(anot, 0, temp, 0, anot.length);
136 aa[activeRow].annotations = anot;
140 if (av.getColumnSelection() != null
141 && av.getColumnSelection().size() > 0
142 && anot[av.getColumnSelection().getMin()] != null)
143 label = anot[av.getColumnSelection().getMin()].displayCharacter;
145 if (evt.getActionCommand().equals(REMOVE))
147 for (int i = 0; i < av.getColumnSelection().size(); i++)
149 anot[av.getColumnSelection().columnAt(i)] = null;
152 else if (evt.getActionCommand().equals(LABEL))
154 label = enterLabel(label, "Enter Label");
161 if ((label.length() > 0) && !aa[activeRow].hasText)
163 aa[activeRow].hasText = true;
166 for (int i = 0; i < av.getColumnSelection().size(); i++)
168 int index = av.getColumnSelection().columnAt(i);
170 if (!av.getColumnSelection().isVisible(index))
173 if (anot[index] == null)
175 anot[index] = new Annotation(label, "", ' ', 0);
178 anot[index].displayCharacter = label;
181 else if (evt.getActionCommand().equals(COLOUR))
183 UserDefinedColours udc = new UserDefinedColours(this, Color.black,
186 Color col = udc.getColor();
188 for (int i = 0; i < av.getColumnSelection().size(); i++)
190 int index = av.getColumnSelection().columnAt(i);
192 if (!av.getColumnSelection().isVisible(index))
195 if (anot[index] == null)
197 anot[index] = new Annotation("", "", ' ', 0);
200 anot[index].colour = col;
207 String symbol = "\u03B1";
209 if (evt.getActionCommand().equals(HELIX))
213 else if (evt.getActionCommand().equals(SHEET))
219 // Added by LML to color stems
220 else if (evt.getActionCommand().equals(STEM))
226 if (!aa[activeRow].hasIcons)
228 aa[activeRow].hasIcons = true;
231 label = enterLabel(symbol, "Enter Label");
238 if ((label.length() > 0) && !aa[activeRow].hasText)
240 aa[activeRow].hasText = true;
241 if (evt.getActionCommand().equals(STEM))
243 aa[activeRow].showAllColLabels = true;
247 for (int i = 0; i < av.getColumnSelection().size(); i++)
249 int index = av.getColumnSelection().columnAt(i);
251 if (!av.getColumnSelection().isVisible(index))
254 if (anot[index] == null)
256 anot[index] = new Annotation(label, "", type, 0);
260 anot[index].secondaryStructure = type != 'S' ? type : label
261 .length() == 0 ? ' ' : label.charAt(0);
262 anot[index].displayCharacter = label;
266 av.getAlignment().validateAnnotation(aa[activeRow]);
268 ap.alignmentChanged();
275 String enterLabel(String text, String label)
277 EditNameDialog dialog = new EditNameDialog(text, null, label, null,
278 ap.alignFrame, "Enter Label", 400, 200, true);
281 return dialog.getName();
287 public void mousePressed(MouseEvent evt)
289 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
295 int height = -scrollOffset;
298 for (int i = 0; i < aa.length; i++)
302 height += aa[i].height;
305 if (evt.getY() < height)
311 else if (aa[i].graph > 0)
315 graphStretchY = evt.getY();
322 if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
325 if (av.getColumnSelection() == null)
330 PopupMenu pop = new PopupMenu(
331 MessageManager.getString("label.structure_type"));
334 * Just display the needed structure options
336 if (av.getAlignment().isNucleotide() == true)
338 item = new MenuItem(STEM);
339 item.addActionListener(this);
344 item = new MenuItem(HELIX);
345 item.addActionListener(this);
347 item = new MenuItem(SHEET);
348 item.addActionListener(this);
351 item = new MenuItem(LABEL);
352 item.addActionListener(this);
354 item = new MenuItem(COLOUR);
355 item.addActionListener(this);
357 item = new MenuItem(REMOVE);
358 item.addActionListener(this);
360 ap.alignFrame.add(pop);
361 pop.show(this, evt.getX(), evt.getY());
371 ap.scalePanel.mousePressed(evt);
375 public void mouseReleased(MouseEvent evt)
379 mouseDragging = false;
383 needValidating = false;
385 ap.scalePanel.mouseReleased(evt);
389 public void mouseClicked(MouseEvent evt)
393 boolean needValidating = false;
396 public void mouseDragged(MouseEvent evt)
398 if (graphStretch > -1)
400 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
402 if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
404 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
406 graphStretchY = evt.getY();
407 av.calcPanelHeight();
408 needValidating = true;
409 ap.paintAlignment(true);
413 ap.scalePanel.mouseDragged(evt);
418 public void mouseMoved(MouseEvent evt)
420 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
427 int height = -scrollOffset;
428 for (int i = 0; i < aa.length; i++)
433 height += aa[i].height;
436 if (evt.getY() < height)
443 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
445 if (av.hasHiddenColumns())
447 res = av.getColumnSelection().adjustForHiddenColumns(res);
450 if (row > -1 && res < aa[row].annotations.length
451 && aa[row].annotations[res] != null)
453 StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
454 if (aa[row].annotations[res].description != null)
456 text.append(" " + aa[row].annotations[res].description);
458 ap.alignFrame.statusBar.setText(text.toString());
463 public void mouseEntered(MouseEvent evt)
465 ap.scalePanel.mouseEntered(evt);
469 public void mouseExited(MouseEvent evt)
471 ap.scalePanel.mouseExited(evt);
474 public int adjustPanelHeight()
476 return adjustPanelHeight(true);
479 public int adjustPanelHeight(boolean repaint)
481 int height = av.calcPanelHeight();
482 this.setSize(new Dimension(getSize().width, height));
491 * calculate the height for visible annotation, revalidating bounds where
492 * necessary ABSTRACT GUI METHOD
494 * @return total height of annotation
497 public void addEditableColumn(int i)
501 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
507 for (int j = 0; j < aa.length; j++)
517 if (activeRes == null)
519 activeRes = new Vector();
520 activeRes.addElement(String.valueOf(i));
524 activeRes.addElement(String.valueOf(i));
528 public void update(Graphics g)
534 public void paint(Graphics g)
536 Dimension d = getSize();
538 // (av.endRes - av.startRes + 1) * av.charWidth;
539 if (imgWidth < 1 || d.height < 1)
543 if (image == null || imgWidth != image.getWidth(this)
544 || d.height != image.getHeight(this))
546 image = createImage(imgWidth, d.height);
547 gg = image.getGraphics();
548 gg.setFont(av.getFont());
549 fm = gg.getFontMetrics();
555 g.drawImage(image, 0, 0, this);
560 gg.setColor(Color.white);
561 gg.fillRect(0, 0, getSize().width, getSize().height);
562 drawComponent(gg, av.startRes, av.endRes + 1);
564 g.drawImage(image, 0, 0, this);
567 public void fastPaint(int horizontal)
570 || av.getAlignment().getAlignmentAnnotation() == null
571 || av.getAlignment().getAlignmentAnnotation().length < 1)
577 gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal
579 int sr = av.startRes, er = av.endRes + 1, transX = 0;
581 if (horizontal > 0) // scrollbar pulled right, image to the left
583 transX = (er - sr - horizontal) * av.charWidth;
584 sr = er - horizontal;
586 else if (horizontal < 0)
588 er = sr - horizontal;
591 gg.translate(transX, 0);
593 drawComponent(gg, sr, er);
595 gg.translate(-transX, 0);
611 public void drawComponent(Graphics g, int startRes, int endRes)
613 Font ofont = av.getFont();
616 g.setColor(Color.white);
617 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
621 fm = g.getFontMetrics();
624 if ((av.getAlignment().getAlignmentAnnotation() == null)
625 || (av.getAlignment().getAlignmentAnnotation().length < 1))
627 g.setColor(Color.white);
628 g.fillRect(0, 0, getSize().width, getSize().height);
629 g.setColor(Color.black);
630 if (av.validCharWidth)
632 g.drawString(MessageManager
633 .getString("label.alignment_has_no_annotations"), 20, 15);
638 g.translate(0, -scrollOffset);
639 renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
640 g.translate(0, +scrollOffset);
643 int scrollOffset = 0;
645 public void setScrollOffset(int value, boolean repaint)
647 scrollOffset = value;
655 public FontMetrics getFontMetrics()
661 public Image getFadedImage()
667 public int getFadedImageWidth()
672 private int[] bounds = new int[2];
675 public int[] getVisibleVRange()
677 if (ap != null && ap.alabels != null)
679 int sOffset = -ap.alabels.scrollOffset;
680 int visHeight = sOffset + ap.annotationPanelHolder.getHeight();
682 bounds[1] = visHeight;