History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/ToolTipManager.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/ToolTipManager.java+828−0
@@ -0,0 +1,828 @@
1/*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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
27package javax.swing;
28
29import java.awt.event.*;
30import java.awt.*;
31
32/**
33 * Manages all the <code>ToolTips</code> in the system.
34 * <p>
35 * ToolTipManager contains numerous properties for configuring how long it
36 * will take for the tooltips to become visible, and how long till they
37 * hide. Consider a component that has a different tooltip based on where
38 * the mouse is, such as JTree. When the mouse moves into the JTree and
39 * over a region that has a valid tooltip, the tooltip will become
40 * visibile after <code>initialDelay</code> milliseconds. After
41 * <code>dismissDelay</code> milliseconds the tooltip will be hidden. If
42 * the mouse is over a region that has a valid tooltip, and the tooltip
43 * is currently visible, when the mouse moves to a region that doesn't have
44 * a valid tooltip the tooltip will be hidden. If the mouse then moves back
45 * into a region that has a valid tooltip within <code>reshowDelay</code>
46 * milliseconds, the tooltip will immediately be shown, otherwise the
47 * tooltip will be shown again after <code>initialDelay</code> milliseconds.
48 *
49 * @see JComponent#createToolTip
50 * @author Dave Moore
51 * @author Rich Schiavi
52 */
53public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
54 Timer enterTimer, exitTimer, insideTimer;
55 String toolTipText;
56 Point preferredLocation;
57 JComponent insideComponent;
58 MouseEvent mouseEvent;
59 boolean showImmediately;
60 private static final Object TOOL_TIP_MANAGER_KEY = new Object();
61 transient Popup tipWindow;
62 /** The Window tip is being displayed in. This will be non-null if
63 * the Window tip is in differs from that of insideComponent's Window.
64 */
65 private Window window;
66 JToolTip tip;
67
68 private Rectangle popupRect = null;
69 private Rectangle popupFrameRect = null;
70
71 boolean enabled = true;
72 private boolean tipShowing = false;
73
74 private FocusListener focusChangeListener = null;
75 private MouseMotionListener moveBeforeEnterListener = null;
76 private KeyListener accessibilityKeyListener = null;
77
78 private KeyStroke postTip;
79 private KeyStroke hideTip;
80
81 // PENDING(ges)
82 protected boolean lightWeightPopupEnabled = true;
83 protected boolean heavyWeightPopupEnabled = false;
84
85 ToolTipManager() {
86 enterTimer = new Timer(750, new insideTimerAction());
87 enterTimer.setRepeats(false);
88 exitTimer = new Timer(500, new outsideTimerAction());
89 exitTimer.setRepeats(false);
90 insideTimer = new Timer(4000, new stillInsideTimerAction());
91 insideTimer.setRepeats(false);
92
93 moveBeforeEnterListener = new MoveBeforeEnterListener();
94 accessibilityKeyListener = new AccessibilityKeyListener();
95
96 postTip = KeyStroke.getKeyStroke(KeyEvent.VK_F1, InputEvent.CTRL_MASK);
97 hideTip = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
98 }
99
100 /**
101 * Enables or disables the tooltip.
102 *
103 * @param flag true to enable the tip, false otherwise
104 */
105 public void setEnabled(boolean flag) {
106 enabled = flag;
107 if (!flag) {
108 hideTipWindow();
109 }
110 }
111
112 /**
113 * Returns true if this object is enabled.
114 *
115 * @return true if this object is enabled, false otherwise
116 */
117 public boolean isEnabled() {
118 return enabled;
119 }
120
121 /**
122 * When displaying the <code>JToolTip</code>, the
123 * <code>ToolTipManager</code> chooses to use a lightweight
124 * <code>JPanel</code> if it fits. This method allows you to
125 * disable this feature. You have to do disable it if your
126 * application mixes light weight and heavy weights components.
127 *
128 * @param aFlag true if a lightweight panel is desired, false otherwise
129 *
130 */
131 public void setLightWeightPopupEnabled(boolean aFlag){
132 lightWeightPopupEnabled = aFlag;
133 }
134
135 /**
136 * Returns true if lightweight (all-Java) <code>Tooltips</code>
137 * are in use, or false if heavyweight (native peer)
138 * <code>Tooltips</code> are being used.
139 *
140 * @return true if lightweight <code>ToolTips</code> are in use
141 */
142 public boolean isLightWeightPopupEnabled() {
143 return lightWeightPopupEnabled;
144 }
145
146
147 /**
148 * Specifies the initial delay value.
149 *
150 * @param milliseconds the number of milliseconds to delay
151 * (after the cursor has paused) before displaying the
152 * tooltip
153 * @see #getInitialDelay
154 */
155 public void setInitialDelay(int milliseconds) {
156 enterTimer.setInitialDelay(milliseconds);
157 }
158
159 /**
160 * Returns the initial delay value.
161 *
162 * @return an integer representing the initial delay value,
163 * in milliseconds
164 * @see #setInitialDelay
165 */
166 public int getInitialDelay() {
167 return enterTimer.getInitialDelay();
168 }
169
170 /**
171 * Specifies the dismissal delay value.
172 *
173 * @param milliseconds the number of milliseconds to delay
174 * before taking away the tooltip
175 * @see #getDismissDelay
176 */
177 public void setDismissDelay(int milliseconds) {
178 insideTimer.setInitialDelay(milliseconds);
179 }
180
181 /**
182 * Returns the dismissal delay value.
183 *
184 * @return an integer representing the dismissal delay value,
185 * in milliseconds
186 * @see #setDismissDelay
187 */
188 public int getDismissDelay() {
189 return insideTimer.getInitialDelay();
190 }
191
192 /**
193 * Used to specify the amount of time before the user has to wait
194 * <code>initialDelay</code> milliseconds before a tooltip will be
195 * shown. That is, if the tooltip is hidden, and the user moves into
196 * a region of the same Component that has a valid tooltip within
197 * <code>milliseconds</code> milliseconds the tooltip will immediately
198 * be shown. Otherwise, if the user moves into a region with a valid
199 * tooltip after <code>milliseconds</code> milliseconds, the user
200 * will have to wait an additional <code>initialDelay</code>
201 * milliseconds before the tooltip is shown again.
202 *
203 * @param milliseconds time in milliseconds
204 * @see #getReshowDelay
205 */
206 public void setReshowDelay(int milliseconds) {
207 exitTimer.setInitialDelay(milliseconds);
208 }
209
210 /**
211 * Returns the reshow delay property.
212 *
213 * @return reshown delay property
214 * @see #setReshowDelay
215 */
216 public int getReshowDelay() {
217 return exitTimer.getInitialDelay();
218 }
219
220 void showTipWindow() {
221 if(insideComponent == null || !insideComponent.isShowing())
222 return;
223 String mode = UIManager.getString("ToolTipManager.enableToolTipMode");
224 if ("activeApplication".equals(mode)) {
225 KeyboardFocusManager kfm =
226 KeyboardFocusManager.getCurrentKeyboardFocusManager();
227 if (kfm.getFocusedWindow() == null) {
228 return;
229 }
230 }
231 if (enabled) {
232 Dimension size;
233 Point screenLocation = insideComponent.getLocationOnScreen();
234 Point location = new Point();
235 GraphicsConfiguration gc;
236 gc = insideComponent.getGraphicsConfiguration();
237 Rectangle sBounds = gc.getBounds();
238 Insets screenInsets = Toolkit.getDefaultToolkit()
239 .getScreenInsets(gc);
240 // Take into account screen insets, decrease viewport
241 sBounds.x += screenInsets.left;
242 sBounds.y += screenInsets.top;
243 sBounds.width -= (screenInsets.left + screenInsets.right);
244 sBounds.height -= (screenInsets.top + screenInsets.bottom);
245 boolean leftToRight
246 = SwingUtilities.isLeftToRight(insideComponent);
247
248 // Just to be paranoid
249 hideTipWindow();
250
251 tip = insideComponent.createToolTip();
252 tip.setTipText(toolTipText);
253 size = tip.getPreferredSize();
254
255 if(preferredLocation != null) {
256 location.x = screenLocation.x + preferredLocation.x;
257 location.y = screenLocation.y + preferredLocation.y;
258 if (!leftToRight) {
259 location.x -= size.width;
260 }
261 } else {
262 location.x = screenLocation.x + mouseEvent.getX();
263 location.y = screenLocation.y + mouseEvent.getY() + 20;
264 if (!leftToRight) {
265 if(location.x - size.width>=0) {
266 location.x -= size.width;
267 }
268 }
269
270 }
271
272 // we do not adjust x/y when using awt.Window tips
273 if (popupRect == null){
274 popupRect = new Rectangle();
275 }
276 popupRect.setBounds(location.x,location.y,
277 size.width,size.height);
278
279 // Fit as much of the tooltip on screen as possible
280 if (location.x < sBounds.x) {
281 location.x = sBounds.x;
282 }
283 else if (location.x - sBounds.x + size.width > sBounds.width) {
284 location.x = sBounds.x + Math.max(0, sBounds.width - size.width)
285;
286 }
287 if (location.y < sBounds.y) {
288 location.y = sBounds.y;
289 }
290 else if (location.y - sBounds.y + size.height > sBounds.height) {
291 location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
292 }
293
294 PopupFactory popupFactory = PopupFactory.getSharedInstance();
295
296 if (lightWeightPopupEnabled) {
297 int y = getPopupFitHeight(popupRect, insideComponent);
298 int x = getPopupFitWidth(popupRect,insideComponent);
299 if (x>0 || y>0) {
300 popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
301 } else {
302 popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
303 }
304 }
305 else {
306 popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
307 }
308 tipWindow = popupFactory.getPopup(insideComponent, tip,
309 location.x,
310 location.y);
311 popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
312
313 tipWindow.show();
314
315 Window componentWindow = SwingUtilities.windowForComponent(
316 insideComponent);
317
318 window = SwingUtilities.windowForComponent(tip);
319 if (window != null && window != componentWindow) {
320 window.addMouseListener(this);
321 }
322 else {
323 window = null;
324 }
325
326 insideTimer.start();
327 tipShowing = true;
328 }
329 }
330
331 void hideTipWindow() {
332 if (tipWindow != null) {
333 if (window != null) {
334 window.removeMouseListener(this);
335 window = null;
336 }
337 tipWindow.hide();
338 tipWindow = null;
339 tipShowing = false;
340 tip = null;
341 insideTimer.stop();
342 }
343 }
344
345 /**
346 * Returns a shared <code>ToolTipManager</code> instance.
347 *
348 * @return a shared <code>ToolTipManager</code> object
349 */
350 public static ToolTipManager sharedInstance() {
351 Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
352 if (value instanceof ToolTipManager) {
353 return (ToolTipManager) value;
354 }
355 ToolTipManager manager = new ToolTipManager();
356 SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
357 return manager;
358 }
359
360 // add keylistener here to trigger tip for access
361 /**
362 * Registers a component for tooltip management.
363 * <p>
364 * This will register key bindings to show and hide the tooltip text
365 * only if <code>component</code> has focus bindings. This is done
366 * so that components that are not normally focus traversable, such
367 * as <code>JLabel</code>, are not made focus traversable as a result
368 * of invoking this method.
369 *
370 * @param component a <code>JComponent</code> object to add
371 * @see JComponent#isFocusTraversable
372 */
373 public void registerComponent(JComponent component) {
374 component.removeMouseListener(this);
375 component.addMouseListener(this);
376 component.removeMouseMotionListener(moveBeforeEnterListener);
377 component.addMouseMotionListener(moveBeforeEnterListener);
378 component.removeKeyListener(accessibilityKeyListener);
379 component.addKeyListener(accessibilityKeyListener);
380 }
381
382 /**
383 * Removes a component from tooltip control.
384 *
385 * @param component a <code>JComponent</code> object to remove
386 */
387 public void unregisterComponent(JComponent component) {
388 component.removeMouseListener(this);
389 component.removeMouseMotionListener(moveBeforeEnterListener);
390 component.removeKeyListener(accessibilityKeyListener);
391 }
392
393 // implements java.awt.event.MouseListener
394 /**
395 * Called when the mouse enters the region of a component.
396 * This determines whether the tool tip should be shown.
397 *
398 * @param event the event in question
399 */
400 public void mouseEntered(MouseEvent event) {
401 initiateToolTip(event);
402 }
403
404 private void initiateToolTip(MouseEvent event) {
405 if (event.getSource() == window) {
406 return;
407 }
408 JComponent component = (JComponent)event.getSource();
409 component.removeMouseMotionListener(moveBeforeEnterListener);
410
411 exitTimer.stop();
412
413 Point location = event.getPoint();
414 // ensure tooltip shows only in proper place
415 if (location.x < 0 ||
416 location.x >=component.getWidth() ||
417 location.y < 0 ||
418 location.y >= component.getHeight()) {
419 return;
420 }
421
422 if (insideComponent != null) {
423 enterTimer.stop();
424 }
425 // A component in an unactive internal frame is sent two
426 // mouseEntered events, make sure we don't end up adding
427 // ourselves an extra time.
428 component.removeMouseMotionListener(this);
429 component.addMouseMotionListener(this);
430
431 boolean sameComponent = (insideComponent == component);
432
433 insideComponent = component;
434 if (tipWindow != null){
435 mouseEvent = event;
436 if (showImmediately) {
437 String newToolTipText = component.getToolTipText(event);
438 Point newPreferredLocation = component.getToolTipLocation(
439 event);
440 boolean sameLoc = (preferredLocation != null) ?
441 preferredLocation.equals(newPreferredLocation) :
442 (newPreferredLocation == null);
443
444 if (!sameComponent || !toolTipText.equals(newToolTipText) ||
445 !sameLoc) {
446 toolTipText = newToolTipText;
447 preferredLocation = newPreferredLocation;
448 showTipWindow();
449 }
450 } else {
451 enterTimer.start();
452 }
453 }
454 }
455
456 // implements java.awt.event.MouseListener
457 /**
458 * Called when the mouse exits the region of a component.
459 * Any tool tip showing should be hidden.
460 *
461 * @param event the event in question
462 */
463 public void mouseExited(MouseEvent event) {
464 boolean shouldHide = true;
465 if (insideComponent == null) {
466 // Drag exit
467 }
468 if (window != null && event.getSource() == window && insideComponent != null) {
469 // if we get an exit and have a heavy window
470 // we need to check if it if overlapping the inside component
471 Container insideComponentWindow = insideComponent.getTopLevelAncestor();
472 // insideComponent may be removed after tooltip is made visible
473 if (insideComponentWindow != null) {
474 Point location = event.getPoint();
475 SwingUtilities.convertPointToScreen(location, window);
476
477 location.x -= insideComponentWindow.getX();
478 location.y -= insideComponentWindow.getY();
479
480 location = SwingUtilities.convertPoint(null, location, insideComponent);
481 if (location.x >= 0 && location.x < insideComponent.getWidth() &&
482 location.y >= 0 && location.y < insideComponent.getHeight()) {
483 shouldHide = false;
484 } else {
485 shouldHide = true;
486 }
487 }
488 } else if(event.getSource() == insideComponent && tipWindow != null) {
489 Window win = SwingUtilities.getWindowAncestor(insideComponent);
490 if (win != null) { // insideComponent may have been hidden (e.g. in a menu)
491 Point location = SwingUtilities.convertPoint(insideComponent,
492 event.getPoint(),
493 win);
494 Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
495 location.x += bounds.x;
496 location.y += bounds.y;
497
498 Point loc = new Point(0, 0);
499 SwingUtilities.convertPointToScreen(loc, tip);
500 bounds.x = loc.x;
501 bounds.y = loc.y;
502 bounds.width = tip.getWidth();
503 bounds.height = tip.getHeight();
504
505 if (location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
506 location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
507 shouldHide = false;
508 } else {
509 shouldHide = true;
510 }
511 }
512 }
513
514 if (shouldHide) {
515 enterTimer.stop();
516 if (insideComponent != null) {
517 insideComponent.removeMouseMotionListener(this);
518 }
519 insideComponent = null;
520 toolTipText = null;
521 mouseEvent = null;
522 hideTipWindow();
523 exitTimer.restart();
524 }
525 }
526
527 // implements java.awt.event.MouseListener
528 /**
529 * Called when the mouse is pressed.
530 * Any tool tip showing should be hidden.
531 *
532 * @param event the event in question
533 */
534 public void mousePressed(MouseEvent event) {
535 hideTipWindow();
536 enterTimer.stop();
537 showImmediately = false;
538 insideComponent = null;
539 mouseEvent = null;
540 }
541
542 // implements java.awt.event.MouseMotionListener
543 /**
544 * Called when the mouse is pressed and dragged.
545 * Does nothing.
546 *
547 * @param event the event in question
548 */
549 public void mouseDragged(MouseEvent event) {
550 }
551
552 // implements java.awt.event.MouseMotionListener
553 /**
554 * Called when the mouse is moved.
555 * Determines whether the tool tip should be displayed.
556 *
557 * @param event the event in question
558 */
559 public void mouseMoved(MouseEvent event) {
560 if (tipShowing) {
561 checkForTipChange(event);
562 }
563 else if (showImmediately) {
564 JComponent component = (JComponent)event.getSource();
565 toolTipText = component.getToolTipText(event);
566 if (toolTipText != null) {
567 preferredLocation = component.getToolTipLocation(event);
568 mouseEvent = event;
569 insideComponent = component;
570 exitTimer.stop();
571 showTipWindow();
572 }
573 }
574 else {
575 // Lazily lookup the values from within insideTimerAction
576 insideComponent = (JComponent)event.getSource();
577 mouseEvent = event;
578 toolTipText = null;
579 enterTimer.restart();
580 }
581 }
582
583 /**
584 * Checks to see if the tooltip needs to be changed in response to
585 * the MouseMoved event <code>event</code>.
586 */
587 private void checkForTipChange(MouseEvent event) {
588 JComponent component = (JComponent)event.getSource();
589 String newText = component.getToolTipText(event);
590 Point newPreferredLocation = component.getToolTipLocation(event);
591
592 if (newText != null || newPreferredLocation != null) {
593 mouseEvent = event;
594 if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
595 ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
596 || newPreferredLocation == null)) {
597 if (tipWindow != null) {
598 insideTimer.restart();
599 } else {
600 enterTimer.restart();
601 }
602 } else {
603 toolTipText = newText;
604 preferredLocation = newPreferredLocation;
605 if (showImmediately) {
606 hideTipWindow();
607 showTipWindow();
608 exitTimer.stop();
609 } else {
610 enterTimer.restart();
611 }
612 }
613 } else {
614 toolTipText = null;
615 preferredLocation = null;
616 mouseEvent = null;
617 insideComponent = null;
618 hideTipWindow();
619 enterTimer.stop();
620 exitTimer.restart();
621 }
622 }
623
624 protected class insideTimerAction implements ActionListener {
625 public void actionPerformed(ActionEvent e) {
626 if(insideComponent != null && insideComponent.isShowing()) {
627 // Lazy lookup
628 if (toolTipText == null && mouseEvent != null) {
629 toolTipText = insideComponent.getToolTipText(mouseEvent);
630 preferredLocation = insideComponent.getToolTipLocation(
631 mouseEvent);
632 }
633 if(toolTipText != null) {
634 showImmediately = true;
635 showTipWindow();
636 }
637 else {
638 insideComponent = null;
639 toolTipText = null;
640 preferredLocation = null;
641 mouseEvent = null;
642 hideTipWindow();
643 }
644 }
645 }
646 }
647
648 protected class outsideTimerAction implements ActionListener {
649 public void actionPerformed(ActionEvent e) {
650 showImmediately = false;
651 }
652 }
653
654 protected class stillInsideTimerAction implements ActionListener {
655 public void actionPerformed(ActionEvent e) {
656 hideTipWindow();
657 enterTimer.stop();
658 showImmediately = false;
659 insideComponent = null;
660 mouseEvent = null;
661 }
662 }
663
664 /* This listener is registered when the tooltip is first registered
665 * on a component in order to catch the situation where the tooltip
666 * was turned on while the mouse was already within the bounds of
667 * the component. This way, the tooltip will be initiated on a
668 * mouse-entered or mouse-moved, whichever occurs first. Once the
669 * tooltip has been initiated, we can remove this listener and rely
670 * solely on mouse-entered to initiate the tooltip.
671 */
672 private class MoveBeforeEnterListener extends MouseMotionAdapter {
673 public void mouseMoved(MouseEvent e) {
674 initiateToolTip(e);
675 }
676 }
677
678 static Frame frameForComponent(Component component) {
679 while (!(component instanceof Frame)) {
680 component = component.getParent();
681 }
682 return (Frame)component;
683 }
684
685 private FocusListener createFocusChangeListener(){
686 return new FocusAdapter(){
687 public void focusLost(FocusEvent evt){
688 hideTipWindow();
689 insideComponent = null;
690 JComponent c = (JComponent)evt.getSource();
691 c.removeFocusListener(focusChangeListener);
692 }
693 };
694 }
695
696 // Returns: 0 no adjust
697 // -1 can't fit
698 // >0 adjust value by amount returned
699 private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){
700 if (invoker != null){
701 Container parent;
702 for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
703 // fix internal frame size bug: 4139087 - 4159012
704 if(parent instanceof JFrame || parent instanceof JDialog ||
705 parent instanceof JWindow) { // no check for awt.Frame since we use Heavy tips
706 return getWidthAdjust(parent.getBounds(),popupRectInScreen);
707 } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
708 if (popupFrameRect == null){
709 popupFrameRect = new Rectangle();
710 }
711 Point p = parent.getLocationOnScreen();
712 popupFrameRect.setBounds(p.x,p.y,
713 parent.getBounds().width,
714 parent.getBounds().height);
715 return getWidthAdjust(popupFrameRect,popupRectInScreen);
716 }
717 }
718 }
719 return 0;
720 }
721
722 // Returns: 0 no adjust
723 // >0 adjust by value return
724 private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){
725 if (invoker != null){
726 Container parent;
727 for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
728 if(parent instanceof JFrame || parent instanceof JDialog ||
729 parent instanceof JWindow) {
730 return getHeightAdjust(parent.getBounds(),popupRectInScreen);
731 } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
732 if (popupFrameRect == null){
733 popupFrameRect = new Rectangle();
734 }
735 Point p = parent.getLocationOnScreen();
736 popupFrameRect.setBounds(p.x,p.y,
737 parent.getBounds().width,
738 parent.getBounds().height);
739 return getHeightAdjust(popupFrameRect,popupRectInScreen);
740 }
741 }
742 }
743 return 0;
744 }
745
746 private int getHeightAdjust(Rectangle a, Rectangle b){
747 if (b.y >= a.y && (b.y + b.height) <= (a.y + a.height))
748 return 0;
749 else
750 return (((b.y + b.height) - (a.y + a.height)) + 5);
751 }
752
753 // Return the number of pixels over the edge we are extending.
754 // If we are over the edge the ToolTipManager can adjust.
755 // REMIND: what if the Tooltip is just too big to fit at all - we currently will just clip
756 private int getWidthAdjust(Rectangle a, Rectangle b){
757 // System.out.println("width b.x/b.width: " + b.x + "/" + b.width +
758 // "a.x/a.width: " + a.x + "/" + a.width);
759 if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width)){
760 return 0;
761 }
762 else {
763 return (((b.x + b.width) - (a.x +a.width)) + 5);
764 }
765 }
766
767
768 //
769 // Actions
770 //
771 private void show(JComponent source) {
772 if (tipWindow != null) { // showing we unshow
773 hideTipWindow();
774 insideComponent = null;
775 }
776 else {
777 hideTipWindow(); // be safe
778 enterTimer.stop();
779 exitTimer.stop();
780 insideTimer.stop();
781 insideComponent = source;
782 if (insideComponent != null){
783 toolTipText = insideComponent.getToolTipText();
784 preferredLocation = new Point(10,insideComponent.getHeight()+
785 10); // manual set
786 showTipWindow();
787 // put a focuschange listener on to bring the tip down
788 if (focusChangeListener == null){
789 focusChangeListener = createFocusChangeListener();
790 }
791 insideComponent.addFocusListener(focusChangeListener);
792 }
793 }
794 }
795
796 private void hide(JComponent source) {
797 hideTipWindow();
798 source.removeFocusListener(focusChangeListener);
799 preferredLocation = null;
800 insideComponent = null;
801 }
802
803 /* This listener is registered when the tooltip is first registered
804 * on a component in order to process accessibility keybindings.
805 * This will apply globally across L&F
806 *
807 * Post Tip: Ctrl+F1
808 * Unpost Tip: Esc and Ctrl+F1
809 */
810 private class AccessibilityKeyListener extends KeyAdapter {
811 public void keyPressed(KeyEvent e) {
812 if (!e.isConsumed()) {
813 JComponent source = (JComponent) e.getComponent();
814 KeyStroke keyStrokeForEvent = KeyStroke.getKeyStrokeForEvent(e);
815 if (hideTip.equals(keyStrokeForEvent)) {
816 if (tipWindow != null) {
817 hide(source);
818 e.consume();
819 }
820 } else if (postTip.equals(keyStrokeForEvent)) {
821 // Shown tooltip will be hidden
822 ToolTipManager.this.show(source);
823 e.consume();
824 }
825 }
826 }
827 }
828}