diff dwtx/jface/internal/text/link/contentassist/ContentAssistant2.d @ 129:eb30df5ca28b

Added JFace Text sources
author Frank Benoit <benoit@tionex.de>
date Sat, 23 Aug 2008 19:10:48 +0200
parents
children c4fb132a086c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/internal/text/link/contentassist/ContentAssistant2.d	Sat Aug 23 19:10:48 2008 +0200
@@ -0,0 +1,1588 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwtx.jface.internal.text.link.contentassist.ContentAssistant2;
+
+import dwt.dwthelper.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import dwt.DWT;
+import dwt.DWTError;
+import dwt.custom.StyledText;
+import dwt.custom.VerifyKeyListener;
+import dwt.events.ControlEvent;
+import dwt.events.ControlListener;
+import dwt.events.DisposeEvent;
+import dwt.events.DisposeListener;
+import dwt.events.FocusEvent;
+import dwt.events.FocusListener;
+import dwt.events.MouseEvent;
+import dwt.events.MouseListener;
+import dwt.events.VerifyEvent;
+import dwt.graphics.Color;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.widgets.Control;
+import dwt.widgets.Display;
+import dwt.widgets.Event;
+import dwt.widgets.Listener;
+import dwt.widgets.Shell;
+import dwt.widgets.Widget;
+import dwtx.core.runtime.Assert;
+import dwtx.jface.text.BadLocationException;
+import dwtx.jface.text.DefaultInformationControl;
+import dwtx.jface.text.IEventConsumer;
+import dwtx.jface.text.IInformationControl;
+import dwtx.jface.text.IInformationControlCreator;
+import dwtx.jface.text.ITextViewer;
+import dwtx.jface.text.ITextViewerExtension;
+import dwtx.jface.text.IViewportListener;
+import dwtx.jface.text.IWidgetTokenKeeper;
+import dwtx.jface.text.IWidgetTokenKeeperExtension;
+import dwtx.jface.text.IWidgetTokenOwner;
+import dwtx.jface.text.IWidgetTokenOwnerExtension;
+import dwtx.jface.text.TextUtilities;
+import dwtx.jface.text.contentassist.CompletionProposal;
+import dwtx.jface.text.contentassist.ICompletionProposal;
+import dwtx.jface.text.contentassist.ICompletionProposalExtension6;
+import dwtx.jface.text.contentassist.IContentAssistProcessor;
+import dwtx.jface.text.contentassist.IContentAssistant;
+import dwtx.jface.text.contentassist.IContentAssistantExtension;
+import dwtx.jface.text.contentassist.IContextInformation;
+import dwtx.jface.text.contentassist.IContextInformationPresenter;
+import dwtx.jface.text.contentassist.IContextInformationValidator;
+
+
+/**
+ * A custom implementation of the <code>IContentAssistant</code> interface.
+ * This implementation is used by the linked mode UI. This is internal and subject
+ * to change without notice.
+ */
+public class ContentAssistant2 : IContentAssistant, IContentAssistantExtension, IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
+
+    /**
+     * A generic closer class used to monitor various
+     * interface events in order to determine whether
+     * content-assist should be terminated and all
+     * associated windows closed.
+     */
+    class Closer : ControlListener, MouseListener, FocusListener, DisposeListener, IViewportListener {
+
+        /** The shell on which we add listeners. */
+        private Shell fShell;
+        private long fViewportListenerStartTime;
+
+        /**
+         * Installs this closer on it's viewer's text widget.
+         */
+        protected void install() {
+            Control w= fViewer.getTextWidget();
+            if (Helper2.okToUse(w)) {
+
+                Shell shell= w.getShell();
+                fShell= shell;
+                shell.addControlListener(this);
+
+                w.addMouseListener(this);
+                w.addFocusListener(this);
+
+                /*
+                 * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
+                 */
+                w.addDisposeListener(this);
+            }
+
+            fViewer.addViewportListener(this);
+            fViewportListenerStartTime= System.currentTimeMillis() + 500;
+        }
+
+        /**
+         * Uninstalls this closer from the viewer's text widget.
+         */
+        protected void uninstall() {
+            Shell shell= fShell;
+            fShell= null;
+            if (Helper2.okToUse(shell))
+                shell.removeControlListener(this);
+
+            Control w= fViewer.getTextWidget();
+            if (Helper2.okToUse(w)) {
+
+                w.removeMouseListener(this);
+                w.removeFocusListener(this);
+
+                /*
+                 * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
+                 */
+                w.removeDisposeListener(this);
+            }
+
+            fViewer.removeViewportListener(this);
+        }
+
+        /*
+         * @see ControlListener#controlResized(ControlEvent)
+         */
+        public void controlResized(ControlEvent e) {
+            hide();
+        }
+
+        /*
+         * @see ControlListener#controlMoved(ControlEvent)
+         */
+        public void controlMoved(ControlEvent e) {
+            hide();
+        }
+
+        /*
+         * @see MouseListener#mouseDown(MouseEvent)
+         */
+        public void mouseDown(MouseEvent e) {
+            hide();
+        }
+
+        /*
+         * @see MouseListener#mouseUp(MouseEvent)
+         */
+        public void mouseUp(MouseEvent e) {
+        }
+
+        /*
+         * @see MouseListener#mouseDoubleClick(MouseEvent)
+         */
+        public void mouseDoubleClick(MouseEvent e) {
+            hide();
+        }
+
+        /*
+         * @see FocusListener#focusGained(FocusEvent)
+         */
+        public void focusGained(FocusEvent e) {
+        }
+
+        /*
+         * @see FocusListener#focusLost(FocusEvent)
+         */
+        public void focusLost(FocusEvent e) {
+            if (fViewer !is null) {
+                Control control= fViewer.getTextWidget();
+                if (control !is null) {
+                    Display d= control.getDisplay();
+                    if (d !is null) {
+                        d.asyncExec(new Runnable() {
+                            public void run() {
+                                if (!hasFocus())
+                                    hide();
+                            }
+                        });
+                    }
+                }
+            }
+        }
+
+        /*
+         * @seeDisposeListener#widgetDisposed(DisposeEvent)
+         */
+        public void widgetDisposed(DisposeEvent e) {
+            /*
+             * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
+             */
+            hide();
+        }
+
+        /*
+         * @see IViewportListener#viewportChanged(int)
+         */
+        public void viewportChanged(int topIndex) {
+            if (System.currentTimeMillis() > fViewportListenerStartTime)
+                hide();
+        }
+    }
+
+    /**
+     * An implementation of <code>IContentAssistListener</code>, this class is
+     * used to monitor key events in support of automatic activation
+     * of the content assistant. If enabled, the implementation utilizes a
+     * thread to watch for input characters matching the activation
+     * characters specified by the content assist processor, and if
+     * detected, will wait the indicated delay interval before
+     * activating the content assistant.
+     */
+    class AutoAssistListener : VerifyKeyListener, Runnable {
+
+        private Thread fThread;
+        private bool fIsReset= false;
+        private Object fMutex= new Object();
+        private int fShowStyle;
+
+        private final static int SHOW_PROPOSALS= 1;
+        private final static int SHOW_CONTEXT_INFO= 2;
+
+        protected AutoAssistListener() {
+        }
+
+        protected void start(int showStyle) {
+            fShowStyle= showStyle;
+            fThread= new Thread(this, ContentAssistMessages.getString("ContentAssistant.assist_delay_timer_name")); //$NON-NLS-1$
+            fThread.start();
+        }
+
+        public void run() {
+            try {
+                while (true) {
+                    synchronized (fMutex) {
+                        if (fAutoActivationDelay !is 0)
+                            fMutex.wait(fAutoActivationDelay);
+                        if (fIsReset) {
+                            fIsReset= false;
+                            continue;
+                        }
+                    }
+                    showAssist(fShowStyle);
+                    break;
+                }
+            } catch (InterruptedException e) {
+            }
+            fThread= null;
+        }
+
+        protected void reset(int showStyle) {
+            synchronized (fMutex) {
+                fShowStyle= showStyle;
+                fIsReset= true;
+                fMutex.notifyAll();
+            }
+        }
+
+        protected void stop() {
+            Thread threadToStop= fThread;
+            if (threadToStop !is null)
+                threadToStop.interrupt();
+        }
+
+        private bool contains(char[] characters, char character) {
+            if (characters !is null) {
+                for (int i= 0; i < characters.length; i++) {
+                    if (character is characters[i])
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        public void verifyKey(VerifyEvent e) {
+            // Only act on typed characters and ignore modifier-only events
+            if (e.character is 0 && (e.keyCode & DWT.KEYCODE_BIT) is 0)
+                return;
+
+            if (e.character !is 0 && (e.stateMask is DWT.ALT))
+                return;
+
+            int showStyle;
+            int pos= fViewer.getSelectedRange().x;
+            char[] activation= getCompletionProposalAutoActivationCharacters(fViewer, pos);
+
+            if (contains(activation, e.character) && !fProposalPopup.isActive())
+                showStyle= SHOW_PROPOSALS;
+            else {
+                activation= getContextInformationAutoActivationCharacters(fViewer, pos);
+                if (contains(activation, e.character) && !fContextInfoPopup.isActive())
+                    showStyle= SHOW_CONTEXT_INFO;
+                else {
+                    if (fThread !is null && fThread.isAlive())
+                        stop();
+                    return;
+                }
+            }
+
+            if (fThread !is null && fThread.isAlive())
+                reset(showStyle);
+            else
+                start(showStyle);
+        }
+
+        protected void showAssist(final int showStyle) {
+            Control control= fViewer.getTextWidget();
+            Display d= control.getDisplay();
+            if (d !is null) {
+                try {
+                    d.syncExec(new Runnable() {
+                        public void run() {
+                            if (showStyle is SHOW_PROPOSALS)
+                                fProposalPopup.showProposals(true);
+                            else if (showStyle is SHOW_CONTEXT_INFO)
+                                fContextInfoPopup.showContextProposals(true);
+                        }
+                    });
+                } catch (DWTError e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * The layout manager layouts the various
+     * windows associated with the content assistant based on the
+     * settings of the content assistant.
+     */
+    class LayoutManager : Listener {
+
+        // Presentation types.
+        /** proposal selector */
+        public final static int LAYOUT_PROPOSAL_SELECTOR= 0;
+        /** context selector */
+        public final static int LAYOUT_CONTEXT_SELECTOR= 1;
+        /** context info */
+        public final static int LAYOUT_CONTEXT_INFO_POPUP= 2;
+
+        int fContextType= LAYOUT_CONTEXT_SELECTOR;
+        Shell[] fShells= new Shell[3];
+        Object[] fPopups= new Object[3];
+
+        protected void add(Object popup, Shell shell, int type, int offset) {
+            Assert.isNotNull(popup);
+            Assert.isTrue(shell !is null && !shell.isDisposed());
+            checkType(type);
+
+            if (fShells[type] !is shell) {
+                if (fShells[type] !is null)
+                    fShells[type].removeListener(DWT.Dispose, this);
+                shell.addListener(DWT.Dispose, this);
+                fShells[type]= shell;
+            }
+
+            fPopups[type]= popup;
+            if (type is LAYOUT_CONTEXT_SELECTOR || type is LAYOUT_CONTEXT_INFO_POPUP)
+                fContextType= type;
+
+            layout(type, offset);
+            adjustListeners(type);
+        }
+
+        protected void checkType(int type) {
+            Assert.isTrue(type is LAYOUT_PROPOSAL_SELECTOR ||
+                type is LAYOUT_CONTEXT_SELECTOR || type is LAYOUT_CONTEXT_INFO_POPUP);
+        }
+
+        public void handleEvent(Event event) {
+            Widget source= event.widget;
+            source.removeListener(DWT.Dispose, this);
+
+            int type= getShellType(source);
+            checkType(type);
+            fShells[type]= null;
+
+            switch (type) {
+                case LAYOUT_PROPOSAL_SELECTOR:
+                    if (fContextType is LAYOUT_CONTEXT_SELECTOR &&
+                            Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) {
+                        // Restore event notification to the tip popup.
+                        addContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
+                    }
+                    break;
+
+                case LAYOUT_CONTEXT_SELECTOR:
+                    if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
+                        if (fProposalPopupOrientation is PROPOSAL_STACKED)
+                            layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
+                        // Restore event notification to the proposal popup.
+                        addContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
+                    }
+                    fContextType= LAYOUT_CONTEXT_INFO_POPUP;
+                    break;
+
+                case LAYOUT_CONTEXT_INFO_POPUP:
+                    if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
+                        if (fContextInfoPopupOrientation is CONTEXT_INFO_BELOW)
+                            layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
+                    }
+                    fContextType= LAYOUT_CONTEXT_SELECTOR;
+                    break;
+            }
+        }
+
+        protected int getShellType(Widget shell) {
+            for (int i=0; i<fShells.length; i++) {
+                if (fShells[i] is shell)
+                    return i;
+            }
+            return -1;
+        }
+
+        protected void layout(int type, int offset) {
+            switch (type) {
+                case LAYOUT_PROPOSAL_SELECTOR:
+                    layoutProposalSelector(offset);
+                    break;
+                case LAYOUT_CONTEXT_SELECTOR:
+                    layoutContextSelector(offset);
+                    break;
+                case LAYOUT_CONTEXT_INFO_POPUP:
+                    layoutContextInfoPopup(offset);
+                    break;
+            }
+        }
+
+        protected void layoutProposalSelector(int offset) {
+            if (fContextType is LAYOUT_CONTEXT_INFO_POPUP &&
+                    fContextInfoPopupOrientation is CONTEXT_INFO_BELOW &&
+                    Helper2.okToUse(fShells[LAYOUT_CONTEXT_INFO_POPUP])) {
+                // Stack proposal selector beneath the tip box.
+                Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
+                shell.setLocation(getStackedLocation(shell, parent));
+            } else if (fContextType !is LAYOUT_CONTEXT_SELECTOR ||
+                        !Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) {
+                // There are no other presentations to be concerned with,
+                // so place the proposal selector beneath the cursor line.
+                Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                shell.setLocation(getBelowLocation(shell, offset));
+            } else {
+                switch (fProposalPopupOrientation) {
+                    case PROPOSAL_REMOVE: {
+                        // Remove the tip selector and place the
+                        // proposal selector beneath the cursor line.
+                        fShells[LAYOUT_CONTEXT_SELECTOR].dispose();
+                        Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                        shell.setLocation(getBelowLocation(shell, offset));
+                        break;
+                    }
+                    case PROPOSAL_OVERLAY: {
+                        // Overlay the tip selector with the proposal selector.
+                        Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                        shell.setLocation(getBelowLocation(shell, offset));
+                        break;
+                    }
+                    case PROPOSAL_STACKED: {
+                        // Stack the proposal selector beneath the tip selector.
+                        Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                        Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
+                        shell.setLocation(getStackedLocation(shell, parent));
+                        break;
+                    }
+                }
+            }
+        }
+
+        protected void layoutContextSelector(int offset) {
+            // Always place the context selector beneath the cursor line.
+            Shell shell= fShells[LAYOUT_CONTEXT_SELECTOR];
+            shell.setLocation(getBelowLocation(shell, offset));
+
+            if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
+                switch (fProposalPopupOrientation) {
+                    case PROPOSAL_REMOVE:
+                        // Remove the proposal selector.
+                        fShells[LAYOUT_PROPOSAL_SELECTOR].dispose();
+                        break;
+
+                    case PROPOSAL_OVERLAY:
+                        // The proposal selector has been overlaid by the tip selector.
+                        break;
+
+                    case PROPOSAL_STACKED: {
+                        // Stack the proposal selector beneath the tip selector.
+                        shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                        Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
+                        shell.setLocation(getStackedLocation(shell, parent));
+                        break;
+                    }
+                }
+            }
+        }
+
+        protected void layoutContextInfoPopup(int offset) {
+            switch (fContextInfoPopupOrientation) {
+                case CONTEXT_INFO_ABOVE: {
+                    // Place the popup above the cursor line.
+                    Shell shell= fShells[LAYOUT_CONTEXT_INFO_POPUP];
+                    shell.setLocation(getAboveLocation(shell, offset));
+                    break;
+                }
+                case CONTEXT_INFO_BELOW: {
+                    // Place the popup beneath the cursor line.
+                    Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
+                    parent.setLocation(getBelowLocation(parent, offset));
+                    if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
+                        // Stack the proposal selector beneath the context info popup.
+                        Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
+                        shell.setLocation(getStackedLocation(shell, parent));
+                    }
+                    break;
+                }
+            }
+        }
+
+        protected void shiftHorizontalLocation(Point location, Rectangle shellBounds, Rectangle displayBounds) {
+            if (location.x + shellBounds.width > displayBounds.width)
+                location.x= displayBounds.width - shellBounds.width;
+
+            if (location.x < displayBounds.x)
+                location.x= displayBounds.x;
+        }
+
+        protected void shiftVerticalLocation(Point location, Rectangle shellBounds, Rectangle displayBounds) {
+            if (location.y + shellBounds.height > displayBounds.height)
+                location.y= displayBounds.height - shellBounds.height;
+
+            if (location.y < displayBounds.y)
+                location.y= displayBounds.y;
+        }
+
+        protected Point getAboveLocation(Shell shell, int offset) {
+            StyledText text= fViewer.getTextWidget();
+            Point location= text.getLocationAtOffset(offset);
+            location= text.toDisplay(location);
+
+            Rectangle shellBounds= shell.getBounds();
+            Rectangle displayBounds= shell.getDisplay().getClientArea();
+
+            location.y=location.y - shellBounds.height;
+
+            shiftHorizontalLocation(location, shellBounds, displayBounds);
+            shiftVerticalLocation(location, shellBounds, displayBounds);
+
+            return location;
+        }
+
+        protected Point getBelowLocation(Shell shell, int offset) {
+            StyledText text= fViewer.getTextWidget();
+            Point location= text.getLocationAtOffset(offset);
+            if (location.x < 0) location.x= 0;
+            if (location.y < 0) location.y= 0;
+            location= text.toDisplay(location);
+
+            Rectangle shellBounds= shell.getBounds();
+            Rectangle displayBounds= shell.getDisplay().getClientArea();
+
+            location.y= location.y + text.getLineHeight(offset);
+            shiftHorizontalLocation(location, shellBounds, displayBounds);
+            shiftVerticalLocation(location, shellBounds, displayBounds);
+
+            return location;
+        }
+
+        protected Point getStackedLocation(Shell shell, Shell parent) {
+            Point p= parent.getLocation();
+            Point size= parent.getSize();
+            p.x += size.x / 4;
+            p.y += size.y;
+
+            p= parent.toDisplay(p);
+
+            Rectangle shellBounds= shell.getBounds();
+            Rectangle displayBounds= shell.getDisplay().getClientArea();
+            shiftHorizontalLocation(p, shellBounds, displayBounds);
+            shiftVerticalLocation(p, shellBounds, displayBounds);
+
+            return p;
+        }
+
+        protected void adjustListeners(int type) {
+            switch (type) {
+                case LAYOUT_PROPOSAL_SELECTOR:
+                    if (fContextType is LAYOUT_CONTEXT_SELECTOR &&
+                            Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR]))
+                        // Disable event notification to the tip selector.
+                        removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
+                    break;
+                case LAYOUT_CONTEXT_SELECTOR:
+                    if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR]))
+                        // Disable event notification to the proposal selector.
+                        removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
+                    break;
+                case LAYOUT_CONTEXT_INFO_POPUP:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Internal key listener and event consumer.
+     */
+    class InternalListener : VerifyKeyListener, IEventConsumer {
+
+        /**
+         * Verifies key events by notifying the registered listeners.
+         * Each listener is allowed to indicate that the event has been
+         * handled and should not be further processed.
+         *
+         * @param e the verify event
+         * @see VerifyKeyListener#verifyKey(dwt.events.VerifyEvent)
+         */
+        public void verifyKey(VerifyEvent e) {
+            IContentAssistListener2[] listeners= (IContentAssistListener2[]) fListeners.clone();
+            for (int i= 0; i < listeners.length; i++) {
+                if (listeners[i] !is null) {
+                    if (!listeners[i].verifyKey(e) || !e.doit)
+                        return;
+                }
+            }
+        }
+
+        /*
+         * @see IEventConsumer#processEvent
+         */
+        public void processEvent(VerifyEvent event) {
+
+            installKeyListener();
+
+            IContentAssistListener2[] listeners= (IContentAssistListener2[])fListeners.clone();
+            for (int i= 0; i < listeners.length; i++) {
+                if (listeners[i] !is null) {
+                    listeners[i].processEvent(event);
+                    if (!event.doit)
+                        return;
+                }
+            }
+        }
+    }
+
+
+    // Content-Assist Listener types
+    final static int CONTEXT_SELECTOR= 0;
+    final static int PROPOSAL_SELECTOR= 1;
+    final static int CONTEXT_INFO_POPUP= 2;
+
+    /**
+     * The popup priority: &gt; info pop-ups, &lt; standard content assist.
+     * Default value: <code>10</code>.
+     *
+     * @since 3.0
+     */
+    public static final int WIDGET_PRIORITY= 10;
+
+
+    private static final int DEFAULT_AUTO_ACTIVATION_DELAY= 500;
+
+    private IInformationControlCreator fInformationControlCreator;
+    private int fAutoActivationDelay= DEFAULT_AUTO_ACTIVATION_DELAY;
+    private bool fIsAutoActivated= false;
+    private bool fIsAutoInserting= false;
+    private int fProposalPopupOrientation= PROPOSAL_OVERLAY;
+    private int fContextInfoPopupOrientation= CONTEXT_INFO_ABOVE;
+    private Map fProcessors;
+    private String fPartitioning;
+
+    private Color fContextInfoPopupBackground;
+    private Color fContextInfoPopupForeground;
+    private Color fContextSelectorBackground;
+    private Color fContextSelectorForeground;
+
+    private ITextViewer fViewer;
+    private String fLastErrorMessage;
+
+    private Closer fCloser;
+    private LayoutManager fLayoutManager;
+    private AutoAssistListener fAutoAssistListener;
+    private InternalListener fInternalListener;
+    private CompletionProposalPopup2 fProposalPopup;
+    private ContextInformationPopup2 fContextInfoPopup;
+
+    private bool fKeyListenerHooked= false;
+    private IContentAssistListener2[] fListeners= new IContentAssistListener2[4];
+    private int fCompletionPosition;
+    private String[] fProposalStrings;
+    private ICompletionProposal[] fProposals;
+    private final List fProposalListeners= new ArrayList();
+    
+    /**
+     * Tells whether colored label support is enabled.
+     * @since 3.4
+     */
+    private bool fIsColoredLabelsSupportEnabled= false;
+    
+
+    /**
+     * Creates a new content assistant. The content assistant is not automatically activated,
+     * overlays the completion proposals with context information list if necessary, and
+     * shows the context information above the location at which it was activated. If auto
+     * activation will be enabled, without further configuration steps, this content assistant
+     * is activated after a 500 ms delay. It uses the default partitioning.
+     */
+    public ContentAssistant2() {
+        setContextInformationPopupOrientation(CONTEXT_INFO_ABOVE);
+        setInformationControlCreator(getInformationControlCreator());
+
+//      JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
+//      IColorManager manager= textTools.getColorManager();
+//
+//      IPreferenceStore store=  JavaPlugin.getDefault().getPreferenceStore();
+//
+//      Color c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, manager);
+//      setProposalSelectorForeground(c);
+//
+//      c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, manager);
+//      setProposalSelectorBackground(c);
+    }
+
+    /**
+     * Creates an <code>IInformationControlCreator</code> to be used to display context information.
+     *
+     * @return an <code>IInformationControlCreator</code> to be used to display context information
+     */
+    private IInformationControlCreator getInformationControlCreator() {
+        return new IInformationControlCreator() {
+            public IInformationControl createInformationControl(Shell parent) {
+                return new DefaultInformationControl(parent, false);
+            }
+        };
+    }
+
+    /**
+     * Sets the document partitioning this content assistant is using.
+     *
+     * @param partitioning the document partitioning for this content assistant
+     */
+    public void setDocumentPartitioning(String partitioning) {
+        Assert.isNotNull(partitioning);
+        fPartitioning= partitioning;
+    }
+
+    /*
+     * @see dwtx.jface.text.contentassist.IContentAssistantExtension#getDocumentPartitioning()
+     * @since 3.0
+     */
+    public String getDocumentPartitioning() {
+        return fPartitioning;
+    }
+
+    /**
+     * Registers a given content assist processor for a particular content type.
+     * If there is already a processor registered for this type, the new processor
+     * is registered instead of the old one.
+     *
+     * @param processor the content assist processor to register, or <code>null</code> to remove an existing one
+     * @param contentType the content type under which to register
+     */
+     public void setContentAssistProcessor(IContentAssistProcessor processor, String contentType) {
+
+        Assert.isNotNull(contentType);
+
+        if (fProcessors is null)
+            fProcessors= new HashMap();
+
+        if (processor is null)
+            fProcessors.remove(contentType);
+        else
+            fProcessors.put(contentType, processor);
+    }
+
+    /*
+     * @see IContentAssistant#getContentAssistProcessor
+     */
+    public IContentAssistProcessor getContentAssistProcessor(String contentType) {
+        if (fProcessors is null)
+            return null;
+
+        return (IContentAssistProcessor) fProcessors.get(contentType);
+    }
+
+    /**
+     * Enables the content assistant's auto activation mode.
+     *
+     * @param enabled indicates whether auto activation is enabled or not
+     */
+    public void enableAutoActivation(bool enabled) {
+        fIsAutoActivated= enabled;
+        manageAutoActivation(fIsAutoActivated);
+    }
+
+    /**
+     * Enables the content assistant's auto insertion mode. If enabled,
+     * the content assistant inserts a proposal automatically if it is
+     * the only proposal. In the case of ambiguities, the user must
+     * make the choice.
+     *
+     * @param enabled indicates whether auto insertion is enabled or not
+     * @since 2.0
+     */
+    public void enableAutoInsert(bool enabled) {
+        fIsAutoInserting= enabled;
+    }
+
+    /**
+     * Returns whether this content assistant is in the auto insertion
+     * mode or not.
+     *
+     * @return <code>true</code> if in auto insertion mode
+     * @since 2.0
+     */
+    bool isAutoInserting() {
+        return fIsAutoInserting;
+    }
+
+    /**
+     * Installs and uninstall the listeners needed for auto-activation.
+     * @param start <code>true</code> if listeners must be installed,
+     *  <code>false</code> if they must be removed
+     * @since 2.0
+     */
+    private void manageAutoActivation(bool start) {
+        if (start) {
+
+            if (fViewer !is null && fAutoAssistListener is null) {
+                fAutoAssistListener= new AutoAssistListener();
+                if (fViewer instanceof ITextViewerExtension) {
+                    ITextViewerExtension extension= (ITextViewerExtension) fViewer;
+                    extension.appendVerifyKeyListener(fAutoAssistListener);
+                } else {
+                    StyledText textWidget= fViewer.getTextWidget();
+                    if (Helper2.okToUse(textWidget))
+                        textWidget.addVerifyKeyListener(fAutoAssistListener);
+                }
+            }
+
+        } else if (fAutoAssistListener !is null) {
+
+            if (fViewer instanceof ITextViewerExtension) {
+                ITextViewerExtension extension= (ITextViewerExtension) fViewer;
+                extension.removeVerifyKeyListener(fAutoAssistListener);
+            } else {
+                StyledText textWidget= fViewer.getTextWidget();
+                if (Helper2.okToUse(textWidget))
+                    textWidget.removeVerifyKeyListener(fAutoAssistListener);
+            }
+
+            fAutoAssistListener= null;
+        }
+    }
+
+    /**
+     * Sets the delay after which the content assistant is automatically invoked
+     * if the cursor is behind an auto activation character.
+     *
+     * @param delay the auto activation delay
+     */
+    public void setAutoActivationDelay(int delay) {
+        fAutoActivationDelay= delay;
+    }
+
+    /**
+     * Sets the proposal pop-ups' orientation.
+     * The following values may be used:
+     * <ul>
+     *   <li>PROPOSAL_OVERLAY<p>
+     *     proposal popup windows should overlay each other
+     *   </li>
+     *   <li>PROPOSAL_REMOVE<p>
+     *     any currently shown proposal popup should be closed
+     *   </li>
+     *   <li>PROPOSAL_STACKED<p>
+     *     proposal popup windows should be vertical stacked, with no overlap,
+     *     beneath the line containing the current cursor location
+     *   </li>
+     * </ul>
+     *
+     * @param orientation the popup's orientation
+     */
+    public void setProposalPopupOrientation(int orientation) {
+        fProposalPopupOrientation= orientation;
+    }
+
+    /**
+     * Sets the context information popup's orientation.
+     * The following values may be used:
+     * <ul>
+     *   <li>CONTEXT_ABOVE<p>
+     *     context information popup should always appear above the line containing
+     *     the current cursor location
+     *   </li>
+     *   <li>CONTEXT_BELOW<p>
+     *     context information popup should always appear below the line containing
+     *     the current cursor location
+     *   </li>
+     * </ul>
+     *
+     * @param orientation the popup's orientation
+     */
+    public void setContextInformationPopupOrientation(int orientation) {
+        fContextInfoPopupOrientation= orientation;
+    }
+
+    /**
+     * Sets the context information popup's background color.
+     *
+     * @param background the background color
+     */
+    public void setContextInformationPopupBackground(Color background) {
+        fContextInfoPopupBackground= background;
+    }
+
+    /**
+     * Returns the background of the context information popup.
+     *
+     * @return the background of the context information popup
+     * @since 2.0
+     */
+    Color getContextInformationPopupBackground() {
+        return fContextInfoPopupBackground;
+    }
+
+    /**
+     * Sets the context information popup's foreground color.
+     *
+     * @param foreground the foreground color
+     * @since 2.0
+     */
+    public void setContextInformationPopupForeground(Color foreground) {
+        fContextInfoPopupForeground= foreground;
+    }
+
+    /**
+     * Returns the foreground of the context information popup.
+     *
+     * @return the foreground of the context information popup
+     * @since 2.0
+     */
+    Color getContextInformationPopupForeground() {
+        return fContextInfoPopupForeground;
+    }
+
+    /**
+     * Sets the context selector's background color.
+     *
+     * @param background the background color
+     * @since 2.0
+     */
+    public void setContextSelectorBackground(Color background) {
+        fContextSelectorBackground= background;
+    }
+
+    /**
+     * Returns the background of the context selector.
+     *
+     * @return the background of the context selector
+     * @since 2.0
+     */
+    Color getContextSelectorBackground() {
+        return fContextSelectorBackground;
+    }
+
+    /**
+     * Sets the context selector's foreground color.
+     *
+     * @param foreground the foreground color
+     * @since 2.0
+     */
+    public void setContextSelectorForeground(Color foreground) {
+        fContextSelectorForeground= foreground;
+    }
+
+    /**
+     * Returns the foreground of the context selector.
+     *
+     * @return the foreground of the context selector
+     * @since 2.0
+     */
+    Color getContextSelectorForeground() {
+        return fContextSelectorForeground;
+    }
+
+    /**
+     * Sets the information control creator for the additional information control.
+     *
+     * @param creator the information control creator for the additional information control
+     * @since 2.0
+     */
+    public void setInformationControlCreator(IInformationControlCreator creator) {
+        fInformationControlCreator= creator;
+    }
+
+    /*
+     * @see IContentAssist#install
+     */
+    public void install(ITextViewer textViewer) {
+        Assert.isNotNull(textViewer);
+
+        fViewer= textViewer;
+
+        fLayoutManager= new LayoutManager();
+        fInternalListener= new InternalListener();
+
+        AdditionalInfoController2 controller= null;
+        if (fInformationControlCreator !is null) {
+            int delay= fAutoActivationDelay;
+            if (delay is 0)
+                delay= DEFAULT_AUTO_ACTIVATION_DELAY;
+            delay= Math.round(delay * 1.5f);
+            controller= new AdditionalInfoController2(fInformationControlCreator, delay);
+        }
+        fContextInfoPopup= new ContextInformationPopup2(this, fViewer);
+        fProposalPopup= new CompletionProposalPopup2(this, fViewer, controller);
+
+        manageAutoActivation(fIsAutoActivated);
+    }
+
+    /*
+     * @see IContentAssist#uninstall
+     */
+    public void uninstall() {
+
+        if (fProposalPopup !is null)
+            fProposalPopup.hide();
+
+        if (fContextInfoPopup !is null)
+            fContextInfoPopup.hide();
+
+        manageAutoActivation(false);
+
+        if (fCloser !is null) {
+            fCloser.uninstall();
+            fCloser= null;
+        }
+
+        fViewer= null;
+    }
+
+    /**
+     * Adds the given shell of the specified type to the layout.
+     * Valid types are defined by <code>LayoutManager</code>.
+     *
+     * @param popup a content assist popup
+     * @param shell the shell of the content-assist popup
+     * @param type the type of popup
+     * @param visibleOffset the offset at which to layout the popup relative to the offset of the viewer's visible region
+     * @since 2.0
+     */
+    void addToLayout(Object popup, Shell shell, int type, int visibleOffset) {
+        fLayoutManager.add(popup, shell, type, visibleOffset);
+    }
+
+    /**
+     * Layouts the registered popup of the given type relative to the
+     * given offset. The offset is relative to the offset of the viewer's visible region.
+     * Valid types are defined by <code>LayoutManager</code>.
+     *
+     * @param type the type of popup to layout
+     * @param visibleOffset the offset at which to layout relative to the offset of the viewer's visible region
+     * @since 2.0
+     */
+    void layout(int type, int visibleOffset) {
+        fLayoutManager.layout(type, visibleOffset);
+    }
+
+    /**
+     * Notifies the controller that a popup has lost focus.
+     *
+     * @param e the focus event
+     */
+    void popupFocusLost(FocusEvent e) {
+        fCloser.focusLost(e);
+    }
+
+    /**
+     * Returns the offset of the selection relative to the offset of the visible region.
+     *
+     * @return the offset of the selection relative to the offset of the visible region
+     * @since 2.0
+     */
+    int getSelectionOffset() {
+        StyledText text= fViewer.getTextWidget();
+        return text.getSelectionRange().x;
+    }
+
+    /**
+     * Returns whether the widget token could be acquired.
+     * The following are valid listener types:
+     * <ul>
+     *   <li>AUTO_ASSIST
+     *   <li>CONTEXT_SELECTOR
+     *   <li>PROPOSAL_SELECTOR
+     *   <li>CONTEXT_INFO_POPUP
+     * <ul>
+     * @param type the listener type for which to acquire
+     * @return <code>true</code> if the widget token could be acquired
+     * @since 2.0
+     */
+    private bool acquireWidgetToken(int type) {
+        switch (type) {
+            case CONTEXT_SELECTOR:
+            case PROPOSAL_SELECTOR:
+                if (fViewer instanceof IWidgetTokenOwner) {
+                    IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer;
+                    return owner.requestWidgetToken(this);
+                } else if (fViewer instanceof IWidgetTokenOwnerExtension)  {
+                    IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fViewer;
+                    return extension.requestWidgetToken(this, WIDGET_PRIORITY);
+                }
+        }
+        return true;
+    }
+
+    /**
+     * Registers a content assist listener.
+     * The following are valid listener types:
+     * <ul>
+     *   <li>AUTO_ASSIST
+     *   <li>CONTEXT_SELECTOR
+     *   <li>PROPOSAL_SELECTOR
+     *   <li>CONTEXT_INFO_POPUP
+     * <ul>
+     * Returns whether the listener could be added successfully. A listener
+     * can not be added if the widget token could not be acquired.
+     *
+     * @param listener the listener to register
+     * @param type the type of listener
+     * @return <code>true</code> if the listener could be added
+     */
+    bool addContentAssistListener(IContentAssistListener2 listener, int type) {
+
+        if (acquireWidgetToken(type)) {
+
+            fListeners[type]= listener;
+
+            if (getNumberOfListeners() is 1) {
+                fCloser= new Closer();
+                fCloser.install();
+                fViewer.setEventConsumer(fInternalListener);
+                installKeyListener();
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Installs a key listener on the text viewer's widget.
+     */
+    private void installKeyListener() {
+        if (!fKeyListenerHooked) {
+            StyledText text= fViewer.getTextWidget();
+            if (Helper2.okToUse(text)) {
+
+                if (fViewer instanceof ITextViewerExtension) {
+                    ITextViewerExtension e= (ITextViewerExtension) fViewer;
+                    e.prependVerifyKeyListener(fInternalListener);
+                } else {
+                    text.addVerifyKeyListener(fInternalListener);
+                }
+
+                fKeyListenerHooked= true;
+            }
+        }
+    }
+
+    /**
+     * Releases the previously acquired widget token if the token
+     * is no longer necessary.
+     * The following are valid listener types:
+     * <ul>
+     *   <li>AUTO_ASSIST
+     *   <li>CONTEXT_SELECTOR
+     *   <li>PROPOSAL_SELECTOR
+     *   <li>CONTEXT_INFO_POPUP
+     * <ul>
+     *
+     * @param type the listener type
+     * @since 2.0
+     */
+    private void releaseWidgetToken(int type) {
+        if (fListeners[CONTEXT_SELECTOR] is null && fListeners[PROPOSAL_SELECTOR] is null) {
+            if (fViewer instanceof IWidgetTokenOwner) {
+                IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer;
+                owner.releaseWidgetToken(this);
+            }
+        }
+    }
+
+    /**
+     * Unregisters a content assist listener.
+     *
+     * @param listener the listener to unregister
+     * @param type the type of listener
+     *
+     * @see #addContentAssistListener
+     */
+    void removeContentAssistListener(IContentAssistListener2 listener, int type) {
+        fListeners[type]= null;
+
+        if (getNumberOfListeners() is 0) {
+
+            if (fCloser !is null) {
+                fCloser.uninstall();
+                fCloser= null;
+            }
+
+            uninstallKeyListener();
+            fViewer.setEventConsumer(null);
+        }
+
+        releaseWidgetToken(type);
+    }
+
+    /**
+     * Uninstall the key listener from the text viewer's widget.
+     */
+    private void uninstallKeyListener() {
+        if (fKeyListenerHooked) {
+            StyledText text= fViewer.getTextWidget();
+            if (Helper2.okToUse(text)) {
+
+                if (fViewer instanceof ITextViewerExtension) {
+                    ITextViewerExtension e= (ITextViewerExtension) fViewer;
+                    e.removeVerifyKeyListener(fInternalListener);
+                } else {
+                    text.removeVerifyKeyListener(fInternalListener);
+                }
+
+                fKeyListenerHooked= false;
+            }
+        }
+    }
+
+    /**
+     * Returns the number of listeners.
+     *
+     * @return the number of listeners
+     * @since 2.0
+     */
+    private int getNumberOfListeners() {
+        int count= 0;
+        for (int i= 0; i <= CONTEXT_INFO_POPUP; i++) {
+            if (fListeners[i] !is null)
+                ++ count;
+        }
+        return count;
+    }
+
+    /*
+     * @see IContentAssist#showPossibleCompletions
+     */
+    public String showPossibleCompletions() {
+        return fProposalPopup.showProposals(false);
+    }
+
+    /**
+     * Hides the proposal popup.
+     */
+    public void hidePossibleCompletions() {
+        if (fProposalPopup !is null)
+            fProposalPopup.hide();
+    }
+
+    /**
+     * Hides any open pop-ups.
+     */
+    protected void hide() {
+        if (fProposalPopup !is null)
+            fProposalPopup.hide();
+        if (fContextInfoPopup !is null)
+            fContextInfoPopup.hide();
+    }
+
+    /**
+     * Callback to signal this content assistant that the presentation of the possible completions has been stopped.
+     * @since 2.1
+     */
+    protected void possibleCompletionsClosed() {
+    }
+
+    /*
+     * @see IContentAssist#showContextInformation
+     */
+    public String showContextInformation() {
+        return fContextInfoPopup.showContextProposals(false);
+    }
+
+
+    /**
+     * Callback to signal this content assistant that the presentation of the context information has been stopped.
+     * @since 2.1
+     */
+    protected void contextInformationClosed() {
+    }
+
+    /**
+     * Requests that the specified context information to be shown.
+     *
+     * @param contextInformation the context information to be shown
+     * @param position the position to which the context information refers to
+     * @since 2.0
+     */
+    void showContextInformation(IContextInformation contextInformation, int position) {
+        fContextInfoPopup.showContextInformation(contextInformation, position);
+    }
+
+    /**
+     * Returns the current content assist error message.
+     *
+     * @return an error message or <code>null</code> if no error has occurred
+     */
+    String getErrorMessage() {
+        return fLastErrorMessage;
+    }
+
+    /**
+     * Returns the content assist processor for the content
+     * type of the specified document position.
+     *
+     * @param viewer the text viewer
+     * @param offset a offset within the document
+     * @return a content-assist processor or <code>null</code> if none exists
+     */
+    private IContentAssistProcessor getProcessor(ITextViewer viewer, int offset) {
+        try {
+            String type= TextUtilities.getContentType(viewer.getDocument(), getDocumentPartitioning(), offset, true);
+            return getContentAssistProcessor(type);
+        } catch (BadLocationException x) {
+        }
+        return null;
+    }
+
+    /**
+     * Returns an array of completion proposals computed based on
+     * the specified document position. The position is used to
+     * determine the appropriate content assist processor to invoke.
+     *
+     * @param viewer the viewer for which to compute the proposals
+     * @param position a document position
+     * @return an array of completion proposals
+     *
+     * @see IContentAssistProcessor#computeCompletionProposals
+     */
+    ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int position) {
+        if (fProposals !is null) {
+            return fProposals;
+        } else if (fProposalStrings !is null) {
+            ICompletionProposal[] result= new ICompletionProposal[fProposalStrings.length];
+            for (int i= 0; i < fProposalStrings.length; i++) {
+                result[i]= new CompletionProposal(fProposalStrings[i], position, fProposalStrings[i].length(), fProposalStrings[i].length());
+            }
+            return result;
+        } else return null;
+    }
+
+    /**
+     * Returns an array of context information objects computed based
+     * on the specified document position. The position is used to determine
+     * the appropriate content assist processor to invoke.
+     *
+     * @param viewer the viewer for which to compute the context information
+     * @param position a document position
+     * @return an array of context information objects
+     *
+     * @see IContentAssistProcessor#computeContextInformation
+     */
+    IContextInformation[] computeContextInformation(ITextViewer viewer, int position) {
+        fLastErrorMessage= null;
+
+        IContextInformation[] result= null;
+
+        IContentAssistProcessor p= getProcessor(viewer, position);
+        if (p !is null) {
+            result= p.computeContextInformation(viewer, position);
+            fLastErrorMessage= p.getErrorMessage();
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns the context information validator that should be used to
+     * determine when the currently displayed context information should
+     * be dismissed. The position is used to determine the appropriate
+     * content assist processor to invoke.
+     *
+     * @param textViewer the text viewer
+     * @param offset a document offset
+     * @return an validator
+     *
+     * @see IContentAssistProcessor#getContextInformationValidator
+     */
+    IContextInformationValidator getContextInformationValidator(ITextViewer textViewer, int offset) {
+        IContentAssistProcessor p= getProcessor(textViewer, offset);
+        return p !is null ? p.getContextInformationValidator() : null;
+    }
+
+    /**
+     * Returns the context information presenter that should be used to
+     * display context information. The position is used to determine the appropriate
+     * content assist processor to invoke.
+     *
+     * @param textViewer the text viewer
+     * @param offset a document offset
+     * @return a presenter
+     * @since 2.0
+     */
+    IContextInformationPresenter getContextInformationPresenter(ITextViewer textViewer, int offset) {
+        IContextInformationValidator validator= getContextInformationValidator(textViewer, offset);
+        if (validator instanceof IContextInformationPresenter)
+            return (IContextInformationPresenter) validator;
+        return null;
+    }
+
+    /**
+     * Returns the characters which when typed by the user should automatically
+     * initiate proposing completions. The position is used to determine the
+     * appropriate content assist processor to invoke.
+     *
+     * @param textViewer the text viewer
+     * @param offset a document offset
+     * @return the auto activation characters
+     *
+     * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters
+     */
+    private char[] getCompletionProposalAutoActivationCharacters(ITextViewer textViewer, int offset) {
+        IContentAssistProcessor p= getProcessor(textViewer, offset);
+        return p !is null ? p.getCompletionProposalAutoActivationCharacters() : null;
+    }
+
+    /**
+     * Returns the characters which when typed by the user should automatically
+     * initiate the presentation of context information. The position is used
+     * to determine the appropriate content assist processor to invoke.
+     *
+     * @param textViewer the text viewer
+     * @param offset a document offset
+     * @return the auto activation characters
+     *
+     * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters
+     */
+    private char[] getContextInformationAutoActivationCharacters(ITextViewer textViewer, int offset) {
+        IContentAssistProcessor p= getProcessor(textViewer, offset);
+        return p !is null ? p.getContextInformationAutoActivationCharacters() : null;
+    }
+
+    /*
+     * @see dwtx.jface.text.IWidgetTokenKeeper#requestWidgetToken(IWidgetTokenOwner)
+     * @since 2.0
+     */
+    public bool requestWidgetToken(IWidgetTokenOwner owner) {
+        hidePossibleCompletions();
+        return true;
+    }
+
+    /**
+     * @param completionPosition
+     */
+    public void setCompletionPosition(int completionPosition) {
+        fCompletionPosition= completionPosition;
+    }
+
+    /**
+     * @return the completion position
+     */
+    public int getCompletionPosition() {
+        return fCompletionPosition;
+    }
+
+    /**
+     * @param proposals
+     */
+    public void setCompletions(String[] proposals) {
+        fProposalStrings= proposals;
+    }
+
+    /**
+     * @param proposals
+     */
+    public void setCompletions(ICompletionProposal[] proposals) {
+        fProposals= proposals;
+    }
+
+    /*
+     * @see dwtx.jface.text.IWidgetTokenKeeperExtension#requestWidgetToken(dwtx.jface.text.IWidgetTokenOwner, int)
+     * @since 3.0
+     */
+    public bool requestWidgetToken(IWidgetTokenOwner owner, int priority) {
+        if (priority > WIDGET_PRIORITY) {
+            hidePossibleCompletions();
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * @see dwtx.jface.text.IWidgetTokenKeeperExtension#setFocus(dwtx.jface.text.IWidgetTokenOwner)
+     * @since 3.0
+     */
+    public bool setFocus(IWidgetTokenOwner owner) {
+        if (fProposalPopup !is null) {
+            fProposalPopup.setFocus();
+            return fProposalPopup.hasFocus();
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether any popups controlled by the receiver have the input focus.
+     *
+     * @return <code>true</code> if any of the managed popups have the focus, <code>false</code> otherwise
+     */
+    public bool hasFocus() {
+        return (fProposalPopup !is null && fProposalPopup.hasFocus())
+                || (fContextInfoPopup !is null && fContextInfoPopup.hasFocus());
+    }
+
+    /*
+     * @see dwtx.jface.text.contentassist.IContentAssistantExtension#completePrefix()
+     */
+    public String completePrefix() {
+        return null;
+    }
+
+    /**
+     * @param proposal
+     */
+    public void fireProposalChosen(ICompletionProposal proposal) {
+        List list= new ArrayList(fProposalListeners);
+        for (Iterator it= list.iterator(); it.hasNext();) {
+            IProposalListener listener= (IProposalListener) it.next();
+            listener.proposalChosen(proposal);
+        }
+
+    }
+
+    /**
+     * @param listener
+     */
+    public void removeProposalListener(IProposalListener listener) {
+        fProposalListeners.remove(listener);
+    }
+
+    /**
+     * @param listener
+     */
+    public void addProposalListener(IProposalListener listener) {
+        fProposalListeners.add(listener);
+    }
+    
+    /**
+     * Tells whether the support for colored labels is enabled.
+     * 
+     * @return <code>true</code> if the support for colored labels is enabled, <code>false</code> otherwise
+     * @since 3.4
+     */
+    bool isColoredLabelsSupportEnabled() {
+        return fIsColoredLabelsSupportEnabled;
+    }
+
+    /**
+     * Enables the support for colored labels in the proposal popup.
+     * <p>Completion proposals can implement {@link ICompletionProposalExtension6}
+     * to provide colored proposal labels.</p>
+     * 
+     * @param isEnabled if <code>true</code> the support for colored labels is enabled in the proposal popup
+     * @since 3.4
+     */
+    public void enableColoredLabels(bool isEnabled) {
+        fIsColoredLabelsSupportEnabled= isEnabled;
+    }
+}
+