Jalview 2.6 source licence
[jalview.git] / src / jalview / appletgui / Tooltip.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)\r
3  * Copyright (C) 2010 J Procter, AM Waterhouse, 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), x\r
90                   + 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((owner.getLocationOnScreen().x - mainContainer\r
146             .getLocationOnScreen().x)\r
147             + evt.getX(), (owner.getLocationOnScreen().y\r
148             - mainContainer.getLocationOnScreen().y + VERTICAL_OFFSET)\r
149             + evt.getY());\r
150 \r
151     // correction, whole tool tip must be visible\r
152     if (mainContainer.getSize().width < (getLocation().x + getSize().width))\r
153     {\r
154       setLocation(mainContainer.getSize().width - getSize().width,\r
155               getLocation().y);\r
156     }\r
157   }\r
158 \r
159   private void removeToolTip()\r
160   {\r
161     if (shown)\r
162     {\r
163       mainContainer.remove(0);\r
164       mainContainer.setLayout(mainLayout);\r
165       mainContainer.validate();\r
166     }\r
167     shown = false;\r
168   }\r
169 \r
170   private void findMainContainer()\r
171   {\r
172     Container parent = owner.getParent();\r
173     while (true)\r
174     {\r
175       if ((parent instanceof Applet) || (parent instanceof Frame))\r
176       {\r
177         mainContainer = parent;\r
178         break;\r
179       }\r
180       else\r
181       {\r
182         parent = parent.getParent();\r
183       }\r
184     }\r
185     mainLayout = mainContainer.getLayout();\r
186   }\r
187 \r
188   public void mouseEntered(MouseEvent me)\r
189   {\r
190     setTipLocation(me);\r
191   }\r
192 \r
193   public void mouseExited(MouseEvent me)\r
194   {\r
195     removeToolTip();\r
196   }\r
197 \r
198   public void mousePressed(MouseEvent me)\r
199   {\r
200     removeToolTip();\r
201   }\r
202 \r
203   public void mouseReleased(MouseEvent me)\r
204   {\r
205   }\r
206 \r
207   public void mouseClicked(MouseEvent me)\r
208   {\r
209   }\r
210 \r
211   public void mouseMoved(MouseEvent me)\r
212   {\r
213     if (!shown)\r
214     {\r
215       findMainContainer();\r
216       mainContainer.setLayout(null);\r
217       mainContainer.add(this, 0);\r
218       mainContainer.validate();\r
219       shown = true;\r
220       setTipLocation(me);\r
221     }\r
222     else if (setPosition)\r
223     {\r
224       setTipLocation(me);\r
225       setPosition = false;\r
226     }\r
227   }\r
228 \r
229   public void mouseDragged(MouseEvent me)\r
230   {\r
231   }\r
232 }\r