2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 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/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
19 package jalview.appletgui;
24 import java.awt.event.*;
26 import jalview.datamodel.*;
27 import jalview.renderer.AnnotationRenderer;
28 import jalview.renderer.AwtRenderPanelI;
29 import jalview.util.MessageManager;
31 public class AnnotationPanel extends Panel implements AwtRenderPanelI,
32 AdjustmentListener, ActionListener, MouseListener,
43 final String HELIX = "Helix";
45 final String SHEET = "Sheet";
48 * For RNA secondary structure "stems" aka helices
50 final String STEM = "RNA Helix";
52 final String LABEL = "Label";
54 final String REMOVE = "Remove Annotation";
56 final String COLOUR = "Colour";
58 final Color HELIX_COLOUR = Color.red.darker();
60 final Color SHEET_COLOUR = Color.green.darker().darker();
70 boolean fastPaint = false;
72 // Used For mouse Dragging and resizing graphs
73 int graphStretch = -1;
75 int graphStretchY = -1;
77 boolean mouseDragging = false;
79 public static int GRAPH_HEIGHT = 40;
83 public final AnnotationRenderer renderer;
85 public AnnotationPanel(AlignmentPanel ap)
87 MAC = new jalview.util.Platform().isAMac();
91 int height = adjustPanelHeight();
92 ap.apvscroll.setValues(0, getSize().height, 0, height);
94 addMouseMotionListener(this);
96 addMouseListener(this);
98 // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
99 renderer = new AnnotationRenderer();
102 public AnnotationPanel(AlignViewport av)
105 renderer = new AnnotationRenderer();
109 public void adjustmentValueChanged(AdjustmentEvent evt)
120 public void actionPerformed(ActionEvent evt)
122 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
127 Annotation[] anot = aa[activeRow].annotations;
129 if (anot.length < av.getColumnSelection().getMax())
131 Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
132 System.arraycopy(anot, 0, temp, 0, anot.length);
134 aa[activeRow].annotations = anot;
138 if (av.getColumnSelection() != null
139 && av.getColumnSelection().size() > 0
140 && anot[av.getColumnSelection().getMin()] != null)
141 label = anot[av.getColumnSelection().getMin()].displayCharacter;
143 if (evt.getActionCommand().equals(REMOVE))
145 for (int i = 0; i < av.getColumnSelection().size(); i++)
147 anot[av.getColumnSelection().columnAt(i)] = null;
150 else if (evt.getActionCommand().equals(LABEL))
152 label = enterLabel(label, "Enter Label");
159 if ((label.length() > 0) && !aa[activeRow].hasText)
161 aa[activeRow].hasText = true;
164 for (int i = 0; i < av.getColumnSelection().size(); i++)
166 int index = av.getColumnSelection().columnAt(i);
168 if (!av.getColumnSelection().isVisible(index))
171 if (anot[index] == null)
173 anot[index] = new Annotation(label, "", ' ', 0);
176 anot[index].displayCharacter = label;
179 else if (evt.getActionCommand().equals(COLOUR))
181 UserDefinedColours udc = new UserDefinedColours(this, Color.black,
184 Color col = udc.getColor();
186 for (int i = 0; i < av.getColumnSelection().size(); i++)
188 int index = av.getColumnSelection().columnAt(i);
190 if (!av.getColumnSelection().isVisible(index))
193 if (anot[index] == null)
195 anot[index] = new Annotation("", "", ' ', 0);
198 anot[index].colour = col;
205 String symbol = "\u03B1";
207 if (evt.getActionCommand().equals(HELIX))
211 else if (evt.getActionCommand().equals(SHEET))
217 // Added by LML to color stems
218 else if (evt.getActionCommand().equals(STEM))
224 if (!aa[activeRow].hasIcons)
226 aa[activeRow].hasIcons = true;
229 label = enterLabel(symbol, "Enter Label");
236 if ((label.length() > 0) && !aa[activeRow].hasText)
238 aa[activeRow].hasText = true;
239 if (evt.getActionCommand().equals(STEM))
241 aa[activeRow].showAllColLabels=true;
245 for (int i = 0; i < av.getColumnSelection().size(); i++)
247 int index = av.getColumnSelection().columnAt(i);
249 if (!av.getColumnSelection().isVisible(index))
252 if (anot[index] == null)
254 anot[index] = new Annotation(label, "", type, 0);
257 anot[index].secondaryStructure = type;
258 anot[index].displayCharacter = label;
262 av.getAlignment().validateAnnotation(aa[activeRow]);
264 ap.alignmentChanged();
271 String enterLabel(String text, String label)
273 EditNameDialog dialog = new EditNameDialog(text, null, label, null,
274 ap.alignFrame, "Enter Label", 400, 200, true);
277 return dialog.getName();
283 public void mousePressed(MouseEvent evt)
285 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
291 int height = -scrollOffset;
294 for (int i = 0; i < aa.length; i++)
298 height += aa[i].height;
301 if (evt.getY() < height)
307 else if (aa[i].graph > 0)
311 graphStretchY = evt.getY();
318 if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
321 if (av.getColumnSelection() == null)
326 PopupMenu pop = new PopupMenu(MessageManager.getString("label.structure_type"));
329 * Just display the needed structure options
331 if (av.getAlignment().isNucleotide() == true)
333 item = new MenuItem(STEM);
334 item.addActionListener(this);
339 item = new MenuItem(HELIX);
340 item.addActionListener(this);
342 item = new MenuItem(SHEET);
343 item.addActionListener(this);
346 item = new MenuItem(LABEL);
347 item.addActionListener(this);
349 item = new MenuItem(COLOUR);
350 item.addActionListener(this);
352 item = new MenuItem(REMOVE);
353 item.addActionListener(this);
355 ap.alignFrame.add(pop);
356 pop.show(this, evt.getX(), evt.getY());
366 ap.scalePanel.mousePressed(evt);
370 public void mouseReleased(MouseEvent evt)
374 mouseDragging = false;
378 needValidating = false;
380 ap.scalePanel.mouseReleased(evt);
384 public void mouseClicked(MouseEvent evt)
388 boolean needValidating = false;
391 public void mouseDragged(MouseEvent evt)
393 if (graphStretch > -1)
395 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
397 if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
399 av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
401 graphStretchY = evt.getY();
402 av.calcPanelHeight();
403 needValidating = true;
404 ap.paintAlignment(true);
408 ap.scalePanel.mouseDragged(evt);
413 public void mouseMoved(MouseEvent evt)
415 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
422 int height = -scrollOffset;
423 for (int i = 0; i < aa.length; i++)
428 height += aa[i].height;
431 if (evt.getY() < height)
438 int res = evt.getX() / av.getCharWidth() + av.getStartRes();
440 if (av.hasHiddenColumns())
442 res = av.getColumnSelection().adjustForHiddenColumns(res);
445 if (row > -1 && res < aa[row].annotations.length
446 && aa[row].annotations[res] != null)
448 StringBuffer text = new StringBuffer("Sequence position " + (res + 1));
449 if (aa[row].annotations[res].description != null)
451 text.append(" " + aa[row].annotations[res].description);
453 ap.alignFrame.statusBar.setText(text.toString());
458 public void mouseEntered(MouseEvent evt)
460 ap.scalePanel.mouseEntered(evt);
464 public void mouseExited(MouseEvent evt)
466 ap.scalePanel.mouseExited(evt);
469 public int adjustPanelHeight()
471 return adjustPanelHeight(true);
474 public int adjustPanelHeight(boolean repaint)
476 int height = av.calcPanelHeight();
477 this.setSize(new Dimension(getSize().width, height));
486 * calculate the height for visible annotation, revalidating bounds where
487 * necessary ABSTRACT GUI METHOD
489 * @return total height of annotation
492 public void addEditableColumn(int i)
496 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
502 for (int j = 0; j < aa.length; j++)
512 if (activeRes == null)
514 activeRes = new Vector();
515 activeRes.addElement(String.valueOf(i));
519 activeRes.addElement(String.valueOf(i));
523 public void update(Graphics g)
529 public void paint(Graphics g)
531 Dimension d = getSize();
533 // (av.endRes - av.startRes + 1) * av.charWidth;
534 if (imgWidth < 1 || d.height < 1)
538 if (image == null || imgWidth != image.getWidth(this)
539 || d.height != image.getHeight(this))
541 image = createImage(imgWidth, d.height);
542 gg = image.getGraphics();
543 gg.setFont(av.getFont());
544 fm = gg.getFontMetrics();
550 g.drawImage(image, 0, 0, this);
555 gg.setColor(Color.white);
556 gg.fillRect(0, 0, getSize().width, getSize().height);
557 drawComponent(gg, av.startRes, av.endRes + 1);
559 g.drawImage(image, 0, 0, this);
562 public void fastPaint(int horizontal)
565 || av.getAlignment().getAlignmentAnnotation() == null
566 || av.getAlignment().getAlignmentAnnotation().length < 1)
572 gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal
574 int sr = av.startRes, er = av.endRes + 1, transX = 0;
576 if (horizontal > 0) // scrollbar pulled right, image to the left
578 transX = (er - sr - horizontal) * av.charWidth;
579 sr = er - horizontal;
581 else if (horizontal < 0)
583 er = sr - horizontal;
586 gg.translate(transX, 0);
588 drawComponent(gg, sr, er);
590 gg.translate(-transX, 0);
606 public void drawComponent(Graphics g, int startRes, int endRes)
608 Font ofont = av.getFont();
611 g.setColor(Color.white);
612 g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);
616 fm = g.getFontMetrics();
619 if ((av.getAlignment().getAlignmentAnnotation() == null)
620 || (av.getAlignment().getAlignmentAnnotation().length < 1))
622 g.setColor(Color.white);
623 g.fillRect(0, 0, getSize().width, getSize().height);
624 g.setColor(Color.black);
625 if (av.validCharWidth)
627 g.drawString(MessageManager.getString("label.alignment_has_no_annotations"), 20, 15);
632 g.translate(0, -scrollOffset);
633 renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
634 g.translate(0, +scrollOffset);
637 int scrollOffset = 0;
639 public void setScrollOffset(int value)
641 scrollOffset = value;
646 public FontMetrics getFontMetrics()
652 public Image getFadedImage()
658 public int getFadedImageWidth()
662 private int[] bounds = new int[2];
664 public int[] getVisibleVRange()
666 if (ap!=null && ap.alabels!=null)
668 int sOffset=-ap.alabels.scrollOffset;
669 int visHeight = sOffset+ap.annotationPanelHolder.getHeight();
670 bounds[0] = sOffset; bounds[1]=visHeight;