/******************************************************************************* * Copyright (c) 2014, 2016 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 Nyßen (itemis AG) - initial API and implementation * *******************************************************************************/ package org.eclipse.gef.mvc.fx.ui.parts; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.gef.mvc.fx.models.SelectionModel; import org.eclipse.gef.mvc.fx.parts.IContentPart; import org.eclipse.gef.mvc.fx.viewer.IViewer; import org.eclipse.jface.util.SafeRunnable; 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 org.eclipse.ui.services.IDisposable; import javafx.collections.ListChangeListener; import javafx.scene.Node; /** * The {@link ContentSelectionProvider} is an {@link ISelectionProvider} * implementation that manages the un-/registration of listeners and their * execution upon selection changes. * * @author anyssen * */ public class ContentSelectionProvider implements ISelectionProvider, IDisposable { private class SelectionObserver implements ListChangeListener<IContentPart<? extends Node>> { @Override public void onChanged( ListChangeListener.Change<? extends IContentPart<? extends Node>> c) { // notify listeners that selection has changed final SelectionChangedEvent e = new SelectionChangedEvent( ContentSelectionProvider.this, getSelection()); for (final ISelectionChangedListener l : selectionChangedListeners) { SafeRunner.run(new SafeRunnable() { @Override public void run() { l.selectionChanged(e); } }); } } } private final SelectionObserver selectionObserver = new SelectionObserver(); private List<ISelectionChangedListener> selectionChangedListeners = new ArrayList<>(); private IViewer viewer; private SelectionModel selectionModel; /** * Creates a new {@link ContentSelectionProvider} for the given * {@link SelectionModel}. * * @param viewer * The {@link IViewer} to associate this * {@link ContentSelectionProvider} to. */ public ContentSelectionProvider(IViewer viewer) { this.viewer = viewer; this.selectionModel = viewer.getAdapter(SelectionModel.class); selectionModel.getSelectionUnmodifiable() .addListener(selectionObserver); } @Override public void addSelectionChangedListener( ISelectionChangedListener listener) { selectionChangedListeners.add(listener); } @Override public void dispose() { if (selectionModel != null) { selectionModel.getSelectionUnmodifiable() .removeListener(selectionObserver); } } @Override public ISelection getSelection() { ISelection selection = StructuredSelection.EMPTY; if (!selectionModel.getSelectionUnmodifiable().isEmpty()) { // extract content elements of selected parts List<? extends IContentPart<? extends Node>> selectedContentParts = selectionModel .getSelectionUnmodifiable(); List<Object> selectedContentElements = new ArrayList<>( selectedContentParts.size()); for (IContentPart<? extends Node> cp : selectedContentParts) { selectedContentElements.add(cp.getContent()); } // return the content elements as our selection selection = new StructuredSelection(selectedContentElements); } return selection; } /** * Returns the {@link IViewer} this {@link ContentSelectionProvider} is * bound to. * * @return The {@link IViewer} this {@link ContentSelectionProvider} is * bound to. */ protected IViewer getViewer() { return viewer; } @Override public void removeSelectionChangedListener( ISelectionChangedListener listener) { selectionChangedListeners.remove(listener); } @Override public void setSelection(ISelection selection) { // update the selection model, which will lead to an update of our // selection and to listener notification. if (selection.isEmpty()) { if (!selectionModel.getSelectionUnmodifiable().isEmpty()) { selectionModel.clearSelection(); } } else if (selection instanceof StructuredSelection) { // find the content parts associated with the selection Object[] selected = ((StructuredSelection) selection).toArray(); List<IContentPart<? extends Node>> parts = new ArrayList<>( selected.length); for (Object content : selected) { IContentPart<? extends Node> part = viewer.getContentPartMap() .get(content); if (part != null) { parts.add(part); } } // set the content parts as the new selection to the SelectionModel if (!selectionModel.getSelectionUnmodifiable().equals(parts)) { selectionModel.setSelection(parts); } } } }