de.uniluebeck.itm.spyglass.plugin.nodesensorrange.NodeSensorRangePerNodeConfigurationComposite.java Source code

Java tutorial

Introduction

Here is the source code for de.uniluebeck.itm.spyglass.plugin.nodesensorrange.NodeSensorRangePerNodeConfigurationComposite.java

Source

/*----------------------------------------------------------------------------------------
 * This file is part of the
 * WSN visualization framework SpyGlass. Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de)
 * project SpyGlass is free software; you can redistribute it and/or modify it under the terms of
 * the BSD License. Refer to spyglass-licence.txt file in the root of the SpyGlass source tree for
 * further details.
 * ---------------------------------------------------------------------------------------
 */
package de.uniluebeck.itm.spyglass.plugin.nodesensorrange;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TableItem;

import de.uniluebeck.itm.spyglass.gui.databinding.ColorEditingSupport;
import de.uniluebeck.itm.spyglass.gui.databinding.DatabindingTextEditingSupport;
import de.uniluebeck.itm.spyglass.gui.databinding.WrappedObservableSet;
import de.uniluebeck.itm.spyglass.gui.databinding.validator.IntegerRangeValidator;
import de.uniluebeck.itm.spyglass.plugin.nodesensorrange.NodeSensorRangeXMLConfig.Config;
import de.uniluebeck.itm.spyglass.plugin.nodesensorrange.NodeSensorRangeXMLConfig.NodeSensorRange;
import de.uniluebeck.itm.spyglass.plugin.nodesensorrange.NodeSensorRangeXMLConfig.RANGE_TYPE;
import de.uniluebeck.itm.spyglass.util.SpyglassLoggerFactory;

// --------------------------------------------------------------------------------
/**
 * @author bimschas
 * 
 */
public class NodeSensorRangePerNodeConfigurationComposite {

    private static final Logger log = SpyglassLoggerFactory
            .getLogger(NodeSensorRangePerNodeConfigurationComposite.class);

    private NodeSensorRangePreferencePage page;

    private TableViewerColumn columnNodeId;

    private TableViewerColumn columnLineWidth;

    private TableViewerColumn columnLineColor;

    private TableViewerColumn columnBackgroundColor;

    private TableViewerColumn columnBackgroundAlpha;

    private TableViewerColumn columnType;

    private TableViewerColumn columnButton;

    /**
     * Reference to the set backing the table. All edits have to go through this set, so that
     * changeListeners are being noticed.
     */
    private IObservableSet tableData;

    private TableViewer table;

    private Composite parent;

    private Button addEntry;

    private Composite buttonComposite;

    private Button delEntry;

    public void addPerNodeConfigurationTable(final Composite parent) {

        this.parent = parent;

        {
            final GridData tableLData = new GridData();
            tableLData.horizontalSpan = 2;
            tableLData.grabExcessHorizontalSpace = true;
            tableLData.horizontalAlignment = GridData.FILL;
            tableLData.verticalAlignment = GridData.FILL;
            tableLData.grabExcessVerticalSpace = true;
            tableLData.heightHint = 100;

            table = new TableViewer(parent, SWT.FULL_SELECTION);
            table.getControl().setLayoutData(tableLData);
            table.getTable().setLinesVisible(true);
            table.getTable().setHeaderVisible(true);
        }
        {
            columnNodeId = new TableViewerColumn(table, SWT.LEFT);
            columnNodeId.getColumn().setWidth(80);
            columnNodeId.getColumn().setText("Node ID");

            // sort by node ID
            table.getTable().setSortColumn(columnNodeId.getColumn());
            table.getTable().setSortDirection(SWT.DOWN);
        }
        {
            columnLineWidth = new TableViewerColumn(table, SWT.LEFT);
            columnLineWidth.getColumn().setWidth(80);
            columnLineWidth.getColumn().setText("Line width");
            // editing support is set later on data binding
        }
        {
            columnLineColor = new TableViewerColumn(table, SWT.LEFT);
            columnLineColor.getColumn().setWidth(150);
            columnLineColor.getColumn().setText("Line color");
            // editing support is set later on data binding
        }
        {
            columnBackgroundColor = new TableViewerColumn(table, SWT.LEFT);
            columnBackgroundColor.getColumn().setWidth(150);
            columnBackgroundColor.getColumn().setText("Background color");
            // editing support is set later on data binding
        }
        {
            columnBackgroundAlpha = new TableViewerColumn(table, SWT.LEFT);
            columnBackgroundAlpha.getColumn().setWidth(120);
            columnBackgroundAlpha.getColumn().setText("Background alpha");
            // editing support is set later on data binding
        }
        {
            columnType = new TableViewerColumn(table, SWT.LEFT);
            columnType.getColumn().setWidth(50);
            columnType.getColumn().setText("Type");
            // editing support is set later on data binding
        }
        {
            columnButton = new TableViewerColumn(table, SWT.NONE);
            columnButton.getColumn().setWidth(50);
        }
        {
            buttonComposite = new Composite(parent, SWT.NONE);
            buttonComposite.setLayout(new GridLayout(2, false));
            final GridData data = new GridData();
            buttonComposite.setLayoutData(data);
        }
        {
            addEntry = new Button(buttonComposite, SWT.PUSH | SWT.CENTER);
            final GridData addEntryLData = new GridData();
            addEntryLData.verticalAlignment = GridData.BEGINNING;
            addEntryLData.horizontalAlignment = GridData.END;
            addEntryLData.widthHint = 100;
            addEntry.setLayoutData(addEntryLData);
            addEntry.setText("Add");
            addEntry.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent evt) {
                    clickedButtonAddEntry(evt);
                }
            });
        }
        {
            final GridData data = new GridData();
            data.widthHint = 100;
            delEntry = new Button(buttonComposite, SWT.PUSH | SWT.CENTER);
            delEntry.setLayoutData(data);
            delEntry.setText("Delete");
            delEntry.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent evt) {
                    clickedButtonDelEntry(evt);
                }
            });
        }

    }

    // --------------------------------------------------------------------------------
    /**
     * Snagged this code from https://bugs.eclipse.org/bugs/show_bug.cgi?id=36977 credit to Tom
     * Schindl
     * 
     * @author Dariush Forouher
     */
    private final class ButtonCellLabelProvider extends CellLabelProvider {

        @Override
        public void update(final ViewerCell cell) {

            final TableItem item = (TableItem) cell.getItem();
            if (item.getData("EDITOR") != null) {
                final TableEditor editor = (TableEditor) item.getData("EDITOR");
                editor.dispose();
            }

            final TableEditor editor = new TableEditor(item.getParent());
            final Composite comp = new Composite(item.getParent(), SWT.NONE);
            comp.setBackground(item.getParent().getBackground());
            comp.setBackgroundMode(SWT.INHERIT_DEFAULT);
            final RowLayout l = new RowLayout();
            l.marginHeight = 0;
            l.marginWidth = 0;
            l.marginTop = 0;
            l.marginBottom = 0;

            comp.setLayout(l);
            final Button button = new Button(comp, SWT.PUSH);
            button.setText("Options");
            button.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent e) {
                    final TableItem item = editor.getItem();
                    final NodeSensorRangeXMLConfig.Config config = (Config) item.getData();

                    final RANGE_TYPE selectedRangeType = config.getRangeType();

                    final NodeSensorRange defaultRange = config.getRange();
                    final NodeRangeDialog dialog = NodeRangeDialog.createDialog(table.getTable().getShell(),
                            selectedRangeType, defaultRange);

                    if (Window.OK == dialog.open()) {
                        config.setRange(dialog.range);
                    }
                }
            });

            // dispose the button when the TableItem is disposed.
            item.addDisposeListener(new DisposeListener() {

                @Override
                public void widgetDisposed(final DisposeEvent e) {
                    comp.dispose();
                }

            });

            editor.grabHorizontal = true;
            editor.setEditor(comp, item, 6); // number of the column starting from zero!!!
        }

    }

    private class NodeSensorRangeColorLabelProvider extends ColumnLabelProvider {

        private String getterMethodName;
        private Color color;

        public NodeSensorRangeColorLabelProvider(final String elementName) {
            this.getterMethodName = "get" + elementName.substring(0, 1).toUpperCase() + elementName.substring(1);
        }

        @Override
        public Color getForeground(final Object element) {
            try {
                final Method method;
                method = element.getClass().getMethod(getterMethodName, new Class<?>[] {});
                final RGB rgb = (RGB) method.invoke(element);
                color = new Color(Display.getDefault(), rgb);
                return color;
            } catch (final Exception e) {
                throw new RuntimeException("Bug", e);
            }
        }

        @Override
        public Color getBackground(final Object element) {
            try {
                final Method method;
                method = element.getClass().getMethod(getterMethodName, new Class<?>[] {});
                final RGB rgb = (RGB) method.invoke(element);
                color = new Color(Display.getDefault(), rgb);
                return color;
            } catch (final Exception e) {
                throw new RuntimeException("Bug", e);
            }
        }

        @Override
        public String getText(final Object element) {
            return "Color";
        }

    };

    // --------------------------------------------------------------------------------
    /**
     * Activates data binding
     * 
     * @param dbc
     *            the {@link DataBindingContext}
     * @param config
     *            the configuration which represents the model
     */
    public void setDataBinding(final DataBindingContext dbc, final NodeSensorRangePreferencePage page) {

        this.page = page;

        columnLineWidth.setEditingSupport(new DatabindingTextEditingSupport(table, dbc,
                NodeSensorRangeXMLConfig.PROPERTYNAME_LINE_WIDTH, null, new IntegerRangeValidator(0, 2000), null));
        columnLineColor.setEditingSupport(
                new ColorEditingSupport(table, dbc, NodeSensorRangeXMLConfig.PROPERTYNAME_COLOR_R_G_B));
        columnBackgroundColor.setEditingSupport(
                new ColorEditingSupport(table, dbc, NodeSensorRangeXMLConfig.PROPERTYNAME_BACKGROUND_R_G_B));
        columnBackgroundAlpha.setEditingSupport(new DatabindingTextEditingSupport(table, dbc,
                NodeSensorRangeXMLConfig.PROPERTYNAME_BACKGROUND_ALPHA, null, new IntegerRangeValidator(0, 255),
                null));

        columnType.setEditingSupport(new ComboBoxRangeTypeEditingSupport(table, dbc,
                NodeSensorRangeXMLConfig.PROPERTYNAME_RANGE_TYPE, new String[] { "Circle", "Cone", "Rectangle" }));

        final ObservableSetContentProvider contentProvider = new ObservableSetContentProvider();
        table.setContentProvider(contentProvider);

        final IObservableMap backgroundColorMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_BACKGROUND_R_G_B);

        final IObservableMap backgroundAlphaMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_BACKGROUND_ALPHA);

        final IObservableMap lineColorMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_COLOR_R_G_B);

        final IObservableMap lineWidthMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_LINE_WIDTH);

        final IObservableMap typeMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_RANGE_TYPE);

        final IObservableMap nodeIdMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_NODE_ID);

        // we need to map something. it doesn't matter what
        final IObservableMap buttonMap = BeansObservables.observeMap(contentProvider.getKnownElements(),
                NodeSensorRangeXMLConfig.Config.class, NodeSensorRangeXMLConfig.PROPERTYNAME_NODE_ID);

        final IObservableMap[] columnMaps = new IObservableMap[] { nodeIdMap, lineWidthMap, lineColorMap,
                backgroundColorMap, backgroundAlphaMap, typeMap, buttonMap };

        table.setLabelProvider(new ObservableMapLabelProvider(columnMaps));

        // after we have defined a generic label provider for the entire table, we can now set
        // individual label providers
        // for specific columns.

        columnBackgroundColor.setLabelProvider(
                new NodeSensorRangeColorLabelProvider(NodeSensorRangeXMLConfig.PROPERTYNAME_BACKGROUND_R_G_B));
        columnLineColor.setLabelProvider(
                new NodeSensorRangeColorLabelProvider(NodeSensorRangeXMLConfig.PROPERTYNAME_COLOR_R_G_B));

        columnButton.setLabelProvider(new ButtonCellLabelProvider());

    }

    public void connectTableWithData(final DataBindingContext dbc, final Set<Config> set,
            final ISetChangeListener setChangeListener) {

        tableData = new WrappedObservableSet(dbc.getValidationRealm(), set, null);
        tableData.addSetChangeListener(setChangeListener);
        table.setInput(tableData);

        table.refresh();

        log.info("set new input");
    }

    private void clickedButtonDelEntry(final SelectionEvent evt) {
        final IStructuredSelection selection = (IStructuredSelection) table.getSelection();
        for (final Object o : selection.toList()) {
            tableData.remove(o);
        }
        page.markFormDirty();
    }

    @SuppressWarnings("unchecked")
    private void clickedButtonAddEntry(final SelectionEvent evt) {
        final InputDialog dlg = new InputDialog(parent.getShell(), "Enter a node ID", "Please enter a node ID", "",
                new IInputValidator() {

                    @Override
                    public String isValid(final String newText) {
                        try {
                            if (Integer.parseInt(newText) < 0) {
                                return "Please enter a positive number";
                            }
                            return null;

                        } catch (final NumberFormatException e) {
                            return "Please enter an integer";
                        }

                    }

                });
        dlg.setBlockOnOpen(true);
        final int ret = dlg.open();
        if (ret == Window.OK) {
            final int nodeId = Integer.parseInt(dlg.getValue());
            // check if there's already a config for this nodeId and simply ignore if there is
            for (final Iterator<Config> iterator = tableData.iterator(); iterator.hasNext();) {
                final Config type = iterator.next();
                if (type.getNodeId() == nodeId) {
                    return;
                }
            }
            final Config cfg = new Config();
            cfg.setNodeId(nodeId);
            tableData.add(cfg);
            page.markFormDirty();
        }

        // this is a hack and will probably not work every time.
        table.refresh();
    }
}