com.nokia.carbide.cpp.internal.project.ui.editors.common.ControlHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.carbide.cpp.internal.project.ui.editors.common.ControlHandler.java

Source

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/
package com.nokia.carbide.cpp.internal.project.ui.editors.common;

import com.nokia.cpp.internal.api.utils.core.Check;
import com.nokia.cpp.internal.api.utils.core.ListenerList;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;

import java.util.*;
import java.util.List;

/**
 * Base class of framework providing these services:
 * - populate control/viewer from data model (in subclasses that are model-aware)
 * - respond to control/viewer events by creating undoable operations (in subclasses that are model-aware)
 * - utilities for populating control/viewer values without triggering undo stack modifications
 * - validation that's simpler than SWT verify events
 * 
 * The handler is attached to the control's data map. Given a Control the handler can
 * be retrieved view getHandlerForControl. Given a Viewe the handler can be retrieved via
 * getHandlerForViewer.
 */
public class ControlHandler {

    public interface IValidator {
        /**
         * Return null or OK status if control state is valid
         */
        IStatus validate(Control control);
    }

    private final Control control;
    // optional viewer associated with the control
    private final StructuredViewer viewer;
    private final IValidator validator;
    private final Listener swtListener;
    private final boolean viewerCaseSensitive;
    // optional label associated with the control
    private Control label;
    private boolean updatingControl;
    private ICheckStateListener checkStateListener;
    private ListenerList<ControlHandlerListener> listeners = new ListenerList<ControlHandlerListener>();
    private String listDelimiter = "\\ "; //$NON-NLS-1$

    static final String DATA_KEY = ControlHandler.class.getPackage() + "." + ControlHandler.class.getName(); //$NON-NLS-1$

    interface ControlHandlerListener {
        void valueModified(Control control);

        void controlSelected(Control control);

        void validationFailed(Control control, String message);

        void validationSucceeded(Control control);
    }

    public static class ControlHandlerAdapter implements ControlHandlerListener {
        public void valueModified(Control control) {
        }

        public void controlSelected(Control control) {
        }

        public void validationFailed(Control control, String message) {
        }

        public void validationSucceeded(Control control) {
        }
    }

    public ControlHandler(Control control, IValidator validator) {
        this(control, null, validator, true);
    }

    /**
     * Initialize to use a structured view to interact with the control
     * @param viewer the viewer
     * @param caseSensitive true if when setting the value to match with case
     * insensitive comparisons
     */
    public ControlHandler(StructuredViewer viewer, boolean caseSensitive) {
        this(viewer.getControl(), viewer, null, caseSensitive);
    }

    protected ControlHandler(final Control control, final StructuredViewer viewer, IValidator validator,
            boolean caseSensitive) {
        Check.checkState(getHandlerForControl(control) == null);
        this.control = control;
        this.viewer = viewer;
        this.validator = validator;
        this.viewerCaseSensitive = caseSensitive;

        swtListener = new Listener() {
            public void handleEvent(Event event) {
                switch (event.type) {
                case SWT.Modify:
                    if (!updatingControl) {
                        textModified();
                    }
                    break;
                case SWT.Selection:
                    if (!updatingControl) {
                        controlSelected();
                    }
                    break;
                case SWT.Dispose:
                    control.setData(DATA_KEY, null);
                    break;
                case SWT.FocusIn:
                    controlFocused();
                    break;
                }
            }
        };
        control.addListener(SWT.Modify, swtListener);
        control.addListener(SWT.Selection, swtListener);
        control.addListener(SWT.Dispose, swtListener);
        control.addListener(SWT.FocusIn, swtListener);

        if (viewer instanceof ICheckable) {
            checkStateListener = new ICheckStateListener() {
                public void checkStateChanged(CheckStateChangedEvent event) {
                    ControlHandler.this.checkStateChanged(event.getElement(), event.getChecked());
                }
            };
            ICheckable checkable = (ICheckable) viewer;
            checkable.addCheckStateListener(checkStateListener);
        }

        control.setData(DATA_KEY, this);
        Check.checkState(getHandlerForControl(control) == this);
    }

    public Control getControl() {
        return control;
    }

    public StructuredViewer getViewer() {
        return viewer;
    }

    public void setLabel(Control label) {
        this.label = label;
    }

    public Control getLabel() {
        return label;
    }

    public static ControlHandler getHandlerForControl(Control control) {
        ControlHandler result = null;
        if (control != null) {
            Object obj = control.getData(DATA_KEY);
            if (obj instanceof ControlHandler) {
                result = (ControlHandler) obj;
            }
        }
        return result;
    }

    public static ControlHandler getHandlerForViewer(StructuredViewer viewer) {
        return getHandlerForControl(viewer.getControl());
    }

    protected void textModified() {
        fireTextModified();
        validate();
    }

    protected void controlSelected() {
        fireControlSelected();
    }

    protected void controlFocused() {
        validate();
    }

    /**
     * Utility to pull the text of of various kinds of Control.
     */
    public static String getControlText(Control control) {
        String result = null;
        Object value = getControlValue(control);
        if (value instanceof List) {
            ControlHandler handler = getHandlerForControl(control);
            if (handler != null) {
                result = handler.listToText((List) value);
            }
        } else if (value != null) {
            result = value.toString();
        }
        return result;
    }

    public static Object getControlValue(Control control) {
        Object result = null;
        ControlHandler handler = getHandlerForControl(control);
        if (handler != null && handler.viewer != null) {
            ISelection selection = handler.viewer.getSelection();
            if (selection instanceof IStructuredSelection) {
                IStructuredSelection ss = (IStructuredSelection) selection;
                List list = ss.toList();
                if (list.size() == 1) {
                    result = list.get(0);
                } else {
                    result = list;
                }
            }
        } else if (control instanceof Text) {
            result = ((Text) control).getText();
        } else if (control instanceof Combo) {
            result = ((Combo) control).getText();
        } else if (control instanceof Button) {
            result = ((Button) control).getSelection();
        }
        return result;
    }

    /**
     * Match the incoming string to the casing in the viewer data
     */
    private static String matchViewerStringCase(StructuredViewer viewer, String value) {
        String result = value;
        IContentProvider contentProvider = viewer.getContentProvider();
        if (contentProvider instanceof IStructuredContentProvider) {
            IStructuredContentProvider scp = (IStructuredContentProvider) contentProvider;
            Object[] elements = scp.getElements(viewer.getInput());
            for (Object element : elements) {
                String strElement = element.toString();
                if (value.equalsIgnoreCase(strElement)) {
                    result = strElement;
                    break;
                }
            }
        }
        return result;
    }

    /**
     * Utility to set the text in various kinds of Control
     */
    public static void setControlText(Control control, String value) {
        if (value == null)
            value = ""; //$NON-NLS-1$
        ControlHandler handler = getHandlerForControl(control);
        if (handler != null && handler.viewer != null) {
            if (!handler.viewerCaseSensitive) {
                value = matchViewerStringCase(handler.viewer, value);
            }
            IStructuredSelection ss = new StructuredSelection(value);
            handler.viewer.setSelection(ss, true);
        } else if (control instanceof Text) {
            Text t = (Text) control;
            t.setText(value);
        } else if (control instanceof Combo) {
            Combo c = (Combo) control;
            c.setText(value);
        }
    }

    public IStatus validate() {
        IStatus result = Status.OK_STATUS;
        if (validator != null) {
            result = validator.validate(control);
            if (result == null || result.isOK()) {
                clearLabelModifications();
                // this is needed so UI can clear out error indications
                fireValidationSucceeded();
            } else {
                if (label != null) {
                    label.setForeground(JFaceColors.getErrorText(control.getDisplay()));
                }
                fireValidationFailed(result.getMessage());
            }
        }
        return result;
    }

    public void clearLabelModifications() {
        if (label != null) {
            label.setForeground(null);
        }
    }

    protected void whileUpdatingControl(Runnable r) {
        boolean savedUpdating = updatingControl;
        updatingControl = true;
        try {
            r.run();
        } finally {
            updatingControl = savedUpdating;
        }
    }

    /**
     * Set the control's text without modifying the operation stack
     * @param value
     */
    public void storeText(final String value) {
        whileUpdatingControl(new Runnable() {
            public void run() {
                setControlText(control, value);
                validate();
            }
        });
    }

    public void setValue(Object valueParam) {
        final Object value = valueParam != null ? valueParam : ""; //$NON-NLS-1$
        whileUpdatingControl(new Runnable() {
            public void run() {
                if (viewer != null) {
                    if (value instanceof List) {
                        IStructuredSelection ss = new StructuredSelection((List) value);
                        viewer.setSelection(ss, true);
                    } else if (value instanceof Object[]) {
                        IStructuredSelection ss = new StructuredSelection((Object[]) value);
                        viewer.setSelection(ss, true);
                    } else {
                        IStructuredSelection ss = new StructuredSelection(value);
                        viewer.setSelection(ss, true);
                    }
                } else {
                    if (control instanceof Button) {
                        Button btn = (Button) control;
                        btn.setSelection(Boolean.valueOf(value.toString()));
                    } else {
                        if (value instanceof List) {
                            setControlText(control, listToText((List) value));
                        } else {
                            setControlText(control, value.toString());
                        }
                    }
                }
                validate();
            }
        });
    }

    /**
     * Hook to translate viewer element objects to underlying model
     * objects. Default version returns the input umodified
     */
    public List<Object> viewerToModelElements(List<Object> elements) {
        return elements;
    }

    /**
     * Hook to translate model objects to viewer objects. Default
     * version returns the input unmodified
     */
    public List<Object> modelToViewerElements(List<Object> elements) {
        return elements;
    }

    /**
     * Set the input on a viewer without modifying the operation stack
     */
    public void setViewerInput(final Object input) {
        Check.checkState(viewer != null);
        whileUpdatingControl(new Runnable() {
            public void run() {
                viewer.setInput(input);
                validate();
            }
        });
    }

    protected void checkStateChanged(Object element, boolean checked) {

    }

    public void addListItems(List items) {
        boolean savedUpdating = updatingControl;
        updatingControl = true;
        try {
            if (viewer != null) {
                refresh();
            } else {
                StringBuffer buf = new StringBuffer(getControlText(control));
                if (buf.length() > 0) {
                    buf.append(listDelimiter);
                }
                buf.append(listToText(items));
                storeText(buf.toString());
            }
        } finally {
            updatingControl = savedUpdating;
        }
    }

    /**
     * Do anything needed to update the control from the model.
     */
    public void refresh() {
        boolean savedUpdating = updatingControl;
        updatingControl = true;
        try {
            clearLabelModifications();
            doRefresh();
        } finally {
            updatingControl = savedUpdating;
        }
    }

    /**
     * Subclasses that cannot relying on simple Viewer refreshing
     * must override this to populate the control value.
     */
    protected void doRefresh() {
        if (viewer != null) {
            viewer.refresh();
        }
    }

    public void setListDelimiter(String delimiter) {
        this.listDelimiter = delimiter;
    }

    public void removeListItems(List items) {
        boolean savedUpdating = updatingControl;
        updatingControl = true;
        try {
            if (viewer != null) {
                refresh();
            } else {
                String[] strings = splitText();
                ArrayList<String> list = new ArrayList<String>();
                for (String str : strings) {
                    list.add(str);
                }
                list.removeAll(items);
                storeText(listToText(list));
            }
        } finally {
            updatingControl = savedUpdating;
        }
    }

    public String[] splitText() {
        String text = getControlText(control);
        String[] strings = text.split(listDelimiter);
        return strings;
    }

    public String listToText(List items) {
        StringBuffer result = new StringBuffer();
        if (items != null) {
            for (Object object : items) {
                if (result.length() > 0) {
                    result.append(listDelimiter);
                }
                result.append(object);
            }
        }
        return result.toString();
    }

    public void addListener(ControlHandlerListener l) {
        listeners.add(l);
    }

    public void removeListener(ControlHandlerListener l) {
        listeners.remove(l);
    }

    protected void fireTextModified() {
        for (ControlHandlerListener l : listeners) {
            l.valueModified(control);
        }
    }

    protected void fireControlSelected() {
        for (ControlHandlerListener l : listeners) {
            l.controlSelected(control);
        }
    }

    protected void fireValidationFailed(String message) {
        for (ControlHandlerListener l : listeners) {
            l.validationFailed(control, message);
        }
    }

    protected void fireValidationSucceeded() {
        for (ControlHandlerListener l : listeners) {
            l.validationSucceeded(control);
        }
    }
}