/******************************************************************************* * 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: * Alexander Nyßen (itemis AG) - initial API and implementation *******************************************************************************/ package org.eclipse.gef.zest.fx.handlers; import java.util.ArrayList; import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; import java.util.Set; import org.eclipse.gef.geometry.planar.Dimension; import org.eclipse.gef.mvc.fx.handlers.TranslateSelectedOnDragHandler; import org.eclipse.gef.mvc.fx.parts.IContentPart; import org.eclipse.gef.mvc.fx.parts.IVisualPart; import org.eclipse.gef.mvc.fx.parts.PartUtils; import org.eclipse.gef.zest.fx.ZestProperties; import org.eclipse.gef.zest.fx.parts.AbstractLabelPart; import org.eclipse.gef.zest.fx.parts.EdgePart; import org.eclipse.gef.zest.fx.parts.NodePart; import org.eclipse.gef.zest.fx.policies.TransformLabelPolicy; import javafx.scene.Node; import javafx.scene.input.MouseEvent; /** * A specific {@link TranslateSelectedOnDragHandler} that includes dragging of * unselected label parts. * * @author anyssen * */ public class TranslateSelectedAndRelocateLabelsOnDragHandler extends TranslateSelectedOnDragHandler { private List<AbstractLabelPart> labelParts; @Override public void abortDrag() { for (AbstractLabelPart lp : getLabelParts()) { rollback(lp.getAdapter(TransformLabelPolicy.class)); restoreRefreshVisuals(lp); } super.abortDrag(); labelParts = null; } /** * Computes the {@link AbstractLabelPart}s that are anchored to the * {@link #getHost()} of this policy and need to be relocated together with * the host. * * @return The {@link AbstractLabelPart}s that need to be relocated together * with the host. */ protected List<AbstractLabelPart> computeLabelParts() { Set<AbstractLabelPart> labelParts = Collections .newSetFromMap(new IdentityHashMap<AbstractLabelPart, Boolean>()); // ensure that linked parts are moved with us during dragging List<IContentPart<? extends Node>> targetParts = getTargetParts(); for (IVisualPart<? extends Node> tp : targetParts) { if (tp instanceof NodePart) { labelParts.addAll(getNodeLabelParts((NodePart) tp)); for (IVisualPart<? extends javafx.scene.Node> anchored : getHost().getAnchoredsUnmodifiable()) { // add labels of edges if edge is not target part if (anchored instanceof EdgePart && !targetParts.contains(anchored)) { labelParts.addAll(getEdgeLabelParts((EdgePart) anchored)); } } } else if (tp instanceof EdgePart) { labelParts.addAll(getEdgeLabelParts((EdgePart) tp)); } } labelParts.removeAll(targetParts); return new ArrayList<>(labelParts); } @Override public void drag(MouseEvent e, Dimension delta) { super.drag(e, delta); for (AbstractLabelPart lp : getLabelParts()) { lp.getAdapter(TransformLabelPolicy.class).preserveLabelOffset(); } } @Override public void endDrag(MouseEvent e, Dimension delta) { for (AbstractLabelPart lp : getLabelParts()) { commit(lp.getAdapter(TransformLabelPolicy.class)); restoreRefreshVisuals(lp); } super.endDrag(e, delta); labelParts = null; } private List<AbstractLabelPart> getEdgeLabelParts(EdgePart edgePart) { List<AbstractLabelPart> linked = new ArrayList<>(); linked.addAll(new ArrayList<>(PartUtils.filterParts(PartUtils.getAnchoreds(edgePart, ZestProperties.LABEL__NE), AbstractLabelPart.class))); linked.addAll(new ArrayList<>(PartUtils.filterParts( PartUtils.getAnchoreds(edgePart, ZestProperties.EXTERNAL_LABEL__NE), AbstractLabelPart.class))); linked.addAll(new ArrayList<>(PartUtils.filterParts( PartUtils.getAnchoreds(edgePart, ZestProperties.SOURCE_LABEL__E), AbstractLabelPart.class))); linked.addAll(new ArrayList<>(PartUtils.filterParts( PartUtils.getAnchoreds(edgePart, ZestProperties.TARGET_LABEL__E), AbstractLabelPart.class))); return linked; } /** * Returns the {@link AbstractLabelPart}s that were previously determined if * available, otherwise the label parts are {@link #computeLabelParts() * computed} and saved. * * @return The {@link AbstractLabelPart}s that were previously determined by * {@link #computeLabelParts()}. */ protected List<AbstractLabelPart> getLabelParts() { if (labelParts == null) { labelParts = computeLabelParts(); } return labelParts; } private List<AbstractLabelPart> getNodeLabelParts(NodePart nodePart) { return new ArrayList<>(PartUtils.filterParts( PartUtils.getAnchoreds(nodePart, ZestProperties.EXTERNAL_LABEL__NE), AbstractLabelPart.class)); } @Override public void startDrag(MouseEvent e) { super.startDrag(e); // init label transform policies for (AbstractLabelPart lp : getLabelParts()) { storeAndDisableRefreshVisuals(lp); init(lp.getAdapter(TransformLabelPolicy.class)); } } }