mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			594 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			594 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* 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;
 | |
|   }
 | |
| }
 |