/**
* $Id: mxCell.java,v 1.1 2012/11/15 13:26:47 gaudenz Exp $
* Copyright (c) 2007, Gaudenz Alder
*/
package com.mxgraph.model;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Cells are the elements of the graph model. They represent the state
* of the groups, vertices and edges in a graph.
* <p/>
* <h4>Edge Labels</h4>
* <p/>
* Using the x- and y-coordinates of a cell's geometry it is
* possible to position the label on edges on a specific location
* on the actual edge shape as it appears on the screen. The
* x-coordinate of an edge's geometry is used to describe the
* distance from the center of the edge from -1 to 1 with 0
* being the center of the edge and the default value. The
* y-coordinate of an edge's geometry is used to describe
* the absolute, orthogonal distance in pixels from that
* point. In addition, the mxGeometry.offset is used
* as a absolute offset vector from the resulting point.
* <p/>
* The width and height of an edge geometry are ignored.
* <p/>
* To add more than one edge label, add a child vertex with
* a relative geometry. The x- and y-coordinates of that
* geometry will have the same semantiv as the above for
* edge labels.
*/
public class mxCell implements mxICell, Cloneable, Serializable {
/**
*
*/
private static final long serialVersionUID = 910211337632342672L;
/**
* Holds the Id. Default is null.
*/
protected String id;
/**
* Holds the user object. Default is null.
*/
protected Object value;
/**
* Holds the geometry. Default is null.
*/
protected mxGeometry geometry;
/**
* Holds the style as a string of the form
* stylename[;key=value]. Default is null.
*/
protected String style;
/**
* Specifies whether the cell is a vertex or edge and whether it is
* connectable, visible and collapsed. Default values are false, false,
* true, true and false respectively.
*/
protected boolean vertex = false, edge = false, connectable = true, visible = true, collapsed = false;
/**
* Reference to the parent cell and source and target terminals for edges.
*/
protected mxICell parent, source, target;
/**
* Holds the child cells and connected edges.
*/
protected List<Object> children, edges;
/**
* Constructs a new cell with an empty user object.
*/
public mxCell() {
this(null);
}
/**
* Constructs a new cell for the given user object.
*
* @param value Object that represents the value of the cell.
*/
public mxCell(Object value) {
this(value, null, null);
}
/**
* Constructs a new cell for the given parameters.
*
* @param value Object that represents the value of the cell.
* @param geometry Specifies the geometry of the cell.
* @param style Specifies the style as a formatted string.
*/
public mxCell(Object value, mxGeometry geometry, String style) {
setValue(value);
setGeometry(geometry);
setStyle(style);
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setId(String)
*/
@Override
public void setId(String id) {
this.id = id;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getValue()
*/
@Override
public Object getValue() {
return value;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setValue(Object)
*/
@Override
public void setValue(Object value) {
this.value = value;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getGeometry()
*/
@Override
public mxGeometry getGeometry() {
return geometry;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setGeometry(com.mxgraph.model.mxGeometry)
*/
@Override
public void setGeometry(mxGeometry geometry) {
this.geometry = geometry;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getStyle()
*/
@Override
public String getStyle() {
return style;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setStyle(String)
*/
@Override
public void setStyle(String style) {
this.style = style;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#isVertex()
*/
@Override
public boolean isVertex() {
return vertex;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setVertex(boolean)
*/
public void setVertex(boolean vertex) {
this.vertex = vertex;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#isEdge()
*/
@Override
public boolean isEdge() {
return edge;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setEdge(boolean)
*/
public void setEdge(boolean edge) {
this.edge = edge;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#isConnectable()
*/
@Override
public boolean isConnectable() {
return connectable;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setConnectable(boolean)
*/
public void setConnectable(boolean connectable) {
this.connectable = connectable;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#isVisible()
*/
@Override
public boolean isVisible() {
return visible;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setVisible(boolean)
*/
@Override
public void setVisible(boolean visible) {
this.visible = visible;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#isCollapsed()
*/
@Override
public boolean isCollapsed() {
return collapsed;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setCollapsed(boolean)
*/
@Override
public void setCollapsed(boolean collapsed) {
this.collapsed = collapsed;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getParent()
*/
@Override
public mxICell getParent() {
return parent;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setParent(com.mxgraph.model.mxICell)
*/
@Override
public void setParent(mxICell parent) {
this.parent = parent;
}
/**
* Returns the source terminal.
*/
public mxICell getSource() {
return source;
}
/**
* Sets the source terminal.
*
* @param source Cell that represents the new source terminal.
*/
public void setSource(mxICell source) {
this.source = source;
}
/**
* Returns the target terminal.
*/
public mxICell getTarget() {
return target;
}
/**
* Sets the target terminal.
*
* @param target Cell that represents the new target terminal.
*/
public void setTarget(mxICell target) {
this.target = target;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getTerminal(boolean)
*/
@Override
public mxICell getTerminal(boolean source) {
return (source) ? getSource() : getTarget();
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#setTerminal(com.mxgraph.model.mxICell, boolean)
*/
@Override
public mxICell setTerminal(mxICell terminal, boolean isSource) {
if (isSource) {
setSource(terminal);
}
else {
setTarget(terminal);
}
return terminal;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getChildCount()
*/
@Override
public int getChildCount() {
return (children != null) ? children.size() : 0;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getIndex(com.mxgraph.model.mxICell)
*/
@Override
public int getIndex(mxICell child) {
return (children != null) ? children.indexOf(child) : -1;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getChildAt(int)
*/
@Override
public mxICell getChildAt(int index) {
return (children != null) ? (mxICell)children.get(index) : null;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#insert(com.mxgraph.model.mxICell)
*/
@Override
public mxICell insert(mxICell child) {
int index = getChildCount();
if (child.getParent() == this) {
index--;
}
return insert(child, index);
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#insert(com.mxgraph.model.mxICell, int)
*/
@Override
public mxICell insert(mxICell child, int index) {
if (child != null) {
child.removeFromParent();
child.setParent(this);
if (children == null) {
children = new ArrayList<Object>();
children.add(child);
}
else {
children.add(index, child);
}
}
return child;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#remove(int)
*/
@Override
public mxICell remove(int index) {
mxICell child = null;
if (children != null && index >= 0) {
child = getChildAt(index);
remove(child);
}
return child;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#remove(com.mxgraph.model.mxICell)
*/
@Override
public mxICell remove(mxICell child) {
if (child != null && children != null) {
children.remove(child);
child.setParent(null);
}
return child;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#removeFromParent()
*/
@Override
public void removeFromParent() {
if (parent != null) {
parent.remove(this);
}
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getEdgeCount()
*/
@Override
public int getEdgeCount() {
return (edges != null) ? edges.size() : 0;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getEdgeIndex(com.mxgraph.model.mxICell)
*/
@Override
public int getEdgeIndex(mxICell edge) {
return (edges != null) ? edges.indexOf(edge) : -1;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#getEdgeAt(int)
*/
@Override
public mxICell getEdgeAt(int index) {
return (edges != null) ? (mxICell)edges.get(index) : null;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#insertEdge(com.mxgraph.model.mxICell, boolean)
*/
@Override
public mxICell insertEdge(mxICell edge, boolean isOutgoing) {
if (edge != null) {
edge.removeFromTerminal(isOutgoing);
edge.setTerminal(this, isOutgoing);
if (edges == null || edge.getTerminal(!isOutgoing) != this || !edges.contains(edge)) {
if (edges == null) {
edges = new ArrayList<Object>();
}
edges.add(edge);
}
}
return edge;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#removeEdge(com.mxgraph.model.mxICell, boolean)
*/
@Override
public mxICell removeEdge(mxICell edge, boolean isOutgoing) {
if (edge != null) {
if (edge.getTerminal(!isOutgoing) != this && edges != null) {
edges.remove(edge);
}
edge.setTerminal(null, isOutgoing);
}
return edge;
}
/* (non-Javadoc)
* @see com.mxgraph.model.mxICell#removeFromTerminal(boolean)
*/
@Override
public void removeFromTerminal(boolean isSource) {
mxICell terminal = getTerminal(isSource);
if (terminal != null) {
terminal.removeEdge(this, isSource);
}
}
/**
* Returns the specified attribute from the user object if it is an XML
* node.
*
* @param name Name of the attribute whose value should be returned.
* @return Returns the value of the given attribute or null.
*/
public String getAttribute(String name) {
return getAttribute(name, null);
}
/**
* Returns the specified attribute from the user object if it is an XML
* node.
*
* @param name Name of the attribute whose value should be returned.
* @param defaultValue Default value to use if the attribute has no value.
* @return Returns the value of the given attribute or defaultValue.
*/
public String getAttribute(String name, String defaultValue) {
Object userObject = getValue();
String val = null;
if (userObject instanceof Element) {
Element element = (Element)userObject;
val = element.getAttribute(name);
}
if (val == null) {
val = defaultValue;
}
return val;
}
/**
* Sets the specified attribute on the user object if it is an XML node.
*
* @param name Name of the attribute whose value should be set.
* @param value New value of the attribute.
*/
public void setAttribute(String name, String value) {
Object userObject = getValue();
if (userObject instanceof Element) {
Element element = (Element)userObject;
element.setAttribute(name, value);
}
}
/**
* Returns a clone of the cell.
*/
@Override
public Object clone() throws CloneNotSupportedException {
mxCell clone = (mxCell)super.clone();
clone.setValue(cloneValue());
clone.setStyle(getStyle());
clone.setCollapsed(isCollapsed());
clone.setConnectable(isConnectable());
clone.setEdge(isEdge());
clone.setVertex(isVertex());
clone.setVisible(isVisible());
clone.setParent(null);
clone.setSource(null);
clone.setTarget(null);
clone.children = null;
clone.edges = null;
mxGeometry geometry = getGeometry();
if (geometry != null) {
clone.setGeometry((mxGeometry)geometry.clone());
}
return clone;
}
/**
* Returns a clone of the user object. This implementation clones any XML
* nodes or otherwise returns the same user object instance.
*/
protected Object cloneValue() {
Object value = getValue();
if (value instanceof Node) {
value = ((Node)value).cloneNode(true);
}
return value;
}
}