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