update author list in license for (JAL-826)
[jalview.git] / src / jalview / appletgui / Tooltip.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle\r
4  * \r
5  * This file is part of Jalview.\r
6  * \r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License \r
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
10  * \r
11  * Jalview is distributed in the hope that it will be useful, but \r
12  * WITHOUT ANY WARRANTY; without even the implied warranty \r
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
14  * PURPOSE.  See the GNU General Public License for more details.\r
15  * \r
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package jalview.appletgui;\r
19 \r
20 import java.applet.*;\r
21 import java.util.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 \r
26 public class Tooltip extends Canvas implements MouseListener,\r
27         MouseMotionListener\r
28 {\r
29   private String[] tip;\r
30 \r
31   private String lastTip = "";\r
32 \r
33   private boolean setPosition = false;\r
34 \r
35   protected Component owner;\r
36 \r
37   private Container mainContainer;\r
38 \r
39   private LayoutManager mainLayout;\r
40 \r
41   private boolean shown;\r
42 \r
43   private final int VERTICAL_OFFSET = 20;\r
44 \r
45   private final int HORIZONTAL_ENLARGE = 10;\r
46 \r
47   int fontHeight = 0;\r
48 \r
49   Image linkImage;\r
50 \r
51   FontMetrics fm;\r
52 \r
53   public Tooltip(String tip, Component owner)\r
54   {\r
55     this.owner = owner;\r
56     owner.addMouseListener(this);\r
57     owner.addMouseMotionListener(this);\r
58     setBackground(new Color(255, 255, 220));\r
59     setTip(tip);\r
60     java.net.URL url = getClass().getResource("/images/link.gif");\r
61     if (url != null)\r
62     {\r
63       linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url);\r
64     }\r
65   }\r
66 \r
67   public void paint(Graphics g)\r
68   {\r
69     int w = getSize().width;\r
70     int h = getSize().height;\r
71 \r
72     g.drawRect(0, 0, w - 1, h - 1);\r
73     int lindex, x;\r
74     for (int i = 0; i < tip.length; i++)\r
75     {\r
76       x = 3;\r
77       lindex = tip[i].indexOf("%LINK%");\r
78       if (lindex != -1)\r
79       {\r
80         if (lindex > 0)\r
81         {\r
82           g.drawString(tip[i].substring(0, lindex), 3, (i + 1) * fontHeight\r
83                   - 3);\r
84           x += fm.stringWidth(tip[i].substring(0, lindex) + 3);\r
85         }\r
86         g.drawImage(linkImage, x, i * fontHeight + 1, this);\r
87         if (lindex + 6 < tip[i].length())\r
88         {\r
89           g.drawString(tip[i].substring(lindex + 6),\r
90                   x + linkImage.getWidth(this), (i + 1) * fontHeight - 3);\r
91         }\r
92       }\r
93       else\r
94       {\r
95         g.drawString(tip[i], 3, (i + 1) * fontHeight - 3);\r
96       }\r
97     }\r
98   }\r
99 \r
100   synchronized void setTip(String tip)\r
101   {\r
102     if (tip == null)\r
103     {\r
104       setTip("");\r
105       return;\r
106     }\r
107 \r
108     if (lastTip.equals(tip))\r
109     {\r
110       return;\r
111     }\r
112 \r
113     lastTip = tip;\r
114     setPosition = true;\r
115 \r
116     fm = getFontMetrics(owner.getFont());\r
117     fontHeight = fm.getHeight();\r
118 \r
119     int longestLine = 0;\r
120     StringTokenizer st = new StringTokenizer(tip, "\n");\r
121     this.tip = new String[st.countTokens()];\r
122     int index = 0;\r
123     while (st.hasMoreElements())\r
124     {\r
125       this.tip[index] = st.nextToken();\r
126       if (fm.stringWidth(this.tip[index]) > longestLine)\r
127       {\r
128         longestLine = fm.stringWidth(this.tip[index]);\r
129       }\r
130       index++;\r
131     }\r
132 \r
133     setSize(longestLine + HORIZONTAL_ENLARGE, fontHeight * this.tip.length);\r
134 \r
135     repaint();\r
136 \r
137   }\r
138 \r
139   void setTipLocation(MouseEvent evt)\r
140   {\r
141     if (mainContainer == null || owner == null)\r
142     {\r
143       return;\r
144     }\r
145     setLocation(\r
146             (owner.getLocationOnScreen().x - mainContainer.getLocationOnScreen().x)\r
147                     + evt.getX(),\r
148             (owner.getLocationOnScreen().y\r
149                     - mainContainer.getLocationOnScreen().y + VERTICAL_OFFSET)\r
150                     + evt.getY());\r
151 \r
152     // correction, whole tool tip must be visible\r
153     if (mainContainer.getSize().width < (getLocation().x + getSize().width))\r
154     {\r
155       setLocation(mainContainer.getSize().width - getSize().width,\r
156               getLocation().y);\r
157     }\r
158   }\r
159 \r
160   private void removeToolTip()\r
161   {\r
162     if (shown)\r
163     {\r
164       mainContainer.remove(0);\r
165       mainContainer.setLayout(mainLayout);\r
166       mainContainer.validate();\r
167     }\r
168     shown = false;\r
169   }\r
170 \r
171   private void findMainContainer()\r
172   {\r
173     Container parent = owner.getParent();\r
174     while (true)\r
175     {\r
176       if ((parent instanceof Applet) || (parent instanceof Frame))\r
177       {\r
178         mainContainer = parent;\r
179         break;\r
180       }\r
181       else\r
182       {\r
183         parent = parent.getParent();\r
184       }\r
185     }\r
186     mainLayout = mainContainer.getLayout();\r
187   }\r
188 \r
189   public void mouseEntered(MouseEvent me)\r
190   {\r
191     setTipLocation(me);\r
192   }\r
193 \r
194   public void mouseExited(MouseEvent me)\r
195   {\r
196     removeToolTip();\r
197   }\r
198 \r
199   public void mousePressed(MouseEvent me)\r
200   {\r
201     removeToolTip();\r
202   }\r
203 \r
204   public void mouseReleased(MouseEvent me)\r
205   {\r
206   }\r
207 \r
208   public void mouseClicked(MouseEvent me)\r
209   {\r
210   }\r
211 \r
212   public void mouseMoved(MouseEvent me)\r
213   {\r
214     if (!shown)\r
215     {\r
216       findMainContainer();\r
217       mainContainer.setLayout(null);\r
218       mainContainer.add(this, 0);\r
219       mainContainer.validate();\r
220       shown = true;\r
221       setTipLocation(me);\r
222     }\r
223     else if (setPosition)\r
224     {\r
225       setTipLocation(me);\r
226       setPosition = false;\r
227     }\r
228   }\r
229 \r
230   public void mouseDragged(MouseEvent me)\r
231   {\r
232   }\r
233 }\r