123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- /* 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;
- }
- }
|