classpath-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cp-patches] FYI: Merge in JToolTip support from libgcj gui branch


From: Mark Wielaard
Subject: [cp-patches] FYI: Merge in JToolTip support from libgcj gui branch
Date: Sat, 31 Jul 2004 17:20:14 +0200

Hi,

This imports the recent JToolTop support from the libgcj gui branch.

2004-07-31  Kim Ho  <address@hidden>

        * java/awt/Container.java:
        (acquireComponentForMouseEvent): Respect
        the event mask when looking for candidate.
        * javax/swing/JComponent.java:
        Remove toolTip field.
        (createToolTip): Create a tooltip on demand.
        (setToolTipText): Register with the ToolTipManager.
        (getToolTipText(MouseEvent)): Return getToolTipText().
        * javax/swing/JToolTip.java: Implement.
        * javax/swing/Timer.java: Jalopy.
        (restart): Call stop, then start.
        (stop): Interrupt the timer rather than wait for
        the timer to come to a stop naturally.
        * javax/swing/ToolTipManager.java: Implement.
        * javax/swing/plaf/basic/BasicLookAndFeel.java:
        Change ToolTip.background color.
        * javax/swing/plaf/basic/BasicToolTipUI.java:
        Implement.

Committed.

Cheers,

Mark
Index: java/awt/Container.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.35
diff -u -r1.35 Container.java
--- java/awt/Container.java     22 Jul 2004 19:45:38 -0000      1.35
+++ java/awt/Container.java     31 Jul 2004 15:18:02 -0000
@@ -1863,8 +1863,9 @@
       {
         candidate =
           SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
-        if (candidate == null)
+        if (candidate == null || (candidate.eventMask & me.getID()) == 0)
         {
+          candidate = null;
           p = SwingUtilities.convertPoint(parent, p.x, p.y, parent.parent);
           parent = parent.parent;
         }
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.19
diff -u -r1.19 JComponent.java
--- javax/swing/JComponent.java 22 Jul 2004 19:45:39 -0000      1.19
+++ javax/swing/JComponent.java 31 Jul 2004 15:18:02 -0000
@@ -192,22 +192,12 @@
   Border border;
 
   /** 
-   * A tooltip associated with this component. 
-   * 
-   * @see #setToolTip
-   * @see #getToolTip
-   * @see #toolTipText
-   */
-  JToolTip toolTip;
-
-  /** 
-   * The text to show in the tooltip associated with this component. 
+   * The text to show in the tooltip associated with this component.
    * 
    * @see #setToolTipText
    * @see #getToolTipText
-   * @see #toolTip
    */
-  String toolTipText;
+   String toolTipText;
 
   /** 
    * <p>Whether to double buffer this component when painting. This flag
@@ -1113,11 +1103,9 @@
    */
   public JToolTip createToolTip()
   {
-    if (toolTip == null)
-      {
-       toolTip = new JToolTip();
+       JToolTip toolTip = new JToolTip();
+       toolTip.setComponent(this);
        toolTip.setTipText(toolTipText);
-      }
     
     return toolTip;
   }
@@ -1145,7 +1133,22 @@
    */
   public void setToolTipText(String text)
   {
+    if (text == null)
+    {
+      ToolTipManager.sharedInstance().unregisterComponent(this);
+      toolTipText = null;
+      return;
+    }
+               
+    // XXX: The tip text doesn't get updated unless you set it to null
+    // and then to something not-null. This is consistent with the behaviour
+    // of Sun's ToolTipManager.
+                       
+    String oldText = toolTipText;
     toolTipText = text;
+               
+    if (oldText == null)
+      ToolTipManager.sharedInstance().registerComponent(this);
   }
 
   /**
@@ -1172,7 +1175,7 @@
    */
   public String getToolTipText(MouseEvent event)
   {
-    return toolTipText;
+    return getToolTipText();
   }
 
   /**
Index: javax/swing/JToolTip.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JToolTip.java,v
retrieving revision 1.6
diff -u -r1.6 JToolTip.java
--- javax/swing/JToolTip.java   26 Jun 2004 16:07:01 -0000      1.6
+++ javax/swing/JToolTip.java   31 Jul 2004 15:18:02 -0000
@@ -1,4 +1,4 @@
-/* JToolTip.java -- 
+/* JToolTip.java --
    Copyright (C) 2002, 2004  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
@@ -35,25 +35,160 @@
 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.AWTEvent;
 import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.swing.plaf.ToolTipUI;
+
 
+/**
+ * This class is used to display ToolTips. ToolTips are small floating windows
+ * that display text when the mouse comes to rest over a Component. ToolTips
+ * are set for JComponents using JComponent.setToolTipText(String).
+ */
 public class JToolTip extends JComponent implements Accessible
 {
+  /** DOCUMENT ME! */
   private static final long serialVersionUID = -1138929898906751643L;
-  
+
+  /**
+   * DOCUMENT ME!
+   */
+  protected class AccessibleJToolTip extends AccessibleJComponent
+  {
+    /**
+     * Creates a new AccessibleJToolTip object.
+     */
+    protected AccessibleJToolTip()
+    {
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public String getAccessibleDescription()
+    {
+      return null;
+    }
+
+    /**
+     * DOCUMENT ME!
+     *
+     * @return DOCUMENT ME!
+     */
+    public AccessibleRole getAccessibleRole()
+    {
+      return null;
+    }
+  }
+
+  /** The text to display in the JToolTip. */
   String text;
 
+  /** The JComponent this JToolTip is used for. */
+  JComponent component;
+
+  /**
+   * Creates a new JToolTip object.
+   */
   public JToolTip()
   {
+    disableEvents(AWTEvent.MOUSE_EVENT_MASK);
+    updateUI();
   }
 
-  public void setTipText(String newText)
+  /**
+   * This method returns the text this JToolTip displays.
+   *
+   * @return The text that this JToolTip displays.
+   */
+  public String getTipText()
   {
-    this.text = newText;
+    return text;
   }
-}
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
+  public AccessibleContext getAccessibleContext()
+  {
+    return null;
+  }
+
+  /**
+   * This method returns the JComponent this JToolTip displays for.
+   *
+   * @return The JComponent this JToolTip displays for.
+   */
+  public JComponent getComponent()
+  {
+    return component;
+  }
+
+  /**
+   * This method returns the UI responsible for displaying this JToolTip.
+   *
+   * @return The UI responsible for displaying this JToolTip.
+   */
+  public ToolTipUI getUI()
+  {
+    return (ToolTipUI) ui;
+  }
 
+  /**
+   * This method returns the String identifier for the UI class.
+   *
+   * @return The String identifier for the UI class.
+   */
+  public String getUIClassID()
+  {
+    return "ToolTipUI";
+  }
+
+  /**
+   * This method returns a debugging String describing the JToolTip.
+   *
+   * @return A debugging String describing the JToolTip.
+   */
+  protected String paramString()
+  {
+    return "JToolTip";
+  }
+
+  /**
+   * This method sets the JComponent that the JToolTip displays for.
+   *
+   * @param c The JComponent that the JToolTip displays for.
+   */
+  public void setComponent(JComponent c)
+  {
+    component = c;
+  }
+
+  /**
+   * This method sets the text that the JToolTip displays.
+   *
+   * @param tipText The text that the JToolTip displays.
+   */
+  public void setTipText(String tipText)
+  {
+    text = tipText;
+  }
+
+  /**
+   * This method resets the UI used to the Look and Feel default.
+   */
+  public void updateUI()
+  {
+    setUI((ToolTipUI) UIManager.getUI(this));
+    revalidate();
+    repaint();
+  }
+}
Index: javax/swing/Timer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/Timer.java,v
retrieving revision 1.9
diff -u -r1.9 Timer.java
--- javax/swing/Timer.java      22 Jul 2004 19:45:39 -0000      1.9
+++ javax/swing/Timer.java      31 Jul 2004 15:18:02 -0000
@@ -1,4 +1,4 @@
-/* Timer.java -- 
+/* Timer.java --
    Copyright (C) 2002, 2004  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
@@ -35,22 +35,26 @@
 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.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.Serializable;
 import java.util.EventListener;
-
 import javax.swing.event.EventListenerList;
 
+
+/**
+ * DOCUMENT ME!
+ */
 public class Timer implements Serializable
 {
+  /** DOCUMENT ME! */
   private static final long serialVersionUID = -1116180831621385484L;
-  
+
+  /** DOCUMENT ME! */
   protected EventListenerList listenerList = new EventListenerList();
-  
+
   // This object manages a "queue" of virtual actionEvents, maintained as a
   // simple long counter. When the timer expires, a new event is queued,
   // and a dispatcher object is pushed into the system event queue. When
@@ -58,79 +62,127 @@
   // ActionEvents as have been queued, unless the timer is set to
   // coalescing mode, in which case it will fire only one ActionEvent.
 
+  /** DOCUMENT ME! */
   private long queue;
+
+  /** DOCUMENT ME! */
   private Object queueLock = new Object();
+
+  /** DOCUMENT ME! */
+  private Waker waker;
+
+  /**
+   * DOCUMENT ME!
+   */
   private void queueEvent()
   {
     synchronized (queueLock)
       {
-        queue++;
-        if (queue == 1)
-          SwingUtilities.invokeLater(new Runnable() { public void run() { 
drainEvents(); } });
+       queue++;
+       if (queue == 1)
+         SwingUtilities.invokeLater(new Runnable()
+             {
+               public void run()
+               {
+                 drainEvents();
+               }
+             });
+
       }
   }
 
+  /**
+   * DOCUMENT ME!
+   */
   private void drainEvents()
   {
     synchronized (queueLock)
       {
-        if (isCoalesce())
-          {
-            if (queue > 0)
-              fireActionPerformed();
-          }
-        else
-          {
-            while(queue > 0)
-              {                  
-                fireActionPerformed();
-                queue--;
-              }          
-          }
-        queue = 0;
+       if (isCoalesce())
+         {
+           if (queue > 0)
+             fireActionPerformed();
+         }
+       else
+         {
+           while (queue > 0)
+             {
+               fireActionPerformed();
+               queue--;
+             }
+         }
+       queue = 0;
       }
   }
-  
 
   static boolean logTimers;
+
+  /** DOCUMENT ME! */
   boolean coalesce = true;
+
+  /** DOCUMENT ME! */
   boolean repeats = true;
+
+  /** DOCUMENT ME! */
   boolean running;
+
+  /** DOCUMENT ME! */
   int ticks;
+
+  /** DOCUMENT ME! */
   int delay;
+
+  /** DOCUMENT ME! */
   int initialDelay;
-    
-  private class Waker 
-    extends Thread
+
+  /**
+   * DOCUMENT ME!
+   */
+  private class Waker extends Thread
   {
+    /**
+     * DOCUMENT ME!
+     */
     public void run()
     {
       running = true;
-      try 
+      try
         {
+         sleep(initialDelay);
 
-          sleep(initialDelay);
-          
-          while (running)
-            {
-              sleep(delay);
-              queueEvent();
-              
-              if (logTimers)
-                System.out.println("javax.swing.Timer -> clocktick");
-              
-              if (! repeats)
-                break;
-            }
-          running = false;
-      } 
-      catch (Exception e) 
+         while (running)
+           {
+             try
+               {
+                 sleep(delay);
+               }
+             catch (InterruptedException e)
+               {
+                 return;
+               }
+             queueEvent();
+
+             if (logTimers)
+               System.out.println("javax.swing.Timer -> clocktick");
+
+             if (! repeats)
+               break;
+           }
+         running = false;
+        }
+      catch (Exception e)
         {
-          System.out.println("swing.Timer::" + e);
+         System.out.println("swing.Timer::" + e);
         }
     }
   }
 
+  /**
+   * Creates a new Timer object.
+   *
+   * @param d DOCUMENT ME!
+   * @param listener DOCUMENT ME!
+   */
   public Timer(int d, ActionListener listener)
   {
     delay = d;
@@ -139,123 +191,213 @@
       addActionListener(listener);
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @param c DOCUMENT ME!
+   */
   public void setCoalesce(boolean c)
   {
     coalesce = c;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public boolean isCoalesce()
   {
     return coalesce;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @param listener DOCUMENT ME!
+   */
   public void addActionListener(ActionListener listener)
   {
-    listenerList.add (ActionListener.class, listener);
+    listenerList.add(ActionListener.class, listener);
   }
-  
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param listener DOCUMENT ME!
+   */
   public void removeActionListener(ActionListener listener)
   {
-    listenerList.remove (ActionListener.class, listener);
+    listenerList.remove(ActionListener.class, listener);
   }
 
   /**
+   * DOCUMENT ME!
+   *
+   * @param listenerType DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   *
    * @since 1.3
    */
-  public EventListener[] getListeners (Class listenerType)
+  public EventListener[] getListeners(Class listenerType)
   {
-    return listenerList.getListeners (listenerType);
+    return listenerList.getListeners(listenerType);
   }
-  
+
   /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   *
    * @since 1.4
    */
-  public ActionListener[] getActionListeners ()
+  public ActionListener[] getActionListeners()
   {
-    return (ActionListener[]) listenerList.getListeners (ActionListener.class);
+    return (ActionListener[]) listenerList.getListeners(ActionListener.class);
   }
 
-  protected void fireActionPerformed (ActionEvent event)
+  /**
+   * DOCUMENT ME!
+   *
+   * @param event DOCUMENT ME!
+   */
+  protected void fireActionPerformed(ActionEvent event)
   {
     ActionListener[] listeners = getActionListeners();
-    
+
     for (int i = 0; i < listeners.length; i++)
-      {
-       listeners [i].actionPerformed (event);
-      }
+      listeners[i].actionPerformed(event);
   }
 
-  void fireActionPerformed ()
+  /**
+   * DOCUMENT ME!
+   */
+  void fireActionPerformed()
   {
-    fireActionPerformed (new ActionEvent (this, ticks++, "Timer"));
+    fireActionPerformed(new ActionEvent(this, ticks++, "Timer"));
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @param lt DOCUMENT ME!
+   */
   public static void setLogTimers(boolean lt)
   {
     logTimers = lt;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public static boolean getLogTimers()
   {
     return logTimers;
   }
-    
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param d DOCUMENT ME!
+   */
   public void setDelay(int d)
   {
     delay = d;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public int getDelay()
   {
     return delay;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @param i DOCUMENT ME!
+   */
   public void setInitialDelay(int i)
   {
     initialDelay = i;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public int getInitialDelay()
   {
     return initialDelay;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @param r DOCUMENT ME!
+   */
   public void setRepeats(boolean r)
   {
     repeats = r;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public boolean isRepeats()
   {
     return repeats;
   }
 
+  /**
+   * DOCUMENT ME!
+   *
+   * @return DOCUMENT ME!
+   */
   public boolean isRunning()
   {
     return running;
   }
 
+  /**
+   * DOCUMENT ME!
+   */
   public void start()
   {
     if (isRunning())
-      {
-       System.err.println("attempt to start a running timer");
        return;
-      }
-    new Waker().start();
+    waker = new Waker();
+    waker.start();
   }
 
+  /**
+   * DOCUMENT ME!
+   */
   public void restart()
   {
-    synchronized (queueLock)
-      {
-        queue = 0;
-      }
+    stop();
     start();
   }
 
+  /**
+   * DOCUMENT ME!
+   */
   public void stop()
   {
     running = false;
+    waker.interrupt();
+    synchronized (queueLock)
+      {
+       queue = 0;
+      }
   }
 }
Index: javax/swing/ToolTipManager.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/ToolTipManager.java,v
retrieving revision 1.4
diff -u -r1.4 ToolTipManager.java
--- javax/swing/ToolTipManager.java     22 Jul 2004 19:45:39 -0000      1.4
+++ javax/swing/ToolTipManager.java     31 Jul 2004 15:18:02 -0000
@@ -37,315 +37,606 @@
 
 package javax.swing;
 
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.*;
 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;
+import javax.swing.JComponent;
+import javax.swing.Popup;
+import javax.swing.PopupFactory;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
 
 
 /**
- * ToolTipManager
- * 
- * @author     Andrew Selkirk
+ * This class is responsible for the registration of JToolTips to Components
+ * and for displaying them when appropriate.
  */
-public class ToolTipManager extends MouseAdapter
-  implements MouseMotionListener
+public class ToolTipManager extends MouseAdapter implements MouseMotionListener
 {
-       /**
-        * stillInsideTimerAction
-        */
-  protected class stillInsideTimerAction
-    implements ActionListener
-  {
-               /**
-                * Constructor stillInsideTimerAction
-                */
+  /**
+   * 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()
     {
-                       // TODO
     }
 
-               /**
-                * actionPerformed
-                * @param event TODO
-                */
+    /**
+     * This method hides the JToolTip when the Timer has finished.
+     *
+     * @param event The ActionEvent.
+     */
     public void actionPerformed(ActionEvent event)
     {
-                       // TODO
+      hideTip();
     }
   }
 
-       /**
-        * outsideTimerAction
-        */
-  protected class outsideTimerAction
-    implements ActionListener
-  {
-               /**
-                * Constructor outsideTimerAction
-                */
+  /**
+   * 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()
     {
-                       // TODO
     }
 
-               /**
-                * actionPerformed
-                * @param value0 TODO
-                */
+    /**
+     * 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
     }
   }
 
-       /**
-        * insideTimerAction
-        */
-  protected class insideTimerAction
-    implements ActionListener
-  {
-               /**
-                * Constructor insideTimerAction
-                */
+  /**
+   * 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()
     {
-                       // TODO
     }
 
-               /**
-                * actionPerformed
-                * @param event TODO
-                */
+    /**
+     * This method displays the JToolTip when the Mouse has been still for the
+     * delay.
+     *
+     * @param event The ActionEvent.
+     */
     public void actionPerformed(ActionEvent event)
     {
-                       // TODO
+      showTip();
+      if (insideTimer != null)
+       insideTimer.start();
     }
   }
 
-       /**
-        * enterTimer
-        */
-       Timer enterTimer;
-
-       /**
-        * exitTimer
-        */
-       Timer exitTimer;
-
-       /**
-        * insideTimer
-        */
-       Timer insideTimer;
-
-       /**
-        * toolTipText
-        */
-       String toolTipText;
-
-       /**
-        * mouseEvent
-        */
-       MouseEvent mouseEvent;
-
-       /**
-        * showImmediately
-        */
-       boolean showImmediately;
-
-       /**
-        * tip
-        */
-       JToolTip tip;
-
-       /**
-        * enabled
-        */
-       boolean enabled;
-
-       /**
-        * timerEnter
-        */
-       private long timerEnter;
-
-       /**
-        * lightWeightPopupEnabled
-        */
-       protected boolean lightWeightPopupEnabled;
-
-       /**
-        * heavyWeightPopupEnabled
-        */
-       protected boolean heavyWeightPopupEnabled;
-
-       /**
-        * Constructor ToolTipManager
-        */
+  /**
+   * 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 static Component currentComponent;
+
+  /** The current tooltip. */
+  private static JToolTip currentTip;
+
+  /** The last known position of the mouse cursor. */
+  private static Point currentPoint;
+
+  /**
+   * The panel that holds the tooltip when the tooltip is displayed fully
+   * inside the current container.
+   */
+  private static Container containerPanel;
+
+  /**
+   * The window used when the tooltip doesn't fit inside the current
+   * container.
+   */
+  private static JWindow tooltipWindow;
+
+  /**
+   * Creates a new ToolTipManager and sets up the timers.
+   */
   ToolTipManager()
   {
-               // TODO
+    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);
   }
 
-       /**
-        * sharedInstance
-   * @return ToolTipManager
-        */
+  /**
+   * This method returns the shared instance of ToolTipManager used by all
+   * JComponents.
+   *
+   * @return The shared instance of ToolTipManager.
+   */
   public static ToolTipManager sharedInstance()
   {
-               return null; // TODO
+    if (shared == null)
+      shared = new ToolTipManager();
+
+    return shared;
   }
 
-       /**
-        * setEnabled
-        * @param enabled TODO
-        */
+  /**
+   * 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)
   {
-               // TODO
+    if (! enabled)
+      {
+       enterTimer.stop();
+       exitTimer.stop();
+       insideTimer.stop();
+      }
+
+    this.enabled = enabled;
   }
 
-       /**
-        * isEnabled
-   * @return boolean
-        */
+  /**
+   * This method returns whether ToolTips are enabled.
+   *
+   * @return Whether ToolTips are enabled.
+   */
   public boolean isEnabled()
   {
-               return false; // TODO
+    return enabled;
   }
 
-       /**
-        * isLightWeightPopupEnabled
-   * @return boolean
-        */
+  /**
+   * This method returns whether LightweightToolTips are enabled.
+   *
+   * @return Whether LighweightToolTips are enabled.
+   */
   public boolean isLightWeightPopupEnabled()
   {
-               return false; // TODO
+    return lightWeightPopupEnabled;
   }
 
-       /**
-        * setLightWeightPopupEnabled
-        * @param enabled TODO
-        */
+  /**
+   * 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)
   {
-               // TODO
+    lightWeightPopupEnabled = enabled;
+    heavyWeightPopupEnabled = ! enabled;
   }
 
-       /**
-        * getInitialDelay
-   * @return int
-        */
+  /**
+   * 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 0; // TODO
+    return enterTimer.getDelay();
   }
 
-       /**
-        * setInitialDelay
-        * @param delay TODO
-        */
+  /**
+   * This method 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.
+   */
   public void setInitialDelay(int delay)
   {
-               // TODO
+    enterTimer.setDelay(delay);
   }
 
-       /**
-        * getDismissDelay
-   * @return int
-        */
+  /**
+   * 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 0; // TODO
+    return insideTimer.getDelay();
   }
 
-       /**
-        * setDismissDelay
-        * @param delay TODO
-        */
+  /**
+   * This method sets the time the ToolTip will be shown before being hidden.
+   *
+   * @param delay The time the ToolTip will be shown before being hidden.
+   */
   public void setDismissDelay(int delay)
   {
-               // TODO
+    insideTimer.setDelay(delay);
   }
 
-       /**
-        * getReshowDelay
-   * @return int
-        */
+  /**
+   * 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 0; // TODO
+    return exitTimer.getDelay();
   }
 
-       /**
-        * setReshowDelay
-        * @param delay TODO
-        */
+  /**
+   * This method sets the amount of delay where if the mouse re-enters a
+   * Component, the tooltip will be shown immediately.
+   *
+   * @param delay The reshow delay.
+   */
   public void setReshowDelay(int delay)
   {
-               // TODO
+    exitTimer.setDelay(delay);
   }
 
-       /**
-        * registerComponent
-        * @param component TODO
-        */
+  /**
+   * This method registers a JComponent with the ToolTipManager.
+   *
+   * @param component The JComponent to register with the ToolTipManager.
+   */
   public void registerComponent(JComponent component)
   {
-               // TODO
+    component.addMouseListener(this);
+    component.addMouseMotionListener(this);
   }
 
-       /**
-        * unregisterComponent
-        * @param component TODO
-        */
+  /**
+   * This method unregisters a JComponent with the ToolTipManager.
+   *
+   * @param component The JComponent to unregister with the ToolTipManager.
+   */
   public void unregisterComponent(JComponent component)
   {
-               // TODO
+    component.removeMouseMotionListener(this);
+    component.removeMouseListener(this);
   }
 
-       /**
-        * mouseEntered
-        * @param event TODO
-        */
+  /**
+   * 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)
   {
-               // TODO
-  }
-
-       /**
-        * mouseExited
-        * @param event TODO
-        */
+    if (currentComponent != null
+        && getContentPaneDeepestComponent(event) == currentComponent)
+      return;
+    currentPoint = event.getPoint();
+    currentComponent = (Component) event.getSource();
+
+    if (exitTimer.isRunning())
+      {
+       exitTimer.stop();
+       showTip();
+       insideTimer.start();
+       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)
   {
-               // TODO
-  }
+    if (getContentPaneDeepestComponent(event) == currentComponent)
+      return;
 
-       /**
-        * mousePressed
-        * @param event TODO
-        */
+    currentPoint = event.getPoint();
+    currentComponent = null;
+    hideTip();
+
+    if (! enterTimer.isRunning() && insideTimer.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)
   {
-               // TODO
-  }
-
-       /**
-        * mouseDragged
-        * @param event TODO
-        */
+    currentPoint = event.getPoint();
+    if (enterTimer.isRunning())
+      enterTimer.restart();
+    else if (insideTimer.isRunning())
+      {
+       insideTimer.stop();
+       hideTip();
+      }
+    currentComponent.invalidate();
+    currentComponent.validate();
+    currentComponent.repaint();
+  }
+
+  /**
+   * 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)
   {
-               // TODO
+    currentPoint = event.getPoint();
+    if (enterTimer.isRunning())
+      enterTimer.restart();
   }
 
-       /**
-        * mouseMoved
-        * @param event TODO
-        */
+  /**
+   * 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)
   {
-               // TODO
+    currentPoint = event.getPoint();
+    if (enterTimer.isRunning())
+      enterTimer.restart();
+  }
+
+  /**
+   * 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.)
+   */
+  private void showTip()
+  {
+    if (! enabled)
+      return;
+
+    if (currentTip == null
+        || currentTip.getComponent() != currentComponent
+        && currentComponent instanceof JComponent)
+      currentTip = ((JComponent) currentComponent).createToolTip();
+    Point p = currentPoint;
+    Dimension dims = currentTip.getPreferredSize();
+    if (canToolTipFit(currentTip))
+      {
+       JLayeredPane pane = ((JRootPane) 
SwingUtilities.getAncestorOfClass(JRootPane.class,
+                                                                          
currentComponent))
+                           .getLayeredPane();
+
+       // This should never happen, but just in case.
+       if (pane == null)
+         return;
+
+       if (containerPanel != null)
+         hideTip();
+       if (isLightWeightPopupEnabled())
+         {
+           containerPanel = new Panel();
+           JRootPane root = new JRootPane();
+           root.getContentPane().add(currentTip);
+           containerPanel.add(root);
+         }
+       else
+         {
+           containerPanel = new JPanel();
+           containerPanel.add(currentTip);
+         }
+       LayoutManager lm = containerPanel.getLayout();
+       if (lm instanceof FlowLayout)
+         {
+           FlowLayout fm = (FlowLayout) lm;
+           fm.setVgap(0);
+           fm.setHgap(0);
+         }
+
+       p = getGoodPoint(p, pane, currentTip, dims);
+
+       pane.add(containerPanel);
+       containerPanel.setBounds(p.x, p.y, dims.width, dims.height);
+       currentTip.setBounds(0, 0, dims.width, dims.height);
+
+       pane.revalidate();
+       pane.repaint();
+      }
+    else
+      {
+       SwingUtilities.convertPointToScreen(p, currentComponent);
+       tooltipWindow = new JWindow();
+       tooltipWindow.getContentPane().add(currentTip);
+       tooltipWindow.setFocusable(false);
+       tooltipWindow.pack();
+       tooltipWindow.setBounds(p.x, p.y, dims.width, dims.height);
+       tooltipWindow.show();
+      }
+    currentTip.setVisible(true);
+  }
+
+  /**
+   * This method hides the ToolTip.
+   */
+  private void hideTip()
+  {
+    if (currentTip == null || ! currentTip.isVisible() || ! enabled)
+      return;
+    currentTip.setVisible(false);
+    if (containerPanel != null)
+      {
+       Container parent = containerPanel.getParent();
+       if (parent == null)
+         return;
+       parent.remove(containerPanel);
+       parent.invalidate();
+       parent.validate();
+       parent.repaint();
+
+       parent = currentTip.getParent();
+       if (parent == null)
+         return;
+       parent.remove(currentTip);
+
+       containerPanel = null;
+      }
+    if (tooltipWindow != null)
+      {
+       tooltipWindow.hide();
+       tooltipWindow.dispose();
+       tooltipWindow = null;
+      }
+  }
+
+  /**
+   * This method returns a point in the LayeredPane where the ToolTip can be
+   * shown. The point returned (if the ToolTip is to be displayed at the
+   * preferred dimensions) will always place the ToolTip inside the
+   * currentComponent if possible.
+   *
+   * @param p The last known good point for the mouse.
+   * @param c The JLayeredPane in the first RootPaneContainer up from the
+   *        currentComponent.
+   * @param tip The ToolTip to display.
+   * @param dims The ToolTip preferred dimensions (can be null).
+   *
+   * @return A good point to place the ToolTip.
+   */
+  private Point getGoodPoint(Point p, JLayeredPane c, JToolTip tip,
+                             Dimension dims)
+  {
+    if (dims == null)
+      dims = tip.getPreferredSize();
+    Rectangle bounds = currentComponent.getBounds();
+    if (p.x + dims.width > bounds.width)
+      p.x = bounds.width - dims.width;
+    if (p.y + dims.height > bounds.height)
+      p.y = bounds.height - dims.height;
+
+    p = SwingUtilities.convertPoint(currentComponent, p, c);
+    return p;
+  }
+
+  /**
+   * 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 = (Container) 
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;
+  }
+
+  /**
+   * This method returns whether the ToolTip can fit in the first
+   * RootPaneContainer up from the currentComponent.
+   *
+   * @param tip The ToolTip.
+   *
+   * @return Whether the ToolTip can fit.
+   */
+  private boolean canToolTipFit(JToolTip tip)
+  {
+    JRootPane root = (JRootPane) 
SwingUtilities.getAncestorOfClass(JRootPane.class,
+                                                                   
currentComponent);
+    if (root == null)
+      return false;
+    Dimension pref = tip.getPreferredSize();
+    Dimension rootSize = root.getSize();
+    if (rootSize.width > pref.width && rootSize.height > pref.height)
+      return true;
+    return false;
   }
 }
Index: javax/swing/plaf/basic/BasicLookAndFeel.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java,v
retrieving revision 1.12
diff -u -r1.12 BasicLookAndFeel.java
--- javax/swing/plaf/basic/BasicLookAndFeel.java        22 Jul 2004 19:45:39 
-0000      1.12
+++ javax/swing/plaf/basic/BasicLookAndFeel.java        31 Jul 2004 15:18:02 
-0000
@@ -881,7 +881,7 @@
       "ToolBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
       "ToolBar.foreground", new ColorUIResource(Color.black),
       "ToolBar.separatorSize", new DimensionUIResource(20, 20),
-      "ToolTip.background", new ColorUIResource(Color.white),
+      "ToolTip.background", new ColorUIResource(122, 178, 241),
       "ToolTip.border", new 
BorderUIResource.LineBorderUIResource(Color.lightGray),
       "ToolTip.font", new FontUIResource("SansSerif", Font.PLAIN, 12),
       "ToolTip.foreground", new ColorUIResource(Color.black),

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]