This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gui][PATCH] Implementation of JToolTip.
- From: Kim Ho <kho at redhat dot com>
- To: java-patches <java-patches at gcc dot gnu dot org>
- Date: Thu, 29 Jul 2004 11:57:45 -0400
- Subject: [gui][PATCH] Implementation of JToolTip.
Hi,
This patch implements JToolTip and has fixes for Timer and the
LightweightDispatcher.
Cheers,
Kim
2004-07-29 Kim Ho <kho@redhat.com>
* Makefile.am: Add new file.
* Makefile.in: Regenerate.
* gcj/Makefile.in: Regenerate
* include/Makefile.in:
* 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.
* testsuite/Makefile.in: Regenerate
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.361.2.29
diff -u -r1.361.2.29 Makefile.am
--- Makefile.am 16 Jul 2004 04:47:01 -0000 1.361.2.29
+++ Makefile.am 29 Jul 2004 15:44:04 -0000
@@ -1333,6 +1333,7 @@
javax/swing/plaf/basic/BasicToggleButtonUI.java \
javax/swing/plaf/basic/BasicToolBarUI.java \
javax/swing/plaf/basic/BasicToolBarSeparatorUI.java \
+javax/swing/plaf/basic/BasicToolTipUI.java \
javax/swing/plaf/basic/BasicTreeUI.java \
javax/swing/plaf/basic/BasicViewportUI.java \
javax/swing/plaf/basic/BasicLookAndFeel.java \
@@ -1450,6 +1451,7 @@
javax/swing/SwingConstants.java \
javax/swing/SwingUtilities.java \
javax/swing/Timer.java \
+javax/swing/ToolTipManager.java \
javax/swing/UIDefaults.java \
javax/swing/UIManager.java \
javax/swing/UnsupportedLookAndFeelException.java \
@@ -1609,7 +1611,6 @@
javax/swing/ProgressMonitorInputStream.java \
javax/swing/RepaintManager.java \
javax/swing/ScrollPaneLayout.java \
-javax/swing/ToolTipManager.java \
javax/swing/ViewportLayout.java
accessibility_java_source_files = \
Index: java/awt/Container.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Container.java,v
retrieving revision 1.34.2.14
diff -u -r1.34.2.14 Container.java
--- java/awt/Container.java 12 Jul 2004 03:26:59 -0000 1.34.2.14
+++ java/awt/Container.java 29 Jul 2004 15:44:07 -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: /cvs/gcc/gcc/libjava/javax/swing/JComponent.java,v
retrieving revision 1.7.2.13
diff -u -r1.7.2.13 JComponent.java
--- javax/swing/JComponent.java 10 Jul 2004 17:53:03 -0000 1.7.2.13
+++ javax/swing/JComponent.java 29 Jul 2004 15:44:08 -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: /cvs/gcc/gcc/libjava/javax/swing/JToolTip.java,v
retrieving revision 1.2.18.3
diff -u -r1.2.18.3 JToolTip.java
--- javax/swing/JToolTip.java 8 Jun 2004 20:04:10 -0000 1.2.18.3
+++ javax/swing/JToolTip.java 29 Jul 2004 15:44:08 -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: /cvs/gcc/gcc/libjava/javax/swing/Timer.java,v
retrieving revision 1.3.18.7
diff -u -r1.3.18.7 Timer.java
--- javax/swing/Timer.java 12 Jul 2004 17:04:37 -0000 1.3.18.7
+++ javax/swing/Timer.java 29 Jul 2004 15:44:08 -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: /cvs/gcc/gcc/libjava/javax/swing/ToolTipManager.java,v
retrieving revision 1.2.8.2
diff -u -r1.2.8.2 ToolTipManager.java
--- javax/swing/ToolTipManager.java 20 Jun 2004 14:45:49 -0000 1.2.8.2
+++ javax/swing/ToolTipManager.java 29 Jul 2004 15:44:08 -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
+ * This ActionListener is associated with the Timer that listens to whether
+ * the JToolTip can be hidden after four seconds.
*/
- protected class stillInsideTimerAction
- implements ActionListener
+ protected class stillInsideTimerAction implements ActionListener
{
/**
- * Constructor stillInsideTimerAction
+ * 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
+ * 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
+ protected class outsideTimerAction implements ActionListener
{
/**
- * Constructor outsideTimerAction
+ * 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
+ * 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
+ protected class insideTimerAction implements ActionListener
{
/**
- * Constructor insideTimerAction
+ * 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
+ * The Timer that determines whether the Mouse has been still long enough
+ * for the JToolTip to be displayed.
*/
Timer enterTimer;
/**
- * exitTimer
+ * The Timer that determines whether the Mouse has re-entered the JComponent
+ * quickly enough for the JToolTip to be displayed immediately.
*/
Timer exitTimer;
/**
- * insideTimer
+ * The Timer that determines whether the JToolTip has been displayed long
+ * enough for it to be hidden.
*/
Timer insideTimer;
- /**
- * toolTipText
- */
- String toolTipText;
+ /** A global enabled setting for the ToolTipManager. */
+ private transient boolean enabled = true;
- /**
- * mouseEvent
- */
- MouseEvent mouseEvent;
+ /** lightWeightPopupEnabled */
+ protected boolean lightWeightPopupEnabled = true;
- /**
- * showImmediately
- */
- boolean showImmediately;
+ /** heavyWeightPopupEnabled */
+ protected boolean heavyWeightPopupEnabled = false;
- /**
- * tip
- */
- JToolTip tip;
+ /** The shared instance of the ToolTipManager. */
+ private static ToolTipManager shared;
- /**
- * enabled
- */
- boolean enabled;
+ /** The current component the tooltip is being displayed for. */
+ private static Component currentComponent;
- /**
- * timerEnter
- */
- private long timerEnter;
+ /** The current tooltip. */
+ private static JToolTip currentTip;
+
+ /** The last known position of the mouse cursor. */
+ private static Point currentPoint;
/**
- * lightWeightPopupEnabled
+ * The panel that holds the tooltip when the tooltip is displayed fully
+ * inside the current container.
*/
- protected boolean lightWeightPopupEnabled;
+ private static Container containerPanel;
/**
- * heavyWeightPopupEnabled
+ * The window used when the tooltip doesn't fit inside the current
+ * container.
*/
- protected boolean heavyWeightPopupEnabled;
+ private static JWindow tooltipWindow;
/**
- * Constructor ToolTipManager
+ * 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
+ 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();
}
/**
- * mouseExited
- * @param event TODO
+ * 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;
+
+ currentPoint = event.getPoint();
+ currentComponent = null;
+ hideTip();
+
+ if (! enterTimer.isRunning() && insideTimer.isRunning())
+ exitTimer.start();
+ if (enterTimer.isRunning())
+ enterTimer.stop();
+ if (insideTimer.isRunning())
+ insideTimer.stop();
}
/**
- * mousePressed
- * @param event TODO
+ * 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
+ currentPoint = event.getPoint();
+ if (enterTimer.isRunning())
+ enterTimer.restart();
+ else if (insideTimer.isRunning())
+ {
+ insideTimer.stop();
+ hideTip();
+ }
+ currentComponent.invalidate();
+ currentComponent.validate();
+ currentComponent.repaint();
}
/**
- * mouseDragged
- * @param event TODO
+ * 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: /cvs/gcc/gcc/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java,v
retrieving revision 1.4.2.15
diff -u -r1.4.2.15 BasicLookAndFeel.java
--- javax/swing/plaf/basic/BasicLookAndFeel.java 12 Jul 2004 19:52:46 -0000 1.4.2.15
+++ javax/swing/plaf/basic/BasicLookAndFeel.java 29 Jul 2004 15:44:08 -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),
Index: javax/swing/plaf/basic/BasicToolTipUI.java
===================================================================
RCS file: javax/swing/plaf/basic/BasicToolTipUI.java
diff -N javax/swing/plaf/basic/BasicToolTipUI.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ javax/swing/plaf/basic/BasicToolTipUI.java 29 Jul 2004 15:44:08 -0000
@@ -0,0 +1,287 @@
+/* BasicToolTipUI.java --
+ Copyright (C) 2004 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., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 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.plaf.basic;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import javax.swing.JComponent;
+import javax.swing.JToolTip;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.ToolTipUI;
+
+
+/**
+ * This is the Basic Look and Feel UI class for JToolTip.
+ */
+public class BasicToolTipUI extends ToolTipUI
+{
+ /** The default Border around the JToolTip. */
+ private static Border defaultBorder = new Border()
+ {
+ // FIXME: This needs to go into Basic Look and Feel
+ // defaults.
+
+ /**
+ * This method returns the border insets.
+ *
+ * @param c The Component to find Border insets for.
+ *
+ * @return The Border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return new Insets(4, 4, 4, 4);
+ }
+
+ /**
+ * This method returns whether the border is opaque.
+ *
+ * @return Whether the border is opaque.
+ */
+ public boolean isBorderOpaque()
+ {
+ return false;
+ }
+
+ /**
+ * This method paints the border.
+ *
+ * @param c The Component to paint this border around.
+ * @param g The Graphics object to paint with.
+ * @param x The x coordinate to start painting at.
+ * @param y The y coordinate to start painting at.
+ * @param w The width of the Component.
+ * @param y The height of the Component.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+
+ g.drawRect(0, 0, w - 1, h - 1);
+
+ g.setColor(saved);
+ }
+ };
+
+ /** The shared instance of BasicToolTipUI used for all ToolTips. */
+ private static BasicToolTipUI shared;
+
+ /**
+ * Creates a new BasicToolTipUI object.
+ */
+ public BasicToolTipUI()
+ {
+ super();
+ }
+
+ /**
+ * This method creates a new BasicToolTip UI for the given
+ * JComponent.
+ *
+ * @param c The JComponent to create a UI for.
+ *
+ * @return A BasicToolTipUI that can be used by the given JComponent.
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ if (shared == null)
+ shared = new BasicToolTipUI();
+ return shared;
+ }
+
+ /**
+ * This method returns the msximum size of the given JComponent.
+ *
+ * @param c The JComponent to find a maximum size for.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the minimum size of the given JComponent.
+ *
+ * @param c The JComponent to find a minimum size for.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the preferred size of the given JComponent.
+ *
+ * @param c The JComponent to find a preferred size for.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ JToolTip tip = (JToolTip) c;
+ Rectangle vr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ Insets insets = tip.getInsets();
+ FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont());
+ SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER, vr, ir, tr, 0);
+ return new Dimension(insets.left + tr.width + insets.right,
+ insets.top + tr.height + insets.bottom);
+ }
+
+ /**
+ * This method installs the defaults for the given JComponent.
+ *
+ * @param c The JComponent to install defaults for.
+ */
+ protected void installDefaults(JComponent c)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ c.setBackground(defaults.getColor("ToolTip.background"));
+ c.setForeground(defaults.getColor("ToolTip.foreground"));
+ c.setFont(defaults.getFont("ToolTip.font"));
+ c.setBorder(defaultBorder);
+ }
+
+ /**
+ * This method installs the listeners for the given JComponent.
+ *
+ * @param c The JComponent to install listeners for.
+ */
+ protected void installListeners(JComponent c)
+ {
+ }
+
+ /**
+ * This method installs the UI for the given JComponent.
+ *
+ * @param c The JComponent to install the UI for.
+ */
+ public void installUI(JComponent c)
+ {
+ c.setOpaque(true);
+ installDefaults(c);
+ installListeners(c);
+ }
+
+ /**
+ * This method paints the given JComponent with the given Graphics object.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ JToolTip tip = (JToolTip) c;
+
+ String text = tip.getTipText();
+ if (text == null)
+ return;
+
+ Rectangle vr = new Rectangle();
+ vr = SwingUtilities.calculateInnerArea(tip, vr);
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont());
+ SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER, vr, ir, tr, 0);
+
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+
+ g.drawString(text, vr.x, vr.y + fm.getAscent());
+
+ g.setColor(saved);
+ }
+
+ /**
+ * This method uninstalls the defaults for the given JComponent.
+ *
+ * @param c The JComponent to uninstall defaults for.
+ */
+ protected void uninstallDefaults(JComponent c)
+ {
+ c.setForeground(null);
+ c.setBackground(null);
+ c.setFont(null);
+ c.setBorder(null);
+ }
+
+ /**
+ * This method uninstalls listeners for the given JComponent.
+ *
+ * @param c The JComponent to uninstall listeners for.
+ */
+ protected void uninstallListeners(JComponent c)
+ {
+ }
+
+ /**
+ * This method uninstalls the UI for the given JComponent.
+ *
+ * @param c The JComponent to uninstall.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ uninstallDefaults(c);
+ uninstallListeners(c);
+ }
+}