/*******************************************************************************
* 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.parts;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.gef.graph.Edge;
import org.eclipse.gef.graph.Graph;
import org.eclipse.gef.mvc.fx.parts.AbstractContentPart;
import org.eclipse.gef.mvc.fx.parts.IVisualPart;
import org.eclipse.gef.zest.fx.ZestProperties;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.util.Pair;
/**
* The {@link GraphPart} is the controller for a {@link Graph} content object.
* It starts a layout pass after activation and when its content children
* change.
*
* @author mwienand
*
*/
// TODO: most of the listeners should probably be moved to GraphLayoutBehavior
public class GraphPart extends AbstractContentPart<Group> {
private ListChangeListener<Object> graphChildrenObserver = new ListChangeListener<Object>() {
@Override
public void onChanged(ListChangeListener.Change<? extends Object> c) {
// synchronize children (triggered through content children)
refreshContentChildren();
refreshVisual();
}
};
@Override
protected void doActivate() {
super.doActivate();
getContent().getNodes().addListener(graphChildrenObserver);
getContent().getEdges().addListener(graphChildrenObserver);
}
@Override
protected void doAddChildVisual(IVisualPart<? extends Node> child, int index) {
getVisual().getChildren().add(index, child.getVisual());
}
@Override
protected Group doCreateVisual() {
Group visual = new Group();
visual.setAutoSizeChildren(false);
return visual;
}
@Override
protected void doDeactivate() {
getContent().getNodes().removeListener(graphChildrenObserver);
getContent().getEdges().removeListener(graphChildrenObserver);
super.doDeactivate();
}
@Override
protected SetMultimap<? extends Object, String> doGetContentAnchorages() {
return HashMultimap.create();
}
@Override
protected List<? extends Object> doGetContentChildren() {
List<Object> children = new ArrayList<>();
// collect visible nodes
ObservableList<org.eclipse.gef.graph.Node> nodes = getContent().getNodes();
ArrayList<org.eclipse.gef.graph.Node> visibleNodes = new ArrayList<>();
for (org.eclipse.gef.graph.Node n : nodes) {
if (!Boolean.TRUE.equals(ZestProperties.getInvisible(n))) {
visibleNodes.add(n);
}
}
// add visible nodes
children.addAll(visibleNodes);
// add labels for visible nodes
for (org.eclipse.gef.graph.Node n : visibleNodes) {
if (ZestProperties.getExternalLabel(n) != null) {
children.add(new Pair<>(n, ZestProperties.EXTERNAL_LABEL__NE));
}
}
// collect visible edges
ObservableList<Edge> edges = getContent().getEdges();
ArrayList<Edge> visibleEdges = new ArrayList<>();
for (Edge e : edges) {
if (!Boolean.TRUE.equals(ZestProperties.getInvisible(e)) && e.getSource() != null
&& !Boolean.TRUE.equals(ZestProperties.getInvisible(e.getSource())) && e.getTarget() != null
&& !Boolean.TRUE.equals(ZestProperties.getInvisible(e.getTarget()))) {
visibleEdges.add(e);
}
}
// add visible edges
children.addAll(visibleEdges);
// add labels for visible edges
for (Edge e : visibleEdges) {
if (ZestProperties.getLabel(e) != null) {
children.add(new Pair<>(e, ZestProperties.LABEL__NE));
}
if (ZestProperties.getExternalLabel(e) != null) {
children.add(new Pair<>(e, ZestProperties.EXTERNAL_LABEL__NE));
}
if (ZestProperties.getSourceLabel(e) != null) {
children.add(new Pair<>(e, ZestProperties.SOURCE_LABEL__E));
}
if (ZestProperties.getTargetLabel(e) != null) {
children.add(new Pair<>(e, ZestProperties.TARGET_LABEL__E));
}
}
return children;
}
@Override
public void doRefreshVisual(Group visual) {
}
@Override
protected void doRemoveChildVisual(IVisualPart<? extends Node> child, int index) {
getVisual().getChildren().remove(child.getVisual());
}
@Override
public Graph getContent() {
return (Graph) super.getContent();
}
@Override
public boolean isSelectable() {
return false;
}
}