/******************************************************************************* * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada. * 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: The Chisel Group, University of Victoria ******************************************************************************/ package org.eclipse.zest.core.viewers.internal; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.zest.core.viewers.EntityConnectionData; import org.eclipse.zest.core.viewers.IFigureProvider; import org.eclipse.zest.core.viewers.IGraphEntityContentProvider; import org.eclipse.zest.core.widgets.Graph; import org.eclipse.zest.core.widgets.GraphConnection; import org.eclipse.zest.core.widgets.GraphItem; import org.eclipse.zest.core.widgets.GraphNode; /* * * @author Ian Bull */ public class GraphModelEntityFactory extends AbstractStylingModelFactory { AbstractStructuredGraphViewer viewer = null; public GraphModelEntityFactory(AbstractStructuredGraphViewer viewer) { super(viewer); this.viewer = viewer; } /* * (non-Javadoc) * * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#createGraphModel() */ public Graph createGraphModel(Graph model) { doBuildGraph(model); return model; } /* * (non-Javadoc) * * @see org.eclipse.zest.core.internal.graphmodel.AbstractStylingModelFactory#doBuildGraph(org.eclipse.zest.core.internal.graphmodel.GraphModel) */ protected void doBuildGraph(Graph model) { super.doBuildGraph(model); Object inputElement = getViewer().getInput(); Object entities[] = getContentProvider().getElements(inputElement); if (entities == null) { return; } for (int i = 0; i < entities.length; i++) { Object data = entities[i]; IFigureProvider figureProvider = null; if (getLabelProvider() instanceof IFigureProvider) { figureProvider = (IFigureProvider) getLabelProvider(); } if (!filterElement(inputElement, data)) { if (figureProvider != null) { createNode(model, data, figureProvider.getFigure(data)); } else { createNode(model, data); } } } // We may have other entities (such as children of containers) Set keySet = ((AbstractStructuredGraphViewer) getViewer()).getNodesMap().keySet(); entities = keySet.toArray(); for (int i = 0; i < entities.length; i++) { Object data = entities[i]; // If this element is filtered, continue to the next one. if (filterElement(inputElement, data)) { continue; } Object[] related = ((IGraphEntityContentProvider) getContentProvider()).getConnectedTo(data); if (related != null) { for (int j = 0; j < related.length; j++) { // if the node this node is connected to is filtered, // don't display this edge if (filterElement(inputElement, related[j])) { continue; } EntityConnectionData connectionData = new EntityConnectionData(data, related[j]); if (filterElement(inputElement, connectionData)) { continue; } createConnection(model, connectionData, data, related[j]); } } } } /* * (non-Javadoc) * * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.zest.core.internal.graphmodel.GraphModel, * java.lang.Object) */ public void refresh(Graph graph, Object element, boolean refreshLabels) { if (element == null) { return; } GraphNode node = viewer.getGraphModelNode(element); if (node == null) { // check to make sure that the user didn't send us an edge. GraphConnection conn = viewer.getGraphModelConnection(element); if (conn != null) { // refresh on the connected nodes. refresh(graph, conn.getSource().getData(), refreshLabels); refresh(graph, conn.getDestination().getData(), refreshLabels); return; } } // can only refresh on nodes in this kind of factory. if (node == null) { // do nothing return; } reconnect(graph, element, refreshLabels); if (refreshLabels) { update(node); for (Iterator it = node.getSourceConnections().iterator(); it.hasNext();) { update((GraphItem) it.next()); } for (Iterator it = node.getTargetConnections().iterator(); it.hasNext();) { update((GraphItem) it.next()); } } } /** * @param graph * @param element * @param refreshLabels */ private void reconnect(Graph graph, Object element, boolean refreshLabels) { GraphNode node = viewer.getGraphModelNode(element); Object[] related = ((IGraphEntityContentProvider) getContentProvider()).getConnectedTo(element); List connections = node.getSourceConnections(); LinkedList toAdd = new LinkedList(); LinkedList toDelete = new LinkedList(); LinkedList toKeep = new LinkedList(); HashSet oldExternalConnections = new HashSet(); HashSet newExternalConnections = new HashSet(); for (Iterator it = connections.iterator(); it.hasNext();) { oldExternalConnections.add(((GraphConnection) it.next()).getExternalConnection()); } for (int i = 0; i < related.length; i++) { newExternalConnections.add(new EntityConnectionData(element, related[i])); } for (Iterator it = oldExternalConnections.iterator(); it.hasNext();) { Object next = it.next(); if (!newExternalConnections.contains(next)) { toDelete.add(next); } else { toKeep.add(next); } } for (Iterator it = newExternalConnections.iterator(); it.hasNext();) { Object next = it.next(); if (!oldExternalConnections.contains(next)) { toAdd.add(next); } } for (Iterator it = toDelete.iterator(); it.hasNext();) { viewer.removeGraphModelConnection(it.next()); } toDelete.clear(); LinkedList newNodeList = new LinkedList(); for (Iterator it = toAdd.iterator(); it.hasNext();) { EntityConnectionData data = (EntityConnectionData) it.next(); GraphNode dest = viewer.getGraphModelNode(data.dest); if (dest == null) { newNodeList.add(data.dest); } createConnection(graph, data, data.source, data.dest); } toAdd.clear(); if (refreshLabels) { for (Iterator i = toKeep.iterator(); i.hasNext();) { styleItem(viewer.getGraphModelConnection(i.next())); } } for (Iterator it = newNodeList.iterator(); it.hasNext();) { // refresh the new nodes so that we get a fully-up-to-date graph. refresh(graph, it.next()); } } /* * (non-Javadoc) * * @see org.eclipse.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.zest.core.internal.graphmodel.GraphModel, * java.lang.Object, boolean) */ public void refresh(Graph graph, Object element) { refresh(graph, element, false); } }