/******************************************************************************* * 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: * Matthias Wienand (itemis AG) - initial API & implementation * *******************************************************************************/ package org.eclipse.gef.zest.fx.behaviors; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.gef.mvc.fx.parts.IVisualPart; import org.eclipse.gef.zest.fx.models.HidingModel; import org.eclipse.gef.zest.fx.parts.HiddenNeighborsFeedbackPart; import org.eclipse.gef.zest.fx.parts.NodePart; import javafx.collections.SetChangeListener; import javafx.scene.Node; /** * The {@link NodeHidingBehavior} is specific to {@link NodePart}. It registers * listeners on the {@link HidingModel} upon activation. When the * {@link HidingModel} changes, the hidden status of the {@link NodePart} is * determined. If the hidden status of the part changed, either {@link #hide()} * or {@link #show()} will be called, respectively, to hide/show the part. * Additionally, a {@link HiddenNeighborsFeedbackPart} is managed by this * {@link NodeHidingBehavior}. The {@link HiddenNeighborsFeedbackPart} shows the * number of hidden neighbors of the {@link NodePart}. * * @author mwienand * */ // Only applicable for NodePart (see #getHost()) public class NodeHidingBehavior extends AbstractHidingBehavior { private IVisualPart<? extends Node> hiddenNeighborsFeedbackPart; private boolean containsAny(Set<org.eclipse.gef.graph.Node> hidden, Set<org.eclipse.gef.graph.Node> neighbors) { boolean containsAny = false; for (org.eclipse.gef.graph.Node n : neighbors) { if (hidden.contains(n)) { containsAny = true; break; } } return containsAny; } /** * Creates the {@link HiddenNeighborsFeedbackPart} that shows the hidden * neighbors of the {@link NodePart} on which this * {@link NodeHidingBehavior} is installed. */ protected void createHiddenNeighborsFeedbackPart() { if (hiddenNeighborsFeedbackPart == null) { // TODO: delegate to factory, ensure adaptable context is updated // before hiddenNeighborsFeedbackPart = new HiddenNeighborsFeedbackPart(); } addAnchoreds(Collections.singletonList(getHost()), Collections.singletonList(hiddenNeighborsFeedbackPart)); } @Override protected boolean determineHiddenStatus() { return getHidingModel().isHidden(getHost().getContent()); } @Override protected void doActivate() { super.doActivate(); // create hidden neighbors part if it is already associated with our // host if (getHidingModel().hasHiddenNeighbors(getHost())) { createHiddenNeighborsFeedbackPart(); } } @Override protected void doDeactivate() { // remove hidden neighbors part if it is currently associated with our // host if (getHidingModel().hasHiddenNeighbors(getHost())) { removeHiddenNeighborsFeedbackPart(); } super.doDeactivate(); } /** * Returns the {@link HiddenNeighborsFeedbackPart} that is managed by this * {@link NodeHidingBehavior}. * * @return The {@link HiddenNeighborsFeedbackPart} that is managed by this * {@link NodeHidingBehavior}. */ protected IVisualPart<? extends Node> getHiddenNeighborsFeedbackPart() { return hiddenNeighborsFeedbackPart; } @Override public NodePart getHost() { return (NodePart) super.getHost(); } @Override protected void onHidingModelChange(SetChangeListener.Change<? extends org.eclipse.gef.graph.Node> change) { super.onHidingModelChange(change); Set<org.eclipse.gef.graph.Node> newHidden = new HashSet<>(change.getSet()); Set<org.eclipse.gef.graph.Node> oldHidden = new HashSet<>(change.getSet()); oldHidden.remove(change.getElementAdded()); oldHidden.add(change.getElementRemoved()); // check if we have to show/hide/update the pruned neighbors part org.eclipse.gef.graph.Node content = getHost().getContent(); Set<org.eclipse.gef.graph.Node> neighbors = content.getNeighbors(); if (!containsAny(oldHidden, neighbors) && containsAny(newHidden, neighbors)) { createHiddenNeighborsFeedbackPart(); } else if (containsAny(oldHidden, neighbors) && !containsAny(newHidden, neighbors)) { removeHiddenNeighborsFeedbackPart(); } else { // TODO: only necessary when neighbors change if (hiddenNeighborsFeedbackPart != null) { updateHiddenNeighborsFeedbackPart(); } } } /** * Removes the {@link HiddenNeighborsFeedbackPart} that is managed by this * {@link NodeHidingBehavior}. */ protected void removeHiddenNeighborsFeedbackPart() { removeAnchoreds(Collections.singletonList(getHost()), Collections.singletonList(hiddenNeighborsFeedbackPart)); } /** * Refreshes the {@link HiddenNeighborsFeedbackPart} that is managed by this * {@link NodeHidingBehavior}. */ protected void updateHiddenNeighborsFeedbackPart() { hiddenNeighborsFeedbackPart.refreshVisual(); } }