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