#181533: better support for heavyweight tooltips diff --git a/debugger.jpda.projects/nbproject/project.xml b/debugger.jpda.projects/nbproject/project.xml --- a/debugger.jpda.projects/nbproject/project.xml +++ b/debugger.jpda.projects/nbproject/project.xml @@ -94,7 +94,7 @@ 2 - 2.1 + 2.10 @@ -244,17 +244,17 @@ org.openide.util - - 8.0 - + + 8.0 + org.openide.util.lookup - - 8.0 - + + 8.0 + org.openide.windows diff --git a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ToolTipAnnotation.java b/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ToolTipAnnotation.java --- a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ToolTipAnnotation.java +++ b/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ToolTipAnnotation.java @@ -87,7 +87,9 @@ import org.netbeans.api.java.source.JavaSource.Phase; import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.editor.BaseDocument; +import org.netbeans.editor.PopupManager; import org.netbeans.editor.Utilities; +import org.netbeans.editor.ext.ToolTipSupport; import org.netbeans.modules.parsing.api.ParserManager; import org.netbeans.modules.parsing.api.ResultIterator; import org.netbeans.modules.parsing.api.Source; @@ -264,7 +266,7 @@ et.repaint(); SwingUtilities.invokeLater(new Runnable() { public @Override void run() { - Utilities.getEditorUI(ep).getToolTipSupport().setToolTip(et); + Utilities.getEditorUI(ep).getToolTipSupport().setToolTip(et, PopupManager.ViewPortBounds, PopupManager.AbovePreferred, 0, 0, ToolTipSupport.FLAGS_HEAVYWEIGHT_TOOLTIP); } }); } diff --git a/editor.lib/apichanges.xml b/editor.lib/apichanges.xml --- a/editor.lib/apichanges.xml +++ b/editor.lib/apichanges.xml @@ -104,6 +104,27 @@ + + Support for heavyweight tooltips + + + + + +

+ Adding flags to o.n.editor.ext.ToolTipSupport class that control + tooltip behavior such as if the tooltip should be hidden on mouse move, timeout, etc. + The flags are FLAG_HIDE_ON_MOUSE_MOVE, FLAG_HIDE_ON_TIMER, FLAG_PERMANENT + and FLAGS_LIGHTWEIGHT_TOOLTIP, FLAGS_HEAVYWEIGHT_TOOLTIP. +

+

+ A new method ToolTipSupport.setTooltip() accepting the additional flags + parameter has also been added. +

+
+ +
+ Adding Utilities.createSingleLineEditor diff --git a/editor.lib/nbproject/project.properties b/editor.lib/nbproject/project.properties --- a/editor.lib/nbproject/project.properties +++ b/editor.lib/nbproject/project.properties @@ -39,7 +39,7 @@ javac.compilerargs=-Xlint:unchecked javac.source=1.6 -spec.version.base=2.9.0 +spec.version.base=2.10.0 is.autoload=true javadoc.arch=${basedir}/arch.xml diff --git a/editor.lib/src/org/netbeans/editor/ext/ToolTipSupport.java b/editor.lib/src/org/netbeans/editor/ext/ToolTipSupport.java --- a/editor.lib/src/org/netbeans/editor/ext/ToolTipSupport.java +++ b/editor.lib/src/org/netbeans/editor/ext/ToolTipSupport.java @@ -106,6 +106,7 @@ */ public class ToolTipSupport { + // -J-Dorg.netbeans.editor.ext.ToolTipSupport.level=FINE private static final Logger LOG = Logger.getLogger(ToolTipSupport.class.getName()); static { @@ -189,34 +190,37 @@ private static final MouseListener NO_OP_MOUSE_LISTENER = new MouseAdapter() {}; + /** @Since 2.10 */ + public static final int FLAG_HIDE_ON_MOUSE_MOVE = 1; + /** @Since 2.10 */ + public static final int FLAG_HIDE_ON_TIMER = 2; + /** @Since 2.10 */ + public static final int FLAG_PERMANENT = 4; + + /** @Since 2.10 */ + public static final int FLAGS_LIGHTWEIGHT_TOOLTIP = FLAG_HIDE_ON_MOUSE_MOVE | FLAG_HIDE_ON_TIMER; + /** @Since 2.10 */ + public static final int FLAGS_HEAVYWEIGHT_TOOLTIP = FLAG_PERMANENT; + private final EditorUI extEditorUI; - - private JComponent toolTip; - - private String toolTipText; - private final Timer enterTimer; - private final Timer exitTimer; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + private final Listener listener = new Listener(); private boolean enabled; - - /** Status of the tooltip visibility. */ - private int status; + private MouseEvent lastMouseEvent; + private boolean glyphListenerAdded = false; - private MouseEvent lastMouseEvent; - - private PropertyChangeSupport pcs; - + // The actual tooltip instance related information + private int status; // Status of the tooltip visibility + private JComponent toolTip; + private String toolTipText; private PopupManager.HorizontalBounds horizontalBounds = PopupManager.ViewPortBounds; private PopupManager.Placement placement = PopupManager.AbovePreferred; - private int verticalAdjustment; private int horizontalAdjustment; - - private boolean glyphListenerAdded = false; - - private final Listener listener = new Listener(); + private int flags; /** Construct new support for tooltips. */ @@ -258,22 +262,45 @@ setToolTip(toolTip, PopupManager.ViewPortBounds, PopupManager.AbovePreferred); } - public void setToolTip(JComponent toolTip, PopupManager.HorizontalBounds horizontalBounds, - PopupManager.Placement placement) { + public void setToolTip(JComponent toolTip, PopupManager.HorizontalBounds horizontalBounds, PopupManager.Placement placement) { setToolTip(toolTip, PopupManager.ViewPortBounds, PopupManager.AbovePreferred, 0, 0); } - public void setToolTip(JComponent toolTip, PopupManager.HorizontalBounds horizontalBounds, - PopupManager.Placement placement, int horizontalAdjustment, int verticalAdjustment) { + public void setToolTip( + JComponent toolTip, + PopupManager.HorizontalBounds horizontalBounds, + PopupManager.Placement placement, + int horizontalAdjustment, + int verticalAdjustment + ) { + setToolTip(toolTip, horizontalBounds, placement, horizontalAdjustment, verticalAdjustment, FLAGS_LIGHTWEIGHT_TOOLTIP); + } + + /** + * @Since 2.10 + */ + public void setToolTip( + JComponent toolTip, + PopupManager.HorizontalBounds horizontalBounds, + PopupManager.Placement placement, + int horizontalAdjustment, + int verticalAdjustment, + int flags + ) { JComponent oldToolTip = this.toolTip; - LOG.log(Level.FINE, "setTooltip: {0}", toolTip); //NOI18N + if (LOG.isLoggable(Level.FINE)) { + LOG.log(Level.FINE, "setTooltip: {0}, horizontalBounds={1}, placement={2}, horizontalAdjustment={3}, verticalAdjustment={4}, flags={5}", new Object [] { //NOI18N + toolTip, horizontalBounds, placement, horizontalAdjustment, verticalAdjustment, flags + }); + } this.toolTip = toolTip; this.horizontalBounds = horizontalBounds; this.placement = placement; this.horizontalAdjustment = horizontalAdjustment; this.verticalAdjustment = verticalAdjustment; + this.flags = flags; if (this.toolTip.getClientProperty(MOUSE_LISTENER) == null) { this.toolTip.putClientProperty(MOUSE_LISTENER, NO_OP_MOUSE_LISTENER); @@ -499,6 +526,10 @@ * @since 2.3 */ public void setToolTipVisible(boolean visible) { + LOG.log(Level.FINE, "setToolTipVisible: visible={0}, status={1}, enabled={2}", new Object [] { //NOI18N + visible, status, enabled + }); + if (!visible) { // ensure the timers are stopped enterTimer.stop(); exitTimer.stop(); @@ -524,6 +555,7 @@ pm.uninstall(toolTip); } } + toolTip = null; } setStatus(STATUS_HIDDEN); @@ -537,6 +569,10 @@ public boolean isToolTipVisible() { return status > STATUS_VISIBILITY_ENABLED; } + + private boolean isToolTipShowing() { + return toolTip != null && toolTip.isShowing(); + } /** @return status of the tooltip visibility. It can * be {@link #STATUS_HIDDEN} @@ -849,24 +885,17 @@ setToolTipText(component.getToolTipText()); } - private synchronized PropertyChangeSupport getPCS() { - if (pcs == null) { - pcs = new PropertyChangeSupport(this); - } - return pcs; - } - /** Add the listener for the property changes. The names * of the supported properties are defined * as "PROP_" public static string constants. * @param listener listener to be added. */ public void addPropertyChangeListener(PropertyChangeListener listener) { - getPCS().addPropertyChangeListener(listener); + pcs.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { - getPCS().removePropertyChangeListener(listener); + pcs.removePropertyChangeListener(listener); } /** Fire the change of the given property. @@ -874,9 +903,8 @@ * @param oldValue old value of the property * @param newValue new value of the property. */ - protected void firePropertyChange(String propertyName, - Object oldValue, Object newValue) { - getPCS().firePropertyChange(propertyName, oldValue, newValue); + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); } private static void filterBindings(ActionMap actionMap) { @@ -956,10 +984,14 @@ public @Override void actionPerformed(ActionEvent evt) { if (evt.getSource() == enterTimer) { - setToolTipVisible(true); + if (!isToolTipShowing() || (flags & FLAG_PERMANENT) == 0) { + setToolTipVisible(true); + } } else if (evt.getSource() == exitTimer) { - setToolTipVisible(false); + if (!isToolTipShowing() || (flags & FLAG_HIDE_ON_TIMER) != 0) { + setToolTipVisible(false); + } } } @@ -1001,7 +1033,7 @@ public @Override void mouseExited(MouseEvent evt) { lastMouseEvent = evt; - if (toolTip != null && toolTip.isShowing()) { + if (isToolTipShowing()) { Rectangle r = new Rectangle(toolTip.getLocationOnScreen(), toolTip.getSize()); if (LOG.isLoggable(Level.FINE)) { @@ -1013,7 +1045,10 @@ return; } } - setToolTipVisible(false); + + if (!isToolTipShowing() || (flags & FLAG_HIDE_ON_MOUSE_MOVE) != 0) { + setToolTipVisible(false); + } } // ------------------------------------------------------------------- @@ -1026,6 +1061,10 @@ } public @Override void mouseMoved(MouseEvent evt) { + if (LOG.isLoggable(Level.FINE)) { + LOG.log(Level.FINE, "mouseMoved: x=" + evt.getX() + "; y=" + evt.getY() + "enabled=" + enabled + ", status=" + status + ", flags=" + flags); //NOI18N + } + if (toolTip != null) { Rectangle r = (Rectangle) toolTip.getClientProperty(MOUSE_MOVE_IGNORED_AREA); if (LOG.isLoggable(Level.FINE)) { @@ -1037,7 +1076,10 @@ } } - setToolTipVisible(false); + if (!isToolTipShowing() || (flags & FLAG_HIDE_ON_MOUSE_MOVE) != 0) { + setToolTipVisible(false); + } + if (enabled) { enterTimer.restart(); }