com.cubrid.common.ui.query.control.jface.contentassist.AbstractControlContentAssistSubjectAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.cubrid.common.ui.query.control.jface.contentassist.AbstractControlContentAssistSubjectAdapter.java

Source

/*******************************************************************************
 * 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
 *******************************************************************************/
package com.cubrid.common.ui.query.control.jface.contentassist;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;

import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;

import org.eclipse.jface.text.IEventConsumer;

/**
 * An <code>AbstractControlContentAssistSubjectAdapter</code> delegates assistance requests from a
 * {@linkplain org.eclipse.jface.text.contentassist.ContentAssistant content assistant}
 * to a <code>Control</code>.
 *
 * A visual feedback can be configured via {@link #setContentAssistCueProvider(ILabelProvider)}.
 *
 * @since 3.0
 * @deprecated As of 3.2, replaced by Platform UI's field assist support
 */
public abstract class AbstractControlContentAssistSubjectAdapter implements IContentAssistSubjectControl {

    protected static final boolean DEBUG = "true" //$NON-NLS-1$
            .equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jface.text/debug/ContentAssistSubjectAdapters")); //$NON-NLS-1$

    /**
     * VerifyKeyListeners for the control.
     */
    private List fVerifyKeyListeners;
    /**
     * KeyListeners for the control.
     */
    private Set fKeyListeners;
    /**
     * The Listener installed on the control which passes events to
     * {@link #fVerifyKeyListeners fVerifyKeyListeners} and {@link #fKeyListeners}.
     */
    private Listener fControlListener;
    /**
     * The cue label provider, or <code>null</code> iff none.
     * @since 3.3
     */
    private ILabelProvider fCueLabelProvider;
    /**
     * The control decoration, or <code>null</code> iff fCueLabelProvider is null.
     * @since 3.3
     */
    private ControlDecoration fControlDecoration;
    /**
     * The default cue image, or <code>null</code> if not cached yet.
     * @since 3.3
     */
    private Image fCachedDefaultCueImage;

    /**
     * Creates a new {@link AbstractControlContentAssistSubjectAdapter}.
     */
    public AbstractControlContentAssistSubjectAdapter() {
        fVerifyKeyListeners = new ArrayList(1);
        fKeyListeners = new HashSet(1);
    }

    /*
     * @see org.eclipse.jface.text.contentassist.IContentAssistSubjectControl#getControl()
     */
    public abstract Control getControl();

    /*
     * @see org.eclipse.jface.text.contentassist.IContentAssistSubjectControl#addKeyListener(org.eclipse.swt.events.KeyListener)
     */
    public void addKeyListener(KeyListener keyListener) {
        fKeyListeners.add(keyListener);

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#addKeyListener()"); //$NON-NLS-1$

        installControlListener();
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#removeKeyListener(org.eclipse.swt.events.KeyListener)
     */
    public void removeKeyListener(KeyListener keyListener) {
        boolean deleted = fKeyListeners.remove(keyListener);

        if (DEBUG) {
            if (!deleted)
                System.out.println("removeKeyListener -> wasn't here"); //$NON-NLS-1$
            System.out.println(
                    "AbstractControlContentAssistSubjectAdapter#removeKeyListener() -> " + fKeyListeners.size()); //$NON-NLS-1$
        }

        uninstallControlListener();
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#supportsVerifyKeyListener()
     */
    public boolean supportsVerifyKeyListener() {
        return true;
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#appendVerifyKeyListener(org.eclipse.swt.custom.VerifyKeyListener)
     */
    public boolean appendVerifyKeyListener(final VerifyKeyListener verifyKeyListener) {
        fVerifyKeyListeners.add(verifyKeyListener);

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#appendVerifyKeyListener() -> " //$NON-NLS-1$
                    + fVerifyKeyListeners.size());

        installControlListener();
        return true;
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#prependVerifyKeyListener(org.eclipse.swt.custom.VerifyKeyListener)
     */
    public boolean prependVerifyKeyListener(final VerifyKeyListener verifyKeyListener) {
        fVerifyKeyListeners.add(0, verifyKeyListener);

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#prependVerifyKeyListener() -> " //$NON-NLS-1$
                    + fVerifyKeyListeners.size());

        installControlListener();
        return true;
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#removeVerifyKeyListener(org.eclipse.swt.custom.VerifyKeyListener)
     */
    public void removeVerifyKeyListener(VerifyKeyListener verifyKeyListener) {
        fVerifyKeyListeners.remove(verifyKeyListener);

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#removeVerifyKeyListener() -> " //$NON-NLS-1$
                    + fVerifyKeyListeners.size());

        uninstallControlListener();
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#setEventConsumer(org.eclipse.jface.text.IEventConsumer)
     */
    public void setEventConsumer(IEventConsumer eventConsumer) {
        // this is not supported
        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#setEventConsumer()"); //$NON-NLS-1$
    }

    /*
     * @see org.eclipse.jface.contentassist.IContentAssistSubjectControl#getLineDelimiter()
     */
    public String getLineDelimiter() {
        return System.getProperty("line.separator"); //$NON-NLS-1$
    }

    /**
     * Installs <code>fControlListener</code>, which handles VerifyEvents and KeyEvents by
     * passing them to {@link #fVerifyKeyListeners} and {@link #fKeyListeners}.
     */
    private void installControlListener() {
        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#installControlListener() -> k: " //$NON-NLS-1$
                    + fKeyListeners.size() + ", v: " + fVerifyKeyListeners.size()); //$NON-NLS-1$

        if (fControlListener != null)
            return;

        fControlListener = new Listener() {
            public void handleEvent(Event e) {
                if (!getControl().isFocusControl())
                    return; //SWT.TRAVERSE_MNEMONIC events can also come in to inactive widgets
                VerifyEvent verifyEvent = new VerifyEvent(e);
                KeyEvent keyEvent = new KeyEvent(e);
                switch (e.type) {
                case SWT.Traverse:

                    if (DEBUG)
                        dump("before traverse", e, verifyEvent); //$NON-NLS-1$

                    verifyEvent.doit = true;
                    for (Iterator iter = fVerifyKeyListeners.iterator(); iter.hasNext();) {
                        ((VerifyKeyListener) iter.next()).verifyKey(verifyEvent);
                        if (!verifyEvent.doit) {
                            e.detail = SWT.TRAVERSE_NONE;
                            e.doit = true;
                            if (DEBUG)
                                dump("traverse eaten by verify", e, verifyEvent); //$NON-NLS-1$
                            return;
                        }

                        if (DEBUG)
                            dump("traverse OK", e, verifyEvent); //$NON-NLS-1$
                    }
                    break;

                case SWT.KeyDown:
                    for (Iterator iter = fVerifyKeyListeners.iterator(); iter.hasNext();) {
                        ((VerifyKeyListener) iter.next()).verifyKey(verifyEvent);
                        if (!verifyEvent.doit) {
                            e.doit = verifyEvent.doit;
                            if (DEBUG)
                                dump("keyDown eaten by verify", e, verifyEvent); //$NON-NLS-1$
                            return;
                        }
                    }

                    if (DEBUG)
                        dump("keyDown OK", e, verifyEvent); //$NON-NLS-1$

                    for (Iterator iter = fKeyListeners.iterator(); iter.hasNext();) {
                        ((KeyListener) iter.next()).keyPressed(keyEvent);
                    }
                    break;

                default:
                    Assert.isTrue(false);
                }
            }

            /**
             * Dump the given events to "standard" output.
             *
             * @param who who dump's
             * @param e the event
             * @param ve the verify event
             */
            private void dump(String who, Event e, VerifyEvent ve) {
                StringBuffer sb = new StringBuffer("--- [AbstractControlContentAssistSubjectAdapter]\n"); //$NON-NLS-1$
                sb.append(who);
                sb.append(" - e: keyCode=" + e.keyCode + hex(e.keyCode)); //$NON-NLS-1$
                sb.append("; character=" + e.character + hex(e.character)); //$NON-NLS-1$
                sb.append("; stateMask=" + e.stateMask + hex(e.stateMask)); //$NON-NLS-1$
                sb.append("; doit=" + e.doit); //$NON-NLS-1$
                sb.append("; detail=" + e.detail + hex(e.detail)); //$NON-NLS-1$
                sb.append("; widget=" + e.widget); //$NON-NLS-1$
                sb.append("\n"); //$NON-NLS-1$
                sb.append("  verifyEvent keyCode=" + e.keyCode + hex(e.keyCode)); //$NON-NLS-1$
                sb.append("; character=" + e.character + hex(e.character)); //$NON-NLS-1$
                sb.append("; stateMask=" + e.stateMask + hex(e.stateMask)); //$NON-NLS-1$
                sb.append("; doit=" + ve.doit); //$NON-NLS-1$
                sb.append("; widget=" + e.widget); //$NON-NLS-1$
                System.out.println(sb);
            }

            private String hex(int i) {
                return "[0x" + Integer.toHexString(i) + ']'; //$NON-NLS-1$
            }
        };
        getControl().addListener(SWT.Traverse, fControlListener);
        getControl().addListener(SWT.KeyDown, fControlListener);

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#installControlListener() - installed"); //$NON-NLS-1$
    }

    /**
     * Uninstalls <code>fControlListener</code> iff there are no <code>KeyListener</code>s and no
     * <code>VerifyKeyListener</code>s registered.
     * Otherwise does nothing.
     */
    private void uninstallControlListener() {
        if (fControlListener == null || fKeyListeners.size() + fVerifyKeyListeners.size() != 0) {

            if (DEBUG)
                System.out.println("AbstractControlContentAssistSubjectAdapter#uninstallControlListener() -> k: " //$NON-NLS-1$
                        + fKeyListeners.size() + ", v: " + fVerifyKeyListeners.size()); //$NON-NLS-1$

            return;
        }
        getControl().removeListener(SWT.Traverse, fControlListener);
        getControl().removeListener(SWT.KeyDown, fControlListener);
        fControlListener = null;

        if (DEBUG)
            System.out.println("AbstractControlContentAssistSubjectAdapter#uninstallControlListener() - done"); //$NON-NLS-1$
    }

    /**
     * Sets the visual feedback provider for content assist.
     * The given {@link ILabelProvider} methods are called with
     * {@link #getControl()} as argument.
     *
     * <ul>
     *   <li><code>getImage(Object)</code> provides the visual cue image.
     *     The image can maximally be 5 pixels wide and 8 pixels high.
     *     If <code>getImage(Object)</code> returns <code>null</code>, a default image is used.
     *   </li>
     *   <li><code>getText(Object)</code> provides the hover info text.
     *     It is shown when hovering over the cue image or the adapted {@link Control}.
     *     No info text is shown if <code>getText(Object)</code> returns <code>null</code>.
     *   </li>
     * </ul>
     * <p>
     * The given {@link ILabelProvider} becomes owned by the {@link AbstractControlContentAssistSubjectAdapter},
     * i.e. it gets disposed when the adapted {@link Control} is disposed
     * or when another {@link ILabelProvider} is set.
     * </p>
     *
     * @param labelProvider a {@link ILabelProvider}, or <code>null</code>
     *    if no visual feedback should be shown
     */
    public void setContentAssistCueProvider(final ILabelProvider labelProvider) {
        if (fCueLabelProvider != null) {
            fCueLabelProvider.dispose();
        }

        fCueLabelProvider = labelProvider;

        if (labelProvider == null) {
            if (fControlDecoration != null) {
                fControlDecoration.dispose();
                fControlDecoration = null;
            }

        } else {
            if (fControlDecoration == null) {
                fControlDecoration = new ControlDecoration(getControl(), (SWT.TOP | SWT.LEFT));
                getControl().addDisposeListener(new DisposeListener() {
                    public void widgetDisposed(DisposeEvent e) {
                        if (fCueLabelProvider != null) {
                            fCueLabelProvider.dispose();
                            fCueLabelProvider = null;
                        }
                        if (fControlDecoration != null) {
                            fControlDecoration.dispose();
                            fControlDecoration = null;
                        }
                        if (fCachedDefaultCueImage != null) {
                            fCachedDefaultCueImage.dispose();
                            fCachedDefaultCueImage = null;
                        }
                    }
                });
                fControlDecoration.setShowHover(true);
                fControlDecoration.setShowOnlyOnFocus(true);
            }

            ILabelProviderListener listener = new ILabelProviderListener() {
                public void labelProviderChanged(LabelProviderChangedEvent event) {
                    fControlDecoration.setDescriptionText(labelProvider.getText(getControl()));
                    Image image = labelProvider.getImage(getControl());
                    if (image == null)
                        image = getDefaultCueImage();
                    fControlDecoration.setImage(image);
                }
            };
            labelProvider.addListener(listener);
            //initialize control decoration:
            listener.labelProviderChanged(new LabelProviderChangedEvent(labelProvider));
        }
    }

    /**
     * Returns the default cue image.
     *
     * @return the default cue image
     * @since 3.3
     */
    private Image getDefaultCueImage() {
        if (fCachedDefaultCueImage == null) {
            ImageDescriptor cueID = ImageDescriptor.createFromFile(AbstractControlContentAssistSubjectAdapter.class,
                    "images/content_assist_cue.gif"); //$NON-NLS-1$
            fCachedDefaultCueImage = cueID.createImage(getControl().getDisplay());
        }
        return fCachedDefaultCueImage;
    }
}