Jalview 2.6 source licence
[jalview.git] / src / jalview / appletgui / AnnotationLabels.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)
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   private boolean hasHiddenRows;
61
62   public AnnotationLabels(AlignmentPanel ap)
63   {
64     this.ap = ap;
65     this.av = ap.av;
66     setLayout(null);
67     addMouseListener(this);
68     addMouseMotionListener(this);
69   }
70
71   public AnnotationLabels(AlignViewport av)
72   {
73     this.av = av;
74   }
75
76   public void setScrollOffset(int y)
77   {
78     scrollOffset = y;
79     repaint();
80   }
81
82   /**
83    * 
84    * @param y
85    * @return -2 if no rows are visible at all, -1 if no visible rows were selected
86    */
87   int getSelectedRow(int y)
88   {
89     int row = -2;
90     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
91
92     if (aa == null)
93     {
94       return row;
95     }
96     int height = 0;
97     for (int i = 0; i < aa.length; i++)
98     {
99       row = -1;
100       if (!aa[i].visible)
101       {
102         continue;
103       }
104       height += aa[i].height;
105       if (y < height)
106       {
107         row = i;
108         break;
109       }
110     }
111
112     return row;
113   }
114
115   public void actionPerformed(ActionEvent evt)
116   {
117     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
118
119     if (evt.getActionCommand().equals(ADDNEW))
120     {
121       AlignmentAnnotation newAnnotation = new AlignmentAnnotation("", null,
122               new Annotation[ap.av.alignment.getWidth()]);
123
124       if (!editLabelDescription(newAnnotation))
125       {
126         return;
127       }
128
129       ap.av.alignment.addAnnotation(newAnnotation);
130       ap.av.alignment.setAnnotationIndex(newAnnotation, 0);
131     }
132     else if (evt.getActionCommand().equals(EDITNAME))
133     {
134       editLabelDescription(aa[selectedRow]);
135     }
136     else if (evt.getActionCommand().equals(HIDE))
137     {
138       aa[selectedRow].visible = false;
139     }
140     else if (evt.getActionCommand().equals(SHOWALL))
141     {
142       for (int i = 0; i < aa.length; i++)
143       {
144         aa[i].visible = (aa[i].annotations == null) ? false : true;
145       }
146     }
147     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
148     {
149       CutAndPasteTransfer cap = new CutAndPasteTransfer(false,
150               ap.alignFrame);
151       Frame frame = new Frame();
152       frame.add(cap);
153       jalview.bin.JalviewLite.addFrame(frame, ap.alignFrame.getTitle()
154               + " - " + aa[selectedRow].label, 500, 100);
155       cap.setText(aa[selectedRow].toString());
156     }
157     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
158     {
159       SequenceI cons = av.getConsensusSeq();
160       if (cons != null)
161       {
162         copy_annotseqtoclipboard(cons);
163       }
164
165     }
166     ap.annotationPanel.adjustPanelHeight();
167     setSize(getSize().width, ap.annotationPanel.getSize().height);
168     ap.validate();
169     ap.paintAlignment(true);
170   }
171
172   boolean editLabelDescription(AlignmentAnnotation annotation)
173   {
174     Checkbox padGaps = new Checkbox("Fill Empty Gaps With \""
175             + ap.av.getGapCharacter() + "\"", annotation.padGaps);
176
177     EditNameDialog dialog = new EditNameDialog(annotation.label,
178             annotation.description, "      Annotation Label",
179             "Annotation Description", ap.alignFrame,
180             "Edit Annotation Name / Description", 500, 180, false);
181
182     Panel empty = new Panel(new FlowLayout());
183     empty.add(padGaps);
184     dialog.add(empty);
185     dialog.pack();
186
187     dialog.setVisible(true);
188
189     if (dialog.accept)
190     {
191       annotation.label = dialog.getName();
192       annotation.description = dialog.getDescription();
193       annotation.setPadGaps(padGaps.getState(), av.getGapCharacter());
194       repaint();
195       return true;
196     }
197     else
198       return false;
199
200   }
201
202   public void mouseMoved(MouseEvent evt)
203   {
204     int row = getSelectedRow(evt.getY() - scrollOffset);
205
206     if (row > -1)
207     {
208       if (tooltip == null)
209       {
210         tooltip = new Tooltip(ap.av.alignment.getAlignmentAnnotation()[row]
211                 .getDescription(true), this);
212       }
213       else
214       {
215         tooltip.setTip(ap.av.alignment.getAlignmentAnnotation()[row]
216                 .getDescription(true));
217       }
218     }
219     else if (tooltip != null)
220     {
221       tooltip.setTip("");
222     }
223
224   }
225
226   public void mouseDragged(MouseEvent evt)
227   {
228   }
229
230   public void mouseClicked(MouseEvent evt)
231   {
232   }
233
234   public void mouseReleased(MouseEvent evt)
235   {
236   }
237
238   public void mouseEntered(MouseEvent evt)
239   {
240   }
241
242   public void mouseExited(MouseEvent evt)
243   {
244   }
245
246   public void mousePressed(MouseEvent evt)
247   {
248     selectedRow = getSelectedRow(evt.getY() - scrollOffset);
249
250     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
251
252     PopupMenu popup = new PopupMenu("Annotations");
253
254     MenuItem item = new MenuItem(ADDNEW);
255     item.addActionListener(this);
256     popup.add(item);
257     if (selectedRow<0)
258     {
259       // this never happens at moment: - see comment on JAL-563 
260       if (hasHiddenRows)
261       {
262          item = new MenuItem(SHOWALL);
263          item.addActionListener(this);
264          popup.add(item);
265       }
266       this.add(popup);
267       popup.show(this, evt.getX(), evt.getY());
268       return;
269     }
270     // add the rest if there are actually rows to show
271     item = new MenuItem(EDITNAME);
272     item.addActionListener(this);
273     popup.add(item);
274     item = new MenuItem(HIDE);
275     item.addActionListener(this);
276     popup.add(item);
277     if (hasHiddenRows) {
278       item = new MenuItem(SHOWALL);
279       item.addActionListener(this);
280       popup.add(item);
281     }
282     this.add(popup);
283     item = new MenuItem(OUTPUT_TEXT);
284     item.addActionListener(this);
285     popup.add(item);
286
287     if (aa[selectedRow] == ap.av.consensus)
288     {
289       popup.addSeparator();
290       final CheckboxMenuItem cbmi = new CheckboxMenuItem(
291               "Ignore Gaps In Consensus", ap.av.getIgnoreGapsConsensus());
292
293       cbmi.addItemListener(new ItemListener()
294       {
295         public void itemStateChanged(ItemEvent e)
296         {
297           ap.av.setIgnoreGapsConsensus(cbmi.getState());
298           ap.paintAlignment(true);
299         }
300       });
301       popup.add(cbmi);
302       item = new MenuItem(COPYCONS_SEQ);
303       item.addActionListener(this);
304       popup.add(item);
305     }
306
307     popup.show(this, evt.getX(), evt.getY());
308
309   }
310
311   /**
312    * DOCUMENT ME!
313    * 
314    * @param e
315    *          DOCUMENT ME!
316    */
317   protected void copy_annotseqtoclipboard(SequenceI sq)
318   {
319     if (sq == null || sq.getLength() < 1)
320     {
321       return;
322     }
323     jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer();
324     jalview.appletgui.AlignFrame.copiedSequences.append(sq.getName() + "\t"
325             + sq.getStart() + "\t" + sq.getEnd() + "\t"
326             + sq.getSequenceAsString() + "\n");
327     if (av.hasHiddenColumns)
328     {
329       jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector();
330       for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
331       {
332         int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
333                 .elementAt(i);
334
335         jalview.appletgui.AlignFrame.copiedHiddenColumns
336                 .addElement(new int[]
337                 { region[0], region[1] });
338       }
339     }
340   }
341
342   public void update(Graphics g)
343   {
344     paint(g);
345   }
346
347   public void paint(Graphics g)
348   {
349     int w = getSize().width;
350     if (image == null || w != image.getWidth(this))
351     {
352       image = createImage(w, ap.annotationPanel.getSize().height);
353     }
354
355     drawComponent(image.getGraphics(), w);
356     g.drawImage(image, 0, 0, this);
357   }
358
359   public void drawComponent(Graphics g, int width)
360   {
361     g.setFont(av.getFont());
362     FontMetrics fm = g.getFontMetrics(av.getFont());
363     g.setColor(Color.white);
364     g.fillRect(0, 0, getSize().width, getSize().height);
365
366     g.translate(0, scrollOffset);
367     g.setColor(Color.black);
368
369     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
370     int y = 0, fy=g.getFont().getSize();
371     int x = 0, offset;
372
373     if (aa != null)
374     {
375       hasHiddenRows=false;
376       for (int i = 0; i < aa.length; i++)
377       {
378         if (!aa[i].visible)
379         {
380           hasHiddenRows=true;
381           continue;
382         }
383
384         x = width - fm.stringWidth(aa[i].label) - 3;
385
386         y += aa[i].height;
387         offset = -(aa[i].height-fy)/2;
388
389         g.drawString(aa[i].label, x, y+offset);
390       }
391     }
392   }
393
394 }