summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/ToolTipManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/ToolTipManager.java')
-rw-r--r--libjava/classpath/javax/swing/ToolTipManager.java593
1 files changed, 593 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/ToolTipManager.java b/libjava/classpath/javax/swing/ToolTipManager.java
new file mode 100644
index 000000000..8a31f79f6
--- /dev/null
+++ b/libjava/classpath/javax/swing/ToolTipManager.java
@@ -0,0 +1,593 @@
+/* ToolTipManager.java --
+ Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * This class is responsible for the registration of JToolTips to Components
+ * and for displaying them when appropriate.
+ */
+public class ToolTipManager extends MouseAdapter implements MouseMotionListener
+{
+ /**
+ * This ActionListener is associated with the Timer that listens to whether
+ * the JToolTip can be hidden after four seconds.
+ */
+ protected class stillInsideTimerAction implements ActionListener
+ {
+ /**
+ * This method creates a new stillInsideTimerAction object.
+ */
+ protected stillInsideTimerAction()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method hides the JToolTip when the Timer has finished.
+ *
+ * @param event The ActionEvent.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ hideTip();
+ }
+ }
+
+ /**
+ * This Actionlistener is associated with the Timer that listens to whether
+ * the mouse cursor has re-entered the JComponent in time for an immediate
+ * redisplay of the JToolTip.
+ */
+ protected class outsideTimerAction implements ActionListener
+ {
+ /**
+ * This method creates a new outsideTimerAction object.
+ */
+ protected outsideTimerAction()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method is called when the Timer that listens to whether the mouse
+ * cursor has re-entered the JComponent has run out.
+ *
+ * @param event The ActionEvent.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ // TODO: What should be done here, if anything?
+ }
+ }
+
+ /**
+ * This ActionListener is associated with the Timer that listens to whether
+ * it is time for the JToolTip to be displayed after the mouse has entered
+ * the JComponent.
+ */
+ protected class insideTimerAction implements ActionListener
+ {
+ /**
+ * This method creates a new insideTimerAction object.
+ */
+ protected insideTimerAction()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method displays the JToolTip when the Mouse has been still for the
+ * delay.
+ *
+ * @param event The ActionEvent.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ showTip();
+ }
+ }
+
+ /**
+ * The Timer that determines whether the Mouse has been still long enough
+ * for the JToolTip to be displayed.
+ */
+ Timer enterTimer;
+
+ /**
+ * The Timer that determines whether the Mouse has re-entered the JComponent
+ * quickly enough for the JToolTip to be displayed immediately.
+ */
+ Timer exitTimer;
+
+ /**
+ * The Timer that determines whether the JToolTip has been displayed long
+ * enough for it to be hidden.
+ */
+ Timer insideTimer;
+
+ /** A global enabled setting for the ToolTipManager. */
+ private transient boolean enabled = true;
+
+ /** lightWeightPopupEnabled */
+ protected boolean lightWeightPopupEnabled = true;
+
+ /** heavyWeightPopupEnabled */
+ protected boolean heavyWeightPopupEnabled = false;
+
+ /** The shared instance of the ToolTipManager. */
+ private static ToolTipManager shared;
+
+ /** The current component the tooltip is being displayed for. */
+ private JComponent currentComponent;
+
+ /** The current tooltip. */
+ private JToolTip currentTip;
+
+ /**
+ * The tooltip text.
+ */
+ private String toolTipText;
+
+ /** The last known position of the mouse cursor. */
+ private Point currentPoint;
+
+ /** */
+ private Popup popup;
+
+ /**
+ * Creates a new ToolTipManager and sets up the timers.
+ */
+ ToolTipManager()
+ {
+ enterTimer = new Timer(750, new insideTimerAction());
+ enterTimer.setRepeats(false);
+
+ insideTimer = new Timer(4000, new stillInsideTimerAction());
+ insideTimer.setRepeats(false);
+
+ exitTimer = new Timer(500, new outsideTimerAction());
+ exitTimer.setRepeats(false);
+ }
+
+ /**
+ * This method returns the shared instance of ToolTipManager used by all
+ * JComponents.
+ *
+ * @return The shared instance of ToolTipManager.
+ */
+ public static ToolTipManager sharedInstance()
+ {
+ if (shared == null)
+ shared = new ToolTipManager();
+
+ return shared;
+ }
+
+ /**
+ * This method sets whether ToolTips are enabled or disabled for all
+ * JComponents.
+ *
+ * @param enabled Whether ToolTips are enabled or disabled for all
+ * JComponents.
+ */
+ public void setEnabled(boolean enabled)
+ {
+ if (! enabled)
+ {
+ enterTimer.stop();
+ exitTimer.stop();
+ insideTimer.stop();
+ }
+
+ this.enabled = enabled;
+ }
+
+ /**
+ * This method returns whether ToolTips are enabled.
+ *
+ * @return Whether ToolTips are enabled.
+ */
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ /**
+ * This method returns whether LightweightToolTips are enabled.
+ *
+ * @return Whether LighweightToolTips are enabled.
+ */
+ public boolean isLightWeightPopupEnabled()
+ {
+ return lightWeightPopupEnabled;
+ }
+
+ /**
+ * This method sets whether LightweightToolTips are enabled. If you mix
+ * Lightweight and Heavyweight components, you must set this to false to
+ * ensure that the ToolTips popup above all other components.
+ *
+ * @param enabled Whether LightweightToolTips will be enabled.
+ */
+ public void setLightWeightPopupEnabled(boolean enabled)
+ {
+ lightWeightPopupEnabled = enabled;
+ heavyWeightPopupEnabled = ! enabled;
+ }
+
+ /**
+ * This method returns the initial delay before the ToolTip is shown when
+ * the mouse enters a Component.
+ *
+ * @return The initial delay before the ToolTip is shown.
+ */
+ public int getInitialDelay()
+ {
+ return enterTimer.getDelay();
+ }
+
+ /**
+ * Sets the initial delay before the ToolTip is shown when the
+ * mouse enters a Component.
+ *
+ * @param delay The initial delay before the ToolTip is shown.
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
+ */
+ public void setInitialDelay(int delay)
+ {
+ enterTimer.setDelay(delay);
+ }
+
+ /**
+ * This method returns the time the ToolTip will be shown before being
+ * hidden.
+ *
+ * @return The time the ToolTip will be shown before being hidden.
+ */
+ public int getDismissDelay()
+ {
+ return insideTimer.getDelay();
+ }
+
+ /**
+ * Sets the time the ToolTip will be shown before being hidden.
+ *
+ * @param delay the delay (in milliseconds) before tool tips are hidden.
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
+ */
+ public void setDismissDelay(int delay)
+ {
+ insideTimer.setDelay(delay);
+ }
+
+ /**
+ * This method returns the amount of delay where if the mouse re-enters a
+ * Component, the tooltip will be shown immediately.
+ *
+ * @return The reshow delay.
+ */
+ public int getReshowDelay()
+ {
+ return exitTimer.getDelay();
+ }
+
+ /**
+ * Sets the amount of delay where if the mouse re-enters a
+ * Component, the tooltip will be shown immediately.
+ *
+ * @param delay The reshow delay (in milliseconds).
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
+ */
+ public void setReshowDelay(int delay)
+ {
+ exitTimer.setDelay(delay);
+ }
+
+ /**
+ * This method registers a JComponent with the ToolTipManager.
+ *
+ * @param component The JComponent to register with the ToolTipManager.
+ */
+ public void registerComponent(JComponent component)
+ {
+ component.addMouseListener(this);
+ component.addMouseMotionListener(this);
+ }
+
+ /**
+ * This method unregisters a JComponent with the ToolTipManager.
+ *
+ * @param component The JComponent to unregister with the ToolTipManager.
+ */
+ public void unregisterComponent(JComponent component)
+ {
+ component.removeMouseMotionListener(this);
+ component.removeMouseListener(this);
+ }
+
+ /**
+ * This method is called whenever the mouse enters a JComponent registered
+ * with the ToolTipManager. When the mouse enters within the period of time
+ * specified by the reshow delay, the tooltip will be displayed
+ * immediately. Otherwise, it must wait for the initial delay before
+ * displaying the tooltip.
+ *
+ * @param event The MouseEvent.
+ */
+ public void mouseEntered(MouseEvent event)
+ {
+ if (currentComponent != null
+ && getContentPaneDeepestComponent(event) == currentComponent)
+ return;
+ currentPoint = event.getPoint();
+
+ currentComponent = (JComponent) event.getSource();
+ toolTipText = currentComponent.getToolTipText(event);
+ if (exitTimer.isRunning())
+ {
+ exitTimer.stop();
+ showTip();
+ return;
+ }
+ // This should always be stopped unless we have just fake-exited.
+ if (!enterTimer.isRunning())
+ enterTimer.start();
+ }
+
+ /**
+ * This method is called when the mouse exits a JComponent registered with the
+ * ToolTipManager. When the mouse exits, the tooltip should be hidden
+ * immediately.
+ *
+ * @param event
+ * The MouseEvent.
+ */
+ public void mouseExited(MouseEvent event)
+ {
+ if (getContentPaneDeepestComponent(event) == currentComponent)
+ return;
+
+ currentPoint = event.getPoint();
+ currentComponent = null;
+ hideTip();
+
+ if (! enterTimer.isRunning())
+ exitTimer.start();
+ if (enterTimer.isRunning())
+ enterTimer.stop();
+ if (insideTimer.isRunning())
+ insideTimer.stop();
+ }
+
+ /**
+ * This method is called when the mouse is pressed on a JComponent
+ * registered with the ToolTipManager. When the mouse is pressed, the
+ * tooltip (if it is shown) must be hidden immediately.
+ *
+ * @param event The MouseEvent.
+ */
+ public void mousePressed(MouseEvent event)
+ {
+ currentPoint = event.getPoint();
+ if (enterTimer.isRunning())
+ enterTimer.restart();
+ else if (insideTimer.isRunning())
+ {
+ insideTimer.stop();
+ hideTip();
+ }
+ }
+
+ /**
+ * This method is called when the mouse is dragged in a JComponent
+ * registered with the ToolTipManager.
+ *
+ * @param event The MouseEvent.
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ currentPoint = event.getPoint();
+ if (enterTimer.isRunning())
+ enterTimer.restart();
+ }
+
+ /**
+ * This method is called when the mouse is moved in a JComponent registered
+ * with the ToolTipManager.
+ *
+ * @param event The MouseEvent.
+ */
+ public void mouseMoved(MouseEvent event)
+ {
+ currentPoint = event.getPoint();
+ if (currentTip != null && currentTip.isShowing())
+ checkTipUpdate(event);
+ else
+ {
+ if (enterTimer.isRunning())
+ enterTimer.restart();
+ }
+ }
+
+ /**
+ * Checks if the tooltip's text or location changes when the mouse is moved
+ * over the component.
+ */
+ private void checkTipUpdate(MouseEvent ev)
+ {
+ JComponent comp = (JComponent) ev.getSource();
+ String newText = comp.getToolTipText(ev);
+ String oldText = toolTipText;
+ if (newText != null)
+ {
+ if (((newText != null && newText.equals(oldText)) || newText == null))
+ {
+ // No change at all. Restart timers.
+ if (popup == null)
+ enterTimer.restart();
+ else
+ insideTimer.restart();
+ }
+ else
+ {
+ // Update the tooltip.
+ toolTipText = newText;
+ hideTip();
+ showTip();
+ exitTimer.stop();
+ }
+ }
+ else
+ {
+ // Hide tooltip.
+ currentTip = null;
+ currentPoint = null;
+ hideTip();
+ enterTimer.stop();
+ exitTimer.stop();
+ }
+ }
+
+ /**
+ * This method displays the ToolTip. It can figure out the method needed to
+ * show it as well (whether to display it in heavyweight/lightweight panel
+ * or a window.) This is package-private to avoid an accessor method.
+ */
+ void showTip()
+ {
+ if (!enabled || currentComponent == null || !currentComponent.isEnabled()
+ || !currentComponent.isShowing())
+ {
+ popup = null;
+ return;
+ }
+
+ if (currentTip == null || currentTip.getComponent() != currentComponent)
+ currentTip = currentComponent.createToolTip();
+ currentTip.setTipText(toolTipText);
+
+ Point p = currentPoint;
+ Point cP = currentComponent.getLocationOnScreen();
+ Dimension dims = currentTip.getPreferredSize();
+
+ JLayeredPane pane = null;
+ JRootPane r = ((JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class,
+ currentComponent));
+ if (r != null)
+ pane = r.getLayeredPane();
+ if (pane == null)
+ return;
+
+ p.translate(cP.x, cP.y);
+ adjustLocation(p, pane, dims);
+
+ currentTip.setBounds(0, 0, dims.width, dims.height);
+
+ PopupFactory factory = PopupFactory.getSharedInstance();
+ popup = factory.getPopup(currentComponent, currentTip, p.x, p.y);
+ popup.show();
+ }
+
+ /**
+ * Adjusts the point to a new location on the component,
+ * using the currentTip's dimensions.
+ *
+ * @param p - the point to convert.
+ * @param c - the component the point is on.
+ * @param d - the dimensions of the currentTip.
+ */
+ private Point adjustLocation(Point p, Component c, Dimension d)
+ {
+ if (p.x + d.width > c.getWidth())
+ p.x -= d.width;
+ if (p.x < 0)
+ p.x = 0;
+ if (p.y + d.height < c.getHeight())
+ p.y += d.height;
+ if (p.y + d.height > c.getHeight())
+ p.y -= d.height;
+
+ return p;
+ }
+
+ /**
+ * This method hides the ToolTip.
+ * This is package-private to avoid an accessor method.
+ */
+ void hideTip()
+ {
+ if (popup != null)
+ popup.hide();
+ }
+
+ /**
+ * This method returns the deepest component in the content pane for the
+ * first RootPaneContainer up from the currentComponent. This method is
+ * used in conjunction with one of the mouseXXX methods.
+ *
+ * @param e The MouseEvent.
+ *
+ * @return The deepest component in the content pane.
+ */
+ private Component getContentPaneDeepestComponent(MouseEvent e)
+ {
+ Component source = (Component) e.getSource();
+ Container parent = SwingUtilities.getAncestorOfClass(JRootPane.class,
+ currentComponent);
+ if (parent == null)
+ return null;
+ parent = ((JRootPane) parent).getContentPane();
+ Point p = e.getPoint();
+ p = SwingUtilities.convertPoint(source, p, parent);
+ Component target = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
+ return target;
+ }
+}