Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.appletgui

File AnnotationLabels.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
56% of files have more coverage

Code metrics

132
307
27
1
924
713
111
0.36
11.37
27
4.11

Classes

Class Line # Actions
AnnotationLabels 56 307 111
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21    package jalview.appletgui;
22   
23    import jalview.analysis.AlignmentUtils;
24    import jalview.datamodel.AlignmentAnnotation;
25    import jalview.datamodel.Annotation;
26    import jalview.datamodel.HiddenColumns;
27    import jalview.datamodel.SequenceGroup;
28    import jalview.datamodel.SequenceI;
29    import jalview.util.MessageManager;
30    import jalview.util.ParseHtmlBodyAndLinks;
31   
32    import java.awt.Checkbox;
33    import java.awt.CheckboxMenuItem;
34    import java.awt.Color;
35    import java.awt.Cursor;
36    import java.awt.Dimension;
37    import java.awt.FlowLayout;
38    import java.awt.FontMetrics;
39    import java.awt.Frame;
40    import java.awt.Graphics;
41    import java.awt.Image;
42    import java.awt.MenuItem;
43    import java.awt.Panel;
44    import java.awt.PopupMenu;
45    import java.awt.event.ActionEvent;
46    import java.awt.event.ActionListener;
47    import java.awt.event.InputEvent;
48    import java.awt.event.ItemEvent;
49    import java.awt.event.ItemListener;
50    import java.awt.event.MouseEvent;
51    import java.awt.event.MouseListener;
52    import java.awt.event.MouseMotionListener;
53    import java.util.Arrays;
54    import java.util.Collections;
55   
 
56    public class AnnotationLabels extends Panel
57    implements ActionListener, MouseListener, MouseMotionListener
58    {
59    Image image;
60   
61    /**
62    * width in pixels within which height adjuster arrows are shown and active
63    */
64    private static final int HEIGHT_ADJUSTER_WIDTH = 50;
65   
66    /**
67    * height in pixels for allowing height adjuster to be active
68    */
69    private static int HEIGHT_ADJUSTER_HEIGHT = 10;
70   
71    boolean active = false;
72   
73    AlignmentPanel ap;
74   
75    AlignViewport av;
76   
77    boolean resizing = false;
78   
79    int oldY, mouseX;
80   
81    static String ADDNEW = "Add New Row";
82   
83    static String EDITNAME = "Edit Label/Description";
84   
85    static String HIDE = "Hide This Row";
86   
87    static String SHOWALL = "Show All Hidden Rows";
88   
89    static String OUTPUT_TEXT = "Show Values In Textbox";
90   
91    static String COPYCONS_SEQ = "Copy Consensus Sequence";
92   
93    int scrollOffset = 0;
94   
95    int selectedRow = -1;
96   
97    Tooltip tooltip;
98   
99    private boolean hasHiddenRows;
100   
 
101  0 toggle public AnnotationLabels(AlignmentPanel ap)
102    {
103  0 this.ap = ap;
104  0 this.av = ap.av;
105  0 setLayout(null);
106  0 addMouseListener(this);
107  0 addMouseMotionListener(this);
108    }
109   
 
110  0 toggle public AnnotationLabels(AlignViewport av)
111    {
112  0 this.av = av;
113    }
114   
 
115  0 toggle public void setScrollOffset(int y, boolean repaint)
116    {
117  0 scrollOffset = y;
118  0 if (repaint)
119    {
120  0 repaint();
121    }
122    }
123   
124    /**
125    *
126    * @param y
127    * @return -2 if no rows are visible at all, -1 if no visible rows were
128    * selected
129    */
 
130  0 toggle int getSelectedRow(int y)
131    {
132  0 int row = -2;
133  0 AlignmentAnnotation[] aa = ap.av.getAlignment()
134    .getAlignmentAnnotation();
135   
136  0 if (aa == null)
137    {
138  0 return row;
139    }
140  0 int height = 0;
141  0 for (int i = 0; i < aa.length; i++)
142    {
143  0 row = -1;
144  0 if (!aa[i].visible)
145    {
146  0 continue;
147    }
148  0 height += aa[i].height;
149  0 if (y < height)
150    {
151  0 row = i;
152  0 break;
153    }
154    }
155   
156  0 return row;
157    }
158   
 
159  0 toggle @Override
160    public void actionPerformed(ActionEvent evt)
161    {
162  0 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
163   
164  0 if (evt.getActionCommand().equals(ADDNEW))
165    {
166  0 AlignmentAnnotation newAnnotation = new AlignmentAnnotation("", null,
167    new Annotation[ap.av.getAlignment().getWidth()]);
168   
169  0 if (!editLabelDescription(newAnnotation))
170    {
171  0 return;
172    }
173   
174  0 ap.av.getAlignment().addAnnotation(newAnnotation);
175  0 ap.av.getAlignment().setAnnotationIndex(newAnnotation, 0);
176    }
177  0 else if (evt.getActionCommand().equals(EDITNAME))
178    {
179  0 editLabelDescription(aa[selectedRow]);
180    }
181  0 else if (evt.getActionCommand().equals(HIDE))
182    {
183  0 aa[selectedRow].visible = false;
184    }
185  0 else if (evt.getActionCommand().equals(SHOWALL))
186    {
187  0 for (int i = 0; i < aa.length; i++)
188    {
189  0 aa[i].visible = (aa[i].annotations == null) ? false : true;
190    }
191    }
192  0 else if (evt.getActionCommand().equals(OUTPUT_TEXT))
193    {
194  0 CutAndPasteTransfer cap = new CutAndPasteTransfer(false,
195    ap.alignFrame);
196  0 Frame frame = new Frame();
197  0 frame.add(cap);
198  0 jalview.bin.JalviewLite.addFrame(frame,
199    ap.alignFrame.getTitle() + " - " + aa[selectedRow].label, 500,
200    100);
201  0 cap.setText(aa[selectedRow].toString());
202    }
203  0 else if (evt.getActionCommand().equals(COPYCONS_SEQ))
204    {
205  0 SequenceGroup group = aa[selectedRow].groupRef;
206  0 SequenceI cons = group == null ? av.getConsensusSeq()
207    : group.getConsensusSeq();
208  0 if (cons != null)
209    {
210  0 copy_annotseqtoclipboard(cons);
211    }
212   
213    }
214  0 refresh();
215    }
216   
217    /**
218    * Adjust size and repaint
219    */
 
220  0 toggle protected void refresh()
221    {
222  0 ap.annotationPanel.adjustPanelHeight();
223  0 setSize(getSize().width, ap.annotationPanel.getSize().height);
224  0 ap.validate();
225    // TODO: only paint if we needed to
226  0 ap.paintAlignment(true, true);
227    }
228   
 
229  0 toggle boolean editLabelDescription(AlignmentAnnotation annotation)
230    {
231  0 Checkbox padGaps = new Checkbox(
232    "Fill Empty Gaps With \"" + ap.av.getGapCharacter() + "\"",
233    annotation.padGaps);
234   
235  0 EditNameDialog dialog = new EditNameDialog(annotation.label,
236    annotation.description, " Annotation Label",
237    "Annotation Description", ap.alignFrame,
238    "Edit Annotation Name / Description", 500, 180, false);
239   
240  0 Panel empty = new Panel(new FlowLayout());
241  0 empty.add(padGaps);
242  0 dialog.add(empty);
243  0 dialog.pack();
244   
245  0 dialog.setVisible(true);
246   
247  0 if (dialog.accept)
248    {
249  0 annotation.label = dialog.getName();
250  0 annotation.description = dialog.getDescription();
251  0 annotation.setPadGaps(padGaps.getState(), av.getGapCharacter());
252  0 repaint();
253  0 return true;
254    }
255    else
256    {
257  0 return false;
258    }
259   
260    }
261   
262    boolean resizePanel = false;
263   
 
264  0 toggle @Override
265    public void mouseMoved(MouseEvent evt)
266    {
267  0 resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT
268    && evt.getX() < HEIGHT_ADJUSTER_WIDTH;
269  0 setCursor(Cursor.getPredefinedCursor(
270  0 resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR));
271  0 int row = getSelectedRow(evt.getY() + scrollOffset);
272   
273  0 if (row > -1)
274    {
275  0 ParseHtmlBodyAndLinks phb = new ParseHtmlBodyAndLinks(
276    av.getAlignment().getAlignmentAnnotation()[row]
277    .getDescription(true),
278    true, "\n");
279  0 if (tooltip == null)
280    {
281  0 tooltip = new Tooltip(phb.getNonHtmlContent(), this);
282    }
283    else
284    {
285  0 tooltip.setTip(phb.getNonHtmlContent());
286    }
287    }
288  0 else if (tooltip != null)
289    {
290  0 tooltip.setTip("");
291    }
292    }
293   
294    /**
295    * curent drag position
296    */
297    MouseEvent dragEvent = null;
298   
299    /**
300    * flag to indicate drag events should be ignored
301    */
302    private boolean dragCancelled = false;
303   
304    /**
305    * clear any drag events in progress
306    */
 
307  0 toggle public void cancelDrag()
308    {
309  0 dragEvent = null;
310  0 dragCancelled = true;
311    }
312   
 
313  0 toggle @Override
314    public void mouseDragged(MouseEvent evt)
315    {
316  0 if (dragCancelled)
317    {
318  0 return;
319    }
320  0 ;
321  0 dragEvent = evt;
322   
323  0 if (resizePanel)
324    {
325  0 Dimension d = ap.annotationPanelHolder.getSize(),
326    e = ap.annotationSpaceFillerHolder.getSize(),
327    f = ap.seqPanelHolder.getSize();
328  0 int dif = evt.getY() - oldY;
329   
330  0 dif /= ap.av.getCharHeight();
331  0 dif *= ap.av.getCharHeight();
332   
333  0 if ((d.height - dif) > 20 && (f.height + dif) > 20)
334    {
335  0 ap.annotationPanel.setSize(d.width, d.height - dif);
336  0 setSize(new Dimension(e.width, d.height - dif));
337  0 ap.annotationSpaceFillerHolder
338    .setSize(new Dimension(e.width, d.height - dif));
339  0 ap.annotationPanelHolder
340    .setSize(new Dimension(d.width, d.height - dif));
341  0 ap.apvscroll.setValues(ap.apvscroll.getValue(), d.height - dif, 0,
342    av.calcPanelHeight());
343  0 f.height += dif;
344  0 ap.seqPanelHolder.setPreferredSize(f);
345  0 ap.setScrollValues(av.getRanges().getStartRes(),
346    av.getRanges().getStartSeq());
347  0 ap.validate();
348    // ap.paintAlignment(true);
349  0 ap.addNotify();
350    }
351   
352    }
353    else
354    {
355  0 int diff;
356  0 if ((diff = 6 - evt.getY()) > 0)
357    {
358    // nudge scroll up
359  0 ap.apvscroll.setValue(ap.apvscroll.getValue() - diff);
360  0 ap.adjustmentValueChanged(null);
361   
362    }
363  0 else if ((0 < (diff = 6
364    - ap.annotationSpaceFillerHolder.getSize().height
365    + evt.getY())))
366    {
367    // nudge scroll down
368  0 ap.apvscroll.setValue(ap.apvscroll.getValue() + diff);
369  0 ap.adjustmentValueChanged(null);
370    }
371  0 repaint();
372    }
373    }
374   
 
375  0 toggle @Override
376    public void mouseClicked(MouseEvent evt)
377    {
378    }
379   
 
380  0 toggle @Override
381    public void mouseReleased(MouseEvent evt)
382    {
383  0 if (!resizePanel && !dragCancelled)
384    {
385  0 int start = selectedRow;
386   
387  0 int end = getSelectedRow(evt.getY() + scrollOffset);
388   
389  0 if (start > -1 && start != end)
390    {
391    // Swap these annotations
392  0 AlignmentAnnotation startAA = ap.av.getAlignment()
393    .getAlignmentAnnotation()[start];
394  0 if (end == -1)
395    {
396  0 end = ap.av.getAlignment().getAlignmentAnnotation().length - 1;
397    }
398  0 AlignmentAnnotation endAA = ap.av.getAlignment()
399    .getAlignmentAnnotation()[end];
400   
401  0 ap.av.getAlignment().getAlignmentAnnotation()[end] = startAA;
402  0 ap.av.getAlignment().getAlignmentAnnotation()[start] = endAA;
403    }
404    }
405  0 resizePanel = false;
406  0 dragEvent = null;
407  0 dragCancelled = false;
408  0 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
409  0 repaint();
410  0 ap.annotationPanel.repaint();
411    }
412   
 
413  0 toggle @Override
414    public void mouseEntered(MouseEvent evt)
415    {
416  0 if (evt.getY() < 10 && evt.getX() < 14)
417    {
418  0 resizePanel = true;
419  0 repaint();
420    }
421  0 setCursor(Cursor.getPredefinedCursor(
422  0 resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR));
423    }
424   
 
425  0 toggle @Override
426    public void mouseExited(MouseEvent evt)
427    {
428  0 dragCancelled = false;
429   
430  0 if (dragEvent == null)
431    {
432  0 resizePanel = false;
433    }
434    else
435    {
436  0 if (!resizePanel)
437    {
438  0 dragEvent = null;
439    }
440    }
441  0 repaint();
442    }
443   
 
444  0 toggle @Override
445    public void mousePressed(MouseEvent evt)
446    {
447  0 oldY = evt.getY();
448  0 if (resizePanel)
449    {
450  0 return;
451    }
452  0 dragCancelled = false;
453    // todo: move below to mouseClicked ?
454  0 selectedRow = getSelectedRow(evt.getY() + scrollOffset);
455   
456  0 AlignmentAnnotation[] aa = ap.av.getAlignment()
457    .getAlignmentAnnotation();
458   
459    // DETECT RIGHT MOUSE BUTTON IN AWT
460  0 if ((evt.getModifiersEx()
461    & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK)
462    {
463   
464  0 PopupMenu popup = new PopupMenu(
465    MessageManager.getString("label.annotations"));
466   
467  0 MenuItem item = new MenuItem(ADDNEW);
468  0 item.addActionListener(this);
469  0 popup.add(item);
470  0 if (selectedRow < 0)
471    {
472    // this never happens at moment: - see comment on JAL-563
473  0 if (hasHiddenRows)
474    {
475  0 item = new MenuItem(SHOWALL);
476  0 item.addActionListener(this);
477  0 popup.add(item);
478    }
479  0 this.add(popup);
480  0 popup.show(this, evt.getX(), evt.getY());
481  0 return;
482    }
483    // add the rest if there are actually rows to show
484  0 item = new MenuItem(EDITNAME);
485  0 item.addActionListener(this);
486  0 popup.add(item);
487  0 item = new MenuItem(HIDE);
488  0 item.addActionListener(this);
489  0 popup.add(item);
490   
491    /*
492    * Hide all <label>:
493    */
494  0 if (selectedRow < aa.length)
495    {
496  0 if (aa[selectedRow].sequenceRef != null)
497    {
498  0 final String label = aa[selectedRow].label;
499  0 MenuItem hideType = new MenuItem(
500    MessageManager.getString("label.hide_all") + " " + label);
501  0 hideType.addActionListener(new ActionListener()
502    {
 
503  0 toggle @Override
504    public void actionPerformed(ActionEvent e)
505    {
506  0 AlignmentUtils.showOrHideSequenceAnnotations(
507    ap.av.getAlignment(), Collections.singleton(label),
508    null, false, false);
509  0 refresh();
510    }
511    });
512  0 popup.add(hideType);
513    }
514    }
515   
516  0 if (hasHiddenRows)
517    {
518  0 item = new MenuItem(SHOWALL);
519  0 item.addActionListener(this);
520  0 popup.add(item);
521    }
522  0 this.add(popup);
523  0 item = new MenuItem(OUTPUT_TEXT);
524  0 item.addActionListener(this);
525  0 popup.add(item);
526  0 if (selectedRow < aa.length)
527    {
528  0 if (aa[selectedRow].autoCalculated)
529    {
530  0 if (aa[selectedRow].label.indexOf("Consensus") > -1)
531    {
532  0 popup.addSeparator();
533  0 final CheckboxMenuItem cbmi = new CheckboxMenuItem(
534    MessageManager.getString("label.ignore_gaps_consensus"),
535  0 (aa[selectedRow].groupRef != null)
536    ? aa[selectedRow].groupRef
537    .getIgnoreGapsConsensus()
538    : ap.av.isIgnoreGapsConsensus());
539  0 final AlignmentAnnotation aaa = aa[selectedRow];
540  0 cbmi.addItemListener(new ItemListener()
541    {
 
542  0 toggle @Override
543    public void itemStateChanged(ItemEvent e)
544    {
545  0 if (aaa.groupRef != null)
546    {
547    // TODO: pass on reference to ap so the view can be updated.
548  0 aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
549    }
550    else
551    {
552  0 ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
553    }
554  0 ap.paintAlignment(true, true);
555    }
556    });
557  0 popup.add(cbmi);
558  0 if (aaa.groupRef != null)
559    {
560  0 final CheckboxMenuItem chist = new CheckboxMenuItem(
561    MessageManager
562    .getString("label.show_group_histogram"),
563    aa[selectedRow].groupRef.isShowConsensusHistogram());
564  0 chist.addItemListener(new ItemListener()
565    {
 
566  0 toggle @Override
567    public void itemStateChanged(ItemEvent e)
568    {
569    // TODO: pass on reference
570    // to ap
571    // so the
572    // view
573    // can be
574    // updated.
575  0 aaa.groupRef.setShowConsensusHistogram(chist.getState());
576  0 ap.repaint();
577    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
578    }
579    });
580  0 popup.add(chist);
581  0 final CheckboxMenuItem cprofl = new CheckboxMenuItem(
582    MessageManager.getString("label.show_group_logo"),
583    aa[selectedRow].groupRef.isShowSequenceLogo());
584  0 cprofl.addItemListener(new ItemListener()
585    {
 
586  0 toggle @Override
587    public void itemStateChanged(ItemEvent e)
588    {
589    // TODO: pass on reference
590    // to ap
591    // so the
592    // view
593    // can be
594    // updated.
595  0 aaa.groupRef.setshowSequenceLogo(cprofl.getState());
596  0 ap.repaint();
597    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
598    }
599    });
600   
601  0 popup.add(cprofl);
602  0 final CheckboxMenuItem cprofn = new CheckboxMenuItem(
603    MessageManager
604    .getString("label.normalise_group_logo"),
605    aa[selectedRow].groupRef.isNormaliseSequenceLogo());
606  0 cprofn.addItemListener(new ItemListener()
607    {
 
608  0 toggle @Override
609    public void itemStateChanged(ItemEvent e)
610    {
611    // TODO: pass on reference
612    // to ap
613    // so the
614    // view
615    // can be
616    // updated.
617  0 aaa.groupRef.setshowSequenceLogo(true);
618  0 aaa.groupRef.setNormaliseSequenceLogo(cprofn.getState());
619  0 ap.repaint();
620    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
621    }
622    });
623  0 popup.add(cprofn);
624    }
625    else
626    {
627  0 final CheckboxMenuItem chist = new CheckboxMenuItem(
628    MessageManager.getString("label.show_histogram"),
629    av.isShowConsensusHistogram());
630  0 chist.addItemListener(new ItemListener()
631    {
 
632  0 toggle @Override
633    public void itemStateChanged(ItemEvent e)
634    {
635    // TODO: pass on reference
636    // to ap
637    // so the
638    // view
639    // can be
640    // updated.
641  0 av.setShowConsensusHistogram(chist.getState());
642  0 ap.alignFrame.showConsensusHistogram
643    .setState(chist.getState()); // TODO: implement
644    // ap.updateGUI()/alignFrame.updateGUI
645    // for applet
646  0 ap.repaint();
647    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
648    }
649    });
650  0 popup.add(chist);
651  0 final CheckboxMenuItem cprof = new CheckboxMenuItem(
652    MessageManager.getString("label.show_logo"),
653    av.isShowSequenceLogo());
654  0 cprof.addItemListener(new ItemListener()
655    {
 
656  0 toggle @Override
657    public void itemStateChanged(ItemEvent e)
658    {
659    // TODO: pass on reference
660    // to ap
661    // so the
662    // view
663    // can be
664    // updated.
665  0 av.setShowSequenceLogo(cprof.getState());
666  0 ap.alignFrame.showSequenceLogo.setState(cprof.getState()); // TODO:
667    // implement
668    // ap.updateGUI()/alignFrame.updateGUI
669    // for
670    // applet
671  0 ap.repaint();
672    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
673    }
674    });
675  0 popup.add(cprof);
676  0 final CheckboxMenuItem cprofn = new CheckboxMenuItem(
677    MessageManager.getString("label.normalise_logo"),
678    av.isNormaliseSequenceLogo());
679  0 cprofn.addItemListener(new ItemListener()
680    {
 
681  0 toggle @Override
682    public void itemStateChanged(ItemEvent e)
683    {
684    // TODO: pass on reference
685    // to ap
686    // so the
687    // view
688    // can be
689    // updated.
690  0 av.setShowSequenceLogo(true);
691  0 ap.alignFrame.normSequenceLogo
692    .setState(cprofn.getState()); // TODO:
693    // implement
694    // ap.updateGUI()/alignFrame.updateGUI
695    // for
696    // applet
697  0 av.setNormaliseSequenceLogo(cprofn.getState());
698  0 ap.repaint();
699    // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
700    }
701    });
702  0 popup.add(cprofn);
703    }
704   
705  0 item = new MenuItem(COPYCONS_SEQ);
706  0 item.addActionListener(this);
707  0 popup.add(item);
708    }
709    }
710    }
711  0 popup.show(this, evt.getX(), evt.getY());
712    }
713    else
714    {
715    // selection action.
716  0 if (selectedRow > -1 && selectedRow < aa.length)
717    {
718  0 if (aa[selectedRow].groupRef != null)
719    {
720  0 if (evt.getClickCount() >= 2)
721    {
722    // todo: make the ap scroll to the selection - not necessary, first
723    // click highlights/scrolls, second selects
724  0 ap.seqPanel.ap.idPanel.highlightSearchResults(null);
725    // process modifiers
726  0 SequenceGroup sg = ap.av.getSelectionGroup();
727  0 if (sg == null || sg == aa[selectedRow].groupRef
728    || !(jalview.util.Platform.isControlDown(evt)
729    || evt.isShiftDown()))
730    {
731  0 if (jalview.util.Platform.isControlDown(evt)
732    || evt.isShiftDown())
733    {
734    // clone a new selection group from the associated group
735  0 ap.av.setSelectionGroup(
736    new SequenceGroup(aa[selectedRow].groupRef));
737    }
738    else
739    {
740    // set selection to the associated group so it can be edited
741  0 ap.av.setSelectionGroup(aa[selectedRow].groupRef);
742    }
743    }
744    else
745    {
746    // modify current selection with associated group
747  0 int remainToAdd = aa[selectedRow].groupRef.getSize();
748  0 for (SequenceI sgs : aa[selectedRow].groupRef.getSequences())
749    {
750  0 if (jalview.util.Platform.isControlDown(evt))
751    {
752  0 sg.addOrRemove(sgs, --remainToAdd == 0);
753    }
754    else
755    {
756    // notionally, we should also add intermediate sequences from
757    // last added sequence ?
758  0 sg.addSequence(sgs, --remainToAdd == 0);
759    }
760    }
761    }
762  0 ap.paintAlignment(false, false);
763  0 PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
764  0 ap.av.sendSelection();
765    }
766    else
767    {
768  0 ap.seqPanel.ap.idPanel.highlightSearchResults(
769    aa[selectedRow].groupRef.getSequences(null));
770    }
771  0 return;
772    }
773  0 else if (aa[selectedRow].sequenceRef != null)
774    {
775  0 if (evt.getClickCount() == 1)
776    {
777  0 ap.seqPanel.ap.idPanel
778    .highlightSearchResults(Arrays.asList(new SequenceI[]
779    { aa[selectedRow].sequenceRef }));
780    }
781  0 else if (evt.getClickCount() >= 2)
782    {
783  0 ap.seqPanel.ap.idPanel.highlightSearchResults(null);
784  0 SequenceGroup sg = ap.av.getSelectionGroup();
785  0 if (sg != null)
786    {
787    // we make a copy rather than edit the current selection if no
788    // modifiers pressed
789    // see Enhancement JAL-1557
790  0 if (!(jalview.util.Platform.isControlDown(evt)
791    || evt.isShiftDown()))
792    {
793  0 sg = new SequenceGroup(sg);
794  0 sg.clear();
795  0 sg.addSequence(aa[selectedRow].sequenceRef, false);
796    }
797    else
798    {
799  0 if (jalview.util.Platform.isControlDown(evt))
800    {
801  0 sg.addOrRemove(aa[selectedRow].sequenceRef, true);
802    }
803    else
804    {
805    // notionally, we should also add intermediate sequences from
806    // last added sequence ?
807  0 sg.addSequence(aa[selectedRow].sequenceRef, true);
808    }
809    }
810    }
811    else
812    {
813  0 sg = new SequenceGroup();
814  0 sg.setStartRes(0);
815  0 sg.setEndRes(ap.av.getAlignment().getWidth() - 1);
816  0 sg.addSequence(aa[selectedRow].sequenceRef, false);
817    }
818  0 ap.av.setSelectionGroup(sg);
819  0 ap.paintAlignment(false, false);
820  0 PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
821  0 ap.av.sendSelection();
822    }
823   
824    }
825    }
826   
827    }
828    }
829   
830    /**
831    * DOCUMENT ME!
832    *
833    * @param e
834    * DOCUMENT ME!
835    */
 
836  0 toggle protected void copy_annotseqtoclipboard(SequenceI sq)
837    {
838  0 if (sq == null || sq.getLength() < 1)
839    {
840  0 return;
841    }
842  0 jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer();
843  0 jalview.appletgui.AlignFrame.copiedSequences
844    .append(sq.getName() + "\t" + sq.getStart() + "\t" + sq.getEnd()
845    + "\t" + sq.getSequenceAsString() + "\n");
846  0 if (av.hasHiddenColumns())
847    {
848  0 jalview.appletgui.AlignFrame.copiedHiddenColumns = new HiddenColumns(
849    av.getAlignment().getHiddenColumns());
850    }
851    }
852   
 
853  0 toggle @Override
854    public void update(Graphics g)
855    {
856  0 paint(g);
857    }
858   
 
859  0 toggle @Override
860    public void paint(Graphics g)
861    {
862  0 int w = getSize().width;
863  0 int h = getSize().height;
864  0 if (image == null || w != image.getWidth(this)
865    || h != image.getHeight(this))
866    {
867  0 image = createImage(w, ap.annotationPanel.getSize().height);
868    }
869   
870  0 drawComponent(image.getGraphics(), w);
871  0 g.drawImage(image, 0, 0, this);
872    }
873   
 
874  0 toggle public void drawComponent(Graphics g, int width)
875    {
876  0 g.setFont(av.getFont());
877  0 FontMetrics fm = g.getFontMetrics(av.getFont());
878  0 g.setColor(Color.white);
879  0 g.fillRect(0, 0, getSize().width, getSize().height);
880   
881  0 g.translate(0, -scrollOffset);
882  0 g.setColor(Color.black);
883   
884  0 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
885  0 int y = 0, fy = g.getFont().getSize();
886  0 int x = 0, offset;
887   
888  0 if (aa != null)
889    {
890  0 hasHiddenRows = false;
891  0 for (int i = 0; i < aa.length; i++)
892    {
893  0 if (!aa[i].visible)
894    {
895  0 hasHiddenRows = true;
896  0 continue;
897    }
898   
899  0 x = width - fm.stringWidth(aa[i].label) - 3;
900   
901  0 y += aa[i].height;
902  0 offset = -(aa[i].height - fy) / 2;
903   
904  0 g.drawString(aa[i].label, x, y + offset);
905    }
906    }
907  0 g.translate(0, +scrollOffset);
908   
909  0 if (!resizePanel && !dragCancelled && dragEvent != null && aa != null)
910    {
911  0 g.setColor(Color.lightGray);
912  0 g.drawString(aa[selectedRow].label, dragEvent.getX(),
913    dragEvent.getY());
914    }
915   
916  0 if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
917    {
918  0 g.setColor(Color.black);
919  0 g.drawString(MessageManager.getString("label.right_click"), 2, 8);
920  0 g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
921    18);
922    }
923    }
924    }