Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java')
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java464
1 files changed, 464 insertions, 0 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java
new file mode 100644
index 00000000000..48cb940642a
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java
@@ -0,0 +1,464 @@
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+
+Contributors:
+ IBM Corporation - Initial implementation
+**********************************************************************/
+
+package org.eclipse.jface.text;
+
+
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackAdapter;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.events.ShellListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.jface.util.Assert;
+
+
+/**
+ * An information control manager that shows information on mouse hover events.
+ * The mouse hover events are caught by registering a <code>MouseTrackListener</code>
+ * on the manager's subject control. The manager has by default an information control closer
+ * that closes the information control as soon as the mouse pointer leaves the subject area, the
+ * user presses a key, or the subject control is resized, moved, or deactivated.<p>
+ * When being activated by a mouse hover event, the manager disables itself, until the mouse
+ * leaves the subject area. Thus, the manager is usually still disabled, when the information control
+ * has already been closed by the closer.
+ *
+ * @see org.eclipse.swt.events.MouseTrackListener
+ * @since 2.0
+ */
+abstract public class AbstractHoverInformationControlManager extends AbstractInformationControlManager {
+
+
+ /**
+ * The information control closer for the hover information. Closes the information control as
+ * soon as the mouse pointer leaves the subject area, the user presses a key, or the subject
+ * control is resized or moved.
+ */
+ class Closer extends MouseTrackAdapter
+ implements IInformationControlCloser, MouseListener, MouseMoveListener, ControlListener, KeyListener {
+
+ /** The closer's subject control */
+ private Control fSubjectControl;
+ /** The closer's information control */
+ private IInformationControl fInformationControl;
+ /** The subject area */
+ private Rectangle fSubjectArea;
+ /** Indicates whether this closer is active */
+ private boolean fIsActive= false;
+
+ /**
+ * Creates a new information control closer.
+ */
+ public Closer() {
+ }
+
+ /*
+ * @see IInformationControlCloser#setSubjectControl(Control)
+ */
+ public void setSubjectControl(Control control) {
+ fSubjectControl= control;
+ }
+
+ /*
+ * @see IInformationControlCloser#setHoverControl(IHoverControl)
+ */
+ public void setInformationControl(IInformationControl control) {
+ fInformationControl= control;
+ }
+
+ /*
+ * @see IInformationControlCloser#start(Rectangle)
+ */
+ public void start(Rectangle subjectArea) {
+
+ if (fIsActive)
+ return;
+ fIsActive= true;
+
+ fSubjectArea= subjectArea;
+
+ setEnabled(false);
+
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ fSubjectControl.addMouseListener(this);
+ fSubjectControl.addMouseMoveListener(this);
+ fSubjectControl.addMouseTrackListener(this);
+ fSubjectControl.addControlListener(this);
+ fSubjectControl.addKeyListener(this);
+ }
+ }
+
+ /*
+ * @see IInformationControlCloser#stop()
+ */
+ public void stop() {
+ stop(false);
+ }
+
+ /**
+ * Stops the information control and if <code>delayRestart</code> is set
+ * allows restart only after a certain delay.
+ *
+ * @param delayRestart <code>true</code> if restart should be delayed
+ */
+ protected void stop(boolean delayRestart) {
+
+ if (!fIsActive)
+ return;
+ fIsActive= false;
+
+ hideInformationControl();
+
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ fSubjectControl.removeMouseListener(this);
+ fSubjectControl.removeMouseMoveListener(this);
+ fSubjectControl.removeMouseTrackListener(this);
+ fSubjectControl.removeControlListener(this);
+ fSubjectControl.removeKeyListener(this);
+ }
+ }
+
+ /*
+ * @see MouseMoveListener#mouseMove
+ */
+ public void mouseMove(MouseEvent event) {
+ if (!fSubjectArea.contains(event.x, event.y))
+ stop();
+ }
+
+ /*
+ * @see MouseListener#mouseUp(MouseEvent)
+ */
+ public void mouseUp(MouseEvent event) {
+ }
+
+ /*
+ * @see MouseListener#mouseDown(MouseEvent)
+ */
+ public void mouseDown(MouseEvent event) {
+ stop();
+ }
+
+ /*
+ * @see MouseListener#mouseDoubleClick(MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent event) {
+ stop();
+ }
+
+ /*
+ * @see MouseTrackAdapter#mouseExit(MouseEvent)
+ */
+ public void mouseExit(MouseEvent event) {
+ stop();
+ }
+
+ /*
+ * @see ControlListener#controlResized(ControlEvent)
+ */
+ public void controlResized(ControlEvent event) {
+ stop();
+ }
+
+ /*
+ * @see ControlListener#controlMoved(ControlEvent)
+ */
+ public void controlMoved(ControlEvent event) {
+ stop();
+ }
+
+ /*
+ * @see KeyListener#keyReleased(KeyEvent)
+ */
+ public void keyReleased(KeyEvent event) {
+ }
+
+ /*
+ * @see KeyListener#keyPressed(KeyEvent)
+ */
+ public void keyPressed(KeyEvent event) {
+ stop(true);
+ }
+ };
+
+
+ /**
+ * To be installed on the manager's subject control. Serves two different purposes:
+ * <ul>
+ * <li> start function: initiates the computation of the information to be presented. This happens on
+ * receipt of a mouse hover event and disables the information control manager,
+ * <li> restart function: tracks mouse move and shell activation event to determine when the information
+ * control manager needs to be reactivated.
+ * </ul>
+ */
+ class MouseTracker extends ShellAdapter implements MouseTrackListener, MouseMoveListener {
+
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=18393
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=19686
+ // http://bugs.eclipse.org/bugs/show_bug.cgi?id=19719
+
+ /** Margin around the original hover event location for coputing the hover area. */
+ private final static int EPSILON= 3;
+
+ /** The area in which the original hover event occurred. */
+ private Rectangle fHoverArea;
+ /** The area for which is computed information is valid. */
+ private Rectangle fSubjectArea;
+ /** The tracker's subject control. */
+ private Control fSubjectControl;
+
+ /** Indicates whether the tracker is computing the start function. */
+ private boolean fIsActive= false;
+ /** Indicates whether the mouse has been lost. */
+ private boolean fMouseLost= false;
+ /** Indicates whether the subject control's shelll has been deactivated. */
+ private boolean fShellDeactivated= false;
+
+ /**
+ * Creates a new mouse tracker.
+ */
+ public MouseTracker() {
+ }
+
+ /**
+ * Sets this mouse tracker's subject area, the area to be tracked in order
+ * to reenable the information control manager.
+ *
+ * @param subjectArea the subject area
+ */
+ public void setSubjectArea(Rectangle subjectArea) {
+ Assert.isNotNull(subjectArea);
+ fSubjectArea= subjectArea;
+ }
+
+ /**
+ * Starts this mouse tracker. The given control becomes this tracker's subject control.
+ * Installs itself as mouse track listener on the subject control.
+ *
+ * @param subjectControl the subject control
+ */
+ public void start(Control subjectControl) {
+ fSubjectControl= subjectControl;
+ if (fSubjectControl != null && !fSubjectControl.isDisposed())
+ fSubjectControl.addMouseTrackListener(this);
+
+ fIsActive= false;
+ fMouseLost= false;
+ fShellDeactivated= false;
+ }
+
+ /**
+ * Stops this mouse tracker. Removes itself as mouse track, mouse move, and
+ * shell listener from the subject control.
+ */
+ public void stop() {
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ fSubjectControl.removeMouseTrackListener(this);
+ fSubjectControl.removeMouseMoveListener(this);
+ fSubjectControl.getShell().removeShellListener(this);
+ }
+
+ fMouseLost= false;
+ fShellDeactivated= false;
+ }
+
+ /**
+ * Initiates the computation of the information to be presented. Sets the initial hover area
+ * to a small rectangle around the hover event location. Adds mouse move and shell activation listeners
+ * to track whether the computed information is, after completion, useful for presentation and to
+ * implement the restart function.
+ */
+ public void mouseHover(MouseEvent event) {
+
+ if (fIsActive)
+ return;
+
+ fIsActive= true;
+ fMouseLost= false;
+ fShellDeactivated= false;
+
+ setEnabled(false);
+
+ fHoverEventLocation= new Point(event.x, event.y);
+ fHoverArea= new Rectangle(event.x - EPSILON, event.y - EPSILON, 2 * EPSILON, 2 * EPSILON );
+ if (fHoverArea.x < 0) fHoverArea.x= 0;
+ if (fHoverArea.y < 0) fHoverArea.y= 0;
+ setSubjectArea(fHoverArea);
+
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ fSubjectControl.addMouseMoveListener(this);
+ fSubjectControl.getShell().addShellListener(this);
+ }
+
+ doShowInformation();
+ }
+
+ /**
+ * Deactivates this tracker's restart function and enables the information control
+ * manager. Does not have any effect if the tracker is still executing the start function (i.e.
+ * computing the information to be presented.
+ */
+ protected void deactivate() {
+ if (fIsActive)
+ return;
+
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ fSubjectControl.removeMouseMoveListener(this);
+ fSubjectControl.getShell().removeShellListener(this);
+ }
+
+ setEnabled(true);
+ }
+
+ /*
+ * @see MouseTrackListener#mouseEnter(MouseEvent)
+ */
+ public void mouseEnter(MouseEvent e) {
+ }
+
+ /*
+ * @see MouseTrackListener#mouseExit(MouseEvent)
+ */
+ public void mouseExit(MouseEvent e) {
+ fMouseLost= true;
+ deactivate();
+ }
+
+ /*
+ * @see MouseMoveListener#mouseMove(MouseEvent)
+ */
+ public void mouseMove(MouseEvent event) {
+ if (!fSubjectArea.contains(event.x, event.y))
+ deactivate();
+ }
+
+ /*
+ * @see ShellListener#shellDeactivated(ShellEvent)
+ */
+ public void shellDeactivated(ShellEvent e) {
+ fShellDeactivated= true;
+ deactivate();
+ }
+
+ /*
+ * @see ShellListener#shellIconified(ShellEvent)
+ */
+ public void shellIconified(ShellEvent e) {
+ fShellDeactivated= true;
+ deactivate();
+ }
+
+ /**
+ * Tells this tracker that the start function processing has been completed.
+ */
+ public void computationCompleted() {
+ fIsActive= false;
+ fMouseLost= false;
+ fShellDeactivated= false;
+ }
+
+ /**
+ * Determines whether the computed information is still useful for presentation.
+ * This is the case, if the shell of the subject control has been deactivated, the mouse
+ * left the subject control, or the mouse moved on, so that it is no longer in the subject
+ * area.
+ *
+ * @return <code>true</code> if information is still useful for presentation, <code>false</code> otherwise
+ */
+ public boolean isMouseLost() {
+
+ if (fMouseLost || fShellDeactivated)
+ return true;
+
+ if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
+ Display display= fSubjectControl.getDisplay();
+ Point p= display.getCursorLocation();
+ p= fSubjectControl.toControl(p);
+ if (!fSubjectArea.contains(p) && !fHoverArea.contains(p))
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ /** The mouse tracker on the subject control */
+ private MouseTracker fMouseTracker= new MouseTracker();
+ /** The remembered hover event location */
+ private Point fHoverEventLocation= new Point(-1, -1);
+
+ /**
+ * Creates a new hover information control manager using the given information control creator.
+ * By default a <code>Closer</code> instance is set as this manager's closer.
+ *
+ * @param creator the information control creator
+ */
+ protected AbstractHoverInformationControlManager(IInformationControlCreator creator) {
+ super(creator);
+ setCloser(new Closer());
+ }
+
+ /*
+ * @see AbstractInformationControlManager#presentInformation()
+ */
+ protected void presentInformation() {
+
+ Rectangle area= getSubjectArea();
+ if (area != null)
+ fMouseTracker.setSubjectArea(area);
+
+ if (fMouseTracker.isMouseLost()) {
+ fMouseTracker.computationCompleted();
+ fMouseTracker.deactivate();
+ } else {
+ fMouseTracker.computationCompleted();
+ super.presentInformation();
+ }
+ }
+
+ /*
+ * @see AbstractInformationControlManager#setEnabled(boolean)
+ */
+ public void setEnabled(boolean enabled) {
+
+ boolean was= isEnabled();
+ super.setEnabled(enabled);
+ boolean is= isEnabled();
+
+ if (was != is) {
+ if (is)
+ fMouseTracker.start(getSubjectControl());
+ else
+ fMouseTracker.stop();
+ }
+ }
+
+ /**
+ * Returns the location at which the most recent mouse hover event
+ * has been issued.
+ *
+ * @return the location of the most recent mouse hover event
+ */
+ protected Point getHoverEventLocation() {
+ return fHoverEventLocation;
+ }
+} \ No newline at end of file

Back to the top