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