KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > ToolTipManager


1 /*
2  * @(#)ToolTipManager.java 1.70 04/01/16
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9 package javax.swing;
10
11 import java.awt.event.*;
12 import java.applet.*;
13 import java.awt.*;
14 import java.io.Serializable JavaDoc;
15 import sun.swing.UIAction;
16
17 /**
18  * Manages all the <code>ToolTips</code> in the system.
19  * <p>
20  * ToolTipManager contains numerous properties for configuring how long it
21  * will take for the tooltips to become visible, and how long till they
22  * hide. Consider a component that has a different tooltip based on where
23  * the mouse is, such as JTree. When the mouse moves into the JTree and
24  * over a region that has a valid tooltip, the tooltip will become
25  * visibile after <code>initialDelay</code> milliseconds. After
26  * <code>dismissDelay</code> milliseconds the tooltip will be hidden. If
27  * the mouse is over a region that has a valid tooltip, and the tooltip
28  * is currently visible, when the mouse moves to a region that doesn't have
29  * a valid tooltip the tooltip will be hidden. If the mouse then moves back
30  * into a region that has a valid tooltip within <code>reshowDelay</code>
31  * milliseconds, the tooltip will immediately be shown, otherwise the
32  * tooltip will be shown again after <code>initialDelay</code> milliseconds.
33  *
34  * @see JComponent#createToolTip
35  * @version 1.70 01/16/04
36  * @author Dave Moore
37  * @author Rich Schiavi
38  */

39 public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
40     Timer JavaDoc enterTimer, exitTimer, insideTimer;
41     String JavaDoc toolTipText;
42     Point preferredLocation;
43     JComponent JavaDoc insideComponent;
44     MouseEvent mouseEvent;
45     boolean showImmediately;
46     final static ToolTipManager JavaDoc sharedInstance = new ToolTipManager JavaDoc();
47     transient Popup JavaDoc tipWindow;
48     /** The Window tip is being displayed in. This will be non-null if
49      * the Window tip is in differs from that of insideComponent's Window.
50      */

51     private Window window;
52     JToolTip JavaDoc tip;
53
54     private Rectangle popupRect = null;
55     private Rectangle popupFrameRect = null;
56
57     boolean enabled = true;
58     private boolean tipShowing = false;
59    
60     private KeyStroke JavaDoc postTip,hideTip;
61     private Action JavaDoc postTipAction, hideTipAction;
62
63     private FocusListener focusChangeListener = null;
64     private MouseMotionListener moveBeforeEnterListener = null;
65
66     // PENDING(ges)
67
protected boolean lightWeightPopupEnabled = true;
68     protected boolean heavyWeightPopupEnabled = false;
69
70     ToolTipManager() {
71         enterTimer = new Timer JavaDoc(750, new insideTimerAction());
72         enterTimer.setRepeats(false);
73         exitTimer = new Timer JavaDoc(500, new outsideTimerAction());
74         exitTimer.setRepeats(false);
75         insideTimer = new Timer JavaDoc(4000, new stillInsideTimerAction());
76         insideTimer.setRepeats(false);
77
78     // create accessibility actions
79
postTip = KeyStroke.getKeyStroke(KeyEvent.VK_F1,Event.CTRL_MASK);
80     postTipAction = new Actions(Actions.SHOW);
81     hideTip = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0);
82     hideTipAction = new Actions(Actions.HIDE);
83
84     moveBeforeEnterListener = new MoveBeforeEnterListener();
85     }
86
87     /**
88      * Enables or disables the tooltip.
89      *
90      * @param flag true to enable the tip, false otherwise
91      */

92     public void setEnabled(boolean flag) {
93         enabled = flag;
94         if (!flag) {
95             hideTipWindow();
96         }
97     }
98
99     /**
100      * Returns true if this object is enabled.
101      *
102      * @return true if this object is enabled, false otherwise
103      */

104     public boolean isEnabled() {
105         return enabled;
106     }
107
108     /**
109      * When displaying the <code>JToolTip</code>, the
110      * <code>ToolTipManager</code> chooses to use a lightweight
111      * <code>JPanel</code> if it fits. This method allows you to
112      * disable this feature. You have to do disable it if your
113      * application mixes light weight and heavy weights components.
114      *
115      * @param aFlag true if a lightweight panel is desired, false otherwise
116      *
117      */

118     public void setLightWeightPopupEnabled(boolean aFlag){
119         lightWeightPopupEnabled = aFlag;
120     }
121     
122     /**
123      * Returns true if lightweight (all-Java) <code>Tooltips</code>
124      * are in use, or false if heavyweight (native peer)
125      * <code>Tooltips</code> are being used.
126      *
127      * @return true if lightweight <code>ToolTips</code> are in use
128      */

129     public boolean isLightWeightPopupEnabled() {
130         return lightWeightPopupEnabled;
131     }
132
133
134     /**
135      * Specifies the initial delay value.
136      *
137      * @param milliseconds the number of milliseconds to delay
138      * (after the cursor has paused) before displaying the
139      * tooltip
140      * @see #getInitialDelay
141      */

142     public void setInitialDelay(int milliseconds) {
143         enterTimer.setInitialDelay(milliseconds);
144     }
145
146     /**
147      * Returns the initial delay value.
148      *
149      * @return an integer representing the initial delay value,
150      * in milliseconds
151      * @see #setInitialDelay
152      */

153     public int getInitialDelay() {
154         return enterTimer.getInitialDelay();
155     }
156
157     /**
158      * Specifies the dismissal delay value.
159      *
160      * @param milliseconds the number of milliseconds to delay
161      * before taking away the tooltip
162      * @see #getDismissDelay
163      */

164     public void setDismissDelay(int milliseconds) {
165         insideTimer.setInitialDelay(milliseconds);
166     }
167
168     /**
169      * Returns the dismissal delay value.
170      *
171      * @return an integer representing the dismissal delay value,
172      * in milliseconds
173      * @see #setDismissDelay
174      */

175     public int getDismissDelay() {
176         return insideTimer.getInitialDelay();
177     }
178
179     /**
180      * Used to specify the amount of time before the user has to wait
181      * <code>initialDelay</code> milliseconds before a tooltip will be
182      * shown. That is, if the tooltip is hidden, and the user moves into
183      * a region of the same Component that has a valid tooltip within
184      * <code>milliseconds</code> milliseconds the tooltip will immediately
185      * be shown. Otherwise, if the user moves into a region with a valid
186      * tooltip after <code>milliseconds</code> milliseconds, the user
187      * will have to wait an additional <code>initialDelay</code>
188      * milliseconds before the tooltip is shown again.
189      *
190      * @param milliseconds time in milliseconds
191      * @see #getReshowDelay
192      */

193     public void setReshowDelay(int milliseconds) {
194         exitTimer.setInitialDelay(milliseconds);
195     }
196
197     /**
198      * Returns the reshow delay property.
199      *
200      * @return reshown delay property
201      * @see #setReshowDelay
202      */

203     public int getReshowDelay() {
204         return exitTimer.getInitialDelay();
205     }
206
207     void showTipWindow() {
208         if(insideComponent == null || !insideComponent.isShowing())
209             return;
210     for (Container p = insideComponent.getParent(); p != null; p = p.getParent()) {
211             if (p instanceof JPopupMenu JavaDoc) break;
212         if (p instanceof Window) {
213         if (!((Window)p).isFocused()) {
214             return;
215         }
216         break;
217         }
218     }
219         if (enabled) {
220             Dimension size;
221             Point screenLocation = insideComponent.getLocationOnScreen();
222             Point location = new Point();
223             Rectangle sBounds = insideComponent.getGraphicsConfiguration().
224                                                 getBounds();
225         boolean leftToRight
226                 = SwingUtilities.isLeftToRight(insideComponent);
227
228             // Just to be paranoid
229
hideTipWindow();
230
231             tip = insideComponent.createToolTip();
232             tip.setTipText(toolTipText);
233             size = tip.getPreferredSize();
234
235             if(preferredLocation != null) {
236                 location.x = screenLocation.x + preferredLocation.x;
237                 location.y = screenLocation.y + preferredLocation.y;
238         if (!leftToRight) {
239             location.x -= size.width;
240         }
241             } else {
242                 location.x = screenLocation.x + mouseEvent.getX();
243                 location.y = screenLocation.y + mouseEvent.getY() + 20;
244         if (!leftToRight) {
245             if(location.x - size.width>=0) {
246                 location.x -= size.width;
247             }
248         }
249
250             }
251
252         // we do not adjust x/y when using awt.Window tips
253
if (popupRect == null){
254         popupRect = new Rectangle();
255         }
256         popupRect.setBounds(location.x,location.y,
257                 size.width,size.height);
258         
259         // Fit as much of the tooltip on screen as possible
260
if (location.x < sBounds.x) {
261                 location.x = sBounds.x;
262             }
263             else if (location.x - sBounds.x + size.width > sBounds.width) {
264                 location.x = sBounds.x + Math.max(0, sBounds.width - size.width)
265 ;
266             }
267             if (location.y < sBounds.y) {
268                 location.y = sBounds.y;
269             }
270             else if (location.y - sBounds.y + size.height > sBounds.height) {
271                 location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
272             }
273
274             PopupFactory JavaDoc popupFactory = PopupFactory.getSharedInstance();
275
276             if (lightWeightPopupEnabled) {
277         int y = getPopupFitHeight(popupRect, insideComponent);
278         int x = getPopupFitWidth(popupRect,insideComponent);
279         if (x>0 || y>0) {
280             popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
281         } else {
282             popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
283         }
284             }
285             else {
286                 popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
287             }
288         tipWindow = popupFactory.getPopup(insideComponent, tip,
289                           location.x,
290                           location.y);
291             popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
292
293         tipWindow.show();
294
295             Window componentWindow = SwingUtilities.windowForComponent(
296                                                     insideComponent);
297
298             window = SwingUtilities.windowForComponent(tip);
299             if (window != null && window != componentWindow) {
300                 window.addMouseListener(this);
301             }
302             else {
303                 window = null;
304             }
305
306             insideTimer.start();
307         tipShowing = true;
308         }
309     }
310
311     void hideTipWindow() {
312         if (tipWindow != null) {
313             if (window != null) {
314                 window.removeMouseListener(this);
315                 window = null;
316             }
317             tipWindow.hide();
318         tipWindow = null;
319         tipShowing = false;
320         (tip.getUI()).uninstallUI(tip);
321             tip = null;
322             insideTimer.stop();
323         }
324     }
325
326     /**
327      * Returns a shared <code>ToolTipManager</code> instance.
328      *
329      * @return a shared <code>ToolTipManager</code> object
330      */

331     public static ToolTipManager JavaDoc sharedInstance() {
332         return sharedInstance;
333     }
334
335     // add keylistener here to trigger tip for access
336
/**
337      * Registers a component for tooltip management.
338      * <p>
339      * This will register key bindings to show and hide the tooltip text
340      * only if <code>component</code> has focus bindings. This is done
341      * so that components that are not normally focus traversable, such
342      * as <code>JLabel</code>, are not made focus traversable as a result
343      * of invoking this method.
344      *
345      * @param component a <code>JComponent</code> object to add
346      * @see JComponent#isFocusTraversable
347      */

348     public void registerComponent(JComponent JavaDoc component) {
349         component.removeMouseListener(this);
350         component.addMouseListener(this);
351         component.removeMouseMotionListener(moveBeforeEnterListener);
352     component.addMouseMotionListener(moveBeforeEnterListener);
353
354     if (shouldRegisterBindings(component)) {
355         // register our accessibility keybindings for this component
356
// this will apply globally across L&F
357
// Post Tip: Ctrl+F1
358
// Unpost Tip: Esc and Ctrl+F1
359
InputMap JavaDoc inputMap = component.getInputMap(JComponent.WHEN_FOCUSED);
360         ActionMap JavaDoc actionMap = component.getActionMap();
361
362         if (inputMap != null && actionMap != null) {
363         inputMap.put(postTip, "postTip");
364         inputMap.put(hideTip, "hideTip");
365         actionMap.put("postTip", postTipAction);
366         actionMap.put("hideTip", hideTipAction);
367         }
368     }
369     }
370
371     /**
372      * Removes a component from tooltip control.
373      *
374      * @param component a <code>JComponent</code> object to remove
375      */

376     public void unregisterComponent(JComponent JavaDoc component) {
377         component.removeMouseListener(this);
378     component.removeMouseMotionListener(moveBeforeEnterListener);
379
380     if (shouldRegisterBindings(component)) {
381         InputMap JavaDoc inputMap = component.getInputMap(JComponent.WHEN_FOCUSED);
382         ActionMap JavaDoc actionMap = component.getActionMap();
383
384         if (inputMap != null && actionMap != null) {
385         inputMap.remove(postTip);
386         inputMap.remove(hideTip);
387         actionMap.remove("postTip");
388         actionMap.remove("hideTip");
389         }
390     }
391     }
392
393     /**
394      * Returns whether or not bindings should be registered on the given
395      * <code>JComponent</code>. This is implemented to return true if the
396      * tool tip manager has a binding in any one of the
397      * <code>InputMaps</code> registered under the condition
398      * <code>WHEN_FOCUSED</code>.
399      * <p>
400      * This does not use <code>isFocusTraversable</code> as
401      * some components may override <code>isFocusTraversable</code> and
402      * base the return value on something other than bindings. For example,
403      * <code>JButton</code> bases its return value on its enabled state.
404      *
405      * @param component the <code>JComponent</code> in question
406      */

407     private boolean shouldRegisterBindings(JComponent JavaDoc component) {
408     InputMap JavaDoc inputMap = component.getInputMap(JComponent.WHEN_FOCUSED,
409                           false);
410     while (inputMap != null && inputMap.size() == 0) {
411         inputMap = inputMap.getParent();
412     }
413     return (inputMap != null);
414     }
415
416     // implements java.awt.event.MouseListener
417
/**
418      * Called when the mouse enters the region of a component.
419      * This determines whether the tool tip should be shown.
420      *
421      * @param event the event in question
422      */

423     public void mouseEntered(MouseEvent event) {
424         initiateToolTip(event);
425     }
426
427     private void initiateToolTip(MouseEvent event) {
428         if (event.getSource() == window) {
429             return;
430         }
431         JComponent JavaDoc component = (JComponent JavaDoc)event.getSource();
432     component.removeMouseMotionListener(moveBeforeEnterListener);
433
434         exitTimer.stop();
435
436     Point location = event.getPoint();
437     // ensure tooltip shows only in proper place
438
if (location.x < 0 ||
439         location.x >=component.getWidth() ||
440         location.y < 0 ||
441         location.y >= component.getHeight()) {
442         return;
443     }
444
445         if (insideComponent != null) {
446             enterTimer.stop();
447         }
448     // A component in an unactive internal frame is sent two
449
// mouseEntered events, make sure we don't end up adding
450
// ourselves an extra time.
451
component.removeMouseMotionListener(this);
452         component.addMouseMotionListener(this);
453
454         boolean sameComponent = (insideComponent == component);
455
456         insideComponent = component;
457     if (tipWindow != null){
458             mouseEvent = event;
459             if (showImmediately) {
460                 String JavaDoc newToolTipText = component.getToolTipText(event);
461                 Point newPreferredLocation = component.getToolTipLocation(
462                                                          event);
463                 boolean sameLoc = (preferredLocation != null) ?
464                             preferredLocation.equals(newPreferredLocation) :
465                             (newPreferredLocation == null);
466
467                 if (!sameComponent || !toolTipText.equals(newToolTipText) ||
468                          !sameLoc) {
469                     toolTipText = newToolTipText;
470                     preferredLocation = newPreferredLocation;
471                     showTipWindow();
472                 }
473             } else {
474                 enterTimer.start();
475             }
476         }
477     }
478
479     // implements java.awt.event.MouseListener
480
/**
481      * Called when the mouse exits the region of a component.
482      * Any tool tip showing should be hidden.
483      *
484      * @param event the event in question
485      */

486     public void mouseExited(MouseEvent event) {
487         boolean shouldHide = true;
488         if (insideComponent == null) {
489             // Drag exit
490
}
491         if (window != null && event.getSource() == window) {
492       // if we get an exit and have a heavy window
493
// we need to check if it if overlapping the inside component
494
Container insideComponentWindow = insideComponent.getTopLevelAncestor();
495             Point location = event.getPoint();
496             SwingUtilities.convertPointToScreen(location, window);
497
498             location.x -= insideComponentWindow.getX();
499             location.y -= insideComponentWindow.getY();
500             
501             location = SwingUtilities.convertPoint(null,location,insideComponent);
502             if (location.x >= 0 && location.x < insideComponent.getWidth() &&
503                location.y >= 0 && location.y < insideComponent.getHeight()) {
504                 shouldHide = false;
505             } else {
506             shouldHide = true;
507         }
508         } else if(event.getSource() == insideComponent && tipWindow != null) {
509         Window win = SwingUtilities.getWindowAncestor(insideComponent);
510         if (win != null) { // insideComponent may have been hidden (e.g. in a menu)
511
Point location = SwingUtilities.convertPoint(insideComponent,
512                                  event.getPoint(),
513                                  win);
514         Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
515         location.x += bounds.x;
516         location.y += bounds.y;
517         
518         Point loc = new Point(0, 0);
519         SwingUtilities.convertPointToScreen(loc, tip);
520         bounds.x = loc.x;
521         bounds.y = loc.y;
522         bounds.width = tip.getWidth();
523         bounds.height = tip.getHeight();
524         
525         if (location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
526             location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
527             shouldHide = false;
528         } else {
529             shouldHide = true;
530         }
531         }
532         }
533         
534         if (shouldHide) {
535             enterTimer.stop();
536         if (insideComponent != null) {
537             insideComponent.removeMouseMotionListener(this);
538         }
539             insideComponent = null;
540             toolTipText = null;
541             mouseEvent = null;
542             hideTipWindow();
543             exitTimer.restart();
544         }
545     }
546
547     // implements java.awt.event.MouseListener
548
/**
549      * Called when the mouse is pressed.
550      * Any tool tip showing should be hidden.
551      *
552      * @param event the event in question
553      */

554     public void mousePressed(MouseEvent event) {
555         hideTipWindow();
556         enterTimer.stop();
557         showImmediately = false;
558         insideComponent = null;
559         mouseEvent = null;
560     }
561
562     // implements java.awt.event.MouseMotionListener
563
/**
564      * Called when the mouse is pressed and dragged.
565      * Does nothing.
566      *
567      * @param event the event in question
568      */

569     public void mouseDragged(MouseEvent event) {
570     }
571
572     // implements java.awt.event.MouseMotionListener
573
/**
574      * Called when the mouse is moved.
575      * Determines whether the tool tip should be displayed.
576      *
577      * @param event the event in question
578      */

579     public void mouseMoved(MouseEvent event) {
580         if (tipShowing) {
581             checkForTipChange(event);
582         }
583         else if (showImmediately) {
584             JComponent JavaDoc component = (JComponent JavaDoc)event.getSource();
585             toolTipText = component.getToolTipText(event);
586             if (toolTipText != null) {
587                 preferredLocation = component.getToolTipLocation(event);
588                 mouseEvent = event;
589                 insideComponent = component;
590                 exitTimer.stop();
591                 showTipWindow();
592             }
593         }
594         else {
595             // Lazily lookup the values from within insideTimerAction
596
insideComponent = (JComponent JavaDoc)event.getSource();
597             mouseEvent = event;
598             toolTipText = null;
599             enterTimer.restart();
600         }
601     }
602
603     /**
604      * Checks to see if the tooltip needs to be changed in response to
605      * the MouseMoved event <code>event</code>.
606      */

607     private void checkForTipChange(MouseEvent event) {
608         JComponent JavaDoc component = (JComponent JavaDoc)event.getSource();
609         String JavaDoc newText = component.getToolTipText(event);
610         Point newPreferredLocation = component.getToolTipLocation(event);
611
612         if (newText != null || newPreferredLocation != null) {
613             mouseEvent = event;
614             if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
615                 ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
616                  || newPreferredLocation == null)) {
617                 if (tipWindow != null) {
618                     insideTimer.restart();
619                 } else {
620                     enterTimer.restart();
621                 }
622             } else {
623                 toolTipText = newText;
624                 preferredLocation = newPreferredLocation;
625                 if (showImmediately) {
626                     hideTipWindow();
627                     showTipWindow();
628                     exitTimer.stop();
629                 } else {
630                     enterTimer.restart();
631                 }
632             }
633         } else {
634             toolTipText = null;
635             preferredLocation = null;
636             mouseEvent = null;
637             insideComponent = null;
638             hideTipWindow();
639             enterTimer.stop();
640             exitTimer.restart();
641         }
642     }
643
644     protected class insideTimerAction implements ActionListener {
645         public void actionPerformed(ActionEvent e) {
646             if(insideComponent != null && insideComponent.isShowing()) {
647                 // Lazy lookup
648
if (toolTipText == null && mouseEvent != null) {
649                     toolTipText = insideComponent.getToolTipText(mouseEvent);
650                     preferredLocation = insideComponent.getToolTipLocation(
651                                               mouseEvent);
652                 }
653                 if(toolTipText != null) {
654                     showImmediately = true;
655                     showTipWindow();
656                 }
657                 else {
658                     insideComponent = null;
659                     toolTipText = null;
660                     preferredLocation = null;
661                     mouseEvent = null;
662                     hideTipWindow();
663                 }
664             }
665         }
666     }
667
668     protected class outsideTimerAction implements ActionListener {
669         public void actionPerformed(ActionEvent e) {
670             showImmediately = false;
671         }
672     }
673
674     protected class stillInsideTimerAction implements ActionListener {
675         public void actionPerformed(ActionEvent e) {
676             hideTipWindow();
677             enterTimer.stop();
678             showImmediately = false;
679             insideComponent = null;
680             mouseEvent = null;
681         }
682     }
683
684   /* This listener is registered when the tooltip is first registered
685    * on a component in order to catch the situation where the tooltip
686    * was turned on while the mouse was already within the bounds of
687    * the component. This way, the tooltip will be initiated on a
688    * mouse-entered or mouse-moved, whichever occurs first. Once the
689    * tooltip has been initiated, we can remove this listener and rely
690    * solely on mouse-entered to initiate the tooltip.
691    */

692     private class MoveBeforeEnterListener extends MouseMotionAdapter {
693         public void mouseMoved(MouseEvent e) {
694         initiateToolTip(e);
695     }
696     }
697
698     static Frame frameForComponent(Component component) {
699         while (!(component instanceof Frame)) {
700             component = component.getParent();
701         }
702         return (Frame)component;
703     }
704
705   private FocusListener createFocusChangeListener(){
706     return new FocusAdapter(){
707       public void focusLost(FocusEvent evt){
708     hideTipWindow();
709         insideComponent = null;
710     JComponent JavaDoc c = (JComponent JavaDoc)evt.getSource();
711     c.removeFocusListener(focusChangeListener);
712       }
713     };
714   }
715
716   // Returns: 0 no adjust
717
// -1 can't fit
718
// >0 adjust value by amount returned
719
private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){
720     if (invoker != null){
721       Container parent;
722       for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
723     // fix internal frame size bug: 4139087 - 4159012
724
if(parent instanceof JFrame JavaDoc || parent instanceof JDialog JavaDoc ||
725        parent instanceof JWindow JavaDoc) { // no check for awt.Frame since we use Heavy tips
726
return getWidthAdjust(parent.getBounds(),popupRectInScreen);
727     } else if (parent instanceof JApplet JavaDoc || parent instanceof JInternalFrame JavaDoc) {
728       if (popupFrameRect == null){
729         popupFrameRect = new Rectangle();
730       }
731       Point p = parent.getLocationOnScreen();
732       popupFrameRect.setBounds(p.x,p.y,
733                    parent.getBounds().width,
734                    parent.getBounds().height);
735       return getWidthAdjust(popupFrameRect,popupRectInScreen);
736     }
737       }
738     }
739     return 0;
740   }
741
742   // Returns: 0 no adjust
743
// >0 adjust by value return
744
private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){
745     if (invoker != null){
746       Container parent;
747       for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
748     if(parent instanceof JFrame JavaDoc || parent instanceof JDialog JavaDoc ||
749        parent instanceof JWindow JavaDoc) {
750       return getHeightAdjust(parent.getBounds(),popupRectInScreen);
751     } else if (parent instanceof JApplet JavaDoc || parent instanceof JInternalFrame JavaDoc) {
752       if (popupFrameRect == null){
753         popupFrameRect = new Rectangle();
754       }
755       Point p = parent.getLocationOnScreen();
756       popupFrameRect.setBounds(p.x,p.y,
757                    parent.getBounds().width,
758                    parent.getBounds().height);
759       return getHeightAdjust(popupFrameRect,popupRectInScreen);
760     }
761       }
762     }
763     return 0;
764   }
765
766   private int getHeightAdjust(Rectangle a, Rectangle b){
767     if (b.y >= a.y && (b.y + b.height) <= (a.y + a.height))
768       return 0;
769     else
770       return (((b.y + b.height) - (a.y + a.height)) + 5);
771   }
772
773   // Return the number of pixels over the edge we are extending.
774
// If we are over the edge the ToolTipManager can adjust.
775
// REMIND: what if the Tooltip is just too big to fit at all - we currently will just clip
776
private int getWidthAdjust(Rectangle a, Rectangle b){
777     // System.out.println("width b.x/b.width: " + b.x + "/" + b.width +
778
// "a.x/a.width: " + a.x + "/" + a.width);
779
if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width)){
780       return 0;
781     }
782     else {
783       return (((b.x + b.width) - (a.x +a.width)) + 5);
784     }
785   }
786
787
788     //
789
// Actions
790
//
791
private void show(JComponent JavaDoc source) {
792         if (tipWindow != null) { // showing we unshow
793
hideTipWindow();
794             insideComponent = null;
795         }
796         else {
797             hideTipWindow(); // be safe
798
enterTimer.stop();
799             exitTimer.stop();
800             insideTimer.stop();
801             insideComponent = source;
802             if (insideComponent != null){
803                 toolTipText = insideComponent.getToolTipText();
804                 preferredLocation = new Point(10,insideComponent.getHeight()+
805                                               10); // manual set
806
showTipWindow();
807                 // put a focuschange listener on to bring the tip down
808
if (focusChangeListener == null){
809                     focusChangeListener = createFocusChangeListener();
810                 }
811                 insideComponent.addFocusListener(focusChangeListener);
812             }
813         }
814     }
815
816     private void hide(JComponent JavaDoc source) {
817         hideTipWindow();
818         source.removeFocusListener(focusChangeListener);
819         preferredLocation = null;
820         insideComponent = null;
821     }
822
823
824     private static class Actions extends UIAction {
825         private static String JavaDoc SHOW = "SHOW";
826         private static String JavaDoc HIDE = "HIDE";
827
828         Actions(String JavaDoc key) {
829             super(key);
830         }
831
832         public void actionPerformed(ActionEvent e) {
833             String JavaDoc key = getName();
834             JComponent JavaDoc source = (JComponent JavaDoc)e.getSource();
835             if (key == SHOW) {
836                 ToolTipManager.sharedInstance().show(source);
837             }
838             else if (key == HIDE) {
839                 ToolTipManager.sharedInstance().hide(source);
840             }
841         }
842
843         public boolean isEnabled(Object JavaDoc sender) {
844             if (getName() == SHOW) {
845                 return true;
846             }
847             return ToolTipManager.sharedInstance().tipShowing;
848         }
849     }
850 }
851
Popular Tags