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