1.2ish awt methods and excluding unused code
[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 import java.awt.image.BufferedImage;
25
26 import jalview.datamodel.*;
27
28 public class AnnotationLabels extends Panel implements ActionListener,
29         MouseListener, MouseMotionListener
30 {
31   Image image;
32
33   boolean active = false;
34
35   AlignmentPanel ap;
36
37   AlignViewport av;
38
39   boolean resizing = false;
40
41   int oldY, mouseX;
42
43   static String ADDNEW = "Add New Row";
44
45   static String EDITNAME = "Edit Label/Description";
46
47   static String HIDE = "Hide This Row";
48
49   static String SHOWALL = "Show All Hidden Rows";
50
51   static String OUTPUT_TEXT = "Show Values In Textbox";
52
53   static String COPYCONS_SEQ = "Copy Consensus Sequence";
54
55   int scrollOffset = 0;
56
57   int selectedRow = -1;
58
59   Tooltip tooltip;
60
61   private boolean hasHiddenRows;
62
63   public AnnotationLabels(AlignmentPanel ap)
64   {
65     this.ap = ap;
66     this.av = ap.av;
67     setLayout(null);
68
69     /**
70      * this retrieves the adjustable height glyph from resources. we don't use it at the moment.
71     java.net.URL url = getClass().getResource("/images/idwidth.gif");
72     Image temp = null;
73
74     if (url != null)
75     {
76       temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);
77     }
78
79     try
80     {
81       MediaTracker mt = new MediaTracker(this);
82       mt.addImage(temp, 0);
83       mt.waitForID(0);
84     } catch (Exception ex)
85     {
86     }
87
88     BufferedImage bi = new BufferedImage(temp.getHeight(this),
89             temp.getWidth(this), BufferedImage.TYPE_INT_RGB);
90     Graphics2D g = (Graphics2D) bi.getGraphics();
91     g.rotate(Math.toRadians(90));
92     g.drawImage(temp, 0, -bi.getWidth(this), this);
93     image = (Image) bi;
94 */
95     addMouseListener(this);
96     addMouseMotionListener(this);
97   }
98
99   public AnnotationLabels(AlignViewport av)
100   {
101     this.av = av;
102   }
103
104   public void setScrollOffset(int y)
105   {
106     scrollOffset = y;
107     repaint();
108   }
109
110   /**
111    * 
112    * @param y
113    * @return -2 if no rows are visible at all, -1 if no visible rows were
114    *         selected
115    */
116   int getSelectedRow(int y)
117   {
118     int row = -2;
119     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
120
121     if (aa == null)
122     {
123       return row;
124     }
125     int height = 0;
126     for (int i = 0; i < aa.length; i++)
127     {
128       row = -1;
129       if (!aa[i].visible)
130       {
131         continue;
132       }
133       height += aa[i].height;
134       if (y < height)
135       {
136         row = i;
137         break;
138       }
139     }
140
141     return row;
142   }
143
144   public void actionPerformed(ActionEvent evt)
145   {
146     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
147
148     if (evt.getActionCommand().equals(ADDNEW))
149     {
150       AlignmentAnnotation newAnnotation = new AlignmentAnnotation("", null,
151               new Annotation[ap.av.alignment.getWidth()]);
152
153       if (!editLabelDescription(newAnnotation))
154       {
155         return;
156       }
157
158       ap.av.alignment.addAnnotation(newAnnotation);
159       ap.av.alignment.setAnnotationIndex(newAnnotation, 0);
160     }
161     else if (evt.getActionCommand().equals(EDITNAME))
162     {
163       editLabelDescription(aa[selectedRow]);
164     }
165     else if (evt.getActionCommand().equals(HIDE))
166     {
167       aa[selectedRow].visible = false;
168     }
169     else if (evt.getActionCommand().equals(SHOWALL))
170     {
171       for (int i = 0; i < aa.length; i++)
172       {
173         aa[i].visible = (aa[i].annotations == null) ? false : true;
174       }
175     }
176     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
177     {
178       CutAndPasteTransfer cap = new CutAndPasteTransfer(false,
179               ap.alignFrame);
180       Frame frame = new Frame();
181       frame.add(cap);
182       jalview.bin.JalviewLite.addFrame(frame, ap.alignFrame.getTitle()
183               + " - " + aa[selectedRow].label, 500, 100);
184       cap.setText(aa[selectedRow].toString());
185     }
186     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
187     {
188       SequenceI cons = av.getConsensusSeq();
189       if (cons != null)
190       {
191         copy_annotseqtoclipboard(cons);
192       }
193
194     }
195     ap.annotationPanel.adjustPanelHeight();
196     setSize(getSize().width, ap.annotationPanel.getSize().height);
197     ap.validate();
198     ap.paintAlignment(true);
199   }
200
201   boolean editLabelDescription(AlignmentAnnotation annotation)
202   {
203     Checkbox padGaps = new Checkbox("Fill Empty Gaps With \""
204             + ap.av.getGapCharacter() + "\"", annotation.padGaps);
205
206     EditNameDialog dialog = new EditNameDialog(annotation.label,
207             annotation.description, "      Annotation Label",
208             "Annotation Description", ap.alignFrame,
209             "Edit Annotation Name / Description", 500, 180, false);
210
211     Panel empty = new Panel(new FlowLayout());
212     empty.add(padGaps);
213     dialog.add(empty);
214     dialog.pack();
215
216     dialog.setVisible(true);
217
218     if (dialog.accept)
219     {
220       annotation.label = dialog.getName();
221       annotation.description = dialog.getDescription();
222       annotation.setPadGaps(padGaps.getState(), av.getGapCharacter());
223       repaint();
224       return true;
225     }
226     else
227       return false;
228
229   }
230
231   boolean resizePanel = false;
232
233   public void mouseMoved(MouseEvent evt)
234   {
235     resizePanel = evt.getY() < 10;
236
237     int row = getSelectedRow(evt.getY() + scrollOffset);
238
239     if (row > -1)
240     {
241       if (tooltip == null)
242       {
243         tooltip = new Tooltip(
244                 ap.av.alignment.getAlignmentAnnotation()[row]
245                         .getDescription(true),
246                 this);
247       }
248       else
249       {
250         tooltip.setTip(ap.av.alignment.getAlignmentAnnotation()[row]
251                 .getDescription(true));
252       }
253     }
254     else if (tooltip != null)
255     {
256       tooltip.setTip("");
257     }
258
259   }
260
261   MouseEvent dragEvent = null;
262
263   public void mouseDragged(MouseEvent evt)
264   {
265     dragEvent = evt;
266
267     if (resizePanel)
268     {
269       Dimension d = ap.annotationPanelHolder.getSize(),e = ap.annotationSpaceFillerHolder.getSize();;
270       int dif = evt.getY() - oldY;
271
272       dif /= ap.av.charHeight;
273       dif *= ap.av.charHeight;
274
275       if ((d.height - dif) > 20)
276       {
277         
278         setSize(new Dimension(e.width,d.height-dif));
279         ap.annotationSpaceFillerHolder.setSize(new Dimension(e.width, d.height - dif));
280         ap.annotationPanelHolder.setSize(new Dimension(d.width, d.height - dif));
281         ap.apvscroll.setValues(ap.apvscroll.getValue(), d.height-dif, 0, ap.annotationPanel.adjustPanelHeight(false));
282         
283         ap.validate();
284         //ap.paintAlignment(true);
285       }
286
287       ap.addNotify();
288     }
289     else
290     {
291       repaint();
292     }
293   }
294
295   public void mouseClicked(MouseEvent evt)
296   {
297   }
298
299   public void mouseReleased(MouseEvent evt)
300   {
301     resizePanel = false;
302     dragEvent = null;
303     repaint();
304     ap.annotationPanel.repaint();
305   }
306
307   public void mouseEntered(MouseEvent evt)
308   {
309     if (evt.getY() < 10)
310     {
311       resizePanel = true;
312       repaint();
313     }
314   }
315
316   public void mouseExited(MouseEvent evt)
317   {
318
319     if (dragEvent == null)
320     {
321       resizePanel = false;
322     }
323     else
324     {
325       if (!resizePanel)
326       {
327         dragEvent = null;
328       }
329     }
330     repaint();
331   }
332
333   public void mousePressed(MouseEvent evt)
334   {
335     oldY = evt.getY();
336     // todo: move below to mouseClicked ?
337     selectedRow = getSelectedRow(evt.getY() + scrollOffset);
338
339     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
340
341     // DETECT RIGHT MOUSE BUTTON IN AWT
342     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
343     {
344
345       PopupMenu popup = new PopupMenu("Annotations");
346
347       MenuItem item = new MenuItem(ADDNEW);
348       item.addActionListener(this);
349       popup.add(item);
350       if (selectedRow < 0)
351       {
352         // this never happens at moment: - see comment on JAL-563
353         if (hasHiddenRows)
354         {
355           item = new MenuItem(SHOWALL);
356           item.addActionListener(this);
357           popup.add(item);
358         }
359         this.add(popup);
360         popup.show(this, evt.getX(), evt.getY());
361         return;
362       }
363       // add the rest if there are actually rows to show
364       item = new MenuItem(EDITNAME);
365       item.addActionListener(this);
366       popup.add(item);
367       item = new MenuItem(HIDE);
368       item.addActionListener(this);
369       popup.add(item);
370       if (hasHiddenRows)
371       {
372         item = new MenuItem(SHOWALL);
373         item.addActionListener(this);
374         popup.add(item);
375       }
376       this.add(popup);
377       item = new MenuItem(OUTPUT_TEXT);
378       item.addActionListener(this);
379       popup.add(item);
380
381       if (aa[selectedRow] == ap.av.consensus)
382       {
383         popup.addSeparator();
384         final CheckboxMenuItem cbmi = new CheckboxMenuItem(
385                 "Ignore Gaps In Consensus", ap.av.getIgnoreGapsConsensus());
386
387         cbmi.addItemListener(new ItemListener()
388         {
389           public void itemStateChanged(ItemEvent e)
390           {
391             ap.av.setIgnoreGapsConsensus(cbmi.getState());
392             ap.paintAlignment(true);
393           }
394         });
395         popup.add(cbmi);
396         item = new MenuItem(COPYCONS_SEQ);
397         item.addActionListener(this);
398         popup.add(item);
399       }
400
401       popup.show(this, evt.getX(), evt.getY());
402     }
403     else
404     {
405       // selection action.
406       if (selectedRow > -1 && selectedRow < aa.length)
407       {
408         if (aa[selectedRow].groupRef != null)
409         {
410           if (evt.getClickCount() >= 2)
411           {
412             // todo: make the ap scroll to the selection - not necessary, first
413             // click highlights/scrolls, second selects
414             ap.seqPanel.ap.idPanel.highlightSearchResults(null);
415             ap.av.setSelectionGroup(// new SequenceGroup(
416             aa[selectedRow].groupRef); // );
417             ap.av.sendSelection();
418             ap.paintAlignment(false);
419             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
420           }
421           else
422           {
423             ap.seqPanel.ap.idPanel
424                     .highlightSearchResults(aa[selectedRow].groupRef
425                             .getSequences(null));
426           }
427           return;
428         }
429         else if (aa[selectedRow].sequenceRef != null)
430         {
431           Vector sr = new Vector();
432           sr.addElement(aa[selectedRow].sequenceRef);
433           if (evt.getClickCount() == 1)
434           {
435             ap.seqPanel.ap.idPanel.highlightSearchResults(sr);
436           }
437           else if (evt.getClickCount() >= 2)
438           {
439             ap.seqPanel.ap.idPanel.highlightSearchResults(null);
440             SequenceGroup sg = new SequenceGroup();
441             sg.addSequence(aa[selectedRow].sequenceRef, false);
442             ap.av.setSelectionGroup(sg);
443             ap.paintAlignment(false);
444             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
445             ap.av.sendSelection();
446           }
447
448         }
449       }
450
451     }
452   }
453
454   /**
455    * DOCUMENT ME!
456    * 
457    * @param e
458    *          DOCUMENT ME!
459    */
460   protected void copy_annotseqtoclipboard(SequenceI sq)
461   {
462     if (sq == null || sq.getLength() < 1)
463     {
464       return;
465     }
466     jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer();
467     jalview.appletgui.AlignFrame.copiedSequences.append(sq.getName() + "\t"
468             + sq.getStart() + "\t" + sq.getEnd() + "\t"
469             + sq.getSequenceAsString() + "\n");
470     if (av.hasHiddenColumns)
471     {
472       jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector();
473       for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
474       {
475         int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
476                 .elementAt(i);
477
478         jalview.appletgui.AlignFrame.copiedHiddenColumns
479                 .addElement(new int[]
480                 { region[0], region[1] });
481       }
482     }
483   }
484
485   public void update(Graphics g)
486   {
487     paint(g);
488   }
489
490   public void paint(Graphics g)
491   {
492     int w = getSize().width;
493     if (image == null || w != image.getWidth(this))
494     {
495       image = createImage(w, ap.annotationPanel.getSize().height);
496     }
497
498     drawComponent(image.getGraphics(), w);
499     g.drawImage(image, 0, 0, this);
500   }
501
502   public void drawComponent(Graphics g, int width)
503   {
504     g.setFont(av.getFont());
505     FontMetrics fm = g.getFontMetrics(av.getFont());
506     g.setColor(Color.white);
507     g.fillRect(0, 0, getSize().width, getSize().height);
508
509     g.translate(0, -scrollOffset);
510     g.setColor(Color.black);
511
512     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
513     int y = 0, fy = g.getFont().getSize();
514     int x = 0, offset;
515
516     if (aa != null)
517     {
518       hasHiddenRows = false;
519       for (int i = 0; i < aa.length; i++)
520       {
521         if (!aa[i].visible)
522         {
523           hasHiddenRows = true;
524           continue;
525         }
526
527         x = width - fm.stringWidth(aa[i].label) - 3;
528
529         y += aa[i].height;
530         offset = -(aa[i].height - fy) / 2;
531
532         g.drawString(aa[i].label, x, y + offset);
533       }
534     }
535     g.translate(0, +scrollOffset);
536     if (resizePanel)
537     {
538       g.setColor(Color.red);
539       g.setPaintMode();
540       g.drawLine(2, 8, 5, 2);
541       g.drawLine(5, 2, 8, 8);
542     }
543     else if (dragEvent != null && aa != null)
544     {
545       g.setColor(Color.lightGray);
546       g.drawString(aa[selectedRow].label, dragEvent.getX(),
547               dragEvent.getY());
548     }
549
550     if ((aa == null) || (aa.length < 1))
551     {
552       g.setColor(Color.black);
553       g.drawString("Right click", 2, 8);
554       g.drawString("to add annotation", 2, 18);
555     }
556   }
557
558 }