14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27 package javax.swing;
28
29 import java.awt.event.*;
30 import java.awt.*;
31 import java.util.Objects;
32
33 /**
34 * Manages all the <code>ToolTips</code> in the system.
35 * <p>
36 * ToolTipManager contains numerous properties for configuring how long it
37 * will take for the tooltips to become visible, and how long till they
38 * hide. Consider a component that has a different tooltip based on where
39 * the mouse is, such as JTree. When the mouse moves into the JTree and
40 * over a region that has a valid tooltip, the tooltip will become
41 * visible after <code>initialDelay</code> milliseconds. After
42 * <code>dismissDelay</code> milliseconds the tooltip will be hidden. If
43 * the mouse is over a region that has a valid tooltip, and the tooltip
44 * is currently visible, when the mouse moves to a region that doesn't have
45 * a valid tooltip the tooltip will be hidden. If the mouse then moves back
46 * into a region that has a valid tooltip within <code>reshowDelay</code>
47 * milliseconds, the tooltip will immediately be shown, otherwise the
48 * tooltip will be shown again after <code>initialDelay</code> milliseconds.
49 *
50 * @see JComponent#createToolTip
51 * @author Dave Moore
52 * @author Rich Schiavi
53 * @since 1.2
54 */
55 public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
56 Timer enterTimer, exitTimer, insideTimer;
57 String toolTipText;
58 Point preferredLocation;
59 JComponent insideComponent;
60 MouseEvent mouseEvent;
61 boolean showImmediately;
62 private static final Object TOOL_TIP_MANAGER_KEY = new Object();
63 transient Popup tipWindow;
64 /** The Window tip is being displayed in. This will be non-null if
65 * the Window tip is in differs from that of insideComponent's Window.
66 */
67 private Window window;
68 JToolTip tip;
109 *
110 * @param flag true to enable the tip, false otherwise
111 */
112 public void setEnabled(boolean flag) {
113 enabled = flag;
114 if (!flag) {
115 hideTipWindow();
116 }
117 }
118
119 /**
120 * Returns true if this object is enabled.
121 *
122 * @return true if this object is enabled, false otherwise
123 */
124 public boolean isEnabled() {
125 return enabled;
126 }
127
128 /**
129 * When displaying the <code>JToolTip</code>, the
130 * <code>ToolTipManager</code> chooses to use a lightweight
131 * <code>JPanel</code> if it fits. This method allows you to
132 * disable this feature. You have to do disable it if your
133 * application mixes light weight and heavy weights components.
134 *
135 * @param aFlag true if a lightweight panel is desired, false otherwise
136 *
137 */
138 public void setLightWeightPopupEnabled(boolean aFlag){
139 lightWeightPopupEnabled = aFlag;
140 }
141
142 /**
143 * Returns true if lightweight (all-Java) <code>Tooltips</code>
144 * are in use, or false if heavyweight (native peer)
145 * <code>Tooltips</code> are being used.
146 *
147 * @return true if lightweight <code>ToolTips</code> are in use
148 */
149 public boolean isLightWeightPopupEnabled() {
150 return lightWeightPopupEnabled;
151 }
152
153
154 /**
155 * Specifies the initial delay value.
156 *
157 * @param milliseconds the number of milliseconds to delay
158 * (after the cursor has paused) before displaying the
159 * tooltip
160 * @see #getInitialDelay
161 */
162 public void setInitialDelay(int milliseconds) {
163 enterTimer.setInitialDelay(milliseconds);
164 }
165
166 /**
167 * Returns the initial delay value.
181 * before taking away the tooltip
182 * @see #getDismissDelay
183 */
184 public void setDismissDelay(int milliseconds) {
185 insideTimer.setInitialDelay(milliseconds);
186 }
187
188 /**
189 * Returns the dismissal delay value.
190 *
191 * @return an integer representing the dismissal delay value,
192 * in milliseconds
193 * @see #setDismissDelay
194 */
195 public int getDismissDelay() {
196 return insideTimer.getInitialDelay();
197 }
198
199 /**
200 * Used to specify the amount of time before the user has to wait
201 * <code>initialDelay</code> milliseconds before a tooltip will be
202 * shown. That is, if the tooltip is hidden, and the user moves into
203 * a region of the same Component that has a valid tooltip within
204 * <code>milliseconds</code> milliseconds the tooltip will immediately
205 * be shown. Otherwise, if the user moves into a region with a valid
206 * tooltip after <code>milliseconds</code> milliseconds, the user
207 * will have to wait an additional <code>initialDelay</code>
208 * milliseconds before the tooltip is shown again.
209 *
210 * @param milliseconds time in milliseconds
211 * @see #getReshowDelay
212 */
213 public void setReshowDelay(int milliseconds) {
214 exitTimer.setInitialDelay(milliseconds);
215 }
216
217 /**
218 * Returns the reshow delay property.
219 *
220 * @return reshown delay property
221 * @see #setReshowDelay
222 */
223 public int getReshowDelay() {
224 return exitTimer.getInitialDelay();
225 }
226
227 // Returns GraphicsConfiguration instance that toFind belongs to or null
367 insideTimer.start();
368 tipShowing = true;
369 }
370 }
371
372 void hideTipWindow() {
373 if (tipWindow != null) {
374 if (window != null) {
375 window.removeMouseListener(this);
376 window = null;
377 }
378 tipWindow.hide();
379 tipWindow = null;
380 tipShowing = false;
381 tip = null;
382 insideTimer.stop();
383 }
384 }
385
386 /**
387 * Returns a shared <code>ToolTipManager</code> instance.
388 *
389 * @return a shared <code>ToolTipManager</code> object
390 */
391 public static ToolTipManager sharedInstance() {
392 Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
393 if (value instanceof ToolTipManager) {
394 return (ToolTipManager) value;
395 }
396 ToolTipManager manager = new ToolTipManager();
397 SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
398 return manager;
399 }
400
401 // add keylistener here to trigger tip for access
402 /**
403 * Registers a component for tooltip management.
404 * <p>
405 * This will register key bindings to show and hide the tooltip text
406 * only if <code>component</code> has focus bindings. This is done
407 * so that components that are not normally focus traversable, such
408 * as <code>JLabel</code>, are not made focus traversable as a result
409 * of invoking this method.
410 *
411 * @param component a <code>JComponent</code> object to add
412 * @see JComponent#isFocusTraversable
413 */
414 public void registerComponent(JComponent component) {
415 component.removeMouseListener(this);
416 component.addMouseListener(this);
417 component.removeMouseMotionListener(moveBeforeEnterListener);
418 component.addMouseMotionListener(moveBeforeEnterListener);
419 component.removeKeyListener(accessibilityKeyListener);
420 component.addKeyListener(accessibilityKeyListener);
421 }
422
423 /**
424 * Removes a component from tooltip control.
425 *
426 * @param component a <code>JComponent</code> object to remove
427 */
428 public void unregisterComponent(JComponent component) {
429 component.removeMouseListener(this);
430 component.removeMouseMotionListener(moveBeforeEnterListener);
431 component.removeKeyListener(accessibilityKeyListener);
432 }
433
434 // implements java.awt.event.MouseListener
435 /**
436 * Called when the mouse enters the region of a component.
437 * This determines whether the tool tip should be shown.
438 *
439 * @param event the event in question
440 */
441 public void mouseEntered(MouseEvent event) {
442 initiateToolTip(event);
443 }
444
445 private void initiateToolTip(MouseEvent event) {
446 if (event.getSource() == window) {
606 toolTipText = component.getToolTipText(event);
607 if (toolTipText != null) {
608 preferredLocation = component.getToolTipLocation(event);
609 mouseEvent = event;
610 insideComponent = component;
611 exitTimer.stop();
612 showTipWindow();
613 }
614 }
615 else {
616 // Lazily lookup the values from within insideTimerAction
617 insideComponent = (JComponent)event.getSource();
618 mouseEvent = event;
619 toolTipText = null;
620 enterTimer.restart();
621 }
622 }
623
624 /**
625 * Checks to see if the tooltip needs to be changed in response to
626 * the MouseMoved event <code>event</code>.
627 */
628 private void checkForTipChange(MouseEvent event) {
629 JComponent component = (JComponent)event.getSource();
630 String newText = component.getToolTipText(event);
631 Point newPreferredLocation = component.getToolTipLocation(event);
632
633 if (newText != null || newPreferredLocation != null) {
634 mouseEvent = event;
635 if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
636 ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
637 || newPreferredLocation == null)) {
638 if (tipWindow != null) {
639 insideTimer.restart();
640 } else {
641 enterTimer.restart();
642 }
643 } else {
644 toolTipText = newText;
645 preferredLocation = newPreferredLocation;
646 if (showImmediately) {
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27 package javax.swing;
28
29 import java.awt.event.*;
30 import java.awt.*;
31 import java.util.Objects;
32
33 /**
34 * Manages all the {@code ToolTips} in the system.
35 * <p>
36 * ToolTipManager contains numerous properties for configuring how long it
37 * will take for the tooltips to become visible, and how long till they
38 * hide. Consider a component that has a different tooltip based on where
39 * the mouse is, such as JTree. When the mouse moves into the JTree and
40 * over a region that has a valid tooltip, the tooltip will become
41 * visible after {@code initialDelay} milliseconds. After
42 * {@code dismissDelay} milliseconds the tooltip will be hidden. If
43 * the mouse is over a region that has a valid tooltip, and the tooltip
44 * is currently visible, when the mouse moves to a region that doesn't have
45 * a valid tooltip the tooltip will be hidden. If the mouse then moves back
46 * into a region that has a valid tooltip within {@code reshowDelay}
47 * milliseconds, the tooltip will immediately be shown, otherwise the
48 * tooltip will be shown again after {@code initialDelay} milliseconds.
49 *
50 * @see JComponent#createToolTip
51 * @author Dave Moore
52 * @author Rich Schiavi
53 * @since 1.2
54 */
55 public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
56 Timer enterTimer, exitTimer, insideTimer;
57 String toolTipText;
58 Point preferredLocation;
59 JComponent insideComponent;
60 MouseEvent mouseEvent;
61 boolean showImmediately;
62 private static final Object TOOL_TIP_MANAGER_KEY = new Object();
63 transient Popup tipWindow;
64 /** The Window tip is being displayed in. This will be non-null if
65 * the Window tip is in differs from that of insideComponent's Window.
66 */
67 private Window window;
68 JToolTip tip;
109 *
110 * @param flag true to enable the tip, false otherwise
111 */
112 public void setEnabled(boolean flag) {
113 enabled = flag;
114 if (!flag) {
115 hideTipWindow();
116 }
117 }
118
119 /**
120 * Returns true if this object is enabled.
121 *
122 * @return true if this object is enabled, false otherwise
123 */
124 public boolean isEnabled() {
125 return enabled;
126 }
127
128 /**
129 * When displaying the {@code JToolTip}, the
130 * {@code ToolTipManager} chooses to use a lightweight
131 * {@code JPanel} if it fits. This method allows you to
132 * disable this feature. You have to do disable it if your
133 * application mixes light weight and heavy weights components.
134 *
135 * @param aFlag true if a lightweight panel is desired, false otherwise
136 *
137 */
138 public void setLightWeightPopupEnabled(boolean aFlag){
139 lightWeightPopupEnabled = aFlag;
140 }
141
142 /**
143 * Returns true if lightweight (all-Java) {@code Tooltips}
144 * are in use, or false if heavyweight (native peer)
145 * {@code Tooltips} are being used.
146 *
147 * @return true if lightweight {@code ToolTips} are in use
148 */
149 public boolean isLightWeightPopupEnabled() {
150 return lightWeightPopupEnabled;
151 }
152
153
154 /**
155 * Specifies the initial delay value.
156 *
157 * @param milliseconds the number of milliseconds to delay
158 * (after the cursor has paused) before displaying the
159 * tooltip
160 * @see #getInitialDelay
161 */
162 public void setInitialDelay(int milliseconds) {
163 enterTimer.setInitialDelay(milliseconds);
164 }
165
166 /**
167 * Returns the initial delay value.
181 * before taking away the tooltip
182 * @see #getDismissDelay
183 */
184 public void setDismissDelay(int milliseconds) {
185 insideTimer.setInitialDelay(milliseconds);
186 }
187
188 /**
189 * Returns the dismissal delay value.
190 *
191 * @return an integer representing the dismissal delay value,
192 * in milliseconds
193 * @see #setDismissDelay
194 */
195 public int getDismissDelay() {
196 return insideTimer.getInitialDelay();
197 }
198
199 /**
200 * Used to specify the amount of time before the user has to wait
201 * {@code initialDelay} milliseconds before a tooltip will be
202 * shown. That is, if the tooltip is hidden, and the user moves into
203 * a region of the same Component that has a valid tooltip within
204 * {@code milliseconds} milliseconds the tooltip will immediately
205 * be shown. Otherwise, if the user moves into a region with a valid
206 * tooltip after {@code milliseconds} milliseconds, the user
207 * will have to wait an additional {@code initialDelay}
208 * milliseconds before the tooltip is shown again.
209 *
210 * @param milliseconds time in milliseconds
211 * @see #getReshowDelay
212 */
213 public void setReshowDelay(int milliseconds) {
214 exitTimer.setInitialDelay(milliseconds);
215 }
216
217 /**
218 * Returns the reshow delay property.
219 *
220 * @return reshown delay property
221 * @see #setReshowDelay
222 */
223 public int getReshowDelay() {
224 return exitTimer.getInitialDelay();
225 }
226
227 // Returns GraphicsConfiguration instance that toFind belongs to or null
367 insideTimer.start();
368 tipShowing = true;
369 }
370 }
371
372 void hideTipWindow() {
373 if (tipWindow != null) {
374 if (window != null) {
375 window.removeMouseListener(this);
376 window = null;
377 }
378 tipWindow.hide();
379 tipWindow = null;
380 tipShowing = false;
381 tip = null;
382 insideTimer.stop();
383 }
384 }
385
386 /**
387 * Returns a shared {@code ToolTipManager} instance.
388 *
389 * @return a shared {@code ToolTipManager} object
390 */
391 public static ToolTipManager sharedInstance() {
392 Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
393 if (value instanceof ToolTipManager) {
394 return (ToolTipManager) value;
395 }
396 ToolTipManager manager = new ToolTipManager();
397 SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
398 return manager;
399 }
400
401 // add keylistener here to trigger tip for access
402 /**
403 * Registers a component for tooltip management.
404 * <p>
405 * This will register key bindings to show and hide the tooltip text
406 * only if {@code component} has focus bindings. This is done
407 * so that components that are not normally focus traversable, such
408 * as {@code JLabel}, are not made focus traversable as a result
409 * of invoking this method.
410 *
411 * @param component a {@code JComponent} object to add
412 * @see JComponent#isFocusTraversable
413 */
414 public void registerComponent(JComponent component) {
415 component.removeMouseListener(this);
416 component.addMouseListener(this);
417 component.removeMouseMotionListener(moveBeforeEnterListener);
418 component.addMouseMotionListener(moveBeforeEnterListener);
419 component.removeKeyListener(accessibilityKeyListener);
420 component.addKeyListener(accessibilityKeyListener);
421 }
422
423 /**
424 * Removes a component from tooltip control.
425 *
426 * @param component a {@code JComponent} object to remove
427 */
428 public void unregisterComponent(JComponent component) {
429 component.removeMouseListener(this);
430 component.removeMouseMotionListener(moveBeforeEnterListener);
431 component.removeKeyListener(accessibilityKeyListener);
432 }
433
434 // implements java.awt.event.MouseListener
435 /**
436 * Called when the mouse enters the region of a component.
437 * This determines whether the tool tip should be shown.
438 *
439 * @param event the event in question
440 */
441 public void mouseEntered(MouseEvent event) {
442 initiateToolTip(event);
443 }
444
445 private void initiateToolTip(MouseEvent event) {
446 if (event.getSource() == window) {
606 toolTipText = component.getToolTipText(event);
607 if (toolTipText != null) {
608 preferredLocation = component.getToolTipLocation(event);
609 mouseEvent = event;
610 insideComponent = component;
611 exitTimer.stop();
612 showTipWindow();
613 }
614 }
615 else {
616 // Lazily lookup the values from within insideTimerAction
617 insideComponent = (JComponent)event.getSource();
618 mouseEvent = event;
619 toolTipText = null;
620 enterTimer.restart();
621 }
622 }
623
624 /**
625 * Checks to see if the tooltip needs to be changed in response to
626 * the MouseMoved event {@code event}.
627 */
628 private void checkForTipChange(MouseEvent event) {
629 JComponent component = (JComponent)event.getSource();
630 String newText = component.getToolTipText(event);
631 Point newPreferredLocation = component.getToolTipLocation(event);
632
633 if (newText != null || newPreferredLocation != null) {
634 mouseEvent = event;
635 if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
636 ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
637 || newPreferredLocation == null)) {
638 if (tipWindow != null) {
639 insideTimer.restart();
640 } else {
641 enterTimer.restart();
642 }
643 } else {
644 toolTipText = newText;
645 preferredLocation = newPreferredLocation;
646 if (showImmediately) {
|