/******************************************************************************* * 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.parts; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; import org.eclipse.gef.common.adapt.AdapterKey; import org.eclipse.gef.fx.utils.NodeUtils; import org.eclipse.gef.geometry.convert.fx.FX2Geometry; import org.eclipse.gef.geometry.planar.Rectangle; import org.eclipse.gef.mvc.fx.domain.IDomain; import org.eclipse.gef.mvc.fx.viewer.IViewer; import com.google.common.collect.Multiset; import javafx.scene.Node; import javafx.scene.Scene; /** * Provides utilities needed in the context of {@link IVisualPart}s. * * @author anyssen * */ public class PartUtils { /** * Searches the given collection of {@link IVisualPart}s for elements of the * specified type. * * @param <T> * The type of returned elements. * @param parts * The collection of parts which is filtered. * @param type * The type of returned elements. * @return A list of all elements of the specified type. */ public static <T extends IVisualPart<? extends Node>> List<T> filterParts( Collection<? extends IVisualPart<? extends Node>> parts, Class<T> type) { return filterParts(parts, (p) -> type.isInstance(p)); } /** * Searches the given collection of {@link IVisualPart}s for elements of the * specified type. * * @param <T> * The type of returned elements. * @param parts * The collection of parts which is filtered. * @param filter * The type of returned elements. * @return A list of all elements of the specified type. */ @SuppressWarnings("unchecked") public static <T extends IVisualPart<? extends Node>> List<T> filterParts( Collection<? extends IVisualPart<? extends Node>> parts, Predicate<? super IVisualPart<? extends Node>> filter) { List<T> filtered = new ArrayList<>(); for (IVisualPart<? extends Node> c : parts) { if (filter.test(c)) { filtered.add((T) c); } } return filtered; } /** * Collects the anchoreds of all given {@link IVisualPart}s. * * @param anchorages * The collection of {@link IVisualPart}s for which the anchoreds * are collected. * @return A list of all the anchoreds of all the given {@link IVisualPart} * s. */ public static List<IVisualPart<? extends Node>> getAnchoreds( Collection<? extends IVisualPart<? extends Node>> anchorages) { List<IVisualPart<? extends Node>> anchoreds = new ArrayList<>(); for (IVisualPart<? extends Node> a : anchorages) { anchoreds.addAll(a.getAnchoredsUnmodifiable()); } return anchoreds; } /** * Collects the anchoreds of the given {@link IVisualPart} which are * registered under the specified role. * * @param anchorage * The {@link IVisualPart} for which the anchoreds are collected. * @param role * The role under which the anchoreds have to be registered to be * collected. * @return A list of the anchoreds of the given {@link IVisualPart} which * are registered under the specified role. */ public static Set<IVisualPart<? extends Node>> getAnchoreds( IVisualPart<? extends Node> anchorage, String role) { HashSet<IVisualPart<? extends Node>> result = new HashSet<>(); Multiset<IVisualPart<? extends Node>> anchoreds = anchorage .getAnchoredsUnmodifiable(); for (IVisualPart<? extends Node> anchored : anchoreds) { if (anchored.getAnchoragesUnmodifiable().containsEntry(anchorage, role)) { result.add(anchored); } } return result; } /** * Returns the unioned visual bounds of the given {@link IVisualPart}s in * the coordinate system of the {@link Scene}. * * @param parts * The {@link IVisualPart}s for which the unioned bounds are * computed. * @return The unioned visual bounds of the given {@link IVisualPart}s in * the coordinate system of the {@link Scene}. */ public static Rectangle getUnionedVisualBoundsInScene( Collection<? extends IVisualPart<? extends Node>> parts) { Rectangle bounds = null; for (IVisualPart<? extends Node> part : parts) { Rectangle boundsInScene = FX2Geometry.toRectangle(part.getVisual() .localToScene(part.getVisual().getLayoutBounds())); if (bounds == null) { bounds = boundsInScene; } else { bounds.union(boundsInScene); } } return bounds; } /** * Returns the {@link IViewer} of the given {@link IDomain} in which the * given {@link Node} is contained, or <code>null</code> if the given * {@link Node} is not contained within an {@link IViewer} of the given * {@link IDomain}. * * @param domain * The {@link IDomain} that contains the {@link IViewer}s that * are tested to contain the given target {@link Node}. * @param target * The {@link Node} for which to determine the containg * {@link IViewer}. * @return The {@link IViewer} in which the given target {@link Node} is * contained, or <code>null</code>. */ public static IViewer retrieveViewer(IDomain domain, Node target) { // determine viewers within domain Map<AdapterKey<? extends IViewer>, IViewer> viewers = domain .getAdapters(IViewer.class); // test if the target node is contained within any of the viewers for (IViewer viewer : viewers.values()) { if (NodeUtils.isNested(viewer.getCanvas(), target)) { return viewer; } } // visual is not contained within any of the viewers of the given domain return null; } /** * Returns the first {@link IVisualPart} in the visual hierarchy of the * given {@link Node}. If no {@link IVisualPart} can be found within the * visual hierarchy of the {@link Node}, the {@link IRootPart} of the given * {@link IViewer} is returned. * * @param viewer * The {@link IViewer} in which the {@link IVisualPart} is * searched. * @param target * The {@link Node} for which the corresponding * {@link IVisualPart} is to be returned. * @return The first {@link IVisualPart} in the visual hierarchy of the * given {@link Node}, or the {@link IRootPart} of the given * {@link IViewer}. */ public static IVisualPart<? extends Node> retrieveVisualPart(IViewer viewer, Node target) { // search for the first visual part in the visual hierarchy IVisualPart<? extends Node> targetPart = null; while (targetPart == null && target != null) { targetPart = viewer.getVisualPartMap().get(target); target = target.getParent(); } // fallback to the root part if no target part was found if (targetPart == null) { targetPart = viewer.getRootPart(); } return targetPart; } }