/*
* License (BSD Style License):
* Copyright (c) 2011
* Software Engineering
* Department of Computer Science
* Technische Universität Darmstadt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Software Engineering Group or Technische
* Universität Darmstadt nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.tud.cs.st.vespucci.vespucci_model.diagram.part;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.ui.parts.SelectionSynchronizer;
import org.eclipse.gef.ui.parts.TreeViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
/**
* SelectionSynchronizer for view components
*
* @author Artem Vovk
*
*/
public class VespucciSelectionSynchronizer extends SelectionSynchronizer {
private final List<EditPartViewer> viewers = new ArrayList<EditPartViewer>();
private boolean isDispatching = false;
private int disabled = 0;
private EditPartViewer pendingSelection;
/**
* Adds a viewer to the set of synchronized viewers
*
* @param viewer
* the viewer
*/
@Override
public void addViewer(final EditPartViewer viewer) {
viewer.addSelectionChangedListener(this);
viewers.add(viewer);
}
/**
* @param viewer
* the viewer to search in
* @param part
* a part from different viewer
* @return Returns EditPart associated with given EditPart in given viewer.
*/
protected List<EditPart> getAssociatedParts(final EditPartViewer viewer, final EditPart part) {
final List<EditPart> parts = new ArrayList<EditPart>();
final EditPart temp = (EditPart) viewer.getEditPartRegistry().get(part.getModel());
if (temp != null) {
int selectionCounter = 0;
if (viewer instanceof TreeViewer) {
final List<?> editParts = viewer.getSelectedEditParts();
for (final Object o : editParts) {
final EditPart editPart = (EditPart) o;
if (editPart.getModel() == temp.getModel()) {
selectionCounter++;
parts.add(editPart);
}
}
// TODO: Why does adding temp depend on selectionCounter?
if (selectionCounter == 1) {
return parts;
} else if (selectionCounter > 1) {
parts.add(temp);
return parts;
}
}
EditPart newPart = null;
newPart = temp;
parts.add(newPart);
}
return parts;
}
/**
* Removes the viewer from the set of synchronized viewers
*
* @param viewer
* the viewer to remove
*/
@Override
public void removeViewer(final EditPartViewer viewer) {
viewer.removeSelectionChangedListener(this);
viewers.remove(viewer);
if (pendingSelection == viewer) {
pendingSelection = null;
}
}
/**
* Receives notification from one viewer, and maps selection to all other
* members.
*
* @param event
* the selection event
*/
@Override
public void selectionChanged(final SelectionChangedEvent event) {
if (isDispatching) {
return;
}
final EditPartViewer source = (EditPartViewer) event.getSelectionProvider();
if (disabled > 0) {
pendingSelection = source;
} else {
final ISelection selection = event.getSelection();
syncSelection(source, selection);
}
}
private void syncSelection(final EditPartViewer source, final ISelection selection) {
isDispatching = true;
for (int i = 0; i < viewers.size(); i++) {
if (viewers.get(i) != source) {
final EditPartViewer viewer = viewers.get(i);
setViewerSelection(viewer, selection);
}
}
isDispatching = false;
}
/**
* Enables or disabled synchronization between viewers.
*
* @since 3.1
* @param value
* <code>true</code> if synchronization should occur
*/
@Override
public void setEnabled(final boolean value) {
if (!value) {
disabled++;
} else if (--disabled == 0 && pendingSelection != null) {
syncSelection(pendingSelection, pendingSelection.getSelection());
pendingSelection = null;
}
}
private void setViewerSelection(final EditPartViewer viewer, final ISelection selection) {
final ArrayList<EditPart> result = new ArrayList<EditPart>();
@SuppressWarnings("unchecked")
final Iterator<EditPart> iter = ((IStructuredSelection) selection).iterator();
while (iter.hasNext()) {
final List<EditPart> parts = getAssociatedParts(viewer, iter.next());
if (parts != null) {
result.addAll(parts);
}
}
viewer.setSelection(new StructuredSelection(result));
if (result.size() > 0) {
viewer.reveal(result.get(result.size() - 1));
}
}
}