applied copyright 2008
[jalview.git] / src / jalview / appletgui / AnnotationLabels.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.appletgui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25
26 import jalview.datamodel.*;
27
28 public class AnnotationLabels
29     extends Panel implements ActionListener, MouseListener, MouseMotionListener
30 {
31   Image image;
32   boolean active = false;
33   AlignmentPanel ap;
34   AlignViewport av;
35   boolean resizing = false;
36   int oldY, mouseX;
37
38   static String ADDNEW = "Add New Row";
39   static String EDITNAME = "Edit Label/Description";
40   static String HIDE = "Hide This Row";
41   static String SHOWALL = "Show All Hidden Rows";
42   static String OUTPUT_TEXT = "Show Values In Textbox";
43   static String COPYCONS_SEQ = "Copy Consensus Sequence";
44
45   int scrollOffset = 0;
46   int selectedRow = -1;
47
48   Tooltip tooltip;
49
50   public AnnotationLabels(AlignmentPanel ap)
51   {
52     this.ap = ap;
53     this.av = ap.av;
54     setLayout(null);
55     addMouseListener(this);
56     addMouseMotionListener(this);
57   }
58
59   public AnnotationLabels(AlignViewport av)
60   {
61     this.av = av;
62   }
63
64   public void setScrollOffset(int y)
65   {
66     scrollOffset = y;
67     repaint();
68   }
69
70   int getSelectedRow(int y)
71   {
72     int row = -1;
73     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
74
75     if (aa == null)
76     {
77       return row;
78     }
79
80     int height = 0;
81     for (int i = 0; i < aa.length; i++)
82     {
83       if (!aa[i].visible)
84       {
85         continue;
86       }
87
88       height += aa[i].height;
89       if (y < height)
90       {
91         row = i;
92         break;
93       }
94     }
95
96     return row;
97   }
98
99   public void actionPerformed(ActionEvent evt)
100   {
101     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
102
103     if (evt.getActionCommand().equals(ADDNEW))
104     {
105       AlignmentAnnotation newAnnotation = new AlignmentAnnotation("",
106           null,
107           new Annotation[ap.av.alignment.getWidth()]);
108
109       if (!editLabelDescription(newAnnotation))
110       {
111         return;
112       }
113
114       ap.av.alignment.addAnnotation(newAnnotation);
115       ap.av.alignment.setAnnotationIndex(newAnnotation, 0);
116     }
117     else if (evt.getActionCommand().equals(EDITNAME))
118     {
119       editLabelDescription(aa[selectedRow]);
120     }
121     else if (evt.getActionCommand().equals(HIDE))
122     {
123       aa[selectedRow].visible = false;
124     }
125     else if (evt.getActionCommand().equals(SHOWALL))
126     {
127       for (int i = 0; i < aa.length; i++)
128       {
129         aa[i].visible = (aa[i].annotations==null) ? false : true;
130       }
131     }
132     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
133     {
134       CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
135       Frame frame = new Frame();
136       frame.add(cap);
137       jalview.bin.JalviewLite.addFrame(frame,
138                                        ap.alignFrame.getTitle() + " - " +
139                                        aa[selectedRow].label, 500, 100);
140       cap.setText(aa[selectedRow].toString());
141     }
142     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
143     {
144       SequenceI cons = av.getConsensusSeq();
145       if (cons != null)
146       {
147         copy_annotseqtoclipboard(cons);
148       }
149
150     }
151     ap.annotationPanel.adjustPanelHeight();
152     setSize(getSize().width, ap.annotationPanel.getSize().height);
153     ap.validate();
154     ap.paintAlignment(true);
155   }
156
157   boolean editLabelDescription(AlignmentAnnotation annotation)
158   {
159     Checkbox padGaps = new Checkbox("Fill Empty Gaps With \""
160                                     +ap.av.getGapCharacter()+"\"",
161                                     annotation.padGaps);
162
163     EditNameDialog dialog = new EditNameDialog(
164         annotation.label,
165         annotation.description,
166         "      Annotation Label",
167         "Annotation Description",
168         ap.alignFrame,
169         "Edit Annotation Name / Description",
170         500, 180, false);
171
172     Panel empty = new Panel(new FlowLayout());
173     empty.add(padGaps);
174     dialog.add(empty);
175     dialog.pack();
176
177     dialog.setVisible(true);
178
179     if (dialog.accept)
180     {
181       annotation.label = dialog.getName();
182       annotation.description = dialog.getDescription();
183       annotation.setPadGaps(padGaps.getState(), av.getGapCharacter());
184       repaint();
185       return true;
186     }
187     else
188       return false;
189
190   }
191
192   public void mouseMoved(MouseEvent evt)
193   {
194     int row = getSelectedRow(evt.getY() - scrollOffset);
195
196     if (row > -1)
197     {
198       if (tooltip == null)
199       {
200         tooltip = new Tooltip(ap.av.alignment.
201                               getAlignmentAnnotation()[row].getDescription(true),
202                               this);
203       }
204       else
205       {
206         tooltip.setTip(ap.av.alignment.
207                        getAlignmentAnnotation()[row].getDescription(true));
208       }
209     }
210     else if (tooltip != null)
211     {
212       tooltip.setTip("");
213     }
214
215   }
216
217   public void mouseDragged(MouseEvent evt)
218   {}
219
220   public void mouseClicked(MouseEvent evt)
221   {}
222
223   public void mouseReleased(MouseEvent evt)
224   {}
225
226   public void mouseEntered(MouseEvent evt)
227   {}
228
229   public void mouseExited(MouseEvent evt)
230   {}
231
232   public void mousePressed(MouseEvent evt)
233   {
234     selectedRow = getSelectedRow(evt.getY() - scrollOffset);
235
236     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
237
238     PopupMenu popup = new PopupMenu("Annotations");
239
240     MenuItem item = new MenuItem(ADDNEW);
241     item.addActionListener(this);
242     popup.add(item);
243     item = new MenuItem(EDITNAME);
244     item.addActionListener(this);
245     popup.add(item);
246     item = new MenuItem(HIDE);
247     item.addActionListener(this);
248     popup.add(item);
249     item = new MenuItem(SHOWALL);
250     item.addActionListener(this);
251     popup.add(item);
252     this.add(popup);
253     item = new MenuItem(OUTPUT_TEXT);
254     item.addActionListener(this);
255     popup.add(item);
256
257     if (aa[selectedRow] == ap.av.consensus)
258     {
259       popup.addSeparator();
260       final CheckboxMenuItem cbmi = new CheckboxMenuItem(
261           "Ignore Gaps In Consensus",
262           ap.av.getIgnoreGapsConsensus());
263
264       cbmi.addItemListener(new ItemListener()
265       {
266         public void itemStateChanged(ItemEvent e)
267         {
268           ap.av.setIgnoreGapsConsensus(cbmi.getState());
269           ap.paintAlignment(true);
270         }
271       });
272       popup.add(cbmi);
273       item = new MenuItem(COPYCONS_SEQ);
274       item.addActionListener(this);
275       popup.add(item);
276     }
277
278     popup.show(this, evt.getX(), evt.getY());
279
280   }
281
282   /**
283    * DOCUMENT ME!
284    *
285    * @param e DOCUMENT ME!
286    */
287   protected void copy_annotseqtoclipboard(SequenceI sq)
288   {
289     if (sq == null || sq.getLength() < 1)
290     {
291       return;
292     }
293     jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer();
294     jalview.appletgui.AlignFrame.copiedSequences.append(sq.getName() + "\t" +
295         sq.getStart() + "\t" +
296         sq.getEnd() + "\t" +
297         sq.getSequenceAsString() + "\n");
298     if (av.hasHiddenColumns)
299     {
300       jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector();
301       for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
302       {
303         int[] region = (int[])
304             av.getColumnSelection().getHiddenColumns().elementAt(i);
305
306         jalview.appletgui.AlignFrame.copiedHiddenColumns.addElement(new int[]
307             {region[0],
308             region[1]});
309       }
310     }
311   }
312
313   public void update(Graphics g)
314   {
315     paint(g);
316   }
317
318   public void paint(Graphics g)
319   {
320     int w = getSize().width;
321     if (image == null || w != image.getWidth(this))
322     {
323       image = createImage(w, ap.annotationPanel.getSize().height);
324     }
325
326     drawComponent(image.getGraphics(), w);
327     g.drawImage(image, 0, 0, this);
328   }
329
330   public void drawComponent(Graphics g, int width)
331   {
332     g.setFont(av.getFont());
333     FontMetrics fm = g.getFontMetrics(av.getFont());
334     g.setColor(Color.white);
335     g.fillRect(0, 0, getSize().width, getSize().height);
336
337     g.translate(0, scrollOffset);
338     g.setColor(Color.black);
339
340     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
341     int y = g.getFont().getSize();
342     int x = 0;
343
344     if (aa != null)
345     {
346       for (int i = 0; i < aa.length; i++)
347       {
348         if (!aa[i].visible)
349         {
350           continue;
351         }
352
353         x = width - fm.stringWidth(aa[i].label) - 3;
354
355         if (aa[i].graph > 0)
356         {
357           y += (aa[i].height / 3);
358         }
359
360         g.drawString(aa[i].label, x, y);
361
362         if (aa[i].graph > 0)
363         {
364           y += (2 * aa[i].height / 3);
365         }
366         else
367         {
368           y += aa[i].height;
369         }
370       }
371     }
372   }
373
374 }