/*******************************************************************************
* Copyright (c) 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:
* Matthias Wienand (itemis AG) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.gef.mvc.fx.handlers;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.gef.geometry.planar.Dimension;
import org.eclipse.gef.mvc.fx.models.SelectionModel;
import org.eclipse.gef.mvc.fx.parts.IContentPart;
import org.eclipse.gef.mvc.fx.parts.IVisualPart;
import org.eclipse.gef.mvc.fx.policies.BendConnectionPolicy;
import javafx.scene.Node;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
/**
* Triggers a normalization of the control points of all content parts that
* support {@link BendConnectionPolicy} and are anchored to the host of this
* policy.
*
* @author mwienand
*
*/
public class NormalizeConnectedOnDragHandler extends AbstractHandler
implements IOnDragHandler {
private Set<IVisualPart<? extends Node>> targetParts;
private boolean invalidGesture = false;
@Override
public void abortDrag() {
if (invalidGesture) {
return;
}
for (IVisualPart<? extends Node> part : targetParts) {
rollback(part.getAdapter(BendConnectionPolicy.class));
restoreRefreshVisuals(part);
}
targetParts = null;
}
/**
* Determines the target parts for this policy.
*
* @return The {@link IVisualPart} that should be considered as target
* parts.
*/
protected Set<IVisualPart<? extends Node>> determineTargetParts() {
Set<IVisualPart<? extends Node>> targetParts = Collections
.newSetFromMap(
new IdentityHashMap<IVisualPart<? extends Node>, Boolean>());
for (IVisualPart<? extends Node> anchored : getHost()
.getAnchoredsUnmodifiable()) {
if (anchored instanceof IContentPart) {
BendConnectionPolicy bendConnectionPolicy = anchored
.getAdapter(BendConnectionPolicy.class);
if (bendConnectionPolicy != null
&& !targetParts.contains(anchored)) {
targetParts.add(anchored);
}
}
}
// filter out selected
SelectionModel selectionModel = getHost().getRoot().getViewer()
.getAdapter(SelectionModel.class);
Iterator<IVisualPart<? extends Node>> it = targetParts.iterator();
while (it.hasNext()) {
IVisualPart<? extends Node> part = it.next();
if (part instanceof IContentPart && selectionModel
.isSelected((IContentPart<? extends Node>) part)) {
it.remove();
}
}
return targetParts;
}
@Override
public void drag(MouseEvent e, Dimension delta) {
if (invalidGesture) {
return;
}
for (IVisualPart<? extends Node> part : targetParts) {
part.getAdapter(BendConnectionPolicy.class).normalize();
}
}
@Override
public void endDrag(MouseEvent e, Dimension delta) {
if (invalidGesture) {
return;
}
for (IVisualPart<? extends Node> part : targetParts) {
commit(part.getAdapter(BendConnectionPolicy.class));
restoreRefreshVisuals(part);
}
targetParts = null;
}
@Override
public void hideIndicationCursor() {
}
/**
* Returns <code>true</code> if the given {@link MouseEvent} should trigger
* normalization. Otherwise returns <code>false</code>. Per default always
* returns <code>true</code> if there are target parts.
*
* @param event
* The {@link MouseEvent} in question.
* @return <code>true</code> to indicate that the given {@link MouseEvent}
* should trigger normalization, otherwise <code>false</code>.
*/
protected boolean isNormalize(MouseEvent event) {
return !targetParts.isEmpty();
}
@Override
public boolean showIndicationCursor(KeyEvent event) {
return false;
}
@Override
public boolean showIndicationCursor(MouseEvent event) {
return false;
}
@Override
public void startDrag(MouseEvent e) {
targetParts = determineTargetParts();
invalidGesture = !isNormalize(e);
if (invalidGesture) {
return;
}
for (IVisualPart<? extends Node> part : targetParts) {
storeAndDisableRefreshVisuals(part);
init(part.getAdapter(BendConnectionPolicy.class));
}
}
}