Make sure mainContainer and owner are not null
[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     if(mainContainer==null || owner==null)\r
141     {\r
142       return;\r
143     }\r
144     setLocation( (owner.getLocationOnScreen().x\r
145                   - mainContainer.getLocationOnScreen().x) + evt.getX(),\r
146                 (owner.getLocationOnScreen().y -\r
147                  mainContainer.getLocationOnScreen().y\r
148                  + VERTICAL_OFFSET) + evt.getY());\r
149 \r
150     // correction, whole tool tip must be visible\r
151     if (mainContainer.getSize().width < (getLocation().x + getSize().width))\r
152     {\r
153       setLocation(mainContainer.getSize().width - getSize().width,\r
154                   getLocation().y);\r
155     }\r
156   }\r
157 \r
158   private void removeToolTip()\r
159   {\r
160     if (shown)\r
161     {\r
162       mainContainer.remove(0);\r
163       mainContainer.setLayout(mainLayout);\r
164       mainContainer.validate();\r
165     }\r
166     shown = false;\r
167   }\r
168 \r
169   private void findMainContainer()\r
170   {\r
171     Container parent = owner.getParent();\r
172     while (true)\r
173     {\r
174       if ( (parent instanceof Applet) || (parent instanceof Frame))\r
175       {\r
176         mainContainer = parent;\r
177         break;\r
178       }\r
179       else\r
180       {\r
181         parent = parent.getParent();\r
182       }\r
183     }\r
184     mainLayout = mainContainer.getLayout();\r
185   }\r
186 \r
187   public void mouseEntered(MouseEvent me)\r
188   {\r
189     setTipLocation(me);\r
190   }\r
191 \r
192   public void mouseExited(MouseEvent me)\r
193   {\r
194     removeToolTip();\r
195   }\r
196 \r
197   public void mousePressed(MouseEvent me)\r
198   {\r
199     removeToolTip();\r
200   }\r
201 \r
202   public void mouseReleased(MouseEvent me)\r
203   {}\r
204 \r
205   public void mouseClicked(MouseEvent me)\r
206   {}\r
207 \r
208   public void mouseMoved(MouseEvent me)\r
209   {\r
210     if (!shown)\r
211     {\r
212       findMainContainer();\r
213       mainContainer.setLayout(null);\r
214       mainContainer.add(this, 0);\r
215       mainContainer.validate();\r
216       shown = true;\r
217       setTipLocation(me);\r
218     }\r
219     else if (setPosition)\r
220     {\r
221       setTipLocation(me);\r
222       setPosition = false;\r
223     }\r
224   }\r
225 \r
226   public void mouseDragged(MouseEvent me)\r
227   {}\r
228 }\r