home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 14.2 KB | 460 lines |
- /*
- * @(#)ToolTipManager.java 1.24 98/01/30
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-
-
- package java.awt.swing;
-
- import java.awt.event.*;
- import java.awt.*;
-
- /**
- * Manages all the ToolTips in the system.
- *
- * @see JComponent#createToolTip
- * @version 1.24 01/30/98
- * @author Dave Moore
- * @author Rich Schiavi
- */
- public class ToolTipManager extends MouseAdapter implements MouseMotionListener{
- Timer enterTimer, exitTimer, insideTimer;
- String toolTipText;
- Point preferredLocation;
- JComponent insideComponent;
- MouseEvent mouseEvent;
- boolean showImmediately;
- final static ToolTipManager sharedInstance = new ToolTipManager();
- Popup tipWindow;
- JToolTip tip;
- boolean enabled = true;
- boolean mouseAboveToolTip = false;
-
- private static final int INIT_POPUP = 0;
- private static final int MEDIUM_POPUP = 1;
- private static final int HEAVY_POPUP = 2;
-
- private int tipType = INIT_POPUP;
-
-
- ToolTipManager() {
- enterTimer = new Timer(750, new insideTimerAction());
- enterTimer.setRepeats(false);
- exitTimer = new Timer(500, new outsideTimerAction());
- exitTimer.setRepeats(false);
- insideTimer = new Timer(4000, new stillInsideTimerAction());
- insideTimer.setRepeats(false);
- }
-
- public void setEnabled(boolean flag) {
- enabled = flag;
- if (!flag) {
- hideTipWindow();
- }
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setInitialDelay(int microSeconds) {
- enterTimer.setInitialDelay(microSeconds);
- }
-
- public int getInitialDelay() {
- return enterTimer.getInitialDelay();
- }
-
- public void setDismissDelay(int microSeconds) {
- insideTimer.setDelay(microSeconds);
- }
-
- public int getDismissDelay() {
- return insideTimer.getDelay();
- }
-
- public void setReshowDelay(int microSeconds) {
- exitTimer.setDelay(microSeconds);
- }
-
- public int getReshowDelay() {
- return exitTimer.getDelay();
- }
-
- void showTipWindow() {
- if(insideComponent == null || !insideComponent.isShowing())
- return;
- if (enabled) {
- Dimension size;
- Point screenLocation = insideComponent.getLocationOnScreen();
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- Point location = new Point();
-
- // Just to be paranoid
- hideTipWindow();
-
- tip = insideComponent.createToolTip();
- tip.setTipText(toolTipText);
- size = tip.getPreferredSize();
-
- /* REMIND: should recycle these - L&F doesn't seem to
- * be working in browsers when using a Panel
- */
-
- switch (tipType){
- case INIT_POPUP:
- Container parent;
- for (parent = insideComponent.getParent(); parent != null; parent = parent.getParent()){
- if (parent instanceof JApplet){
- tipType = MEDIUM_POPUP;
- tipWindow = new PanelPopup(tip, size);
- }
- }
- if (tipType == INIT_POPUP)
- {
- tipWindow = new WindowPopup((frameForComponent(insideComponent)),tip,size);
- tipType = HEAVY_POPUP;
- }
- break;
- case HEAVY_POPUP:
- tipWindow = new WindowPopup((frameForComponent(insideComponent)),tip,size);
- break;
- case MEDIUM_POPUP:
- tipWindow = new PanelPopup(tip,size);
- break;
- default:
- tipWindow = new WindowPopup((frameForComponent(insideComponent)),tip,size);
- break;
- }
-
- tipWindow.addMouseListener(this);
-
- if(preferredLocation != null) {
- location.x = screenLocation.x + preferredLocation.x;
- location.y = screenLocation.y + preferredLocation.y;
- } else {
- location.x = screenLocation.x + mouseEvent.getX();
- location.y = screenLocation.y + mouseEvent.getY() + 20;
-
- if (location.x + size.width > screenSize.width) {
- location.x -= size.width;
- }
- if (location.y + size.height > screenSize.height) {
- location.y -= (size.height + 20);
- }
- }
-
- tipWindow.show(insideComponent,location.x,location.y);
- insideTimer.start();
- }
- }
-
- void hideTipWindow() {
- if (tipWindow != null) {
- tipWindow.removeMouseListener(this);
- tipWindow.hide();
- tipWindow = null;
- (tip.getUI()).uninstallUI(tip);
- tip = null;
- insideTimer.stop();
- }
- }
-
- public static ToolTipManager sharedInstance() {
- return sharedInstance;
- }
-
- public void registerComponent(JComponent component) {
- component.removeMouseListener(this);
- component.addMouseListener(this);
- }
-
- public void unregisterComponent(JComponent component) {
- component.removeMouseListener(this);
- }
-
- public void mouseEntered(MouseEvent event) {
- if(event.getSource() == tipWindow)
- return;
- JComponent component = (JComponent)event.getSource();
- toolTipText = component.getToolTipText(event);
- preferredLocation = component.getToolTipLocation(event);
-
- exitTimer.stop();
-
- Point location = event.getPoint();
- // ensure tooltip shows only in proper place
- if (location.x < 0 ||
- location.x >=component.getWidth() ||
- location.y < 0 ||
- location.y >= component.getHeight())
- {
- return;
- }
-
- if (insideComponent != null) {
- enterTimer.stop();
- insideComponent = null;
- }
-
- component.addMouseMotionListener(this);
-
- insideComponent = component;
- if (toolTipText != null) {
- mouseEvent = event;
- if (showImmediately) {
- showTipWindow();
- } else {
- enterTimer.start();
- }
- }
- }
-
- public void mouseExited(MouseEvent event) {
- boolean shouldHide = true;
- if (insideComponent == null) {
- // Drag exit
- }
- if(event.getSource() == tipWindow) {
- Container insideComponentWindow = insideComponent.getTopLevelAncestor();
- Rectangle b = tipWindow.getBounds();
- Point location = event.getPoint();
- location.x += b.x;
- location.y += b.y;
-
- b = insideComponentWindow.getBounds();
- location.x -= b.x;
- location.y -= b.y;
-
- location = SwingUtilities.convertPoint(null,location,insideComponent);
- if(location.x >= 0 && location.x < insideComponent.getWidth() &&
- location.y >= 0 && location.y < insideComponent.getHeight()) {
- shouldHide = false;
- } else
- shouldHide = true;
- } else if(event.getSource() == insideComponent && tipWindow != null) {
- Point location = SwingUtilities.convertPoint(insideComponent,
- event.getPoint(),
- null);
- Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
- location.x += bounds.x;
- location.y += bounds.y;
-
- bounds = tipWindow.getBounds();
- if(location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
- location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
- shouldHide = false;
- } else
- shouldHide = true;
- }
-
- if(shouldHide) {
- enterTimer.stop();
- if (insideComponent != null)
- insideComponent.removeMouseMotionListener(this);
- insideComponent = null;
- toolTipText = null;
- mouseEvent = null;
- hideTipWindow();
- exitTimer.start();
- }
- }
-
- public void mousePressed(MouseEvent event) {
- hideTipWindow();
- enterTimer.stop();
- showImmediately = false;
- }
-
- public void mouseDragged(MouseEvent event) {
- }
-
- public void mouseMoved(MouseEvent event) {
- JComponent component = (JComponent)event.getSource();
- String newText = component.getToolTipText(event);
- Point newPreferredLocation = component.getToolTipLocation(event);
-
- if (newText != null || newPreferredLocation != null) {
- mouseEvent = event;
- if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
- ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
- || newPreferredLocation == null)) {
- if (tipWindow != null) {
- insideTimer.restart();
- } else {
- enterTimer.restart();
- }
- } else {
- toolTipText = newText;
- preferredLocation = newPreferredLocation;
- if (showImmediately) {
- hideTipWindow();
- showTipWindow();
- } else {
- enterTimer.restart();
- }
- }
- } else {
- toolTipText = null;
- preferredLocation = null;
- mouseEvent = null;
- hideTipWindow();
- enterTimer.stop();
- exitTimer.start();
- }
- }
-
- protected class insideTimerAction implements ActionListener {
- public void actionPerformed(ActionEvent e) {
- if(insideComponent != null && insideComponent.isShowing()) {
- showImmediately = true;
- showTipWindow();
- }
- }
- }
-
- protected class outsideTimerAction implements ActionListener {
- public void actionPerformed(ActionEvent e) {
- showImmediately = false;
- }
- }
-
- protected class stillInsideTimerAction implements ActionListener {
- public void actionPerformed(ActionEvent e) {
- hideTipWindow();
- enterTimer.stop();
- showImmediately = false;
- }
- }
-
- static Frame frameForComponent(Component component) {
- while (!(component instanceof Frame)) {
- component = component.getParent();
- }
- return (Frame)component;
- }
-
- /*
- * The following interface describes what a popup should implement.
- * We do this because the ToolTip manager uses popup that can be windows or
- * panels. The reason is two-fold: Navigator does not display Windows properly,
- * and there is a problem with layout when using a Panel with
- * Java Apps on the Solaris VM which doesn't occur in Applets or on Win32 VM apps.
- * Solaris also has some strange behaviour with extra MOUSE_EXIT events when
- * using a Panel which required a different workaround, hence Windows for Apps,
- * Panels for Applets.
- */
- private interface Popup {
- public void show(JComponent invoker, int x, int y);
- public void hide();
- public void addMouseListener(ToolTipManager c);
- public void removeMouseListener(ToolTipManager c);
- public Rectangle getBounds();
- }
-
-
- // MEDIUM
- class PanelPopup extends Panel implements Popup {
-
- public PanelPopup(JComponent t, Dimension s) {
- super();
- setLayout(new BorderLayout());
- add(t, BorderLayout.CENTER);
- setSize(s);
- }
-
- public Rectangle getBounds(){
- return super.getBounds();
- }
-
- public void show(JComponent invoker, int x, int y) {
- Point p = new Point(x,y);
- SwingUtilities.convertPointFromScreen(p,invoker.getRootPane().getLayeredPane());
- this.setBounds(p.x,p.y,getSize().width, getSize().height);
- invoker.getRootPane().getLayeredPane().add(this,JLayeredPane.POPUP_LAYER,0);
- }
-
- public void hide() {
- Container parent = getParent();
- Rectangle r = this.getBounds();
- if(parent != null)
- parent.remove(this);
- parent.repaint(r.x,r.y,r.width,r.height);
- }
-
- public void addMouseListener(ToolTipManager c){
- super.addMouseListener(c);
- }
-
- public void removeMouseListener(ToolTipManager c){
- super.removeMouseListener(c);
- }
-
- }
-
- // HEAVY
- class WindowPopup extends Window implements Popup {
- boolean firstShow = true;
-
- public WindowPopup(Frame f,JComponent t, Dimension size) {
- super(f);
- add(t);
- setSize(size);
- }
-
- public Rectangle getBounds(){
- return super.getBounds();
- }
-
- public void show(JComponent invoker, int x, int y) {
- this.setBounds(x,y, getSize().width,getSize().height);
- this.setLocation(x,y);
- this.setVisible(true);
-
- /** This hack is to workaround a bug on Solaris where the windows does not really show
- * the first time
- */
- if(firstShow) {
- this.hide();
- this.setVisible(true);
- firstShow = false;
- }
- }
-
- public void hide() {
- super.hide();
- /** We need to call removeNotify() here because hide() does something only if
- * Component.visible is true. When the app frame is miniaturized, the parent
- * frame of this frame is invisible, causing AWT to believe that this frame
- * is invisible and causing hide() to do nothing
- */
- removeNotify();
- }
-
- public void addMouseListener(ToolTipManager c){
- super.addMouseListener(c);
- }
-
- public void removeMouseListener(ToolTipManager c){
- super.removeMouseListener(c);
- }
-
- }
-
- }
-