org.csstudio.sds.ui.internal.layers.LayerTreeViewer.java Source code

Java tutorial

Introduction

Here is the source code for org.csstudio.sds.ui.internal.layers.LayerTreeViewer.java

Source

/*
 * Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
 * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
 *
 * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
 * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
 * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
 * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
 * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
 * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
 * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
 * OR MODIFICATIONS.
 * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
 * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
 * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
 * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
 */
package org.csstudio.sds.ui.internal.layers;

import org.csstudio.sds.internal.model.ILayerModelListener;
import org.csstudio.sds.internal.model.Layer;
import org.csstudio.sds.internal.model.LayerSupport;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;

/**
 * This class provides a {@link TreeViewer} to display the defined {@link Layer}s
 * of a Display in the Run-Mode. It also allows to toggle the visibility of the
 * Layers. If an {@link IWorkbenchPartSite} is set, the {@link TreeViewer} as a
 * popup-menu to add or remove or to change the order of the layer.
 *
 * @author Kai Meyer
 *
 */
public final class LayerTreeViewer implements ILayerModelListener {

    /**
     * The id of the parent view.
     */
    private final String _viewID;

    /**
     * The {@link IWorkbenchPartSite} where the popup-menu is registered.
     */
    private IWorkbenchPartSite _site;

    /**
     * The treeviewer which displays the layers.
     */
    private TreeViewer _treeViewer;

    /**
     * The current {@link LayerSupport}.
     */
    private LayerSupport _layerSupport;

    /**
     * The {@link CommandStack}, where several commands are executed.
     * If t is not <code>null</code> the commands can be undone.
     */
    private CommandStack _commandStack = null;

    /**
     * Constructor.
     * @param site The {@link IWorkbenchPartSite} for the popup-menu (can be null)
     * @param parent The parent {@link Composite} for the {@link TreeViewer}
     * @param viewID The ID of the parent view
     */
    public LayerTreeViewer(final IWorkbenchPartSite site, final Composite parent, final String viewID) {
        _site = site;
        _viewID = viewID;
        // configure viewer
        _treeViewer = new TreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);

        _treeViewer.setLabelProvider(new WorkbenchLabelProvider());
        _treeViewer.setContentProvider(new BaseWorkbenchContentProvider() {

            @Override
            public Object[] getElements(final Object element) {
                return ((LayerSupport) element).getLayers().toArray();
            }

        });

        // handle selections (sets active layer)
        _treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(final SelectionChangedEvent event) {
                IStructuredSelection sel = (IStructuredSelection) event.getSelection();

                Layer layer = (Layer) sel.getFirstElement();

                if (layer != null && _layerSupport != null) {
                    _layerSupport.setActiveLayer(layer);
                }
            }
        });
        // handle doubleclicks (toggles layer visibility)
        _treeViewer.addDoubleClickListener(new IDoubleClickListener() {

            public void doubleClick(final DoubleClickEvent event) {
                IStructuredSelection sel = (IStructuredSelection) event.getSelection();
                Layer layer = (Layer) sel.getFirstElement();

                if (layer != null) {
                    if (_commandStack == null) {
                        layer.setVisible(!layer.isVisible());
                    } else {
                        _commandStack.execute(new ToggleVisibilityCommand(layer));
                    }
                }
            }

        });

        // DnD
        addDragSupport(_treeViewer);
        addDropSupport(_treeViewer);

        // context menu
        hookPopupMenu(_treeViewer);
    }

    /**
     * Hooks the PopupMenu to the given TreeViewer.
     *
     * @param viewer
     *            The TreeViewer
     */
    private void hookPopupMenu(final TreeViewer viewer) {
        MenuManager popupMenu = new MenuManager(_viewID);
        popupMenu.add(new Separator("additions"));
        Menu menu = popupMenu.createContextMenu(viewer.getTree());

        viewer.getTree().setMenu(menu);
        if (_site != null) {
            _site.registerContextMenu(popupMenu, viewer);
        }
    }

    /**
     * Adds drag support for layers to the specified viewer.
     *
     * @param treeViewer
     *            the viewer that should support dragging of layers
     */
    private void addDragSupport(final TreeViewer treeViewer) {
        // Allow data to be copied or moved from the drag source
        treeViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT,
                new Transfer[] { LayerTransfer.getInstance() }, new DragSourceAdapter() {
                    @Override
                    public void dragStart(final DragSourceEvent event) {
                        if (_treeViewer.getSelection() == null) {
                            event.doit = false;
                        }
                    }

                    @Override
                    public void dragSetData(final DragSourceEvent event) {
                        if (LayerTransfer.getInstance().isSupportedType(event.dataType)) {

                            IStructuredSelection sel = (IStructuredSelection) _treeViewer.getSelection();
                            Layer layer = (Layer) sel.getFirstElement();

                            if (layer != null) {
                                LayerTransfer.getInstance().setSelectedLayer(layer);
                                event.data = layer;
                            }
                        }
                    }

                    @Override
                    public void dragFinished(final DragSourceEvent event) {
                        LayerTransfer.getInstance().setSelectedLayer(null);
                    }

                });
    }

    /**
     * Adds drop support for layers to the specified viewer.
     *
     * @param treeViewer
     *            the viewer that should support dropping of layers
     */
    private void addDropSupport(final TreeViewer treeViewer) {
        // drop
        treeViewer.addDropSupport(DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT,
                new Transfer[] { LayerTransfer.getInstance() }, new DropTargetAdapter() {
                    @Override
                    public void drop(final DropTargetEvent event) {
                        if (LayerTransfer.getInstance().isSupportedType(event.currentDataType)) {
                            // get the layer that was moved
                            Layer movedLayer = (Layer) LayerTransfer.getInstance()
                                    .nativeToJava(event.currentDataType);

                            // get the layer, on which the moved layer was dropped
                            Layer dropLayer = (Layer) (event.item != null ? event.item.getData() : null);

                            if (movedLayer != null && dropLayer != null && _layerSupport != null) {
                                int index = _layerSupport.getLayerIndex(dropLayer);
                                if (_commandStack == null) {
                                    _layerSupport.changeLayerPosition(movedLayer, index);
                                } else {
                                    _commandStack.execute(new MoveLayerCommand(_layerSupport, movedLayer, index));
                                }
                            }
                        }
                    }

                    @Override
                    public void dropAccept(final DropTargetEvent event) {
                        if (!LayerTransfer.getInstance().isSupportedType(event.currentDataType)
                                || event.item == null) {
                            event.detail = DND.DROP_NONE;
                        } else {
                            event.detail = DND.DROP_MOVE;
                        }
                    }

                    @Override
                    public void dragEnter(final DropTargetEvent event) {
                        if (!LayerTransfer.getInstance().isSupportedType(event.currentDataType)
                                || event.item == null) {
                            event.detail = DND.DROP_NONE;
                        } else {
                            event.detail = DND.DROP_MOVE;
                        }
                    }

                    @Override
                    public void dragOver(final DropTargetEvent event) {
                        if (!LayerTransfer.getInstance().isSupportedType(event.currentDataType)
                                || event.item == null) {
                            event.detail = DND.DROP_NONE;
                        } else {
                            event.detail = DND.DROP_MOVE;
                        }
                    }

                });
    }

    /**
     * {@inheritDoc}
     */
    public void layerChanged(final Layer layer, final String property) {
        // just refresh the viewer completely if anything changes
        _treeViewer.refresh();
        _treeViewer.setSelection(new StructuredSelection(_layerSupport.getActiveLayer()));
    }

    /**
     * Sets the selection of the internal {@link TreeViewer}.
     * @param selection The new selection
     */
    public void setSelection(final ISelection selection) {
        _treeViewer.setSelection(selection);
    }

    /**
     * Set the layout data for the internal {@link TreeViewer}.
     * @param layoutData The layout Data
     */
    public void setLayoutData(final Object layoutData) {
        _treeViewer.getTree().setLayoutData(layoutData);
    }

    /**
     * Sets the currently used {@link LayerSupport}.
     * @param layerSupport The {@link LayerSupport}
     */
    public void setLayerSupport(final LayerSupport layerSupport) {
        _layerSupport = layerSupport;
        _layerSupport.addLayerModelListener(this);
        _treeViewer.setInput(_layerSupport);
    }

    /**
     * Sets the currently used {@link CommandStack}.
     * Set the {@link CommandStack} to enable Undo/Redo functionality.
     * @param commandStack The {@link CommandStack} (can be null)
     */
    public void setCommandStack(final CommandStack commandStack) {
        _commandStack = commandStack;
    }

    /**
     * Disposes the {@link TreeViewer}.
     */
    public void dispose() {
        _layerSupport.removeLayerModelListener(this);
        _layerSupport = null;
        _treeViewer.getTree().dispose();
    }

}