1 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 ; 15 import sun.swing.UIAction; 16 17 39 public class ToolTipManager extends MouseAdapter implements MouseMotionListener { 40 Timer enterTimer, exitTimer, insideTimer; 41 String toolTipText; 42 Point preferredLocation; 43 JComponent insideComponent; 44 MouseEvent mouseEvent; 45 boolean showImmediately; 46 final static ToolTipManager sharedInstance = new ToolTipManager (); 47 transient Popup tipWindow; 48 51 private Window window; 52 JToolTip 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 postTip,hideTip; 61 private Action postTipAction, hideTipAction; 62 63 private FocusListener focusChangeListener = null; 64 private MouseMotionListener moveBeforeEnterListener = null; 65 66 protected boolean lightWeightPopupEnabled = true; 68 protected boolean heavyWeightPopupEnabled = false; 69 70 ToolTipManager() { 71 enterTimer = new Timer (750, new insideTimerAction()); 72 enterTimer.setRepeats(false); 73 exitTimer = new Timer (500, new outsideTimerAction()); 74 exitTimer.setRepeats(false); 75 insideTimer = new Timer (4000, new stillInsideTimerAction()); 76 insideTimer.setRepeats(false); 77 78 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 92 public void setEnabled(boolean flag) { 93 enabled = flag; 94 if (!flag) { 95 hideTipWindow(); 96 } 97 } 98 99 104 public boolean isEnabled() { 105 return enabled; 106 } 107 108 118 public void setLightWeightPopupEnabled(boolean aFlag){ 119 lightWeightPopupEnabled = aFlag; 120 } 121 122 129 public boolean isLightWeightPopupEnabled() { 130 return lightWeightPopupEnabled; 131 } 132 133 134 142 public void setInitialDelay(int milliseconds) { 143 enterTimer.setInitialDelay(milliseconds); 144 } 145 146 153 public int getInitialDelay() { 154 return enterTimer.getInitialDelay(); 155 } 156 157 164 public void setDismissDelay(int milliseconds) { 165 insideTimer.setInitialDelay(milliseconds); 166 } 167 168 175 public int getDismissDelay() { 176 return insideTimer.getInitialDelay(); 177 } 178 179 193 public void setReshowDelay(int milliseconds) { 194 exitTimer.setInitialDelay(milliseconds); 195 } 196 197 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 ) 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 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 if (popupRect == null){ 254 popupRect = new Rectangle(); 255 } 256 popupRect.setBounds(location.x,location.y, 257 size.width,size.height); 258 259 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 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 331 public static ToolTipManager sharedInstance() { 332 return sharedInstance; 333 } 334 335 348 public void registerComponent(JComponent component) { 349 component.removeMouseListener(this); 350 component.addMouseListener(this); 351 component.removeMouseMotionListener(moveBeforeEnterListener); 352 component.addMouseMotionListener(moveBeforeEnterListener); 353 354 if (shouldRegisterBindings(component)) { 355 InputMap inputMap = component.getInputMap(JComponent.WHEN_FOCUSED); 360 ActionMap 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 376 public void unregisterComponent(JComponent component) { 377 component.removeMouseListener(this); 378 component.removeMouseMotionListener(moveBeforeEnterListener); 379 380 if (shouldRegisterBindings(component)) { 381 InputMap inputMap = component.getInputMap(JComponent.WHEN_FOCUSED); 382 ActionMap 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 407 private boolean shouldRegisterBindings(JComponent component) { 408 InputMap 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 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 component = (JComponent )event.getSource(); 432 component.removeMouseMotionListener(moveBeforeEnterListener); 433 434 exitTimer.stop(); 435 436 Point location = event.getPoint(); 437 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 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 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 486 public void mouseExited(MouseEvent event) { 487 boolean shouldHide = true; 488 if (insideComponent == null) { 489 } 491 if (window != null && event.getSource() == window) { 492 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) { 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 554 public void mousePressed(MouseEvent event) { 555 hideTipWindow(); 556 enterTimer.stop(); 557 showImmediately = false; 558 insideComponent = null; 559 mouseEvent = null; 560 } 561 562 569 public void mouseDragged(MouseEvent event) { 570 } 571 572 579 public void mouseMoved(MouseEvent event) { 580 if (tipShowing) { 581 checkForTipChange(event); 582 } 583 else if (showImmediately) { 584 JComponent component = (JComponent )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 insideComponent = (JComponent )event.getSource(); 597 mouseEvent = event; 598 toolTipText = null; 599 enterTimer.restart(); 600 } 601 } 602 603 607 private void checkForTipChange(MouseEvent event) { 608 JComponent component = (JComponent )event.getSource(); 609 String 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 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 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 c = (JComponent )evt.getSource(); 711 c.removeFocusListener(focusChangeListener); 712 } 713 }; 714 } 715 716 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 if(parent instanceof JFrame || parent instanceof JDialog || 725 parent instanceof JWindow ) { return getWidthAdjust(parent.getBounds(),popupRectInScreen); 727 } else if (parent instanceof JApplet || parent instanceof JInternalFrame ) { 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 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 || parent instanceof JDialog || 749 parent instanceof JWindow ) { 750 return getHeightAdjust(parent.getBounds(),popupRectInScreen); 751 } else if (parent instanceof JApplet || parent instanceof JInternalFrame ) { 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 private int getWidthAdjust(Rectangle a, Rectangle b){ 777 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 private void show(JComponent source) { 792 if (tipWindow != null) { hideTipWindow(); 794 insideComponent = null; 795 } 796 else { 797 hideTipWindow(); 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); showTipWindow(); 807 if (focusChangeListener == null){ 809 focusChangeListener = createFocusChangeListener(); 810 } 811 insideComponent.addFocusListener(focusChangeListener); 812 } 813 } 814 } 815 816 private void hide(JComponent 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 SHOW = "SHOW"; 826 private static String HIDE = "HIDE"; 827 828 Actions(String key) { 829 super(key); 830 } 831 832 public void actionPerformed(ActionEvent e) { 833 String key = getName(); 834 JComponent source = (JComponent )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 sender) { 844 if (getName() == SHOW) { 845 return true; 846 } 847 return ToolTipManager.sharedInstance().tipShowing; 848 } 849 } 850 } 851 | Popular Tags |