org.eclipse.gef4.mvc.fx.ui.parts.SelectionForwarder.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gef4.mvc.fx.ui.parts.SelectionForwarder.java

Source

/*******************************************************************************
 * Copyright (c) 2014, 2015 itemis AG 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:
 *     Alexander Nyen (itemis AG) - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.gef4.mvc.fx.ui.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.gef4.common.reflect.Types;
import org.eclipse.gef4.mvc.models.SelectionModel;
import org.eclipse.gef4.mvc.parts.IContentPart;
import org.eclipse.gef4.mvc.viewer.IViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;

import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;

/**
 * The {@link SelectionForwarder} can be used to propagate selections from the
 * Eclipse workbench to the MVC application and vice versa.
 *
 * @author anyssen
 *
 * @param <VR>
 *            The visual root node of the UI toolkit, e.g. javafx.scene.Node in
 *            case of JavaFX.
 */
public class SelectionForwarder<VR> implements PropertyChangeListener, ISelectionChangedListener {

    private final ISelectionProvider selectionProvider;
    private final IViewer<VR> viewer;
    private final SelectionModel<VR> selectionModel;

    /**
     * Creates a new {@link SelectionForwarder} that registers listeners on the
     * given {@link ISelectionProvider} and the {@link SelectionModel} of the
     * given {@link IViewer} to propagate selections from the Eclipse workbench
     * to the viewer, and vice versa.
     *
     * @param selectionProvider
     *            The {@link ISelectionProvider} of the Eclipse workbench
     * @param viewer
     *            The {@link IViewer} of which the {@link SelectionModel} should
     *            be held in sync with the Eclipse workbench selection.
     */
    public SelectionForwarder(final ISelectionProvider selectionProvider, IViewer<VR> viewer) {
        if (viewer == null) {
            throw new IllegalArgumentException("The given IViewer<VR> may not be null.");
        }
        this.selectionProvider = selectionProvider;
        this.viewer = viewer;
        this.selectionModel = getSelectionModel();

        // register listeners
        if (selectionProvider != null) {
            selectionProvider.addSelectionChangedListener(this);
        }
        selectionModel.addPropertyChangeListener(this);
    }

    /**
     * Unregisters all listeners.
     */
    public void dispose() {
        // unregister listeners
        if (this.selectionProvider != null) {
            this.selectionProvider.removeSelectionChangedListener(this);
        }
        if (selectionModel != null) {
            selectionModel.removePropertyChangeListener(this);
        }
    }

    /**
     * Returns the {@link SelectionModel} attached to the viewer.
     *
     * @return The {@link SelectionModel} that should be used.
     */
    @SuppressWarnings("serial")
    protected SelectionModel<VR> getSelectionModel() {
        SelectionModel<VR> selectionModel = viewer.getAdapter(new TypeToken<SelectionModel<VR>>() {
        }.where(new TypeParameter<VR>() {
        }, Types.<VR>argumentOf(viewer.getClass())));
        return selectionModel;
    }

    @Override
    public void propertyChange(final PropertyChangeEvent event) {
        if (SelectionModel.SELECTION_PROPERTY.equals(event.getPropertyName())) {
            // forward selection changes to selection provider (in case
            // there is any)
            if (event.getNewValue() == null) {
                selectionProvider.setSelection(StructuredSelection.EMPTY);
            } else {
                // extract content elements of selected parts
                @SuppressWarnings("unchecked")
                List<IContentPart<VR, ? extends VR>> selectedParts = (List<IContentPart<VR, ? extends VR>>) event
                        .getNewValue();
                List<Object> selectedContentElements = new ArrayList<>(selectedParts.size());
                for (IContentPart<VR, ? extends VR> cp : selectedParts) {
                    selectedContentElements.add(cp.getContent());
                }
                // set the content elements as the new selection on the
                // selection provider
                // TODO: verify no events are fired when the same selection is
                // set again
                selectionProvider.setSelection(new StructuredSelection(selectedContentElements));
            }
        }
    }

    @Override
    public void selectionChanged(SelectionChangedEvent event) {
        ISelection selection = event.getSelection();
        if (selection instanceof StructuredSelection) {
            StructuredSelection sel = (StructuredSelection) selection;
            if (sel.isEmpty()) {
                selectionModel.prependToSelection(Collections.<IContentPart<VR, ? extends VR>>emptyList());
            } else {
                // find the content parts associated with the selection
                Object[] selected = sel.toArray();
                List<IContentPart<VR, ? extends VR>> parts = new ArrayList<>(selected.length);
                for (Object content : selected) {
                    IContentPart<VR, ? extends VR> part = viewer.getContentPartMap().get(content);
                    if (part != null) {
                        parts.add(part);
                    }
                }
                // set the content parts as the new selection on the
                // SelectionModel
                if (!selectionModel.getSelection().equals(parts)) {
                    selectionModel.prependToSelection(parts);
                }
            }
        }
    }

}