1. /*
  2. * @(#)ToolTipManager.java 1.41 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.event.*;
  9. import java.applet.*;
  10. import java.awt.*;
  11. import java.io.Serializable;
  12. /**
  13. * Manages all the ToolTips in the system.
  14. *
  15. * @see JComponent#createToolTip
  16. * @version 1.41 11/29/01
  17. * @author Dave Moore
  18. * @author Rich Schiavi
  19. */
  20. public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
  21. Timer enterTimer, exitTimer, insideTimer;
  22. String toolTipText;
  23. Point preferredLocation;
  24. JComponent insideComponent;
  25. MouseEvent mouseEvent;
  26. boolean showImmediately;
  27. final static ToolTipManager sharedInstance = new ToolTipManager();
  28. Popup tipWindow;
  29. JToolTip tip;
  30. private Rectangle popupRect = null;
  31. private Rectangle popupFrameRect = null;
  32. boolean enabled = true;
  33. boolean mouseAboveToolTip = false;
  34. private boolean tipShowing = false;
  35. private long timerEnter = 0;
  36. private KeyStroke postTip,hideTip;
  37. private ActionListener postTipAction, hideTipAction;
  38. private FocusListener focusChangeListener = null;
  39. protected boolean lightWeightPopupEnabled = true;
  40. protected boolean heavyWeightPopupEnabled = false;
  41. ToolTipManager() {
  42. enterTimer = new Timer(750, new insideTimerAction());
  43. enterTimer.setRepeats(false);
  44. exitTimer = new Timer(500, new outsideTimerAction());
  45. exitTimer.setRepeats(false);
  46. insideTimer = new Timer(4000, new stillInsideTimerAction());
  47. insideTimer.setRepeats(false);
  48. // create accessibility actions
  49. postTip = KeyStroke.getKeyStroke(KeyEvent.VK_F1,Event.CTRL_MASK);
  50. postTipAction = new ActionListener(){
  51. public void actionPerformed(ActionEvent e){
  52. if (tipWindow != null) // showing we unshow
  53. hideTipWindow();
  54. else {
  55. hideTipWindow(); // be safe
  56. enterTimer.stop();
  57. exitTimer.stop();
  58. insideTimer.stop();
  59. insideComponent = (JComponent)e.getSource();
  60. if (insideComponent != null){
  61. toolTipText = insideComponent.getToolTipText();
  62. preferredLocation = new Point(10,insideComponent.getHeight()+10); // manual set
  63. showTipWindow();
  64. // put a focuschange listener on to bring the tip down
  65. if (focusChangeListener == null){
  66. focusChangeListener = createFocusChangeListener();
  67. }
  68. insideComponent.addFocusListener(focusChangeListener);
  69. }
  70. }
  71. }
  72. };
  73. hideTip = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0);
  74. hideTipAction = new ActionListener(){
  75. public void actionPerformed(ActionEvent e){
  76. hideTipWindow();
  77. JComponent jc = (JComponent)e.getSource();
  78. jc.removeFocusListener(focusChangeListener);
  79. preferredLocation = null;
  80. }
  81. };
  82. }
  83. /**
  84. * Enables or disables the tooltip.
  85. *
  86. * @param flag true to enable the tip
  87. */
  88. public void setEnabled(boolean flag) {
  89. enabled = flag;
  90. if (!flag) {
  91. hideTipWindow();
  92. }
  93. }
  94. /**
  95. * Returns true if this object is enabled.
  96. *
  97. * @return true if this object is enabled
  98. */
  99. public boolean isEnabled() {
  100. return enabled;
  101. }
  102. /**
  103. * When displaying the JToolTip, the ToolTipManager choose to use a light weight JPanel if
  104. * it fits. This method allows you to disable this feature. You have to do disable
  105. * it if your application mixes light weight and heavy weights components.
  106. * @deprecated As of Swing1.1
  107. * replaced by <code>setToolTipWindowUsePolicy(int)</code>.
  108. */
  109. public void setLightWeightPopupEnabled(boolean aFlag){
  110. lightWeightPopupEnabled = aFlag;
  111. }
  112. /**
  113. * Returns true if lightweight (all-Java) Tooltips are in use,
  114. * or false if heavyweight (native peer) Tooltips are being used.
  115. *
  116. * @return true if lightweight ToolTips are in use
  117. */
  118. public boolean isLightWeightPopupEnabled() {
  119. return lightWeightPopupEnabled;
  120. }
  121. /**
  122. * Specifies the initial delay value.
  123. *
  124. * @param microSeconds an int specifying the number of microseconds
  125. * to delay (after the cursor has paused) before displaying the
  126. * tooltip
  127. * @see #getInitialDelay
  128. */
  129. public void setInitialDelay(int microSeconds) {
  130. enterTimer.setInitialDelay(microSeconds);
  131. }
  132. /**
  133. * Returns the initial delay value.
  134. *
  135. * @return an int representing the initial delay value
  136. * @see #setInitialDelay
  137. */
  138. public int getInitialDelay() {
  139. return enterTimer.getInitialDelay();
  140. }
  141. /**
  142. * Specifies the dismisal delay value.
  143. *
  144. * @param microSeconds an int specifying the number of microseconds
  145. * to delay (after the cursor has moved on) before taking away
  146. * the tooltip
  147. * @see #getDismissDelay
  148. */
  149. public void setDismissDelay(int microSeconds) {
  150. insideTimer.setInitialDelay(microSeconds);
  151. }
  152. /**
  153. * Returns the dismisal delay value.
  154. *
  155. * @return an int representing the dismisal delay value
  156. * @see #setDismissDelay
  157. */
  158. public int getDismissDelay() {
  159. return insideTimer.getInitialDelay();
  160. }
  161. /**
  162. * Specifies the time to delay before reshowing the tooltip.
  163. *
  164. * @param microSeconds an int specifying the time in microseconds
  165. * before reshowing the tooltip if the cursor stops again
  166. * @see #getReshowDelay
  167. */
  168. public void setReshowDelay(int microSeconds) {
  169. exitTimer.setInitialDelay(microSeconds);
  170. }
  171. /**
  172. * Returns the reshow delay value.
  173. *
  174. * @return an int representing the reshow delay value
  175. * @see #setReshowDelay
  176. */
  177. public int getReshowDelay() {
  178. return exitTimer.getInitialDelay();
  179. }
  180. void showTipWindow() {
  181. if(insideComponent == null || !insideComponent.isShowing())
  182. return;
  183. if (enabled) {
  184. Dimension size;
  185. Point screenLocation = insideComponent.getLocationOnScreen();
  186. Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  187. Point location = new Point();
  188. // Just to be paranoid
  189. hideTipWindow();
  190. tip = insideComponent.createToolTip();
  191. tip.setTipText(toolTipText);
  192. size = tip.getPreferredSize();
  193. // fix bug 4135787: Tooltips don't work when used in awt.Frame or awt.Applet, etc
  194. // this is a quick and dirty check
  195. if (insideComponent.getRootPane() == null){
  196. tipWindow = new WindowPopup((frameForComponent(insideComponent)),tip,size);
  197. heavyWeightPopupEnabled = true;
  198. }
  199. else if (lightWeightPopupEnabled){
  200. heavyWeightPopupEnabled = false;
  201. tipWindow = new JPanelPopup(tip,size);
  202. }
  203. else {
  204. heavyWeightPopupEnabled = false;
  205. tipWindow = new PanelPopup(tip,size);
  206. }
  207. tipWindow.addMouseListener(this);
  208. if(preferredLocation != null) {
  209. location.x = screenLocation.x + preferredLocation.x;
  210. location.y = screenLocation.y + preferredLocation.y;
  211. } else {
  212. location.x = screenLocation.x + mouseEvent.getX();
  213. location.y = screenLocation.y + mouseEvent.getY() + 20;
  214. if (location.x + size.width > screenSize.width) {
  215. location.x -= size.width;
  216. }
  217. if (location.y + size.height > screenSize.height) {
  218. location.y -= (size.height + 20);
  219. }
  220. }
  221. // we do not adjust x/y when using awt.Window tips
  222. if (!heavyWeightPopupEnabled){
  223. if (popupRect == null){
  224. popupRect = new Rectangle();
  225. }
  226. popupRect.setBounds(location.x,location.y,
  227. tipWindow.getBounds().width,tipWindow.getBounds().height);
  228. int y = getPopupFitHeight(popupRect, insideComponent);
  229. int x = getPopupFitWidth(popupRect,insideComponent);
  230. if (y > 0){
  231. location.y -= y;
  232. }
  233. if (x > 0){
  234. // adjust
  235. location.x -= x;
  236. }
  237. }
  238. tipWindow.show(insideComponent,location.x,location.y);
  239. insideTimer.start();
  240. timerEnter = System.currentTimeMillis();
  241. tipShowing = true;
  242. }
  243. }
  244. void hideTipWindow() {
  245. if (tipWindow != null) {
  246. tipWindow.removeMouseListener(this);
  247. tipWindow.hide();
  248. tipWindow = null;
  249. tipShowing = false;
  250. timerEnter = 0;
  251. (tip.getUI()).uninstallUI(tip);
  252. tip = null;
  253. insideTimer.stop();
  254. }
  255. }
  256. /**
  257. * Returns a shared ToolTipManager instance.
  258. *
  259. * @return a shared ToolTipManager object
  260. */
  261. public static ToolTipManager sharedInstance() {
  262. return sharedInstance;
  263. }
  264. // add keylistener here to trigger tip for access
  265. /**
  266. * Register a component for tooltip management.
  267. *
  268. * @param component a JComponent object
  269. */
  270. public void registerComponent(JComponent component) {
  271. component.removeMouseListener(this);
  272. component.addMouseListener(this);
  273. // register our accessibility keybindings for this component
  274. // this will apply globally across L&F
  275. // Post Tip: Ctrl+F1
  276. // Unpost Tip: Esc and Ctrl+F1
  277. component.registerKeyboardAction(postTipAction,postTip,JComponent.WHEN_FOCUSED);
  278. component.registerKeyboardAction(hideTipAction,hideTip,JComponent.WHEN_FOCUSED);
  279. }
  280. /**
  281. * Remove a component from tooltip control.
  282. *
  283. * @param component a JComponent object
  284. */
  285. public void unregisterComponent(JComponent component) {
  286. component.removeMouseListener(this);
  287. component.unregisterKeyboardAction(postTip);
  288. component.unregisterKeyboardAction(hideTip);
  289. }
  290. // implements java.awt.event.MouseListener
  291. public void mouseEntered(MouseEvent event) {
  292. // this is here for a workaround for a Solaris *application* only bug
  293. // in which an extra MouseExit/Enter events are generated when a Panel
  294. // initially is shown
  295. if ((tipShowing) && !lightWeightPopupEnabled)
  296. {
  297. if (System.currentTimeMillis() - timerEnter < 200){
  298. return;
  299. }
  300. }
  301. if(event.getSource() == tipWindow)
  302. return;
  303. JComponent component = (JComponent)event.getSource();
  304. toolTipText = component.getToolTipText(event);
  305. preferredLocation = component.getToolTipLocation(event);
  306. exitTimer.stop();
  307. Point location = event.getPoint();
  308. // ensure tooltip shows only in proper place
  309. if (location.x < 0 ||
  310. location.x >=component.getWidth() ||
  311. location.y < 0 ||
  312. location.y >= component.getHeight())
  313. {
  314. return;
  315. }
  316. if (insideComponent != null) {
  317. enterTimer.stop();
  318. insideComponent = null;
  319. }
  320. component.addMouseMotionListener(this);
  321. insideComponent = component;
  322. // if (toolTipText != null) {
  323. // fix for 4133318
  324. if (tipWindow != null){
  325. // fix for 4139679
  326. // without this - the tip flashes
  327. // since we get extra enter from the
  328. // tip window when being displayed over top
  329. // of the component - the behaviour is
  330. // the same whether or not we are over the
  331. // component - so additional location checks unneeded
  332. if (heavyWeightPopupEnabled){
  333. return;
  334. }
  335. else {
  336. mouseEvent = event;
  337. if (showImmediately) {
  338. showTipWindow();
  339. } else {
  340. enterTimer.start();
  341. }
  342. }
  343. }
  344. }
  345. // implements java.awt.event.MouseListener
  346. public void mouseExited(MouseEvent event) {
  347. // this is here for a workaround for a Solaris *application* only bug
  348. // when Panels are used
  349. if ((tipShowing) && !lightWeightPopupEnabled)
  350. {
  351. if (System.currentTimeMillis() - timerEnter < 200)
  352. {
  353. return;
  354. }
  355. }
  356. boolean shouldHide = true;
  357. if (insideComponent == null) {
  358. // Drag exit
  359. }
  360. if(event.getSource() == tipWindow) {
  361. // if we get an exit and have a heavy window
  362. // we need to check if it if overlapping the inside component
  363. Container insideComponentWindow = insideComponent.getTopLevelAncestor();
  364. Rectangle b = tipWindow.getBounds();
  365. Point location = event.getPoint();
  366. location.x += b.x;
  367. location.y += b.y;
  368. b = insideComponentWindow.getBounds();
  369. location.x -= b.x;
  370. location.y -= b.y;
  371. location = SwingUtilities.convertPoint(null,location,insideComponent);
  372. if(location.x >= 0 && location.x < insideComponent.getWidth() &&
  373. location.y >= 0 && location.y < insideComponent.getHeight()) {
  374. shouldHide = false;
  375. } else
  376. shouldHide = true;
  377. } else if(event.getSource() == insideComponent && tipWindow != null) {
  378. Point location = SwingUtilities.convertPoint(insideComponent,
  379. event.getPoint(),
  380. null);
  381. Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
  382. location.x += bounds.x;
  383. location.y += bounds.y;
  384. bounds = tipWindow.getBounds();
  385. if(location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
  386. location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
  387. shouldHide = false;
  388. } else
  389. shouldHide = true;
  390. }
  391. if(shouldHide) {
  392. enterTimer.stop();
  393. if (insideComponent != null) {
  394. insideComponent.removeMouseMotionListener(this);
  395. }
  396. insideComponent = null;
  397. toolTipText = null;
  398. mouseEvent = null;
  399. hideTipWindow();
  400. exitTimer.start();
  401. }
  402. }
  403. // implements java.awt.event.MouseListener
  404. public void mousePressed(MouseEvent event) {
  405. hideTipWindow();
  406. enterTimer.stop();
  407. showImmediately = false;
  408. }
  409. // implements java.awt.event.MouseMotionListener
  410. public void mouseDragged(MouseEvent event) {
  411. }
  412. // implements java.awt.event.MouseMotionListener
  413. public void mouseMoved(MouseEvent event) {
  414. JComponent component = (JComponent)event.getSource();
  415. String newText = component.getToolTipText(event);
  416. Point newPreferredLocation = component.getToolTipLocation(event);
  417. if (newText != null || newPreferredLocation != null) {
  418. mouseEvent = event;
  419. if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
  420. ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
  421. || newPreferredLocation == null)) {
  422. if (tipWindow != null) {
  423. insideTimer.restart();
  424. } else {
  425. enterTimer.restart();
  426. }
  427. } else {
  428. toolTipText = newText;
  429. preferredLocation = newPreferredLocation;
  430. if (showImmediately) {
  431. hideTipWindow();
  432. showTipWindow();
  433. } else {
  434. enterTimer.restart();
  435. }
  436. }
  437. } else {
  438. toolTipText = null;
  439. preferredLocation = null;
  440. mouseEvent = null;
  441. hideTipWindow();
  442. enterTimer.stop();
  443. exitTimer.start();
  444. }
  445. }
  446. protected class insideTimerAction implements ActionListener {
  447. public void actionPerformed(ActionEvent e) {
  448. if(insideComponent != null && insideComponent.isShowing()) {
  449. showImmediately = true;
  450. showTipWindow();
  451. }
  452. }
  453. }
  454. protected class outsideTimerAction implements ActionListener {
  455. public void actionPerformed(ActionEvent e) {
  456. showImmediately = false;
  457. }
  458. }
  459. protected class stillInsideTimerAction implements ActionListener {
  460. public void actionPerformed(ActionEvent e) {
  461. hideTipWindow();
  462. enterTimer.stop();
  463. showImmediately = false;
  464. }
  465. }
  466. static Frame frameForComponent(Component component) {
  467. while (!(component instanceof Frame)) {
  468. component = component.getParent();
  469. }
  470. return (Frame)component;
  471. }
  472. private FocusListener createFocusChangeListener(){
  473. return new FocusAdapter(){
  474. public void focusLost(FocusEvent evt){
  475. hideTipWindow();
  476. JComponent c = (JComponent)evt.getSource();
  477. c.removeFocusListener(focusChangeListener);
  478. }
  479. };
  480. }
  481. // Returns: 0 no adjust
  482. // -1 can't fit
  483. // >0 adjust value by amount returned
  484. private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){
  485. if (invoker != null){
  486. Container parent;
  487. for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
  488. // fix internal frame size bug: 4139087 - 4159012
  489. if(parent instanceof JFrame || parent instanceof JDialog ||
  490. parent instanceof JWindow) { // no check for awt.Frame since we use Heavy tips
  491. return getWidthAdjust(parent.getBounds(),popupRectInScreen);
  492. } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
  493. if (popupFrameRect == null){
  494. popupFrameRect = new Rectangle();
  495. }
  496. Point p = parent.getLocationOnScreen();
  497. popupFrameRect.setBounds(p.x,p.y,
  498. parent.getBounds().width,
  499. parent.getBounds().height);
  500. return getWidthAdjust(popupFrameRect,popupRectInScreen);
  501. }
  502. }
  503. }
  504. return 0;
  505. }
  506. // Returns: 0 no adjust
  507. // >0 adjust by value return
  508. private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){
  509. if (invoker != null){
  510. Container parent;
  511. for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
  512. if(parent instanceof JFrame || parent instanceof JDialog ||
  513. parent instanceof JWindow) {
  514. return getHeightAdjust(parent.getBounds(),popupRectInScreen);
  515. } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
  516. if (popupFrameRect == null){
  517. popupFrameRect = new Rectangle();
  518. }
  519. Point p = parent.getLocationOnScreen();
  520. popupFrameRect.setBounds(p.x,p.y,
  521. parent.getBounds().width,
  522. parent.getBounds().height);
  523. return getHeightAdjust(popupFrameRect,popupRectInScreen);
  524. }
  525. }
  526. }
  527. return 0;
  528. }
  529. private int getHeightAdjust(Rectangle a, Rectangle b){
  530. if (b.y >= a.y && (b.y + b.height) <= (a.y + a.height))
  531. return 0;
  532. else
  533. return (((b.y + b.height) - (a.y + a.height)) + 5);
  534. }
  535. // Return the number of pixels over the edge we are extending.
  536. // If we are over the edge the ToolTipManager can adjust.
  537. // REMIND: what if the Tooltip is just too big to fit at all - we currently will just clip
  538. private int getWidthAdjust(Rectangle a, Rectangle b){
  539. // System.out.println("width b.x/b.width: " + b.x + "/" + b.width +
  540. // "a.x/a.width: " + a.x + "/" + a.width);
  541. if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width)){
  542. return 0;
  543. }
  544. else {
  545. return (((b.x + b.width) - (a.x +a.width)) + 5);
  546. }
  547. }
  548. /*
  549. * The following interface describes what a popup should implement.
  550. * We do this because the ToolTip manager uses popup that can be windows or
  551. * panels. The reason is two-fold: We'd like to use panels mostly, but when the
  552. * panel (or tooltip) would not fit, we need to use a Window to avoid the panel
  553. * being clipped or not shown.
  554. *
  555. */
  556. private interface Popup {
  557. public void show(JComponent invoker, int x, int y);
  558. public void hide();
  559. public void addMouseListener(ToolTipManager c);
  560. public void removeMouseListener(ToolTipManager c);
  561. public Rectangle getBounds();
  562. }
  563. class JPanelPopup extends JPanel implements Popup {
  564. public JPanelPopup(JComponent t, Dimension s) {
  565. super();
  566. setLayout(new BorderLayout());
  567. setDoubleBuffered(true);
  568. this.setOpaque(true);
  569. add(t, BorderLayout.CENTER);
  570. setSize(s);
  571. }
  572. public void update(Graphics g) {
  573. paint(g);
  574. }
  575. public Rectangle getBounds(){
  576. return super.getBounds();
  577. }
  578. public void show(JComponent invoker, int x, int y) {
  579. Point p = new Point(x,y);
  580. SwingUtilities.convertPointFromScreen(p,invoker.getRootPane().getLayeredPane());
  581. this.setBounds(p.x,p.y,getSize().width, getSize().height);
  582. invoker.getRootPane().getLayeredPane().add(this,JLayeredPane.POPUP_LAYER,0);
  583. }
  584. public void hide() {
  585. Container parent = getParent();
  586. Rectangle r = this.getBounds();
  587. if(parent != null){
  588. parent.remove(this);
  589. parent.repaint(r.x,r.y,r.width,r.height);
  590. }
  591. }
  592. public void addMouseListener(ToolTipManager c){
  593. super.addMouseListener(c);
  594. }
  595. public void removeMouseListener(ToolTipManager c){
  596. super.removeMouseListener(c);
  597. }
  598. }
  599. // MEDIUM
  600. class PanelPopup extends Panel implements Popup {
  601. public PanelPopup(JComponent t, Dimension s) {
  602. super();
  603. setLayout(new BorderLayout());
  604. add(t, BorderLayout.CENTER);
  605. setSize(s);
  606. }
  607. public Rectangle getBounds(){
  608. return super.getBounds();
  609. }
  610. public void show(JComponent invoker, int x, int y) {
  611. Point p = new Point(x,y);
  612. SwingUtilities.convertPointFromScreen(p,invoker.getRootPane().getLayeredPane());
  613. invoker.getRootPane().getLayeredPane().add(this,JLayeredPane.POPUP_LAYER,0);
  614. // 4144271
  615. this.setBounds(p.x,p.y,getSize().width, getSize().height);
  616. }
  617. public void hide() {
  618. Container parent = getParent();
  619. Rectangle r = this.getBounds();
  620. if(parent != null){
  621. parent.remove(this);
  622. parent.repaint(r.x,r.y,r.width,r.height);
  623. }
  624. }
  625. public void addMouseListener(ToolTipManager c){
  626. super.addMouseListener(c);
  627. }
  628. public void removeMouseListener(ToolTipManager c){
  629. super.removeMouseListener(c);
  630. }
  631. }
  632. class WindowPopup extends Window implements Popup {
  633. boolean firstShow = true;
  634. JComponent tip;
  635. Frame frame;
  636. public WindowPopup(Frame f,JComponent t, Dimension size) {
  637. super(f);
  638. this.tip = t;
  639. this.frame = f;
  640. add(t, BorderLayout.CENTER);
  641. pack();
  642. // setSize(size);
  643. }
  644. public Rectangle getBounds(){
  645. return super.getBounds();
  646. }
  647. public void show(JComponent invoker, int x, int y) {
  648. this.setLocation(x,y);
  649. this.setVisible(true);
  650. /** This hack is to workaround a bug on Solaris where the windows does not really show
  651. * the first time
  652. * It causes a side effect of MS JVM reporting IllegalArumentException: null source
  653. * fairly frequently - also happens if you use HeavyWeight JPopup, ie JComboBox
  654. */
  655. if(firstShow) {
  656. this.hide();
  657. this.setVisible(true);
  658. firstShow = false;
  659. }
  660. }
  661. public void hide() {
  662. super.hide();
  663. /** We need to call removeNotify() here because hide() does something only if
  664. * Component.visible is true. When the app frame is miniaturized, the parent
  665. * frame of this frame is invisible, causing AWT to believe that this frame
  666. * is invisible and causing hide() to do nothing
  667. */
  668. removeNotify();
  669. }
  670. public void addMouseListener(ToolTipManager c){
  671. super.addMouseListener(c);
  672. }
  673. public void removeMouseListener(ToolTipManager c){
  674. super.removeMouseListener(c);
  675. }
  676. }
  677. }