/*
* Copyright (c) 2004- michael lawley and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation
* which accompanies this distribution, and is available by writing to
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Contributors:
* michael lawley
*
*
*
*/
package tefkat.engine.view;
import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.jgraph.graph.ConnectionSet;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.DefaultPort;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.Port;
/**
* @author lawley
*
*/
public abstract class AbstractResourceModel extends DefaultGraphModel {
protected List modelCells;
protected Map cellMap;
static final float[] DASH_PATTERN = { 2f, 4f };
static int width = 80;
static int height = 40;
static int gap = 5;
protected boolean includeRefs = false;
protected abstract void addAll();
public DefaultGraphCell getGraphCell(Object obj) {
return (DefaultGraphCell) cellMap.get(obj);
}
/**
* Supplied objects were added to the Resource - update the model with
* Cells and Edges as required.
*
* @param nodes
*/
protected void addAll(List nodes) {
ArrayList cells = new ArrayList();
Map attrs = new HashMap();
ConnectionSet cs = new ConnectionSet();
addAllNodes(cells, attrs, cs, null, nodes, 0, 0);
addReferencedObjects(cells, attrs, cs);
addReferenceEdges(cells, attrs, cs);
insert(cells.toArray(), attrs, cs, null, null);
}
/**
* Supplied objects were removed from direct ownership by the Resource
* (but are still transitively owned) - update the model with Edges as
* required.
*
* @param nodes
*/
protected void updateAll(List nodes) {
ArrayList cells = new ArrayList();
Map attrs = new HashMap();
ConnectionSet cs = new ConnectionSet();
List edges = new ArrayList();
for (int i = 0; i < nodes.size(); i++) {
Iterator itr = edges(nodes.get(i));
// System.err.println(((EObject) nodes.get(i)).eContainer());
while (itr.hasNext()) {
Object edge = itr.next();
edges.add(edge);
}
}
remove(edges.toArray());
addReferencedObjects(cells, attrs, cs);
addContainmentEdges(nodes, cells, attrs, cs);
addReferenceEdges(cells, attrs, cs);
// System.err.println(edges.size() + " " + cells.size());
insert(cells.toArray(), attrs, cs, null, null);
}
protected int addAllNodes(
List cells,
Map attrs,
ConnectionSet cs,
Port parent,
List l,
int startX,
int startY) {
int y = startY;
Iterator itr = l.iterator();
while (itr.hasNext()) {
EObject obj = (EObject) itr.next();
if (cellMap.containsKey(obj)) {
continue;
}
// create vertex
DefaultGraphCell node = new DefaultGraphCell(obj);
cellMap.put(obj, node);
Map nodeAttrs = GraphConstants.createMap();
attrs.put(node, nodeAttrs);
// setup vertex attrs
y = y + height;
GraphConstants.setBounds(
nodeAttrs,
new Rectangle(startX, y, width - gap, height - gap));
GraphConstants.setBorderColor(nodeAttrs, Color.black);
// add a port
DefaultPort port = new DefaultPort();
node.add(port);
cells.add(node);
// add edge from parent if there is one
if (null != parent) {
DefaultEdge edge = new DefaultEdge();
Map edgeAttrs = GraphConstants.createMap();
edgeAttrs.put(RadialTreeLayoutAlgorithm.CONTAINMENT_EDGE, Boolean.TRUE);
attrs.put(edge, edgeAttrs);
GraphConstants.setLineEnd(edgeAttrs, GraphConstants.ARROW_CLASSIC);
cs.connect(edge, parent, port);
cells.add(edge);
}
y = addAllNodes(
cells,
attrs,
cs,
port,
obj.eContents(),
startX + width,
y);
}
return y;
}
private void addReferenceEdges(List cells, Map attrs, ConnectionSet cs) {
// Add edges for any other references
// Now add edges
for (Iterator cellItr = cellMap.keySet().iterator(); cellItr.hasNext();) {
EObject srcObj = (EObject) cellItr.next();
Port srcPort = (Port) getGraphCell(srcObj).getChildAt(0);
for (Iterator refItr = srcObj.eCrossReferences().iterator(); refItr.hasNext();) {
Object dstObj = refItr.next();
DefaultGraphCell dstCell = getGraphCell(dstObj);
if (null != dstCell) {
Port dstPort = (Port) dstCell.getChildAt(0);
DefaultEdge edge = new DefaultEdge();
Map edgeAttrs = GraphConstants.createMap();
attrs.put(edge, edgeAttrs);
GraphConstants.setDashPattern(edgeAttrs, DASH_PATTERN);
GraphConstants.setLineEnd(edgeAttrs, GraphConstants.ARROW_CLASSIC);
cs.connect(edge, srcPort, dstPort);
cells.add(edge);
// } else {
// System.err.println("No Cell for: "
// + ((EObject) dstObj).eClass().getName() + ":"
// + dstObj.hashCode());
}
}
}
}
private void addContainmentEdges(List nodes, List cells, Map attrs, ConnectionSet cs) {
// Now add edges
for (Iterator cellItr = nodes.iterator(); cellItr.hasNext();) {
EObject srcObj = (EObject) cellItr.next();
Port srcPort = (Port) getGraphCell(srcObj).getChildAt(0);
// Add edge to container if there is one
Object parentObj = srcObj.eContainer();
DefaultGraphCell parentCell = getGraphCell(parentObj);
if (null != parentCell) {
Port parentPort = (Port) parentCell.getChildAt(0);
DefaultEdge edge = new DefaultEdge();
Map edgeAttrs = GraphConstants.createMap();
edgeAttrs.put(RadialTreeLayoutAlgorithm.CONTAINMENT_EDGE, Boolean.TRUE);
attrs.put(edge, edgeAttrs);
GraphConstants.setLineEnd(edgeAttrs, GraphConstants.ARROW_CLASSIC);
cs.connect(edge, parentPort, srcPort);
cells.add(edge);
}
// Add edges to contained things
for (Iterator refItr = srcObj.eContents().iterator(); refItr.hasNext();) {
Object dstObj = refItr.next();
DefaultGraphCell dstCell = getGraphCell(dstObj);
if (null != dstCell) {
Port dstPort = (Port) dstCell.getChildAt(0);
DefaultEdge edge = new DefaultEdge();
Map edgeAttrs = GraphConstants.createMap();
edgeAttrs.put(RadialTreeLayoutAlgorithm.CONTAINMENT_EDGE, Boolean.TRUE);
attrs.put(edge, edgeAttrs);
GraphConstants.setLineEnd(edgeAttrs, GraphConstants.ARROW_CLASSIC);
cs.connect(edge, srcPort, dstPort);
cells.add(edge);
}
}
}
}
/**
* @param cells
* @param attrs
* @param cs
*/
private void addReferencedObjects(List cells, Map attrs, ConnectionSet cs) {
// Make sure all referenced objects are added
if (includeRefs) {
List l = new ArrayList();
for (Iterator cellItr = cellMap.keySet().iterator(); cellItr.hasNext();) {
EObject srcObj = (EObject) cellItr.next();
for (Iterator refItr = srcObj.eCrossReferences().iterator(); refItr.hasNext();) {
Object dstObj = refItr.next();
DefaultGraphCell dstCell = getGraphCell(dstObj);
if (null == dstCell) {
l.add(dstObj);
}
}
}
if (l.size() > 0) {
addAllNodes(cells, attrs, cs, null, l, 0, 0);
}
}
}
}