Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Keller2008-05-13 16:50:23 +0000
committerMarkus Keller2008-05-13 16:50:23 +0000
commit1a0d4a0970b4db3044663fa2594a5d5a74d95ce9 (patch)
tree76e8b6e9133329fc03029a0e7116a3ce04cb5b3b
parented20ea32b5943811ded97e3d2f5c167284d747fc (diff)
downloadeclipse.platform.text-1a0d4a0970b4db3044663fa2594a5d5a74d95ce9.tar.gz
eclipse.platform.text-1a0d4a0970b4db3044663fa2594a5d5a74d95ce9.tar.xz
eclipse.platform.text-1a0d4a0970b4db3044663fa2594a5d5a74d95ce9.zip
112921: [content assist] Enhance additional info popup
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/AccessorUtil.java98
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/DelayedInputChangeListener.java45
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/IInformationControlReplacer.java75
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InformationControlReplacer.java206
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InternalAccessor.java102
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/internal/text/StickyHoverManager.java155
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java73
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControlManager.java80
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AdditionalInfoController.java34
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java67
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/PopupCloser.java150
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java55
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java11
13 files changed, 755 insertions, 396 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/AccessorUtil.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/AccessorUtil.java
deleted file mode 100644
index dc43eea5780..00000000000
--- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/AccessorUtil.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jface.internal.text;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-
-/**
- * Helper class for calling non-accessible methods.
- *
- * @since 3.4
- */
-public class AccessorUtil {
-
- /**
- * Invokes a zero-parameter method via reflection, making the method accessible first.
- *
- * @param targetObject the target object
- * @param declaringClass the declaring class of the method to be called
- * @param methodName the method name
- * @return the result
- * @throws RuntimeException if the invocation fails
- */
- public static Object invoke(Object targetObject, Class declaringClass, String methodName) {
- return invoke(targetObject, declaringClass, methodName, (Class[]) null, null);
- }
-
- /**
- * Invokes a single-parameter method via reflection, making the method accessible first.
- *
- * @param targetObject the target object
- * @param declaringClass the declaring class of the method to be called
- * @param methodName the method name
- * @param parameterType0 the method's parameter type
- * @param arg0 the argument used for the method call
- * @return the result
- * @throws RuntimeException if the invocation fails
- */
- public static Object invoke(Object targetObject, Class declaringClass, String methodName, Class parameterType0, Object arg0) {
- return invoke(targetObject, declaringClass, methodName, new Class[] { parameterType0 }, new Object[] { arg0 });
- }
-
- /**
- * Invokes a method via reflection, making the method accessible first.
- *
- * @param targetObject the target object
- * @param declaringClass the declaring class of the method to be called
- * @param methodName the method name
- * @param parameterTypes the method's parameter types, or <code>null</code> if none
- * @param args the arguments used for the method call, or <code>null</code> if none
- * @return the result
- * @throws RuntimeException if the invocation fails
- */
- public static Object invoke(Object targetObject, Class declaringClass, String methodName, Class[] parameterTypes, Object[] args) {
- try {
- Method method= declaringClass.getDeclaredMethod(methodName, parameterTypes);
- method.setAccessible(true);
- return method.invoke(targetObject, args);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Reads the value of a field via reflection, making the field accessible first.
- *
- * @param targetObject the target object
- * @param declaringClass the declaring class of the field to be read
- * @param fieldName the field name
- * @return the value of the field
- * @throws RuntimeException if the invocation fails
- */
- public static Object getValue(Object targetObject, Class declaringClass, String fieldName) {
- try {
- Field field= declaringClass.getDeclaredField(fieldName);
- field.setAccessible(true);
- return field.get(targetObject);
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/DelayedInputChangeListener.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/DelayedInputChangeListener.java
new file mode 100644
index 00000000000..496e5ce3ec2
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/DelayedInputChangeListener.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.text;
+
+import org.eclipse.jface.text.IDelayedInputChangeProvider;
+import org.eclipse.jface.text.IInputChangedListener;
+
+
+/**
+ * A delayed input change listener that forwards delayed input changes to an information control replacer.
+ *
+ * @since 3.4
+ */
+public final class DelayedInputChangeListener implements IInputChangedListener {
+
+ private final IDelayedInputChangeProvider fChangeProvider;
+ private final InformationControlReplacer fInformationControlReplacer;
+
+ /**
+ * Creates a new listener.
+ *
+ * @param changeProvider the information control with delayed input changes
+ * @param informationControlReplacer the information control replacer, whose information control should get the new input
+ */
+ public DelayedInputChangeListener(IDelayedInputChangeProvider changeProvider, InformationControlReplacer informationControlReplacer) {
+ fChangeProvider= changeProvider;
+ fInformationControlReplacer= informationControlReplacer;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IDelayedInputChangeListener#inputChanged(java.lang.Object)
+ */
+ public void inputChanged(Object newInput) {
+ fChangeProvider.setDelayedInputChangeListener(null);
+ fInformationControlReplacer.setDelayedInput(newInput);
+ }
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/IInformationControlReplacer.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/IInformationControlReplacer.java
deleted file mode 100644
index c69756ae328..00000000000
--- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/IInformationControlReplacer.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jface.internal.text;
-
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.eclipse.jface.text.AbstractInformationControlManager;
-import org.eclipse.jface.text.IInformationControl;
-import org.eclipse.jface.text.IInformationControlCreator;
-
-
-/**
- * An information control replacer can replace an
- * {@link AbstractInformationControlManager}'s control.
- *
- * @see AbstractInformationControlManager#setInformationControlReplacer(IInformationControlReplacer)
- * @since 3.4
- */
-public interface IInformationControlReplacer {
-
- /**
- * Replace the information control.
- *
- * @param informationPresenterControlCreator the information presenter control creator
- * @param contentBounds the bounds of the content area of the information control
- * @param information the information to show
- * @param subjectArea the subject area
- * @param takeFocus <code>true</code> iff the replacing information control should take focus
- */
- public void replaceInformationControl(IInformationControlCreator informationPresenterControlCreator, Rectangle contentBounds, Object information, Rectangle subjectArea, boolean takeFocus);
-
- /**
- * Tells whether the replacer is currently replacing another information control.
- *
- * @return <code>true</code> while code from {@link #replaceInformationControl(IInformationControlCreator, Rectangle, Object, Rectangle, boolean)} is run
- */
- public boolean isReplacing();
-
- /**
- * @return the current information control, or <code>null</code> if none available
- */
- public IInformationControl getCurrentInformationControl2();
-
- /**
- * Disposes this information control replacer.
- * <p>
- * Can be called more than once. Calling
- * {@link AbstractInformationControlManager#setInformationControlReplacer(IInformationControlReplacer)}
- * will dispose its old replacer if set.
- * </p>
- *
- * @see AbstractInformationControlManager
- */
- public void dispose();
-
- /**
- * The number of pixels to blow up the keep-up zone.
- *
- * @return the margin in pixels
- */
- public int getKeepUpMargin();
-
- /**
- * @param input the delayed input, or <code>null</code> to request cancellation
- */
- public void setDelayedInput(Object input);
-}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InformationControlReplacer.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InformationControlReplacer.java
new file mode 100644
index 00000000000..eaa6e991b59
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InformationControlReplacer.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.text;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.jface.text.AbstractInformationControlManager;
+import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.text.IInformationControlExtension3;
+import org.eclipse.jface.util.Geometry;
+
+
+/**
+ * An information control replacer can replace an
+ * {@link AbstractInformationControlManager}'s control.
+ *
+ * @see AbstractInformationControlManager#setInformationControlReplacer(InformationControlReplacer)
+ * @since 3.4
+ */
+public class InformationControlReplacer extends AbstractInformationControlManager {
+
+ /**
+ * Minimal width in pixels.
+ */
+ private static final int MIN_WIDTH= 80;
+ /**
+ * Minimal height in pixels.
+ */
+ private static final int MIN_HEIGHT= 50;
+
+ /**
+ * Default control creator.
+ */
+ protected static class DefaultInformationControlCreator extends AbstractReusableInformationControlCreator {
+ public IInformationControl doCreateInformationControl(Shell shell) {
+ return new DefaultInformationControl(shell, true);
+ }
+ }
+
+ private boolean fIsReplacing;
+ private Object fReplacableInformation;
+ private boolean fDelayedInformationSet;
+ private Rectangle fReplaceableArea;
+ private Rectangle fContentBounds;
+
+
+ /**
+ * Creates a new information control replacer.
+ *
+ * @param creator the default information control creator
+ */
+ public InformationControlReplacer(IInformationControlCreator creator) {
+ super(creator);
+ takesFocusWhenVisible(false);
+ }
+
+ /**
+ * Replace the information control.
+ *
+ * @param informationPresenterControlCreator the information presenter control creator
+ * @param contentBounds the bounds of the content area of the information control
+ * @param information the information to show
+ * @param subjectArea the subject area
+ * @param takeFocus <code>true</code> iff the replacing information control should take focus
+ */
+ public void replaceInformationControl(IInformationControlCreator informationPresenterControlCreator, Rectangle contentBounds, Object information, final Rectangle subjectArea, boolean takeFocus) {
+
+ try {
+ fIsReplacing= true;
+ if (! fDelayedInformationSet)
+ fReplacableInformation= information;
+ else
+ takeFocus= true; // delayed input has been set, so the original info control must have been focused
+ fContentBounds= contentBounds;
+ fReplaceableArea= subjectArea;
+
+ setCustomInformationControlCreator(informationPresenterControlCreator);
+
+ takesFocusWhenVisible(takeFocus);
+
+ showInformation();
+ } finally {
+ fIsReplacing= false;
+ fReplacableInformation= null;
+ fDelayedInformationSet= false;
+ fReplaceableArea= null;
+ setCustomInformationControlCreator(null);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControlManager#computeInformation()
+ */
+ protected void computeInformation() {
+ if (fIsReplacing && fReplacableInformation != null) {
+ setInformation(fReplacableInformation, fReplaceableArea);
+ return;
+ }
+
+ if (DEBUG)
+ System.out.println("InformationControlReplacer: no active replaceable"); //$NON-NLS-1$
+ }
+
+ /**
+ * Opens the information control with the given information and the specified
+ * subject area. It also activates the information control closer.
+ *
+ * @param subjectArea the information area
+ * @param information the information
+ */
+ public void showInformationControl(Rectangle subjectArea, Object information) {
+ IInformationControl informationControl= getInformationControl();
+
+ Rectangle controlBounds= fContentBounds;
+ if (informationControl instanceof IInformationControlExtension3) {
+ IInformationControlExtension3 iControl3= (IInformationControlExtension3) informationControl;
+ Rectangle trim= iControl3.computeTrim();
+ controlBounds= Geometry.add(controlBounds, trim);
+
+ /*
+ * Ensure minimal size. Interacting with a tiny information control
+ * (resizing, selecting text) would be a pain.
+ */
+ controlBounds.width= Math.max(controlBounds.width, MIN_WIDTH);
+ controlBounds.height= Math.max(controlBounds.height, MIN_HEIGHT);
+
+ getInternalAccessor().cropToClosestMonitor(controlBounds);
+ }
+
+ Point location= Geometry.getLocation(controlBounds);
+ Point size= Geometry.getSize(controlBounds);
+
+ // Caveat: some IInformationControls fail unless setSizeConstraints(..) is called with concrete values
+ informationControl.setSizeConstraints(size.x, size.y);
+
+ if (informationControl instanceof IInformationControlExtension2)
+ ((IInformationControlExtension2) informationControl).setInput(information);
+ else
+ informationControl.setInformation(information.toString());
+
+ informationControl.setLocation(location);
+ informationControl.setSize(size.x, size.y);
+
+ showInformationControl(subjectArea);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControlManager#hideInformationControl()
+ */
+ public void hideInformationControl() {
+ super.hideInformationControl();
+ }
+
+ /**
+ * @param input the delayed input, or <code>null</code> to request cancellation
+ */
+ public void setDelayedInput(Object input) {
+ fReplacableInformation= input;
+ if (! isReplacing()) {
+ fDelayedInformationSet= true;
+ } else if (getCurrentInformationControl2() instanceof IInformationControlExtension2) {
+ ((IInformationControlExtension2) getCurrentInformationControl2()).setInput(input);
+ } else if (getCurrentInformationControl2() != null) {
+ getCurrentInformationControl2().setInformation(input.toString());
+ }
+ }
+
+ /**
+ * Tells whether the replacer is currently replacing another information control.
+ *
+ * @return <code>true</code> while code from {@link #replaceInformationControl(IInformationControlCreator, Rectangle, Object, Rectangle, boolean)} is run
+ */
+ public boolean isReplacing() {
+ return fIsReplacing;
+ }
+
+ /**
+ * @return the current information control, or <code>null</code> if none available
+ */
+ public IInformationControl getCurrentInformationControl2() {
+ return getInternalAccessor().getCurrentInformationControl();
+ }
+
+ /**
+ * The number of pixels to blow up the keep-up zone.
+ *
+ * @return the margin in pixels
+ */
+ public int getKeepUpMargin() {
+ return 15;
+ }
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InternalAccessor.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InternalAccessor.java
new file mode 100644
index 00000000000..6e56d90e813
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/InternalAccessor.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.text;
+
+import org.eclipse.swt.graphics.Rectangle;
+
+import org.eclipse.jface.text.AbstractInformationControlManager;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension3;
+import org.eclipse.jface.text.ITextViewerExtension8;
+import org.eclipse.jface.text.ITextViewerExtension8.EnrichMode;
+
+
+/**
+ * An internal class that gives access to internal methods of {@link
+ * AbstractInformationControlManager} and subclasses.
+ *
+ * @since 3.4
+ */
+public abstract class InternalAccessor {
+
+ /**
+ * Returns the current information control, or <code>null</code> if none.
+ *
+ * @return the current information control, or <code>null</code> if none
+ */
+ public abstract IInformationControl getCurrentInformationControl();
+
+ /**
+ * Sets the information control replacer for this manager and disposes the
+ * old one if set.
+ *
+ * @param replacer the information control replacer for this manager, or
+ * <code>null</code> if no information control replacing should
+ * take place
+ */
+ public abstract void setInformationControlReplacer(InformationControlReplacer replacer);
+
+ /**
+ * Returns the current information control replacer or <code>null</code> if none has been installed.
+ *
+ * @return the current information control replacer or <code>null</code> if none has been installed
+ */
+ public abstract InformationControlReplacer getInformationControlReplacer();
+
+ /**
+ * Tests whether the given information control is replaceable.
+ *
+ * @param iControl information control or <code>null</code> if none
+ * @return <code>true</code> if information control is replaceable, <code>false</code> otherwise
+ */
+ public abstract boolean canReplace(IInformationControl iControl);
+
+ /**
+ * Tells whether this manager's information control is currently being replaced.
+ *
+ * @return <code>true</code> if a replace is in progress
+ */
+ public abstract boolean isReplaceInProgress();
+
+ /**
+ * Crops the given bounds such that they lie completely on the closest monitor.
+ *
+ * @param bounds shell bounds to crop
+ */
+ public abstract void cropToClosestMonitor(Rectangle bounds);
+
+ /**
+ * Sets the hover enrich mode. Only applicable when an information
+ * control replacer has been set with
+ * {@link #setInformationControlReplacer(InformationControlReplacer)} .
+ *
+ * @param mode the enrich mode
+ * @see ITextViewerExtension8#setHoverEnrichMode(org.eclipse.jface.text.ITextViewerExtension8.EnrichMode)
+ */
+ public abstract void setHoverEnrichMode(EnrichMode mode);
+
+ /**
+ * Indicates whether the mouse cursor is allowed to leave the subject area without closing the hover.
+ *
+ * @return whether the mouse cursor is allowed to leave the subject area without closing the hover
+ */
+ public abstract boolean getAllowMouseExit();
+
+ /**
+ * Replaces this manager's information control as defined by
+ * the information control replacer.
+ * <strong>Must only be called when the information control is instanceof {@link IInformationControlExtension3}!</strong>
+ *
+ * @param takeFocus <code>true</code> iff the replacing information control should take focus
+ */
+ public abstract void replaceInformationControl(boolean takeFocus);
+
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/StickyHoverManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/StickyHoverManager.java
index 6a4f1ff49b6..c183999f603 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/StickyHoverManager.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/StickyHoverManager.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.jface.internal.text;
-
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
@@ -26,14 +25,8 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.jface.text.AbstractInformationControlManager;
-import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
-import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
-import org.eclipse.jface.text.IInformationControlCreator;
-import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.text.IInformationControlExtension3;
import org.eclipse.jface.text.IInformationControlExtension5;
import org.eclipse.jface.text.IViewportListener;
@@ -60,7 +53,7 @@ import org.eclipse.jface.util.Geometry;
*
* @since 3.4
*/
-public class StickyHoverManager extends AbstractInformationControlManager implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension, IInformationControlReplacer {
+public class StickyHoverManager extends InformationControlReplacer implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
/**
* Priority of the info controls managed by this sticky hover manager.
@@ -71,24 +64,6 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
*/
private static final int WIDGET_PRIORITY= -5;
- /**
- * Minimal width in pixels.
- */
- private static final int MIN_WIDTH= 80;
- /**
- * Minimal height in pixels.
- */
- private static final int MIN_HEIGHT= 50;
-
- /**
- * Default control creator.
- */
- private static class DefaultInformationControlCreator extends AbstractReusableInformationControlCreator {
- public IInformationControl doCreateInformationControl(Shell shell) {
- return new DefaultInformationControl(shell, true);
- }
- }
-
/**
* Internal information control closer. Listens to several events issued by its subject control
@@ -119,7 +94,7 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
* @see IInformationControlCloser#setInformationControl(IInformationControl)
*/
public void setInformationControl(IInformationControl control) {
- // NOTE: we use fInformationControl from the outer class
+ // NOTE: we use getCurrentInformationControl2() from the outer class
}
/*
@@ -294,12 +269,7 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
}
- private TextViewer fTextViewer;
- private boolean fIsReplacing;
- private Object fReplacableInformation;
- private boolean fDelayedInformationSet;
- private Rectangle fReplaceableArea;
- private Rectangle fContentBounds;
+ private final TextViewer fTextViewer;
/**
@@ -312,25 +282,11 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
fTextViewer= textViewer;
setCloser(new Closer());
- takesFocusWhenVisible(false);
install(fTextViewer.getTextWidget());
}
/*
- * @see AbstractInformationControlManager#computeInformation()
- */
- protected void computeInformation() {
- if (fIsReplacing && fReplacableInformation != null) {
- setInformation(fReplacableInformation, fReplaceableArea);
- return;
- }
-
- if (DEBUG)
- System.out.println("StickyHover: no active replaceable"); //$NON-NLS-1$
- }
-
- /*
* @see AbstractInformationControlManager#showInformationControl(Rectangle)
*/
protected void showInformationControl(Rectangle subjectArea) {
@@ -344,7 +300,7 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
/*
* @see AbstractInformationControlManager#hideInformationControl()
*/
- protected void hideInformationControl() {
+ public void hideInformationControl() {
try {
super.hideInformationControl();
} finally {
@@ -417,107 +373,4 @@ public class StickyHoverManager extends AbstractInformationControlManager implem
return iControl.isFocusControl();
}
- /*
- * @see org.eclipse.jface.text.IInformationControlReplacer#replaceInformationControl(IInformationControlCreator, org.eclipse.swt.graphics.Rectangle, java.lang.Object, org.eclipse.swt.graphics.Rectangle, boolean)
- */
- public void replaceInformationControl(IInformationControlCreator informationPresenterControlCreator, Rectangle contentBounds, Object information, final Rectangle subjectArea, boolean takeFocus) {
-
- try {
- fIsReplacing= true;
- if (! fDelayedInformationSet)
- fReplacableInformation= information;
- else
- takeFocus= true; // delayed input has been set, so the original info control must have been focused
- fContentBounds= contentBounds;
- fReplaceableArea= subjectArea;
-
- setCustomInformationControlCreator(informationPresenterControlCreator);
-
- takesFocusWhenVisible(takeFocus);
-
- showInformation();
- } finally {
- fIsReplacing= false;
- fReplacableInformation= null;
- fDelayedInformationSet= false;
- fReplaceableArea= null;
- setCustomInformationControlCreator(null);
- }
- }
-
- /*
- * @see org.eclipse.jface.text.AbstractInformationControlManager#internalShowInformationControl(org.eclipse.swt.graphics.Rectangle, java.lang.Object)
- */
- public void internalShowInformationControl2(Rectangle subjectArea, Object information) {
- IInformationControl informationControl= getInformationControl();
-
- Rectangle controlBounds= fContentBounds;
- if (informationControl instanceof IInformationControlExtension3) {
- IInformationControlExtension3 iControl3= (IInformationControlExtension3) informationControl;
- Rectangle trim= iControl3.computeTrim();
- controlBounds= Geometry.add(controlBounds, trim);
-
- /*
- * Ensure minimal size. Interacting with a tiny information control
- * (resizing, selecting text) would be a pain.
- */
- controlBounds.width= Math.max(controlBounds.width, MIN_WIDTH);
- controlBounds.height= Math.max(controlBounds.height, MIN_HEIGHT);
-
- // reflective version of cropToClosestMonitor(controlBounds);
- AccessorUtil.invoke(this, AbstractInformationControlManager.class, "cropToClosestMonitor", Rectangle.class, controlBounds); //$NON-NLS-1$
- }
-
- Point location= Geometry.getLocation(controlBounds);
- Point size= Geometry.getSize(controlBounds);
-
- // Caveat: some IInformationControls fail unless setSizeConstraints(..) is called with concrete values
- informationControl.setSizeConstraints(size.x, size.y);
-
- if (informationControl instanceof IInformationControlExtension2)
- ((IInformationControlExtension2) informationControl).setInput(information);
- else
- informationControl.setInformation(information.toString());
-
- informationControl.setLocation(location);
- informationControl.setSize(size.x, size.y);
-
- showInformationControl(subjectArea);
- }
-
- /*
- * @see org.eclipse.jface.text.IInformationControlReplacer#setDelayedInput(java.lang.Object)
- */
- public void setDelayedInput(Object input) {
- fReplacableInformation= input;
- if (! isReplacing()) {
- fDelayedInformationSet= true;
- } else if (getCurrentInformationControl2() instanceof IInformationControlExtension2) {
- ((IInformationControlExtension2) getCurrentInformationControl2()).setInput(input);
- } else if (getCurrentInformationControl2() != null) {
- getCurrentInformationControl2().setInformation(input.toString());
- }
- }
-
- /*
- * @see org.eclipse.jface.text.IInformationControlReplacer#getKeepUpMargin()
- */
- public int getKeepUpMargin() {
- return 15;
- }
-
- /*
- * @see org.eclipse.jface.text.IInformationControlReplacer#isReplacing()
- */
- public boolean isReplacing() {
- return fIsReplacing;
- }
-
- /*
- * @see org.eclipse.jface.text.IInformationControlReplacer#getCurrentInformationControl()
- */
- public IInformationControl getCurrentInformationControl2() {
- // reflective version of super.getCurrentInformationControl()
- return (IInformationControl) AccessorUtil.invoke(this, AbstractInformationControlManager.class, "getCurrentInformationControl"); //$NON-NLS-1$
- }
}
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
index 0958b590be9..ca66688219a 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractHoverInformationControlManager.java
@@ -38,8 +38,9 @@ import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
-import org.eclipse.jface.internal.text.AccessorUtil;
-import org.eclipse.jface.internal.text.IInformationControlReplacer;
+import org.eclipse.jface.internal.text.DelayedInputChangeListener;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
+import org.eclipse.jface.internal.text.InternalAccessor;
import org.eclipse.jface.text.ITextViewerExtension8.EnrichMode;
import org.eclipse.jface.text.source.AnnotationBarHoverManager;
import org.eclipse.jface.util.Geometry;
@@ -100,7 +101,7 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
* @see IInformationControlCloser#setHoverControl(IHoverControl)
*/
public void setInformationControl(IInformationControl control) {
- // NOTE: we use fInformationControl from the outer class
+ // NOTE: we use getCurrentInformationControl() from the outer class
}
/*
@@ -372,7 +373,7 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
IInformationControl iControl= getCurrentInformationControl();
if (!hasInformationControlReplacer() || !canMoveIntoInformationControl(iControl)) {
if (AbstractHoverInformationControlManager.this instanceof AnnotationBarHoverManager) {
- if (Boolean.TRUE.equals(AccessorUtil.getValue(AbstractHoverInformationControlManager.this, AnnotationBarHoverManager.class, "fAllowMouseExit"))) //$NON-NLS-1$
+ if (getInternalAccessor().getAllowMouseExit())
return;
}
hideInformationControl();
@@ -405,33 +406,6 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
}
/**
- * The delayed input change listener implementation.
- * @since 3.4
- */
- private static final class DelayedInputChangeListener implements IInputChangedListener {
-
- private final IDelayedInputChangeProvider fChangeProvider;
- private final IInformationControlReplacer fInformationControlReplacer;
-
- /**
- * @param changeProvider the information control with delayed input changes
- * @param informationControlReplacer the information control replacer, whose information control should get the new input
- */
- private DelayedInputChangeListener(IDelayedInputChangeProvider changeProvider, IInformationControlReplacer informationControlReplacer) {
- fChangeProvider= changeProvider;
- fInformationControlReplacer= informationControlReplacer;
- }
-
- /*
- * @see org.eclipse.jface.text.IDelayedInputChangeListener#inputChanged(java.lang.Object)
- */
- public void inputChanged(Object newInput) {
- fChangeProvider.setDelayedInputChangeListener(null);
- fInformationControlReplacer.setDelayedInput(newInput);
- }
- }
-
- /**
* 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
@@ -766,6 +740,22 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
}
}
return false;
+
+ } else if (subjectArea.x + subjectArea.width < iControlBounds.x) {
+ // special case for hover events (e.g. in annotation ruler): subjectArea totally left of iControl
+ // +-----------+--------------------+
+ // +-----------+ | |
+ // |subjectArea|also keepUp| InformationControl |
+ // +-----------+ | |
+ // +-----------+--------------------+
+ if (subjectArea.x + subjectArea.width <= x && x <= iControlBounds.x) {
+ // is horizontally between subject area and iControl
+ if (iControlBounds.y <= y && y <= iControlBounds.y + iControlBounds.height) {
+ // is to the left of iControl (in a horizontal projection)
+ return true;
+ }
+ }
+ return false;
}
}
@@ -800,14 +790,13 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
/**
* Sets the hover enrich mode. Only applicable when an information
* control replacer has been set with
- * {@link #setInformationControlReplacer(IInformationControlReplacer)} .
+ * {@link #setInformationControlReplacer(InformationControlReplacer)} .
*
* @param mode the enrich mode
* @since 3.4
* @see ITextViewerExtension8#setHoverEnrichMode(org.eclipse.jface.text.ITextViewerExtension8.EnrichMode)
*/
void setHoverEnrichMode(EnrichMode mode) {
- // Do not rename! Called reflectively from SourceViewer.
fEnrichMode= mode;
}
@@ -971,5 +960,23 @@ abstract public class AbstractHoverInformationControlManager extends AbstractInf
protected int getHoverEventStateMask() {
return fHoverEventStateMask;
}
+
+ /**
+ * Returns an adapter that gives access to internal methods.
+ * <p>
+ * <strong>Note:</strong> This method is not intended to be referenced or overridden by clients.</p>
+ *
+ * @return the replaceable information control accessor
+ * @since 3.4
+ * @noreference This method is not intended to be referenced by clients.
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ */
+ public InternalAccessor getInternalAccessor() {
+ return new MyInternalAccessor() {
+ public void setHoverEnrichMode(EnrichMode mode) {
+ AbstractHoverInformationControlManager.this.setHoverEnrichMode(mode);
+ }
+ };
+ }
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControlManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControlManager.java
index 39f37d02f0b..10138289e91 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControlManager.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControlManager.java
@@ -27,8 +27,9 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.internal.text.IInformationControlReplacer;
-import org.eclipse.jface.internal.text.StickyHoverManager;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
+import org.eclipse.jface.internal.text.InternalAccessor;
+import org.eclipse.jface.text.ITextViewerExtension8.EnrichMode;
import org.eclipse.jface.util.Geometry;
@@ -51,6 +52,49 @@ import org.eclipse.jface.util.Geometry;
abstract public class AbstractInformationControlManager {
/**
+ * An internal class that gives access to internal methods.
+ *
+ * @since 3.4
+ */
+ class MyInternalAccessor extends InternalAccessor {
+ public IInformationControl getCurrentInformationControl() {
+ return AbstractInformationControlManager.this.getCurrentInformationControl();
+ }
+
+ public void setInformationControlReplacer(InformationControlReplacer replacer) {
+ AbstractInformationControlManager.this.setInformationControlReplacer(replacer);
+ }
+
+ public InformationControlReplacer getInformationControlReplacer() {
+ return AbstractInformationControlManager.this.getInformationControlReplacer();
+ }
+
+ public boolean canReplace(IInformationControl control) {
+ return AbstractInformationControlManager.this.canReplace(control);
+ }
+
+ public boolean isReplaceInProgress() {
+ return AbstractInformationControlManager.this.isReplaceInProgress();
+ }
+
+ public void replaceInformationControl(boolean takeFocus) {
+ AbstractInformationControlManager.this.replaceInformationControl(takeFocus);
+ }
+
+ public void cropToClosestMonitor(Rectangle bounds) {
+ AbstractInformationControlManager.this.cropToClosestMonitor(bounds);
+ }
+
+ public void setHoverEnrichMode(EnrichMode mode) {
+ throw new UnsupportedOperationException("only implemented in AbstractHoverInformationControlManager"); //$NON-NLS-1$
+ }
+
+ public boolean getAllowMouseExit() {
+ throw new UnsupportedOperationException("only implemented in AnnotationBarHoverManager"); //$NON-NLS-1$
+ }
+ }
+
+ /**
* Interface of an information control closer. An information control closer
* monitors its information control and its subject control and closes the
* information control if necessary.
@@ -226,7 +270,7 @@ abstract public class AbstractInformationControlManager {
*
* @since 3.4
*/
- private IInformationControlReplacer fInformationControlReplacer;
+ private InformationControlReplacer fInformationControlReplacer;
/** Indicates the enable state of this manager */
private boolean fEnabled= false;
@@ -391,8 +435,7 @@ abstract public class AbstractInformationControlManager {
* take place
* @since 3.4
*/
- void setInformationControlReplacer(IInformationControlReplacer replacer) {
- // Do not rename! Called reflectively from StickyHoverManager.
+ void setInformationControlReplacer(InformationControlReplacer replacer) {
if (fInformationControlReplacer != null)
fInformationControlReplacer.dispose();
fInformationControlReplacer= replacer;
@@ -404,7 +447,7 @@ abstract public class AbstractInformationControlManager {
* @return the current information control replacer or <code>null</code> if none has been installed
* @since 3.4
*/
- IInformationControlReplacer getInformationControlReplacer() {
+ InformationControlReplacer getInformationControlReplacer() {
return fInformationControlReplacer;
}
@@ -438,7 +481,6 @@ abstract public class AbstractInformationControlManager {
* @since 3.4
*/
IInformationControl getCurrentInformationControl() {
- // Do not rename! Called reflectively from StickyHoverManager.
return fInformationControl;
}
@@ -1104,8 +1146,8 @@ abstract public class AbstractInformationControlManager {
* @param information the information
*/
private void internalShowInformationControl(Rectangle subjectArea, Object information) {
- if (this instanceof StickyHoverManager) {
- ((StickyHoverManager) this).internalShowInformationControl2(subjectArea, information);
+ if (this instanceof InformationControlReplacer) {
+ ((InformationControlReplacer) this).showInformationControl(subjectArea, information);
return;
}
@@ -1173,7 +1215,6 @@ abstract public class AbstractInformationControlManager {
* @since 3.4
*/
void cropToClosestMonitor(Rectangle bounds) {
- // Do not rename! Called reflectively from StickyHoverManager.
Rectangle monitorBounds= getClosestMonitor(fSubjectControl.getDisplay(), bounds).getClientArea();
bounds.intersect(monitorBounds);
}
@@ -1249,6 +1290,11 @@ abstract public class AbstractInformationControlManager {
setEnabled(false);
disposeInformationControl();
+ if (fInformationControlReplacer != null) {
+ fInformationControlReplacer.dispose();
+ fInformationControlReplacer= null;
+ }
+
if (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControlDisposeListener != null)
fSubjectControl.removeDisposeListener(fSubjectControlDisposeListener);
fSubjectControl= null;
@@ -1369,4 +1415,18 @@ abstract public class AbstractInformationControlManager {
return bounds;
}
+
+ /**
+ * Returns an adapter that gives access to internal methods.
+ * <p>
+ * <strong>Note:</strong> This method is not intended to be referenced or overridden by clients.</p>
+ *
+ * @return the replaceable information control accessor
+ * @since 3.4
+ * @noreference This method is not intended to be referenced by clients.
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ */
+ public InternalAccessor getInternalAccessor() {
+ return new MyInternalAccessor();
+ }
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AdditionalInfoController.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AdditionalInfoController.java
index 665e456f7f4..1c23e1efd36 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AdditionalInfoController.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AdditionalInfoController.java
@@ -22,10 +22,14 @@ 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.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.text.AbstractInformationControlManager;
+import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
+import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IInformationControlExtension3;
@@ -373,6 +377,14 @@ class AdditionalInfoController extends AbstractInformationControlManager {
public void widgetDefaultSelected(SelectionEvent e) {
}
}
+ /**
+ * Default control creator.
+ */
+ private static class DefaultInformationControlCreator extends AbstractReusableInformationControlCreator {
+ public IInformationControl doCreateInformationControl(Shell shell) {
+ return new DefaultInformationControl(shell, true);
+ }
+ }
/** The proposal table. */
private Table fProposalTable;
@@ -417,6 +429,9 @@ class AdditionalInfoController extends AbstractInformationControlManager {
*/
int spacing= -1;
setMargins(spacing, spacing); // see also adjustment in #computeLocation
+
+ InformationControlReplacer replacer= new InformationControlReplacer(new DefaultInformationControlCreator());
+ getInternalAccessor().setInformationControlReplacer(replacer);
}
/*
@@ -434,8 +449,13 @@ class AdditionalInfoController extends AbstractInformationControlManager {
Assert.isTrue(control instanceof Table);
fProposalTable= (Table) control;
fProposalTable.addSelectionListener(fSelectionListener);
+ getInternalAccessor().getInformationControlReplacer().install(fProposalTable);
+
fTimer= new Timer(fProposalTable.getDisplay(), fDelay) {
protected void showInformation(ICompletionProposal proposal, Object info) {
+ InformationControlReplacer replacer= getInternalAccessor().getInformationControlReplacer();
+ if (replacer != null)
+ replacer.hideInformationControl();
AdditionalInfoController.this.showInformation(proposal, info);
}
};
@@ -551,6 +571,20 @@ class AdditionalInfoController extends AbstractInformationControlManager {
sizeConstraint.y= size.y;
return sizeConstraint;
}
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControlManager#hideInformationControl()
+ */
+ protected void hideInformationControl() {
+ super.hideInformationControl();
+ }
+
+ /**
+ * @return the current information control, or <code>null</code> if none available
+ */
+ public IInformationControl getCurrentInformationControl2() {
+ return getInternalAccessor().getCurrentInformationControl();
+ }
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
index bb6a10d674d..76259e6c3ea 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java
@@ -14,6 +14,13 @@ package org.eclipse.jface.text.contentassist;
import java.util.ArrayList;
import java.util.List;
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.StyleRange;
@@ -30,6 +37,8 @@ import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
@@ -48,22 +57,13 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.IHandler;
-
-import org.eclipse.core.runtime.Assert;
-
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.util.Geometry;
-import org.eclipse.jface.viewers.StyledString;
-
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
@@ -71,12 +71,15 @@ import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
+import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.AbstractInformationControlManager.Anchor;
+import org.eclipse.jface.util.Geometry;
+import org.eclipse.jface.viewers.StyledString;
/**
@@ -650,7 +653,7 @@ class CompletionProposalPopup implements IContentAssistListener {
}
});
- fPopupCloser.install(fContentAssistant, fProposalTable);
+ fPopupCloser.install(fContentAssistant, fProposalTable, fAdditionalInfoController);
fProposalShell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
@@ -693,12 +696,27 @@ class CompletionProposalPopup implements IContentAssistListener {
if (commandSequence != null && !commandSequence.isEmpty() && fContentAssistant.isRepeatedInvocationMode()) {
control.addFocusListener(new FocusListener() {
private CommandKeyListener fCommandKeyListener;
+ private TraverseListener fTraverseListener;
public void focusGained(FocusEvent e) {
if (Helper.okToUse(control)) {
if (fCommandKeyListener == null) {
fCommandKeyListener= new CommandKeyListener(commandSequence);
fProposalTable.addKeyListener(fCommandKeyListener);
}
+ if (fTraverseListener == null) {
+ fTraverseListener= new TraverseListener() {
+ public void keyTraversed(TraverseEvent event) {
+ if (event.detail == SWT.TRAVERSE_TAB_NEXT) {
+ IInformationControl iControl= fAdditionalInfoController.getCurrentInformationControl2();
+ if (fAdditionalInfoController.getInternalAccessor().canReplace(iControl)) {
+ fAdditionalInfoController.getInternalAccessor().replaceInformationControl(true);
+ event.doit= false;
+ }
+ }
+ }
+ };
+ fProposalTable.addTraverseListener(fTraverseListener);
+ }
}
}
public void focusLost(FocusEvent e) {
@@ -706,6 +724,10 @@ class CompletionProposalPopup implements IContentAssistListener {
control.removeKeyListener(fCommandKeyListener);
fCommandKeyListener= null;
}
+ if (fTraverseListener != null) {
+ control.removeTraverseListener(fTraverseListener);
+ fTraverseListener= null;
+ }
}
});
}
@@ -940,8 +962,27 @@ class CompletionProposalPopup implements IContentAssistListener {
* @return <code>true</code> if the popup has the focus
*/
public boolean hasFocus() {
- if (Helper.okToUse(fProposalShell))
- return (fProposalShell.isFocusControl() || fProposalTable.isFocusControl());
+ if (Helper.okToUse(fProposalShell)) {
+ if ((fProposalShell.isFocusControl() || fProposalTable.isFocusControl()))
+ return true;
+ /*
+ * We have to delegate this query to the additional info controller
+ * as well, since the content assistant is the widget token owner
+ * and its closer does not know that the additional info control can
+ * now also take focus.
+ */
+ if (fAdditionalInfoController != null) {
+ IInformationControl informationControl= fAdditionalInfoController.getCurrentInformationControl2();
+ if (informationControl != null && informationControl.isFocusControl())
+ return true;
+ InformationControlReplacer replacer= fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer();
+ if (replacer != null) {
+ informationControl= replacer.getCurrentInformationControl2();
+ if (informationControl != null && informationControl.isFocusControl())
+ return true;
+ }
+ }
+ }
return false;
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/PopupCloser.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/PopupCloser.java
index 495401c1866..5d1e5a2ca69 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/PopupCloser.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/PopupCloser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,17 +10,28 @@
*******************************************************************************/
package org.eclipse.jface.text.contentassist;
+import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
+import org.eclipse.jface.internal.text.DelayedInputChangeListener;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
+import org.eclipse.jface.text.IDelayedInputChangeProvider;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension5;
+import org.eclipse.jface.text.IInputChangedListener;
+
/**
* A generic closer class used to monitor various
@@ -28,7 +39,7 @@ import org.eclipse.swt.widgets.Table;
* a content assistant should be terminated and all
* associated windows be closed.
*/
-class PopupCloser extends ShellAdapter implements FocusListener, SelectionListener {
+class PopupCloser extends ShellAdapter implements FocusListener, SelectionListener, Listener {
/** The content assistant to be monitored. */
private ContentAssistant fContentAssistant;
@@ -43,6 +54,16 @@ class PopupCloser extends ShellAdapter implements FocusListener, SelectionListen
* @since 3.1
*/
private Shell fShell;
+ /**
+ * The display on which some filters are registered.
+ * @since 3.4
+ */
+ private Display fDisplay;
+ /**
+ * The additional info controller, or <code>null</code>.
+ * @since 3.4
+ */
+ private AdditionalInfoController fAdditionalInfoController;
/**
* Installs this closer on the given table opened by the given content assistant.
@@ -51,19 +72,38 @@ class PopupCloser extends ShellAdapter implements FocusListener, SelectionListen
* @param table the table to be tracked
*/
public void install(ContentAssistant contentAssistant, Table table) {
+ install(contentAssistant, table, null);
+ }
+
+ /**
+ * Installs this closer on the given table opened by the given content assistant.
+ *
+ * @param contentAssistant the content assistant
+ * @param table the table to be tracked
+ * @param additionalInfoController the additional info controller, or <code>null</code>
+ * @since 3.4
+ */
+ public void install(ContentAssistant contentAssistant, Table table, AdditionalInfoController additionalInfoController) {
fContentAssistant= contentAssistant;
fTable= table;
+ fAdditionalInfoController= additionalInfoController;
+
if (Helper.okToUse(fTable)) {
- Shell shell= fTable.getShell();
- if (Helper.okToUse(shell)) {
- fShell= shell;
- fShell.addShellListener(this);
- }
-
+ fShell= fTable.getShell();
+ fDisplay= fShell.getDisplay();
+
+ fShell.addShellListener(this);
fTable.addFocusListener(this);
fScrollbar= fTable.getVerticalBar();
if (fScrollbar != null)
fScrollbar.addSelectionListener(this);
+
+ fDisplay.addFilter(SWT.Activate, this);
+ fDisplay.addFilter(SWT.MouseWheel, this);
+
+ fDisplay.addFilter(SWT.Deactivate, this);
+
+ fDisplay.addFilter(SWT.MouseUp, this);
}
}
@@ -79,6 +119,14 @@ class PopupCloser extends ShellAdapter implements FocusListener, SelectionListen
fScrollbar.removeSelectionListener(this);
if (Helper.okToUse(fTable))
fTable.removeFocusListener(this);
+ if (fDisplay != null && ! fDisplay.isDisposed()) {
+ fDisplay.removeFilter(SWT.Activate, this);
+ fDisplay.removeFilter(SWT.MouseWheel, this);
+
+ fDisplay.removeFilter(SWT.Deactivate, this);
+
+ fDisplay.removeFilter(SWT.MouseUp, this);
+ }
}
/*
@@ -120,7 +168,7 @@ class PopupCloser extends ShellAdapter implements FocusListener, SelectionListen
* @since 3.1
*/
public void shellDeactivated(ShellEvent e) {
- if (fContentAssistant != null)
+ if (fContentAssistant != null && ! fContentAssistant.hasProposalPopupFocus())
fContentAssistant.hide();
}
@@ -133,4 +181,88 @@ class PopupCloser extends ShellAdapter implements FocusListener, SelectionListen
if (fContentAssistant != null)
fContentAssistant.hide();
}
+
+ /*
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+ * @since 3.4
+ */
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.Activate:
+ case SWT.MouseWheel:
+ if (fAdditionalInfoController == null)
+ return;
+ if (event.widget == fShell || event.widget == fTable || event.widget == fScrollbar)
+ return;
+
+ if (fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer() == null)
+ fAdditionalInfoController.hideInformationControl();
+ else if (!fAdditionalInfoController.getInternalAccessor().isReplaceInProgress()) {
+ IInformationControl infoControl= fAdditionalInfoController.getCurrentInformationControl2();
+ // During isReplaceInProgress(), events can come from the replacing information control
+ if (event.widget instanceof Control && infoControl instanceof IInformationControlExtension5) {
+ Control control= (Control) event.widget;
+ IInformationControlExtension5 iControl5= (IInformationControlExtension5) infoControl;
+ if (!(iControl5.containsControl(control)))
+ fAdditionalInfoController.hideInformationControl();
+ else if (event.type == SWT.MouseWheel)
+ fAdditionalInfoController.getInternalAccessor().replaceInformationControl(false);
+ } else if (infoControl != null && infoControl.isFocusControl()) {
+ fAdditionalInfoController.getInternalAccessor().replaceInformationControl(true);
+ }
+ }
+ break;
+
+ case SWT.MouseUp:
+ if (fAdditionalInfoController.getInternalAccessor().isReplaceInProgress())
+ break;
+ if (event.widget instanceof Control) {
+ Control control= (Control) event.widget;
+ IInformationControl infoControl= fAdditionalInfoController.getCurrentInformationControl2();
+ if (infoControl instanceof IInformationControlExtension5) {
+ final IInformationControlExtension5 iControl5= (IInformationControlExtension5) infoControl;
+ if (iControl5.containsControl(control)) {
+ if (infoControl instanceof IDelayedInputChangeProvider) {
+ final IDelayedInputChangeProvider delayedICP= (IDelayedInputChangeProvider) infoControl;
+ final IInputChangedListener inputChangeListener= new DelayedInputChangeListener(delayedICP, fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer());
+ delayedICP.setDelayedInputChangeListener(inputChangeListener);
+ // cancel automatic input updating after a small timeout:
+ control.getShell().getDisplay().timerExec(1000, new Runnable() {
+ public void run() {
+ delayedICP.setDelayedInputChangeListener(null);
+ }
+ });
+ }
+
+ // XXX: workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212392 :
+ control.getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ fAdditionalInfoController.getInternalAccessor().replaceInformationControl(true);
+ }
+ });
+ }
+ }
+ }
+ break;
+
+ case SWT.Deactivate:
+ InformationControlReplacer replacer= fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer();
+ if (replacer != null && fContentAssistant != null) {
+ IInformationControl iControl= replacer.getCurrentInformationControl2();
+ if (event.widget instanceof Control && iControl instanceof IInformationControlExtension5) {
+ Control control= (Control) event.widget;
+ IInformationControlExtension5 iControl5= (IInformationControlExtension5) iControl;
+ if (iControl5.containsControl(control)) {
+ control.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fContentAssistant != null && ! fContentAssistant.hasProposalPopupFocus())
+ fContentAssistant.hide();
+ }
+ });
+ }
+ }
+ }
+ break;
+ }
+ }
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java
index 2dcef45b118..daadea9074e 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationBarHoverManager.java
@@ -35,6 +35,9 @@ import org.eclipse.swt.widgets.Listener;
import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.internal.text.InformationControlReplacer;
+import org.eclipse.jface.internal.text.InternalAccessor;
+
import org.eclipse.jface.text.AbstractHoverInformationControlManager;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.BadLocationException;
@@ -46,6 +49,7 @@ import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.ITextViewerExtension8.EnrichMode;
/**
@@ -734,5 +738,56 @@ public class AnnotationBarHoverManager extends AbstractHoverInformationControlMa
public IAnnotationHover getCurrentAnnotationHover() {
return fCurrentHover;
}
+
+ /**
+ * Returns an adapter that gives access to internal methods.
+ * <p>
+ * <strong>Note:</strong> This method is not intended to be referenced or overridden by clients.
+ * </p>
+ *
+ * @return the replaceable information control accessor
+ * @since 3.4
+ * @noreference This method is not intended to be referenced by clients.
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ */
+ public InternalAccessor getInternalAccessor() {
+ return new InternalAccessor() {
+ public IInformationControl getCurrentInformationControl() {
+ return AnnotationBarHoverManager.super.getInternalAccessor().getCurrentInformationControl();
+ }
+
+ public void setInformationControlReplacer(InformationControlReplacer replacer) {
+ AnnotationBarHoverManager.super.getInternalAccessor().setInformationControlReplacer(replacer);
+ }
+
+ public InformationControlReplacer getInformationControlReplacer() {
+ return AnnotationBarHoverManager.super.getInternalAccessor().getInformationControlReplacer();
+ }
+
+ public boolean canReplace(IInformationControl control) {
+ return AnnotationBarHoverManager.super.getInternalAccessor().canReplace(control);
+ }
+
+ public boolean isReplaceInProgress() {
+ return AnnotationBarHoverManager.super.getInternalAccessor().isReplaceInProgress();
+ }
+
+ public void replaceInformationControl(boolean takeFocus) {
+ AnnotationBarHoverManager.super.getInternalAccessor().replaceInformationControl(takeFocus);
+ }
+
+ public void cropToClosestMonitor(Rectangle bounds) {
+ AnnotationBarHoverManager.super.getInternalAccessor().cropToClosestMonitor(bounds);
+ }
+
+ public void setHoverEnrichMode(EnrichMode mode) {
+ AnnotationBarHoverManager.super.getInternalAccessor().setHoverEnrichMode(mode);
+ }
+
+ public boolean getAllowMouseExit() {
+ return fAllowMouseExit;
+ }
+ };
+ }
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java
index eba48bfe3aa..04471030774 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java
@@ -21,13 +21,10 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
-import org.eclipse.jface.internal.text.AccessorUtil;
-import org.eclipse.jface.internal.text.IInformationControlReplacer;
import org.eclipse.jface.internal.text.NonDeletingPositionUpdater;
import org.eclipse.jface.internal.text.StickyHoverManager;
import org.eclipse.jface.text.AbstractHoverInformationControlManager;
-import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DocumentRewriteSession;
@@ -442,7 +439,7 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
if (fVerticalRuler != null && (fAnnotationHover != null || !isVerticalRulerOnlyShowingAnnotations()) && fVerticalRulerHoveringController == null && fHoverControlCreator != null) {
fVerticalRulerHoveringController= new AnnotationBarHoverManager(fVerticalRuler, this, fAnnotationHover, fHoverControlCreator);
fVerticalRulerHoveringController.install(fVerticalRuler.getControl());
- AccessorUtil.invoke(fVerticalRulerHoveringController, AbstractInformationControlManager.class, "setInformationControlReplacer", IInformationControlReplacer.class, new StickyHoverManager(this)); //$NON-NLS-1$
+ fVerticalRulerHoveringController.getInternalAccessor().setInformationControlReplacer(new StickyHoverManager(this));
}
}
@@ -453,7 +450,7 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
if (fOverviewRuler != null && fOverviewRulerAnnotationHover != null && fOverviewRulerHoveringController == null && fHoverControlCreator != null) {
fOverviewRulerHoveringController= new OverviewRulerHoverManager(fOverviewRuler, this, fOverviewRulerAnnotationHover, fHoverControlCreator);
fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
- AccessorUtil.invoke(fOverviewRulerHoveringController, AbstractInformationControlManager.class, "setInformationControlReplacer", IInformationControlReplacer.class, new StickyHoverManager(this)); //$NON-NLS-1$
+ fOverviewRulerHoveringController.getInternalAccessor().setInformationControlReplacer(new StickyHoverManager(this));
}
}
@@ -464,9 +461,9 @@ public class SourceViewer extends TextViewer implements ISourceViewer, ISourceVi
public void setHoverEnrichMode(EnrichMode mode) {
super.setHoverEnrichMode(mode);
if (fVerticalRulerHoveringController != null)
- AccessorUtil.invoke(fVerticalRulerHoveringController, AbstractHoverInformationControlManager.class, "setHoverEnrichMode", EnrichMode.class, mode); //$NON-NLS-1$
+ fVerticalRulerHoveringController.getInternalAccessor().setHoverEnrichMode(mode);
if (fOverviewRulerHoveringController != null)
- AccessorUtil.invoke(fOverviewRulerHoveringController, AbstractHoverInformationControlManager.class, "setHoverEnrichMode", EnrichMode.class, mode); //$NON-NLS-1$
+ fOverviewRulerHoveringController.getInternalAccessor().setHoverEnrichMode(mode);
}
/*

Back to the top