com.xse.eclipseui.widgets.ComboBoxWidget.java Source code

Java tutorial

Introduction

Here is the source code for com.xse.eclipseui.widgets.ComboBoxWidget.java

Source

/*******************************************************************************
 * Eclipse UI
 *
 * Copyright (c) 2015 Mentor Graphics 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:
 *      Mentor Graphics - initial API and implementation
 ******************************************************************************/
package com.xse.eclipseui.widgets;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

import com.xse.eclipseui.SelectionUtil;

public class ComboBoxWidget<T> extends AbstractBaseWidget<T> {

    private class ComboBoxLabelProvider implements ILabelProvider {

        @Override
        public void addListener(final ILabelProviderListener listener) {
        }

        @Override
        public void dispose() {
        }

        @Override
        public boolean isLabelProperty(final Object element, final String property) {
            return false;
        }

        @Override
        public void removeListener(final ILabelProviderListener listener) {
        }

        @Override
        public Image getImage(final Object element) {
            return null;
        }

        @Override
        public String getText(final Object element) {
            if (element != null) {
                return element.toString();
            }
            return "";
        }

    }

    private class ComboBoxContentProvider implements IStructuredContentProvider {

        private Collection<T> input;

        @Override
        public void dispose() {
        }

        @SuppressWarnings("unchecked")
        @Override
        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            if (newInput != oldInput) {
                if (newInput instanceof Collection) {
                    this.input = (Collection<T>) newInput;
                }
            }
        }

        @Override
        public Object[] getElements(final Object inputElement) {
            if (this.input != null) {
                return this.input.toArray();
            }
            return new Object[0];
        }
    }

    protected ComboViewer comboControl;

    private String caption;
    private final int captionMargin;

    private final int minComboWidth;

    private ComboBoxContentProvider contentProvider;

    private final List<IComboSelectionChangedListener<T>> listenerList = new ArrayList<>();
    private boolean listenerActive = true;

    /* TODO: allow creation of ComboBoxes without passing an input list in the constructor
     * -> possible solution: pass one instance of the type to allow Java to infer the type parameter type */
    public ComboBoxWidget(final Composite parent, final int style, final Collection<T> inputList) {
        this(parent, style, null, inputList);
    }

    public ComboBoxWidget(final Composite parent, final int style, final String caption,
            final Collection<T> inputList) {
        this(parent, style, caption, 2, 8, inputList);
    }

    public ComboBoxWidget(final Composite parent, final int style, final String caption, final int captionMargin,
            final int minComboWidth, final Collection<T> inputList) {
        super(parent, style);

        this.caption = caption;
        this.captionMargin = captionMargin;

        this.minComboWidth = minComboWidth;

        this.contentProvider = new ComboBoxContentProvider();

        this.createContent();

        this.setInput(inputList);
    }

    @SuppressWarnings("unchecked")
    public Collection<T> getInput() {
        return (Collection<T>) this.comboControl.getInput();
    }

    public void setInput(final Collection<T> inputList) {
        this.comboControl.setInput(inputList);
    }

    public void setContentList(final Collection<T> content) {
        this.comboControl.setInput(content);
    }

    protected ComboViewer createViewer() {
        return new ComboViewer(this, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
    }

    protected void createContent() {
        final GridLayout layout;
        if (this.caption != null) {
            layout = new GridLayout(2, false);
        } else {
            layout = new GridLayout(1, false);
        }
        layout.marginWidth = 0;
        layout.marginHeight = 4;
        this.setLayout(layout);

        this.setBackground(this.getParent().getBackground());

        if (this.caption != null) {
            final Label captionLabel = new Label(this, SWT.NONE);
            final GridData labelGridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
            labelGridData.widthHint = this.captionMargin;
            captionLabel.setLayoutData(labelGridData);
            captionLabel.setText(this.caption);
        }

        this.comboControl = this.createViewer();

        // this.comboControl.getCombo().setText(this.caption);
        final GridData comboGridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
        comboGridData.horizontalIndent = 2; // somebody needs 6 here! -> make configurable!
        comboGridData.minimumWidth = this.minComboWidth;
        this.comboControl.getCombo().setLayoutData(comboGridData);

        this.comboControl.setLabelProvider(new ComboBoxLabelProvider());
        this.comboControl.setContentProvider(this.contentProvider);

        this.controlDecoration = new ControlDecoration(this.comboControl.getCombo(), SWT.LEFT | SWT.TOP);

        this.comboControl.addPostSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                ComboBoxWidget.this.isValid();
            }
        });

        this.comboControl.addPostSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                if (ComboBoxWidget.this.listenerActive) {
                    for (final IComboSelectionChangedListener<T> listener : ComboBoxWidget.this.listenerList) {
                        listener.selectionChanged(ComboBoxWidget.this, ComboBoxWidget.this.getValue());
                    }
                }
            }
        });
    }

    public void setLabelProvider(final ILabelProvider labelProvider) {
        this.comboControl.setLabelProvider(labelProvider);
    }

    /**
     * Adds a special {@link IComboSelectionChangedListener} to this control that will NOT be fired
     * if the text of this widget gets changed via setText(...) of this class.
     *
     * @param listener
     */
    public void addComboSelectionChangedListener(final IComboSelectionChangedListener<T> listener) {
        this.listenerList.add(listener);
    }

    public void removeComboSelectionChangedListener(final IComboSelectionChangedListener<T> listener) {
        this.listenerList.remove(listener);
    }

    public void addSelectionChangedListener(final ISelectionChangedListener listener) {
        this.comboControl.addSelectionChangedListener(listener);
    }

    public void removeSelectionChangedListener(final ISelectionChangedListener listener) {
        this.comboControl.removeSelectionChangedListener(listener);
    }

    // the set method is synchronized because of the listener handling, not because of any inconsistent states
    public synchronized void setValue(final T value) {
        this.listenerActive = false;
        if (value != null) {
            this.comboControl.setSelection(new StructuredSelection(value));
        } else {
            this.comboControl.setSelection(null);
        }
        this.listenerActive = true;
    }

    // because nothing else can be contained in the Combo
    @SuppressWarnings("unchecked")
    @Override
    // the set method is synchronized because of the listener handling, not because of any inconsistent states
    public T getValue() {
        return (T) SelectionUtil.getFirstElement(this.comboControl.getSelection());
    }

    public Combo getComboControl() {
        return this.comboControl.getCombo();
    }

    public ComboViewer getViewer() {
        return this.comboControl;
    }

}