package com.mxgraph.view;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxRectangle;
public class mxSwimlaneManager extends mxEventSource
{
/**
* Defines the type of the source or target terminal. The type is a string
* passed to mxCell.is to check if the rule applies to a cell.
*/
protected mxGraph graph;
/**
* Optional string that specifies the value of the attribute to be passed
* to mxCell.is to check if the rule applies to a cell.
*/
protected boolean enabled;
/**
* Optional string that specifies the attributename to be passed to
* mxCell.is to check if the rule applies to a cell.
*/
protected boolean horizontal;
/**
* Optional string that specifies the attributename to be passed to
* mxCell.is to check if the rule applies to a cell.
*/
protected boolean siblings;
/**
* Optional string that specifies the attributename to be passed to
* mxCell.is to check if the rule applies to a cell.
*/
protected boolean bubbling;
/**
*
*/
protected mxIEventListener addHandler = new mxIEventListener()
{
public void invoke(Object source, mxEventObject evt)
{
if (isEnabled())
{
cellsAdded((Object[]) evt.getProperty("cells"));
}
}
};
/**
*
*/
protected mxIEventListener resizeHandler = new mxIEventListener()
{
public void invoke(Object source, mxEventObject evt)
{
if (isEnabled())
{
cellsResized((Object[]) evt.getProperty("cells"));
}
}
};
/**
*
*/
public mxSwimlaneManager(mxGraph graph)
{
setGraph(graph);
}
/**
*
*/
public boolean isSwimlaneIgnored(Object swimlane)
{
return !getGraph().isSwimlane(swimlane);
}
/**
* @return the enabled
*/
public boolean isEnabled()
{
return enabled;
}
/**
* @param value the enabled to set
*/
public void setEnabled(boolean value)
{
enabled = value;
}
/**
* @return the bubbling
*/
public boolean isHorizontal()
{
return horizontal;
}
/**
* @param value the bubbling to set
*/
public void setHorizontal(boolean value)
{
horizontal = value;
}
/**
* @return the bubbling
*/
public boolean isSiblings()
{
return siblings;
}
/**
* @param value the bubbling to set
*/
public void setSiblings(boolean value)
{
siblings = value;
}
/**
* @return the bubbling
*/
public boolean isBubbling()
{
return bubbling;
}
/**
* @param value the bubbling to set
*/
public void setBubbling(boolean value)
{
bubbling = value;
}
/**
* @return the graph
*/
public mxGraph getGraph()
{
return graph;
}
/**
* @param graph the graph to set
*/
public void setGraph(mxGraph graph)
{
if (this.graph != null)
{
this.graph.removeListener(addHandler);
this.graph.removeListener(resizeHandler);
}
this.graph = graph;
if (this.graph != null)
{
this.graph.addListener(mxEvent.ADD_CELLS, addHandler);
this.graph.addListener(mxEvent.CELLS_RESIZED, resizeHandler);
}
}
/**
*
*/
protected void cellsAdded(Object[] cells)
{
if (cells != null)
{
mxIGraphModel model = getGraph().getModel();
model.beginUpdate();
try
{
for (int i = 0; i < cells.length; i++)
{
if (!isSwimlaneIgnored(cells[i]))
{
swimlaneAdded(cells[i]);
}
}
}
finally
{
model.endUpdate();
}
}
}
/**
*
*/
protected void swimlaneAdded(Object swimlane)
{
mxIGraphModel model = getGraph().getModel();
// Tries to find existing swimlane for dimensions
// TODO: Use parent geometry - header if inside
// parent swimlane
mxGeometry geo = null;
Object parent = model.getParent(swimlane);
int childCount = model.getChildCount(parent);
for (int i = 0; i < childCount; i++)
{
Object child = model.getChildAt(parent, i);
if (child != swimlane && !isSwimlaneIgnored(child))
{
geo = model.getGeometry(child);
break;
}
}
// Applies dimension to new child
if (geo != null)
{
model.beginUpdate();
try
{
resizeSwimlane(swimlane, geo.getWidth(), geo.getHeight());
}
finally
{
model.endUpdate();
}
}
}
/**
*
*/
protected void cellsResized(Object[] cells)
{
if (cells != null)
{
mxIGraphModel model = getGraph().getModel();
model.beginUpdate();
try
{
for (int i = 0; i < cells.length; i++)
{
if (!isSwimlaneIgnored(cells[i]))
{
swimlaneResized(cells[i]);
}
}
}
finally
{
model.endUpdate();
}
}
}
/**
*
*/
protected void swimlaneResized(Object swimlane)
{
mxIGraphModel model = getGraph().getModel();
mxGeometry geo = model.getGeometry(swimlane);
if (geo != null)
{
double w = geo.getWidth();
double h = geo.getHeight();
model.beginUpdate();
try
{
Object parent = model.getParent(swimlane);
if (isSiblings())
{
int childCount = model.getChildCount(parent);
for (int i = 0; i < childCount; i++)
{
Object child = model.getChildAt(parent, i);
if (child != swimlane && !isSwimlaneIgnored(child))
{
resizeSwimlane(child, w, h);
}
}
}
if (isBubbling() && !isSwimlaneIgnored(parent))
{
resizeParent(parent, w, h);
swimlaneResized(parent);
}
}
finally
{
model.endUpdate();
}
}
}
/**
*
*/
protected void resizeSwimlane(Object swimlane, double w, double h)
{
mxIGraphModel model = getGraph().getModel();
mxGeometry geo = model.getGeometry(swimlane);
if (geo != null)
{
geo = (mxGeometry) geo.clone();
if (isHorizontal())
{
geo.setWidth(w);
}
else
{
geo.setHeight(h);
}
model.setGeometry(swimlane, geo);
}
}
/**
*
*/
protected void resizeParent(Object parent, double w, double h)
{
mxIGraphModel model = getGraph().getModel();
mxGeometry geo = model.getGeometry(parent);
if (geo != null)
{
geo = (mxGeometry) geo.clone();
mxRectangle size = graph.getStartSize(parent);
if (isHorizontal())
{
geo.setWidth(w + size.getWidth());
}
else
{
geo.setHeight(h + size.getHeight());
}
model.setGeometry(parent, geo);
}
}
/**
*
*/
public void destroy()
{
setGraph(null);
}
}