001: package net.xoetrope.awt;
002:
003: import java.applet.Applet;
004:
005: import java.awt.Canvas;
006: import java.awt.Color;
007: import java.awt.Component;
008: import java.awt.Container;
009: import java.awt.Font;
010: import java.awt.FontMetrics;
011: import java.awt.Frame;
012: import java.awt.Graphics;
013: import java.awt.LayoutManager;
014: import java.awt.Point;
015: import java.awt.event.MouseEvent;
016: import java.awt.event.MouseListener;
017: import java.util.Date;
018:
019: /**
020: * A Tooltip class for AWT components. Unlike other XUI-AWT components the
021: * tooltips are not added via the component factory. In this initial
022: * implementation tooltips must be added explicitly.
023: * <p> Copyright (c) Xoetrope Ltd., 2002-2004</p>
024: * <p> $Revision: 1.3 $</p>
025: * <p> License: see License.txt</p>
026: */
027: public class XToolTip extends Canvas implements MouseListener {
028: protected String tip;
029: protected Component owner;
030:
031: protected Container mainContainer;
032: private LayoutManager mainLayout;
033:
034: protected boolean shown;
035:
036: protected final int VERTICAL_OFFSET = 1;
037: protected final int HORIZONTAL_ENLARGE = 10;
038: protected Font font;
039: protected boolean showTip = false;
040:
041: protected int lag = 500;
042: protected TooltipThread tooltipThread;
043:
044: /**
045: * Create anew tooltip
046: * @param tip the tip text
047: * @param owner the owner component
048: */
049: public XToolTip(String tip, Component owner) {
050: this .tip = tip;
051: this .owner = owner;
052: owner.addMouseListener(this );
053: setBackground(new Color(255, 255, 220));
054: font = new Font("Arial", Font.PLAIN, 12);
055: setFont(font);
056: }
057:
058: /**
059: * Get the tip's text
060: * @return the tooltip text
061: */
062: public String getTip() {
063: return tip;
064: }
065:
066: /**
067: * Get the tip's text
068: * @param newTip the new text
069: */
070: public void setTip(String newTip) {
071: tip = newTip;
072: }
073:
074: public void paint(Graphics g) {
075: g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
076: int iPos = tip.indexOf("\n");
077: FontMetrics fm = getFontMetrics(font);
078: g.drawString(tip, 5, getSize().height - 5);
079: }
080:
081: protected void addToolTip(Point pt) {
082: if (!shown) {
083: mainContainer.setLayout(null);
084:
085: calcsize();
086: setToolTipLocation(pt);
087:
088: // correction, whole tool tip must be visible
089: if (mainContainer.getSize().width < (getLocation().x + getSize().width)) {
090: setLocation(mainContainer.getSize().width
091: - getSize().width, getLocation().y);
092: }
093: mainContainer.add(this , 0);
094: mainContainer.validate();
095: repaint();
096: }
097: shown = true;
098: }
099:
100: protected void calcsize() {
101: FontMetrics fm = getFontMetrics(font);
102: setSize(fm.stringWidth(tip) + HORIZONTAL_ENLARGE, fm
103: .getHeight()
104: + (VERTICAL_OFFSET * 4));
105: }
106:
107: protected void setToolTipLocation(Point pt) {
108: setLocation((owner.getLocationOnScreen().x - mainContainer
109: .getLocationOnScreen().x)
110: + pt.x + 5, (owner.getLocationOnScreen().y
111: - mainContainer.getLocationOnScreen().y + owner
112: .getSize().height));
113: // correction, whole tool tip must be visible
114: if (mainContainer.getSize().width < (getLocation().x + getSize().width))
115: setLocation(
116: mainContainer.getSize().width - getSize().width,
117: getLocation().y);
118: if (mainContainer.getSize().height < (getLocation().y + getSize().height))
119: setLocation(getLocation().x, mainContainer.getSize().height
120: - getSize().height);
121: }
122:
123: protected void removeToolTip() {
124: if (shown) {
125: if (mainContainer.getComponentCount() > 0
126: && (mainContainer.getComponent(0) instanceof XToolTip)) {
127: mainContainer.remove(this );
128: mainContainer.repaint();
129: mainContainer.setLayout(mainLayout);
130: mainContainer.validate();
131: }
132: shown = false;
133: }
134: showTip = false;
135: }
136:
137: private void findMainContainer() {
138: Container parent = owner.getParent();
139: while (true) {
140: if ((parent instanceof Applet) || (parent instanceof Frame)) {
141: mainContainer = parent;
142: break;
143: } else {
144: parent = parent.getParent();
145: }
146: }
147: if (!(mainContainer.getComponent(0) instanceof XToolTip))
148: mainContainer.add(this , 0);
149: mainLayout = mainContainer.getLayout();
150: }
151:
152: /**
153: * Show the tooltip at the specified point
154: * @param pt
155: */
156: protected void showTip(Point pt) {
157: if (tooltipThread == null) {
158: tooltipThread = new TooltipThread(this );
159: tooltipThread.start();
160: }
161:
162: tooltipThread.setTipLocation(pt);
163: }
164:
165: /**
166: * Invoked when the mouse exits a component.
167: */
168: public void mouseExited(MouseEvent e) {
169: showTip = false;
170: removeToolTip();
171: }
172:
173: /**
174: * Invoked when the mouse enters a component.
175: */
176: public void mouseEntered(MouseEvent e) {
177: if (!showTip) {
178: showTip = true;
179: showTip(e.getPoint());
180: }
181: }
182:
183: /**
184: * Invoked when a mouse button has been released on a component.
185: */
186: public void mouseReleased(MouseEvent e) {
187: }
188:
189: /**
190: * Invoked when a mouse button has been pressed on a component.
191: */
192: public void mousePressed(MouseEvent e) {
193: showTip = false;
194: removeToolTip();
195: }
196:
197: /**
198: * Invoked when the mouse button has been clicked (pressed
199: * and released) on a component.
200: */
201: public void mouseClicked(MouseEvent e) {
202: }
203:
204: /**
205: * Support for setting the tooltips
206: */
207: class TooltipThread extends Thread {
208: Point tipLocation;
209: XToolTip tooltip;
210: int maxIdle;
211:
212: public TooltipThread(XToolTip tt) {
213: tooltip = tt;
214: maxIdle = 100;
215: }
216:
217: public synchronized void setTipLocation(Point pt) {
218: tipLocation = pt;
219: }
220:
221: public void run() {
222: int idleCount = 0;
223: Date startTime = new Date();
224: do {
225: try {
226: sleep(tooltip.lag);
227: idleCount++;
228: } catch (InterruptedException ex) {
229: }
230: if (tooltip.showTip) {
231: tooltip.findMainContainer();
232: tooltip.addToolTip(tipLocation);
233: idleCount = 0;
234: }
235: if (new Date().getTime() - startTime.getTime() > 5000) {
236: showTip = false;
237: removeToolTip();
238: break;
239: }
240:
241: } while (idleCount < maxIdle);
242: tooltip.tooltipThread = null;
243: }
244: }
245: }
|