set index of new annotation
[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 active = false;\r
45     Image image;\r
46     AlignmentPanel ap;\r
47     AlignViewport av;\r
48     boolean resizing = false;\r
49     int oldY;\r
50     int mouseX;\r
51     int selectedRow = 0;\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     /**\r
112      * DOCUMENT ME!\r
113      *\r
114      * @param evt DOCUMENT ME!\r
115      */\r
116     public void actionPerformed(ActionEvent evt)\r
117     {\r
118         int dif = 0;\r
119         AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();\r
120 \r
121         if (evt.getActionCommand().equals(ADDNEW))\r
122         {\r
123             String label = JOptionPane.showInputDialog(this,\r
124                     "Label for annotation");\r
125 \r
126             if (label == null)\r
127             {\r
128                 label = "";\r
129             }\r
130 \r
131             AlignmentAnnotation newAnnotation = new AlignmentAnnotation(label,\r
132                     "New description",\r
133                     new Annotation[ap.av.alignment.getWidth()]);\r
134 \r
135             ap.av.alignment.addAnnotation(newAnnotation);\r
136             ap.av.alignment.setAnnotationIndex(newAnnotation, 0);\r
137             dif = aa[aa.length - 1].height;\r
138         }\r
139         else if (evt.getActionCommand().equals(HIDE))\r
140         {\r
141             aa[selectedRow].visible = false;\r
142 \r
143             if (aa[selectedRow].label.equals("Conservation"))\r
144             {\r
145                 ap.av.showConservation = false;\r
146             }\r
147 \r
148             if (aa[selectedRow].label.equals("Quality"))\r
149             {\r
150                 ap.av.showQuality = false;\r
151             }\r
152 \r
153             if (aa[selectedRow].label.equals("Consensus"))\r
154             {\r
155                 ap.av.showIdentity = false;\r
156             }\r
157 \r
158             dif = aa[selectedRow].height * -1;\r
159         }\r
160         else if (evt.getActionCommand().equals(DELETE))\r
161         {\r
162             ap.av.alignment.deleteAnnotation(aa[selectedRow]);\r
163             dif = aa[selectedRow].height * -1;\r
164         }\r
165         else if (evt.getActionCommand().equals(SHOWALL))\r
166         {\r
167             for (int i = 0; i < aa.length; i++)\r
168             {\r
169                 if (!aa[i].visible)\r
170                 {\r
171                     dif += aa[i].height;\r
172                     aa[i].visible = true;\r
173                 }\r
174             }\r
175         }\r
176         else if (evt.getActionCommand().equals(OUTPUT_TEXT))\r
177         {\r
178             CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
179             Desktop.addInternalFrame(cap,\r
180                 ap.alignFrame.getTitle() + " - " + aa[selectedRow].label, 500,\r
181                 100);\r
182             cap.setText(aa[selectedRow].toString());\r
183         }\r
184 \r
185 \r
186         ap.annotationPanel.adjustPanelHeight();\r
187         ap.annotationScroller.validate();\r
188         ap.repaint();\r
189     }\r
190 \r
191     /**\r
192      * DOCUMENT ME!\r
193      *\r
194      * @param evt DOCUMENT ME!\r
195      */\r
196     public void mousePressed(MouseEvent evt)\r
197     {\r
198         oldY = evt.getY();\r
199     }\r
200 \r
201     /**\r
202      * DOCUMENT ME!\r
203      *\r
204      * @param evt DOCUMENT ME!\r
205      */\r
206     public void mouseReleased(MouseEvent evt)\r
207     {\r
208         active = false;\r
209         repaint();\r
210     }\r
211 \r
212     /**\r
213      * DOCUMENT ME!\r
214      *\r
215      * @param evt DOCUMENT ME!\r
216      */\r
217     public void mouseEntered(MouseEvent evt)\r
218     {\r
219         active = true;\r
220         repaint();\r
221     }\r
222 \r
223     /**\r
224      * DOCUMENT ME!\r
225      *\r
226      * @param evt DOCUMENT ME!\r
227      */\r
228     public void mouseExited(MouseEvent evt)\r
229     {\r
230         active = false;\r
231         repaint();\r
232     }\r
233 \r
234     /**\r
235      * DOCUMENT ME!\r
236      *\r
237      * @param evt DOCUMENT ME!\r
238      */\r
239     public void mouseDragged(MouseEvent evt)\r
240     {\r
241         active = true;\r
242 \r
243         Dimension d = ap.annotationScroller.getPreferredSize();\r
244         int dif = evt.getY() - oldY;\r
245 \r
246         dif /= ap.av.charHeight;\r
247         dif *= ap.av.charHeight;\r
248 \r
249         if ((d.height - dif) > 20)\r
250         {\r
251             ap.annotationScroller.setPreferredSize(new Dimension(d.width,\r
252                     d.height - dif));\r
253             d = ap.annotationSpaceFillerHolder.getPreferredSize();\r
254             ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(\r
255                     d.width, d.height - dif));\r
256             ap.repaint();\r
257         }\r
258 \r
259         ap.addNotify();\r
260     }\r
261 \r
262     /**\r
263      * DOCUMENT ME!\r
264      *\r
265      * @param evt DOCUMENT ME!\r
266      */\r
267     public void mouseMoved(MouseEvent evt)\r
268     {\r
269     }\r
270 \r
271     /**\r
272      * DOCUMENT ME!\r
273      *\r
274      * @param evt DOCUMENT ME!\r
275      */\r
276     public void mouseClicked(MouseEvent evt)\r
277     {\r
278         int y = evt.getY() - scrollOffset;\r
279         AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();\r
280 \r
281         if ((aa == null) || (aa.length == 0))\r
282         {\r
283             JPopupMenu pop = new JPopupMenu("Annotations");\r
284             JMenuItem item = new JMenuItem(ADDNEW);\r
285             item.addActionListener(this);\r
286             pop.add(item);\r
287             pop.show(this, evt.getX(), evt.getY());\r
288 \r
289             return;\r
290         }\r
291 \r
292         int height = 0;\r
293 \r
294         for (int i = 0; i < aa.length; i++)\r
295         {\r
296             if (!aa[i].visible)\r
297             {\r
298                 continue;\r
299             }\r
300 \r
301             height += aa[i].height;\r
302 \r
303             if (y < height)\r
304             {\r
305                 selectedRow = i;\r
306 \r
307                 break;\r
308             }\r
309         }\r
310 \r
311         JPopupMenu pop = new JPopupMenu("Annotations");\r
312         JMenuItem item = new JMenuItem(ADDNEW);\r
313         item.addActionListener(this);\r
314         pop.add(item);\r
315         item = new JMenuItem(HIDE);\r
316         item.addActionListener(this);\r
317         pop.add(item);\r
318         item = new JMenuItem(DELETE);\r
319         item.addActionListener(this);\r
320         pop.add(item);\r
321         item = new JMenuItem(SHOWALL);\r
322         item.addActionListener(this);\r
323         pop.add(item);\r
324         item = new JMenuItem(OUTPUT_TEXT);\r
325         item.addActionListener(this);\r
326         pop.add(item);\r
327 \r
328         if (aa[selectedRow].label.equals("Consensus"))\r
329         {\r
330           pop.addSeparator();\r
331           final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(\r
332               "Ignore Gaps In Consensus",\r
333               ap.av.getIgnoreGapsConsensus());\r
334           cbmi.addActionListener(new ActionListener()\r
335               {public void actionPerformed(ActionEvent e)\r
336                {\r
337                  ap.av.setIgnoreGapsConsensus(cbmi.getState());\r
338                  ap.repaint();\r
339                }\r
340               });\r
341           pop.add(cbmi);\r
342 \r
343         }\r
344 \r
345         pop.show(this, evt.getX(), evt.getY());\r
346     }\r
347 \r
348     /**\r
349      * DOCUMENT ME!\r
350      *\r
351      * @param g1 DOCUMENT ME!\r
352      */\r
353     public void paintComponent(Graphics g)\r
354     {\r
355 \r
356         int width = getWidth();\r
357         if(width==0)\r
358          width = ap.calculateIdWidth().width + 4;\r
359 \r
360        Graphics2D g2 = (Graphics2D) g;\r
361        if(av.antiAlias)\r
362         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
363             RenderingHints.VALUE_ANTIALIAS_ON);\r
364 \r
365        drawComponent(g2, width);\r
366 \r
367     }\r
368 \r
369     /**\r
370      * DOCUMENT ME!\r
371      *\r
372      * @param g DOCUMENT ME!\r
373      */\r
374     public void drawComponent(Graphics g, int width)\r
375     {\r
376         if(av.getFont().getSize()<10)\r
377           g.setFont(new Font("Arial", Font.PLAIN, av.getFont().getSize()-1));\r
378         else\r
379           g.setFont(font);\r
380 \r
381         FontMetrics fm = g.getFontMetrics(g.getFont());\r
382         g.setColor(Color.white);\r
383         g.fillRect(0, 0, getWidth(), getHeight());\r
384 \r
385         g.translate(0, scrollOffset);\r
386         g.setColor(Color.black);\r
387 \r
388         AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
389         int fontHeight = g.getFont().getSize();\r
390         int y = fontHeight;\r
391         int x = 0;\r
392         int graphExtras = 0;\r
393 \r
394 \r
395 \r
396         if (aa != null)\r
397         {\r
398             for (int i = 0; i < aa.length; i++)\r
399             {\r
400                 if (!aa[i].visible)\r
401                 {\r
402                     continue;\r
403                 }\r
404 \r
405                 x = width - fm.stringWidth(aa[i].label) - 3;\r
406 \r
407                 if (aa[i].graph>0)\r
408                 {\r
409                     graphExtras = y;\r
410 \r
411                     y += (aa[i].height / 3);\r
412 \r
413                     if(aa[i].graphGroup<0)\r
414                         graphExtras = y + fontHeight;\r
415                 }\r
416 \r
417                 if(aa[i].graphGroup>-1)\r
418                 {\r
419                   int groupSize = 0;\r
420                   for (int gg = 0; gg < aa.length; gg++)\r
421                   {\r
422                     if (aa[gg].graphGroup == aa[i].graphGroup)\r
423                       groupSize++;\r
424                   }\r
425 \r
426                   if(groupSize * (fontHeight+8) < aa[i].height)\r
427                     graphExtras += (aa[i].height -( groupSize * (fontHeight+8)) )/2;\r
428 \r
429                  for(int gg=0; gg<aa.length; gg++)\r
430                  {\r
431                    if(aa[gg].graphGroup==aa[i].graphGroup)\r
432                    {\r
433                      x = width - fm.stringWidth(aa[gg].label) - 3;\r
434                      g.drawString(aa[gg].label, x, graphExtras );\r
435                      if(aa[gg].annotations[0]!=null)\r
436                        g.setColor(aa[gg].annotations[0].colour);\r
437 \r
438                      g.drawLine( x, graphExtras+3,\r
439                                  x+fm.stringWidth(aa[gg].label),\r
440                                  graphExtras+3);\r
441 \r
442                      g.setColor(Color.black);\r
443                      graphExtras += fontHeight+8;\r
444                    }\r
445                  }\r
446                 }\r
447                 else\r
448                   g.drawString(aa[i].label, x, y);\r
449 \r
450                 if (aa[i].graph>0)\r
451                 {\r
452                   if (aa[i].graphLines != null)\r
453                   {\r
454                     for (int gl = 0; gl < aa[i].graphLines.size(); gl++)\r
455                     {\r
456                        x = width - fm.stringWidth(aa[i].getGraphLine(gl).label) - 3;\r
457                       g.drawString(aa[i].getGraphLine(gl).label, x, graphExtras);\r
458                       g.setColor(aa[i].getGraphLine(gl).colour);\r
459                       Graphics2D g2 = (Graphics2D) g;\r
460                       g2.setStroke(new BasicStroke(1,\r
461                           BasicStroke.CAP_SQUARE,\r
462                           BasicStroke.JOIN_ROUND, 3f,\r
463                           new float[]\r
464                           {5f, 3f}, 0f));\r
465 \r
466                       graphExtras += 3;\r
467 \r
468                       g.drawLine(x, graphExtras,\r
469                                  x+fm.stringWidth(aa[i].label),\r
470                                  graphExtras);\r
471                       g2.setStroke(new BasicStroke());\r
472                     }\r
473                   }\r
474                     y += ((2 * aa[i].height) / 3);\r
475                 }\r
476                 else\r
477                 {\r
478                     y += aa[i].height;\r
479                 }\r
480             }\r
481         }\r
482 \r
483         if (active)\r
484         {\r
485             if (image != null)\r
486             {\r
487                 g.drawImage(image, 2, 0 - scrollOffset, this);\r
488             }\r
489         }\r
490 \r
491         if ((aa == null) || (aa.length < 1))\r
492         {\r
493             g.drawString("Right click", 2, 8);\r
494             g.drawString("to add annotation", 2, 18);\r
495         }\r
496     }\r
497 }\r