javadoc and constraint to ensure annotation labels are not wider than alignment frame
[jalview.git] / src / jalview / gui / IdPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 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.gui;
20
21 import java.awt.*;
22 import java.awt.event.*;
23 import javax.swing.*;
24
25 import jalview.datamodel.*;
26
27 /**
28  * DOCUMENT ME!
29  *
30  * @author $author$
31  * @version $Revision$
32  */
33 public class IdPanel
34     extends JPanel implements MouseListener,
35     MouseMotionListener, MouseWheelListener
36 {
37   protected IdCanvas idCanvas;
38   protected AlignViewport av;
39   protected AlignmentPanel alignPanel;
40   ScrollThread scrollThread = null;
41   int offy;
42   // int width;
43   int lastid = -1;
44   boolean mouseDragging = false;
45
46   /**
47    * Creates a new IdPanel object.
48    *
49    * @param av DOCUMENT ME!
50    * @param parent DOCUMENT ME!
51    */
52   public IdPanel(AlignViewport av, AlignmentPanel parent)
53   {
54     this.av = av;
55     alignPanel = parent;
56     idCanvas = new IdCanvas(av);
57     setLayout(new BorderLayout());
58     add(idCanvas, BorderLayout.CENTER);
59     addMouseListener(this);
60     addMouseMotionListener(this);
61     addMouseWheelListener(this);
62     ToolTipManager.sharedInstance().registerComponent(this);
63   }
64
65   /**
66    * DOCUMENT ME!
67    *
68    * @param e DOCUMENT ME!
69    */
70   public void mouseMoved(MouseEvent e)
71   {
72     int seq = Math.max(0, alignPanel.seqPanel.findSeq(e));
73     String tmp;
74     if (seq > -1 && seq < av.alignment.getHeight())
75     {
76       SequenceI sequence = av.alignment.getSequenceAt(seq);
77       StringBuffer tip = new StringBuffer();
78       tip.append("<i>");
79
80       int maxWidth = 0;
81       if (sequence.getDescription() != null)
82       {
83         tmp = sequence.getDescription();
84         tip.append("<br>"+tmp);
85         maxWidth = Math.max(maxWidth, tmp.length());
86       }
87
88       DBRefEntry[] dbrefs = sequence.getDatasetSequence().getDBRef();
89       if (dbrefs != null)
90       {
91         for (int i = 0; i < dbrefs.length; i++)
92         {
93           tip.append("<br>");
94           tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
95           tip.append(tmp);
96           maxWidth = Math.max(maxWidth, tmp.length());
97         }
98       }
99
100
101       //ADD NON POSITIONAL SEQUENCE INFO
102       SequenceFeature[] features = sequence.getDatasetSequence().
103           getSequenceFeatures();
104       if (features != null)
105       {
106         for (int i = 0; i < features.length; i++)
107         {
108           if (features[i].begin == 0 && features[i].end == 0)
109           {
110             tmp = features[i].featureGroup
111                        + " " + features[i].getType() + " " +
112                        features[i].description;
113             tip.append("<br>" + tmp);
114             maxWidth = Math.max(maxWidth, tmp.length());
115           }
116         }
117       }
118
119       if(maxWidth > 60)
120       {
121          tip.insert(0, "<table width=350 border=0><tr><td><i>");
122          tip.append("</i></td></tr></table>");
123       }
124
125       tip.append("</html>");
126
127       setToolTipText("<html>"+sequence.getDisplayId(true)+tip.toString());
128     }
129   }
130
131   /**
132    * DOCUMENT ME!
133    *
134    * @param e DOCUMENT ME!
135    */
136   public void mouseDragged(MouseEvent e)
137   {
138     mouseDragging = true;
139
140     int seq = Math.max(0, alignPanel.seqPanel.findSeq(e));
141
142     if (seq < lastid)
143     {
144       selectSeqs(lastid - 1, seq);
145     }
146     else if (seq > lastid)
147     {
148       selectSeqs(lastid + 1, seq);
149     }
150
151     lastid = seq;
152     alignPanel.paintAlignment(true);
153   }
154
155   public void mouseWheelMoved(MouseWheelEvent e)
156   {
157     e.consume();
158       if (e.getWheelRotation() > 0)
159       {
160         alignPanel.scrollUp(false);
161       }
162       else
163       {
164         alignPanel.scrollUp(true);
165       }
166   }
167
168   /**
169    * DOCUMENT ME!
170    *
171    * @param e DOCUMENT ME!
172    */
173   public void mouseClicked(MouseEvent e)
174   {
175     if (e.getClickCount() < 2)
176     {
177       return;
178     }
179
180     java.util.Vector links = Preferences.sequenceURLLinks;
181     if (links == null || links.size() < 1)
182     {
183       return;
184     }
185
186     int seq = alignPanel.seqPanel.findSeq(e);
187
188     //DEFAULT LINK IS FIRST IN THE LINK LIST
189
190     String id = av.getAlignment().getSequenceAt(seq).getName();
191     if (id.indexOf("|") > -1)
192     {
193       id = id.substring(id.lastIndexOf("|") + 1);
194     }
195
196     String url = links.elementAt(0).toString();
197     url = url.substring(url.indexOf("|") + 1);
198
199     int index = url.indexOf("$SEQUENCE_ID$");
200     url = url.substring(0, index) + id + url.substring(index + 13);
201
202     try
203     {
204       jalview.util.BrowserLauncher.openURL(url);
205     }
206     catch (Exception ex)
207     {
208       JOptionPane.showInternalMessageDialog(Desktop.desktop,
209                                             "Unixers: Couldn't find default web browser."
210                                             +
211           "\nAdd the full path to your browser in Preferences.",
212                                             "Web browser not found",
213                                             JOptionPane.WARNING_MESSAGE);
214       ex.printStackTrace();
215     }
216   }
217
218   /**
219    * DOCUMENT ME!
220    *
221    * @param e DOCUMENT ME!
222    */
223   public void mouseEntered(MouseEvent e)
224   {
225     if (scrollThread != null)
226     {
227       scrollThread.running = false;
228     }
229   }
230
231   /**
232    * DOCUMENT ME!
233    *
234    * @param e DOCUMENT ME!
235    */
236   public void mouseExited(MouseEvent e)
237   {
238     if (av.getWrapAlignment())
239     {
240       return;
241     }
242
243     if (mouseDragging && (e.getY() < 0) && (av.getStartSeq() > 0))
244     {
245       scrollThread = new ScrollThread(true);
246     }
247
248     if (mouseDragging && (e.getY() >= getHeight()) &&
249         (av.alignment.getHeight() > av.getEndSeq()))
250     {
251       scrollThread = new ScrollThread(false);
252     }
253   }
254
255   /**
256    * DOCUMENT ME!
257    *
258    * @param e DOCUMENT ME!
259    */
260   public void mousePressed(MouseEvent e)
261   {
262     if (e.getClickCount() == 2)
263     {
264       return;
265     }
266
267     int seq = alignPanel.seqPanel.findSeq(e);
268
269     if (javax.swing.SwingUtilities.isRightMouseButton(e))
270     {
271       jalview.gui.PopupMenu pop = new jalview.gui.PopupMenu(alignPanel,
272           (Sequence) av.getAlignment().getSequenceAt(seq),
273           Preferences.sequenceURLLinks);
274       pop.show(this, e.getX(), e.getY());
275
276       return;
277     }
278
279     if ( (av.getSelectionGroup() == null) ||
280         ( (!e.isControlDown() && !e.isShiftDown()) && av.getSelectionGroup() != null))
281     {
282       av.setSelectionGroup(new SequenceGroup());
283       av.getSelectionGroup().setStartRes(0);
284       av.getSelectionGroup().setEndRes(av.alignment.getWidth() - 1);
285     }
286
287     if (e.isShiftDown() && (lastid != -1))
288     {
289       selectSeqs(lastid, seq);
290     }
291     else
292     {
293       selectSeq(seq);
294     }
295
296     alignPanel.paintAlignment(true);
297   }
298
299   /**
300    * DOCUMENT ME!
301    *
302    * @param seq DOCUMENT ME!
303    */
304   void selectSeq(int seq)
305   {
306     lastid = seq;
307
308     SequenceI pickedSeq = av.getAlignment().getSequenceAt(seq);
309     av.getSelectionGroup().addOrRemove(pickedSeq, true);
310   }
311
312   /**
313    * DOCUMENT ME!
314    *
315    * @param start DOCUMENT ME!
316    * @param end DOCUMENT ME!
317    */
318   void selectSeqs(int start, int end)
319   {
320     if (av.getSelectionGroup() == null)
321     {
322       return;
323     }
324
325     if (end >= av.getAlignment().getHeight())
326     {
327       end = av.getAlignment().getHeight() - 1;
328     }
329
330     lastid = start;
331
332     if (end < start)
333     {
334       int tmp = start;
335       start = end;
336       end = tmp;
337       lastid = end;
338     }
339
340     for (int i = start; i <= end; i++)
341     {
342       av.getSelectionGroup().addSequence(av.getAlignment().getSequenceAt(i),
343                                          true);
344     }
345   }
346
347   /**
348    * DOCUMENT ME!
349    *
350    * @param e DOCUMENT ME!
351    */
352   public void mouseReleased(MouseEvent e)
353   {
354     if (scrollThread != null)
355     {
356       scrollThread.running = false;
357     }
358
359     mouseDragging = false;
360     PaintRefresher.Refresh(this, av.getSequenceSetId());
361   }
362
363   /**
364    * DOCUMENT ME!
365    *
366    * @param found DOCUMENT ME!
367    */
368   public void highlightSearchResults(java.util.Vector found)
369   {
370     idCanvas.setHighlighted(found);
371
372     if (found == null)
373     {
374       return;
375     }
376
377     int index = av.alignment.findIndex( (SequenceI) found.get(0));
378
379     // do we need to scroll the panel?
380     if ( (av.getStartSeq() > index) || (av.getEndSeq() < index))
381     {
382       alignPanel.setScrollValues(av.getStartRes(), index);
383     }
384   }
385
386   // this class allows scrolling off the bottom of the visible alignment
387   class ScrollThread
388       extends Thread
389   {
390     boolean running = false;
391     boolean up = true;
392
393     public ScrollThread(boolean up)
394     {
395       this.up = up;
396       start();
397     }
398
399     public void stopScrolling()
400     {
401       running = false;
402     }
403
404     public void run()
405     {
406       running = true;
407
408       while (running)
409       {
410         if (alignPanel.scrollUp(up))
411         {
412           // scroll was ok, so add new sequence to selection
413           int seq = av.getStartSeq();
414
415           if (!up)
416           {
417             seq = av.getEndSeq();
418           }
419
420           if (seq < lastid)
421           {
422             selectSeqs(lastid - 1, seq);
423           }
424           else if (seq > lastid)
425           {
426             selectSeqs(lastid + 1, seq);
427           }
428
429           lastid = seq;
430         }
431         else
432         {
433           running = false;
434         }
435
436         alignPanel.paintAlignment(false);
437
438         try
439         {
440           Thread.sleep(100);
441         }
442         catch (Exception ex)
443         {
444         }
445       }
446     }
447   }
448 }