50849e136bca4ca2671d4b48048d9ed5ed9a70d7
[jalview.git] / src / jalview / gui / AnnotationLabels.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 import java.awt.image.*;\r
26 \r
27 import javax.swing.*;\r
28 \r
29 \r
30 /**\r
31  * DOCUMENT ME!\r
32  *\r
33  * @author $author$\r
34  * @version $Revision$\r
35  */\r
36 public class AnnotationLabels extends JPanel implements MouseListener,\r
37     MouseMotionListener, ActionListener\r
38 {\r
39     static String ADDNEW = "Add New Row";\r
40     static String HIDE = "Hide This Row";\r
41     static String DELETE = "Delete This Row";\r
42     static String SHOWALL = "Show All Hidden Rows";\r
43     static String OUTPUT_TEXT = "Show Values In Textbox";\r
44     boolean resizePanel = false;\r
45     Image image;\r
46     AlignmentPanel ap;\r
47     AlignViewport av;\r
48     boolean resizing = false;\r
49     MouseEvent dragEvent;\r
50     int oldY;\r
51     int selectedRow;\r
52     int scrollOffset = 0;\r
53     Font font = new Font("Arial", Font.PLAIN, 11);\r
54 \r
55 \r
56     /**\r
57      * Creates a new AnnotationLabels object.\r
58      *\r
59      * @param ap DOCUMENT ME!\r
60      */\r
61     public AnnotationLabels(AlignmentPanel ap)\r
62     {\r
63         this.ap = ap;\r
64         av = ap.av;\r
65 \r
66         java.net.URL url = getClass().getResource("/images/idwidth.gif");\r
67         Image temp = null;\r
68 \r
69         if (url != null)\r
70         {\r
71             temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);\r
72         }\r
73 \r
74         try\r
75         {\r
76             MediaTracker mt = new MediaTracker(this);\r
77             mt.addImage(temp, 0);\r
78             mt.waitForID(0);\r
79         }\r
80         catch (Exception ex)\r
81         {\r
82         }\r
83 \r
84         BufferedImage bi = new BufferedImage(temp.getHeight(this),\r
85                 temp.getWidth(this), BufferedImage.TYPE_INT_RGB);\r
86         Graphics2D g = (Graphics2D) bi.getGraphics();\r
87         g.rotate(Math.toRadians(90));\r
88         g.drawImage(temp, 0, -bi.getWidth(this), this);\r
89         image = (Image) bi;\r
90 \r
91         addMouseListener(this);\r
92         addMouseMotionListener(this);\r
93     }\r
94 \r
95     public AnnotationLabels(AlignViewport av)\r
96     {\r
97       this.av = av;\r
98     }\r
99 \r
100     /**\r
101      * DOCUMENT ME!\r
102      *\r
103      * @param y DOCUMENT ME!\r
104      */\r
105     public void setScrollOffset(int y)\r
106     {\r
107         scrollOffset = y;\r
108         repaint();\r
109     }\r
110 \r
111     void getSelectedRow(int y)\r
112     {\r
113       int height = 0;\r
114       AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();\r
115 \r
116       for (int i = 0; i < aa.length; i++)\r
117       {\r
118         if (!aa[i].visible)\r
119         {\r
120           continue;\r
121         }\r
122 \r
123         height += aa[i].height;\r
124 \r
125         if (y < height)\r
126         {\r
127           selectedRow = i;\r
128 \r
129           break;\r
130         }\r
131       }\r
132     }\r
133 \r
134     /**\r
135      * DOCUMENT ME!\r
136      *\r
137      * @param evt DOCUMENT ME!\r
138      */\r
139     public void actionPerformed(ActionEvent evt)\r
140     {\r
141         int dif = 0;\r
142         AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();\r
143 \r
144         if (evt.getActionCommand().equals(ADDNEW))\r
145         {\r
146             String label = JOptionPane.showInputDialog(this,\r
147                     "Label for annotation");\r
148 \r
149             if (label == null)\r
150             {\r
151                 label = "";\r
152             }\r
153 \r
154             AlignmentAnnotation newAnnotation = new AlignmentAnnotation(label,\r
155                     "New description",\r
156                     new Annotation[ap.av.alignment.getWidth()]);\r
157 \r
158             ap.av.alignment.addAnnotation(newAnnotation);\r
159             ap.av.alignment.setAnnotationIndex(newAnnotation, 0);\r
160             dif = aa[aa.length - 1].height;\r
161         }\r
162         else if (evt.getActionCommand().equals(HIDE))\r
163         {\r
164             aa[selectedRow].visible = false;\r
165 \r
166             if (aa[selectedRow].label.equals("Conservation"))\r
167             {\r
168                 ap.av.showConservation = false;\r
169             }\r
170 \r
171             if (aa[selectedRow].label.equals("Quality"))\r
172             {\r
173                 ap.av.showQuality = false;\r
174             }\r
175 \r
176             if (aa[selectedRow].label.equals("Consensus"))\r
177             {\r
178                 ap.av.showIdentity = false;\r
179             }\r
180 \r
181             dif = aa[selectedRow].height * -1;\r
182         }\r
183         else if (evt.getActionCommand().equals(DELETE))\r
184         {\r
185             ap.av.alignment.deleteAnnotation(aa[selectedRow]);\r
186             dif = aa[selectedRow].height * -1;\r
187         }\r
188         else if (evt.getActionCommand().equals(SHOWALL))\r
189         {\r
190             for (int i = 0; i < aa.length; i++)\r
191             {\r
192                 if (!aa[i].visible)\r
193                 {\r
194                     dif += aa[i].height;\r
195                     aa[i].visible = true;\r
196                 }\r
197             }\r
198         }\r
199         else if (evt.getActionCommand().equals(OUTPUT_TEXT))\r
200         {\r
201             CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
202             Desktop.addInternalFrame(cap,\r
203                 ap.alignFrame.getTitle() + " - " + aa[selectedRow].label, 500,\r
204                 100);\r
205             cap.setText(aa[selectedRow].toString());\r
206         }\r
207 \r
208 \r
209         ap.annotationPanel.adjustPanelHeight();\r
210         ap.annotationScroller.validate();\r
211         ap.repaint();\r
212     }\r
213 \r
214     /**\r
215      * DOCUMENT ME!\r
216      *\r
217      * @param evt DOCUMENT ME!\r
218      */\r
219     public void mousePressed(MouseEvent evt)\r
220     {\r
221         getSelectedRow(evt.getY() - scrollOffset);\r
222         oldY = evt.getY();\r
223     }\r
224 \r
225     /**\r
226      * DOCUMENT ME!\r
227      *\r
228      * @param evt DOCUMENT ME!\r
229      */\r
230     public void mouseReleased(MouseEvent evt)\r
231     {\r
232         int start = selectedRow;\r
233         getSelectedRow(evt.getY() - scrollOffset);\r
234         int end = selectedRow;\r
235 \r
236         if(start!=end)\r
237         {\r
238           //Swap these annotations\r
239           AlignmentAnnotation startAA = ap.av.alignment.getAlignmentAnnotation()[start];\r
240           AlignmentAnnotation endAA = ap.av.alignment.getAlignmentAnnotation()[end];\r
241 \r
242 \r
243           ap.av.alignment.getAlignmentAnnotation()[end] = startAA;\r
244           ap.av.alignment.getAlignmentAnnotation()[start] = endAA;\r
245         }\r
246 \r
247         resizePanel = false;\r
248         dragEvent = null;\r
249         repaint();\r
250         ap.annotationPanel.repaint();\r
251     }\r
252 \r
253     /**\r
254      * DOCUMENT ME!\r
255      *\r
256      * @param evt DOCUMENT ME!\r
257      */\r
258     public void mouseEntered(MouseEvent evt)\r
259     {\r
260       if(evt.getY()<10)\r
261       {\r
262         resizePanel = true;\r
263         repaint();\r
264       }\r
265     }\r
266 \r
267     /**\r
268      * DOCUMENT ME!\r
269      *\r
270      * @param evt DOCUMENT ME!\r
271      */\r
272     public void mouseExited(MouseEvent evt)\r
273     {       }\r
274 \r
275     /**\r
276      * DOCUMENT ME!\r
277      *\r
278      * @param evt DOCUMENT ME!\r
279      */\r
280     public void mouseDragged(MouseEvent evt)\r
281     {\r
282       dragEvent = evt;\r
283 \r
284       if (resizePanel)\r
285       {\r
286         Dimension d = ap.annotationScroller.getPreferredSize();\r
287         int dif = evt.getY() - oldY;\r
288 \r
289         dif /= ap.av.charHeight;\r
290         dif *= ap.av.charHeight;\r
291 \r
292         if ( (d.height - dif) > 20)\r
293         {\r
294           ap.annotationScroller.setPreferredSize(new Dimension(d.width,\r
295               d.height - dif));\r
296           d = ap.annotationSpaceFillerHolder.getPreferredSize();\r
297           ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(\r
298               d.width, d.height - dif));\r
299           ap.repaint();\r
300         }\r
301 \r
302         ap.addNotify();\r
303       }\r
304       else\r
305         repaint();\r
306     }\r
307 \r
308     /**\r
309      * DOCUMENT ME!\r
310      *\r
311      * @param evt DOCUMENT ME!\r
312      */\r
313     public void mouseMoved(MouseEvent evt)\r
314     {\r
315       resizePanel = evt.getY()<10;\r
316 \r
317       repaint();\r
318     }\r
319 \r
320     /**\r
321      * DOCUMENT ME!\r
322      *\r
323      * @param evt DOCUMENT ME!\r
324      */\r
325     public void mouseClicked(MouseEvent evt)\r
326     {\r
327        if(!SwingUtilities.isRightMouseButton(evt))\r
328          return;\r
329 \r
330         AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();\r
331 \r
332         if ((aa == null) || (aa.length == 0))\r
333         {\r
334             JPopupMenu pop = new JPopupMenu("Annotations");\r
335             JMenuItem item = new JMenuItem(ADDNEW);\r
336             item.addActionListener(this);\r
337             pop.add(item);\r
338             pop.show(this, evt.getX(), evt.getY());\r
339 \r
340             return;\r
341         }\r
342 \r
343 \r
344         JPopupMenu pop = new JPopupMenu("Annotations");\r
345         JMenuItem item = new JMenuItem(ADDNEW);\r
346         item.addActionListener(this);\r
347         pop.add(item);\r
348         item = new JMenuItem(HIDE);\r
349         item.addActionListener(this);\r
350         pop.add(item);\r
351         item = new JMenuItem(DELETE);\r
352         item.addActionListener(this);\r
353         pop.add(item);\r
354         item = new JMenuItem(SHOWALL);\r
355         item.addActionListener(this);\r
356         pop.add(item);\r
357         item = new JMenuItem(OUTPUT_TEXT);\r
358         item.addActionListener(this);\r
359         pop.add(item);\r
360 \r
361         if (aa[selectedRow].label.equals("Consensus"))\r
362         {\r
363           pop.addSeparator();\r
364           final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(\r
365               "Ignore Gaps In Consensus",\r
366               ap.av.getIgnoreGapsConsensus());\r
367           cbmi.addActionListener(new ActionListener()\r
368               {public void actionPerformed(ActionEvent e)\r
369                {\r
370                  ap.av.setIgnoreGapsConsensus(cbmi.getState());\r
371                  ap.repaint();\r
372                }\r
373               });\r
374           pop.add(cbmi);\r
375 \r
376         }\r
377 \r
378         pop.show(this, evt.getX(), evt.getY());\r
379     }\r
380 \r
381     /**\r
382      * DOCUMENT ME!\r
383      *\r
384      * @param g1 DOCUMENT ME!\r
385      */\r
386     public void paintComponent(Graphics g)\r
387     {\r
388 \r
389         int width = getWidth();\r
390         if(width==0)\r
391          width = ap.calculateIdWidth().width + 4;\r
392 \r
393        Graphics2D g2 = (Graphics2D) g;\r
394        if(av.antiAlias)\r
395         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
396             RenderingHints.VALUE_ANTIALIAS_ON);\r
397 \r
398        drawComponent(g2, width);\r
399 \r
400     }\r
401 \r
402     /**\r
403      * DOCUMENT ME!\r
404      *\r
405      * @param g DOCUMENT ME!\r
406      */\r
407     public void drawComponent(Graphics g, int width)\r
408     {\r
409         if(av.getFont().getSize()<10)\r
410           g.setFont(new Font("Arial", Font.PLAIN, av.getFont().getSize()-1));\r
411         else\r
412           g.setFont(font);\r
413 \r
414         FontMetrics fm = g.getFontMetrics(g.getFont());\r
415         g.setColor(Color.white);\r
416         g.fillRect(0, 0, getWidth(), getHeight());\r
417 \r
418         g.translate(0, scrollOffset);\r
419         g.setColor(Color.black);\r
420 \r
421         AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
422         int fontHeight = g.getFont().getSize();\r
423         int y = fontHeight;\r
424         int x = 0;\r
425         int graphExtras = 0;\r
426 \r
427 \r
428 \r
429         if (aa != null)\r
430         {\r
431             for (int i = 0; i < aa.length; i++)\r
432             {\r
433                 if (!aa[i].visible)\r
434                 {\r
435                     continue;\r
436                 }\r
437 \r
438                 x = width - fm.stringWidth(aa[i].label) - 3;\r
439 \r
440                 if (aa[i].graph>0)\r
441                 {\r
442                     graphExtras = y;\r
443 \r
444                     y += (aa[i].height / 3);\r
445 \r
446                     if(aa[i].graphGroup<0)\r
447                         graphExtras = y + fontHeight;\r
448                 }\r
449 \r
450                 if(aa[i].graphGroup>-1)\r
451                 {\r
452                   int groupSize = 0;\r
453                   for (int gg = 0; gg < aa.length; gg++)\r
454                   {\r
455                     if (aa[gg].graphGroup == aa[i].graphGroup)\r
456                       groupSize++;\r
457                   }\r
458 \r
459                   if(groupSize * (fontHeight+8) < aa[i].height)\r
460                     graphExtras += (aa[i].height -( groupSize * (fontHeight+8)) )/2;\r
461 \r
462                  for(int gg=0; gg<aa.length; gg++)\r
463                  {\r
464                    if(aa[gg].graphGroup==aa[i].graphGroup)\r
465                    {\r
466                      x = width - fm.stringWidth(aa[gg].label) - 3;\r
467                      g.drawString(aa[gg].label, x, graphExtras );\r
468                      if(aa[gg].annotations[0]!=null)\r
469                        g.setColor(aa[gg].annotations[0].colour);\r
470 \r
471                      g.drawLine( x, graphExtras+3,\r
472                                  x+fm.stringWidth(aa[gg].label),\r
473                                  graphExtras+3);\r
474 \r
475                      g.setColor(Color.black);\r
476                      graphExtras += fontHeight+8;\r
477                    }\r
478                  }\r
479                 }\r
480                 else\r
481                   g.drawString(aa[i].label, x, y);\r
482 \r
483                 if (aa[i].graph>0)\r
484                 {\r
485                 /*  if (aa[i].graphLines != null)\r
486                   {\r
487                     for (int gl = 0; gl < aa[i].graphLines.size(); gl++)\r
488                     {\r
489                        x = width - fm.stringWidth(aa[i].getGraphLine(gl).label) - 3;\r
490                       g.drawString(aa[i].getGraphLine(gl).label, x, graphExtras);\r
491                       g.setColor(aa[i].getGraphLine(gl).colour);\r
492                       Graphics2D g2 = (Graphics2D) g;\r
493                       g2.setStroke(new BasicStroke(1,\r
494                           BasicStroke.CAP_SQUARE,\r
495                           BasicStroke.JOIN_ROUND, 3f,\r
496                           new float[]\r
497                           {5f, 3f}, 0f));\r
498 \r
499                       graphExtras += 3;\r
500 \r
501                       g.drawLine(x, graphExtras,\r
502                                  x+fm.stringWidth(aa[i].label),\r
503                                  graphExtras);\r
504                       g2.setStroke(new BasicStroke());\r
505                     }\r
506                   }*/\r
507                     y += ((2 * aa[i].height) / 3);\r
508                 }\r
509                 else\r
510                 {\r
511                     y += aa[i].height;\r
512                 }\r
513             }\r
514         }\r
515 \r
516         if (resizePanel)\r
517         {\r
518           g.drawImage(image, 2, 0 - scrollOffset, this);\r
519         }\r
520         else if (dragEvent != null)\r
521         {\r
522           g.setColor(Color.lightGray);\r
523           g.drawString(aa[selectedRow].label, dragEvent.getX(), dragEvent.getY() - scrollOffset);\r
524         }\r
525 \r
526 \r
527         if ((aa == null) || (aa.length < 1))\r
528         {\r
529             g.drawString("Right click", 2, 8);\r
530             g.drawString("to add annotation", 2, 18);\r
531         }\r
532     }\r
533 }\r