JAL-1432 updated copyright notices
[jalview.git] / src / jalview / appletgui / Tooltip.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3  * Copyright (C) 2014 The Jalview Authors
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  * The Jalview Authors are detailed in the 'AUTHORS' file.
18  */
19 package jalview.appletgui;
20
21 import java.applet.*;
22 import java.util.*;
23
24 import java.awt.*;
25 import java.awt.event.*;
26
27 public class Tooltip extends Canvas implements MouseListener,
28         MouseMotionListener
29 {
30   private String[] tip;
31
32   private String lastTip = "";
33
34   private boolean setPosition = false;
35
36   protected Component owner;
37
38   private Container mainContainer;
39
40   private LayoutManager mainLayout;
41
42   private boolean shown;
43
44   private final int VERTICAL_OFFSET = 20;
45
46   private final int HORIZONTAL_ENLARGE = 10;
47
48   int fontHeight = 0;
49
50   Image linkImage;
51
52   FontMetrics fm;
53
54   public Tooltip(String tip, Component owner)
55   {
56     this.owner = owner;
57     owner.addMouseListener(this);
58     owner.addMouseMotionListener(this);
59     setBackground(new Color(255, 255, 220));
60     setTip(tip);
61     java.net.URL url = getClass().getResource("/images/link.gif");
62     if (url != null)
63     {
64       linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url);
65     }
66   }
67
68   public void paint(Graphics g)
69   {
70     int w = getSize().width;
71     int h = getSize().height;
72
73     g.drawRect(0, 0, w - 1, h - 1);
74     int lindex, x;
75     for (int i = 0; i < tip.length; i++)
76     {
77       x = 3;
78       lindex = tip[i].indexOf("%LINK%");
79       if (lindex != -1)
80       {
81         if (lindex > 0)
82         {
83           g.drawString(tip[i].substring(0, lindex), 3, (i + 1) * fontHeight
84                   - 3);
85           x += fm.stringWidth(tip[i].substring(0, lindex) + 3);
86         }
87         g.drawImage(linkImage, x, i * fontHeight + 1, this);
88         if (lindex + 6 < tip[i].length())
89         {
90           g.drawString(tip[i].substring(lindex + 6),
91                   x + linkImage.getWidth(this), (i + 1) * fontHeight - 3);
92         }
93       }
94       else
95       {
96         g.drawString(tip[i], 3, (i + 1) * fontHeight - 3);
97       }
98     }
99   }
100
101   synchronized void setTip(String tip)
102   {
103     if (tip == null)
104     {
105       setTip("");
106       return;
107     }
108
109     if (lastTip.equals(tip))
110     {
111       return;
112     }
113
114     lastTip = tip;
115     setPosition = true;
116
117     fm = getFontMetrics(owner.getFont());
118     fontHeight = fm.getHeight();
119
120     int longestLine = 0;
121     StringTokenizer st = new StringTokenizer(tip, "\n");
122     this.tip = new String[st.countTokens()];
123     int index = 0;
124     while (st.hasMoreElements())
125     {
126       this.tip[index] = st.nextToken();
127       if (fm.stringWidth(this.tip[index]) > longestLine)
128       {
129         longestLine = fm.stringWidth(this.tip[index]);
130       }
131       index++;
132     }
133
134     setSize(longestLine + HORIZONTAL_ENLARGE, fontHeight * this.tip.length);
135
136     repaint();
137
138   }
139
140   void setTipLocation(MouseEvent evt)
141   {
142     if (mainContainer == null || owner == null)
143     {
144       return;
145     }
146     setLocation(
147             (owner.getLocationOnScreen().x - mainContainer.getLocationOnScreen().x)
148                     + evt.getX(),
149             (owner.getLocationOnScreen().y
150                     - mainContainer.getLocationOnScreen().y + VERTICAL_OFFSET)
151                     + evt.getY());
152
153     // correction, whole tool tip must be visible
154     if (mainContainer.getSize().width < (getLocation().x + getSize().width))
155     {
156       setLocation(mainContainer.getSize().width - getSize().width,
157               getLocation().y);
158     }
159   }
160
161   private void removeToolTip()
162   {
163     if (shown)
164     {
165       mainContainer.remove(0);
166       mainContainer.setLayout(mainLayout);
167       mainContainer.validate();
168     }
169     shown = false;
170   }
171
172   private void findMainContainer()
173   {
174     Container parent = owner.getParent();
175     while (true)
176     {
177       if ((parent instanceof Applet) || (parent instanceof Frame))
178       {
179         mainContainer = parent;
180         break;
181       }
182       else
183       {
184         parent = parent.getParent();
185       }
186     }
187     mainLayout = mainContainer.getLayout();
188   }
189
190   public void mouseEntered(MouseEvent me)
191   {
192     setTipLocation(me);
193   }
194
195   public void mouseExited(MouseEvent me)
196   {
197     removeToolTip();
198   }
199
200   public void mousePressed(MouseEvent me)
201   {
202     removeToolTip();
203   }
204
205   public void mouseReleased(MouseEvent me)
206   {
207   }
208
209   public void mouseClicked(MouseEvent me)
210   {
211   }
212
213   public void mouseMoved(MouseEvent me)
214   {
215     if (!shown)
216     {
217       findMainContainer();
218       mainContainer.setLayout(null);
219       mainContainer.add(this, 0);
220       mainContainer.validate();
221       shown = true;
222       setTipLocation(me);
223     }
224     else if (setPosition)
225     {
226       setTipLocation(me);
227       setPosition = false;
228     }
229   }
230
231   public void mouseDragged(MouseEvent me)
232   {
233   }
234 }