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