com.xored.af.ui.SearchControl.java Source code

Java tutorial

Introduction

Here is the source code for com.xored.af.ui.SearchControl.java

Source

/*******************************************************************************
 * Copyright (c) 2010-2013 xored software, Inc.
 *
 * 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:
 *     xored software, Inc. - initial API and Implementation (Igor Zapletnev)
 *******************************************************************************/
package com.xored.af.ui;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import com.xored.af.ui.internal.AfUiPlugin;

/**
 * Design and behavior from org.eclipse.ui.dialogs.FilteredTree class
 */
public class SearchControl extends Composite {

    private static final String FilteredTree_ClearToolTip = "Clear";
    private static final String FilteredTree_AccessibleListenerClearButton = "Clear filter field";
    private static final String FilteredTree_FilterMessage = "type filter text";
    /**
     * The filter text widget to be used by this tree. This value may be
     * <code>null</code> if there is no filter widget, or if the controls have
     * not yet been created.
     */
    protected Text filterText;
    /**
     * The control representing the clear button for the filter text entry. This
     * value may be <code>null</code> if no such button exists, or if the
     * controls have not yet been created.
     * <p>
     * <strong>Note:</strong> This is only used if the new look is chosen.
     * </p>
     * 
     * @since 3.5
     */
    protected Control clearButtonControl;
    /**
     * The parent composite of the search control.
     * 
     * @since 3.3
     */
    protected Composite parent;

    private Composite filterComposite;

    private Control searchResultControl;

    /**
     * The text to initially show in the filter text control.
     */
    protected String initialText = ""; //$NON-NLS-1$   

    public SearchControl(final Composite parent) {
        super(parent, SWT.NONE);

        final GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        setLayout(layout);
        setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        if (useNativeSearchField(parent)) {
            filterComposite = new Composite(this, SWT.NONE);
        } else {
            filterComposite = new Composite(this, SWT.BORDER);
            filterComposite.setBackground(getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
        }
        final GridLayout filterLayout = new GridLayout(2, false);
        filterLayout.marginHeight = 1;
        filterLayout.marginWidth = 1;
        filterLayout.marginLeft = 5;
        filterComposite.setLayout(filterLayout);
        filterComposite.setFont(parent.getFont());

        createFilterControls(filterComposite);
        filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    }

    protected void createFilterControls(final Composite parent) {
        createFilterText(parent);
        createClearText(parent);
        if (clearButtonControl != null) {
            // initially there is no text to clear
            clearButtonControl.setVisible(false);
        }
        setInitialText(FilteredTree_FilterMessage);
    }

    private void createFilterText(final Composite parent) {
        filterText = doCreateFilterText(parent);
        final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);

        if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0)
            gridData.horizontalSpan = 2;
        filterText.setLayoutData(gridData);

        filterText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
            @Override
            public void getName(final AccessibleEvent e) {
                final String filterTextString = filterText.getText();
                if (filterTextString.length() == 0 || filterTextString.equals(initialText)) {
                    e.result = initialText;
                } else {
                    e.result = "";
                }
            }
        });

        filterText.addFocusListener(new FocusAdapter() {

            @Override
            public void focusGained(final FocusEvent e) {
            }

            @Override
            public void focusLost(final FocusEvent e) {
                if (filterText.getText().equals(initialText)) {
                    setFilterText(""); //$NON-NLS-1$
                    textChanged();
                }
            }
        });

        filterText.addMouseListener(new MouseAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.MouseAdapter#mouseDown(org.eclipse.swt
             * .events.MouseEvent)
             */
            @Override
            public void mouseDown(final MouseEvent e) {
                if (filterText.getText().equals(initialText)) {
                    // XXX: We cannot call clearText() due to
                    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=260664
                    setFilterText(""); //$NON-NLS-1$   
                    textChanged();
                }
            }
        });

        filterText.addKeyListener(new KeyAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt
             * .events.KeyEvent)
             */
            @Override
            public void keyPressed(final KeyEvent e) {
                // on a CR we want to transfer focus to the list

                if (searchResultControl != null && e.keyCode == SWT.ARROW_DOWN) {
                    searchResultControl.setFocus();
                    return;
                }
            }
        });

        // enter key set focus to tree
        filterText.addTraverseListener(new TraverseListener() {
            public void keyTraversed(final TraverseEvent e) {
                if (e.detail == SWT.TRAVERSE_RETURN) {
                    e.doit = false;
                    if (searchResultControl != null) {
                        searchResultControl.setFocus();
                    }
                }
            }
        });

        // if we're using a field with built in cancel we need to listen for
        // default selection changes (which tell us the cancel button has been
        // pressed)
        if ((filterText.getStyle() & SWT.ICON_CANCEL) != 0) {
            filterText.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetDefaultSelected(final SelectionEvent e) {
                    if (e.detail == SWT.ICON_CANCEL)
                        clearText();
                }
            });
        }

        filterText.addModifyListener(new ModifyListener() {
            public void modifyText(final ModifyEvent e) {
                textChanged();
            }
        });
    }

    protected Text doCreateFilterText(final Composite parent) {
        if (useNativeSearchField(parent)) {
            return new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
        }
        return new Text(parent, SWT.SINGLE);
    }

    /**
     * Create the button that clears the text.
     * 
     * @param parent
     *            parent <code>Composite</code> of toolbar button
     */
    private void createClearText(final Composite parent) {
        // only create the button if the text widget doesn't support one
        // natively
        if ((filterText.getStyle() & SWT.ICON_CANCEL) == 0) {
            final Image inactiveImage = (Image) JFaceResources.getResources()
                    .get(AfUiPlugin.TOOL_SEARCH_CLEAR_DISABLED);
            final Image activeImage = (Image) JFaceResources.getResources().get(AfUiPlugin.TOOL_SEARCH_CLEAR);
            final Image pressedImage = new Image(getDisplay(), activeImage, SWT.IMAGE_GRAY);

            final Label clearButton = new Label(parent, SWT.NONE);
            clearButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
            clearButton.setImage(inactiveImage);
            clearButton.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
            clearButton.setToolTipText(FilteredTree_ClearToolTip);
            clearButton.addMouseListener(new MouseAdapter() {
                private MouseMoveListener fMoveListener;

                @Override
                public void mouseDown(final MouseEvent e) {
                    clearButton.setImage(pressedImage);
                    fMoveListener = new MouseMoveListener() {
                        private boolean fMouseInButton = true;

                        public void mouseMove(final MouseEvent e) {
                            final boolean mouseInButton = isMouseInButton(e);
                            if (mouseInButton != fMouseInButton) {
                                fMouseInButton = mouseInButton;
                                clearButton.setImage(mouseInButton ? pressedImage : inactiveImage);
                            }
                        }
                    };
                    clearButton.addMouseMoveListener(fMoveListener);
                }

                @Override
                public void mouseUp(final MouseEvent e) {
                    if (fMoveListener != null) {
                        clearButton.removeMouseMoveListener(fMoveListener);
                        fMoveListener = null;
                        final boolean mouseInButton = isMouseInButton(e);
                        clearButton.setImage(mouseInButton ? activeImage : inactiveImage);
                        if (mouseInButton) {
                            clearText();
                            filterText.setFocus();
                        }
                    }
                }

                private boolean isMouseInButton(final MouseEvent e) {
                    final Point buttonSize = clearButton.getSize();
                    return 0 <= e.x && e.x < buttonSize.x && 0 <= e.y && e.y < buttonSize.y;
                }
            });
            clearButton.addMouseTrackListener(new MouseTrackListener() {
                public void mouseEnter(final MouseEvent e) {
                    clearButton.setImage(activeImage);
                }

                public void mouseExit(final MouseEvent e) {
                    clearButton.setImage(inactiveImage);
                }

                public void mouseHover(final MouseEvent e) {
                }
            });
            clearButton.addDisposeListener(new DisposeListener() {
                public void widgetDisposed(final DisposeEvent e) {
                    pressedImage.dispose();
                }
            });
            clearButton.getAccessible().addAccessibleListener(new AccessibleAdapter() {
                @Override
                public void getName(final AccessibleEvent e) {
                    e.result = FilteredTree_AccessibleListenerClearButton;
                }
            });
            clearButton.getAccessible().addAccessibleControlListener(new AccessibleControlAdapter() {
                @Override
                public void getRole(final AccessibleControlEvent e) {
                    e.detail = ACC.ROLE_PUSHBUTTON;
                }
            });
            this.clearButtonControl = clearButton;
        }
    }

    /**
     * Get the initial text for the receiver.
     * 
     * @return String
     */
    public String getInitialText() {
        return initialText;
    }

    /**
     * Set the text that will be shown until the first focus. A default value is
     * provided, so this method only need be called if overriding the default
     * initial text is desired.
     * 
     * @param text
     *            initial text to appear in text field
     */
    public void setInitialText(final String text) {
        initialText = text;
        if (filterText != null) {
            filterText.setMessage(text);
            if (filterText.isFocusControl()) {
                setFilterText(initialText);
                textChanged();
            } else {
                getDisplay().asyncExec(new Runnable() {
                    public void run() {
                        if (!filterText.isDisposed() && filterText.isFocusControl()) {
                            setFilterText(initialText);
                            textChanged();
                        }
                    }
                });
            }
        } else {
            setFilterText(initialText);
            textChanged();
        }
    }

    /**
     * Clears the text in the filter text widget.
     */
    protected void clearText() {
        setFilterText(""); //$NON-NLS-1$   
        textChanged();
    }

    /**
     * Set the text in the filter control.
     * 
     * @param string
     */
    protected void setFilterText(final String string) {
        if (filterText != null) {
            filterText.setText(string);
            selectAll();
        }
    }

    /**
     * Select all text in the filter text field.
     * 
     */
    protected void selectAll() {
        if (filterText != null) {
            filterText.selectAll();
        }
    }

    /**
     * Get the filter text for the receiver, if it was created. Otherwise return
     * <code>null</code>.
     * 
     * @return the filter Text, or null if it was not created
     */
    public Text getFilterControl() {
        return filterText;
    }

    /**
     * Convenience method to return the text of the filter control. If the text
     * widget is not created, then null is returned.
     * 
     * @return String in the text, or null if the text does not exist
     */
    public String getFilterString() {
        return filterText != null ? filterText.getText() : null;
    }

    public Control getSearchResultControl() {
        return searchResultControl;
    }

    public void setSearchResultControl(final Control searchResultControl) {
        this.searchResultControl = searchResultControl;
    }

    protected void textChanged() {
        if (clearButtonControl != null) {
            final boolean haveText = (filterText != null) && !filterText.getText().equals("")
                    && !filterText.getText().equals(initialText);
            clearButtonControl.setVisible(haveText);
        }
    }

    private static Boolean useNativeSearchField;

    private static boolean useNativeSearchField(final Composite composite) {
        if (useNativeSearchField == null) {
            useNativeSearchField = Boolean.FALSE;
            Text testText = null;
            try {
                testText = new Text(composite, SWT.SEARCH | SWT.ICON_CANCEL);
                useNativeSearchField = new Boolean((testText.getStyle() & SWT.ICON_CANCEL) != 0);
            } finally {
                if (testText != null) {
                    testText.dispose();
                }
            }

        }
        return useNativeSearchField.booleanValue();
    }
}