com.mxgraph.layout.mxStackLayout Maven / Gradle / Ivy
package com.mxgraph.layout;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxICell;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;
public class mxStackLayout extends mxGraphLayout
{
/**
* Specifies the orientation of the layout. Default is true.
*/
protected boolean horizontal;
/**
* Specifies the spacing between the cells. Default is 0.
*/
protected int spacing;
/**
* Specifies the horizontal origin of the layout. Default is 0.
*/
protected int x0;
/**
* Specifies the vertical origin of the layout. Default is 0.
*/
protected int y0;
/**
* Border to be added if fill is true. Default is 0.
*/
protected int border;
/**
* Boolean indicating if dimension should be changed to fill out the parent
* cell. Default is false.
*/
protected boolean fill = false;
/**
* If the parent should be resized to match the width/height of the
* stack. Default is false.
*/
protected boolean resizeParent = false;
/**
* Value at which a new column or row should be created. Default is 0.
*/
protected int wrap = 0;
/**
* Constructs a new stack layout layout for the specified graph,
* spacing, orientation and offset.
*/
public mxStackLayout(mxGraph graph)
{
this(graph, true);
}
/**
* Constructs a new stack layout layout for the specified graph,
* spacing, orientation and offset.
*/
public mxStackLayout(mxGraph graph, boolean horizontal)
{
this(graph, horizontal, 0);
}
/**
* Constructs a new stack layout layout for the specified graph,
* spacing, orientation and offset.
*/
public mxStackLayout(mxGraph graph, boolean horizontal, int spacing)
{
this(graph, horizontal, spacing, 0, 0, 0);
}
/**
* Constructs a new stack layout layout for the specified graph,
* spacing, orientation and offset.
*/
public mxStackLayout(mxGraph graph, boolean horizontal, int spacing,
int x0, int y0, int border)
{
super(graph);
this.horizontal = horizontal;
this.spacing = spacing;
this.x0 = x0;
this.y0 = y0;
this.border = border;
}
/**
*
*/
public boolean isHorizontal()
{
return horizontal;
}
/*
* (non-Javadoc)
* @see com.mxgraph.layout.mxGraphLayout#move(java.lang.Object, double, double)
*/
public void moveCell(Object cell, double x, double y)
{
mxIGraphModel model = graph.getModel();
Object parent = model.getParent(cell);
boolean horizontal = isHorizontal();
if (cell instanceof mxICell && parent instanceof mxICell)
{
int i = 0;
double last = 0;
int childCount = model.getChildCount(parent);
double value = (horizontal) ? x : y;
mxCellState pstate = graph.getView().getState(parent);
if (pstate != null)
{
value -= (horizontal) ? pstate.getX() : pstate.getY();
}
for (i = 0; i < childCount; i++)
{
Object child = model.getChildAt(parent, i);
if (child != cell)
{
mxGeometry bounds = model.getGeometry(child);
if (bounds != null)
{
double tmp = (horizontal) ? bounds.getX()
+ bounds.getWidth() / 2 : bounds.getY()
+ bounds.getHeight() / 2;
if (last < value && tmp > value)
{
break;
}
last = tmp;
}
}
}
// Changes child order in parent
int idx = ((mxICell) parent).getIndex((mxICell) cell);
idx = Math.max(0, i - ((i > idx) ? 1 : 0));
model.add(parent, cell, idx);
}
}
/**
* Hook for subclassers to return the container size.
*/
public mxRectangle getContainerSize()
{
return new mxRectangle();
}
/*
* (non-Javadoc)
* @see com.mxgraph.layout.mxIGraphLayout#execute(java.lang.Object)
*/
public void execute(Object parent)
{
if (parent != null)
{
boolean horizontal = isHorizontal();
mxIGraphModel model = graph.getModel();
mxGeometry pgeo = model.getGeometry(parent);
// Handles special case where the parent is either a layer with no
// geometry or the current root of the view in which case the size
// of the graph's container will be used.
if (pgeo == null && model.getParent(parent) == model.getRoot()
|| parent == graph.getView().getCurrentRoot())
{
mxRectangle tmp = getContainerSize();
pgeo = new mxGeometry(0, 0, tmp.getWidth(), tmp.getHeight());
}
double fillValue = 0;
if (pgeo != null)
{
fillValue = (horizontal) ? pgeo.getHeight() : pgeo.getWidth();
}
fillValue -= 2 * spacing + 2 * border;
// Handles swimlane start size
mxRectangle size = graph.getStartSize(parent);
fillValue -= (horizontal) ? size.getHeight() : size.getWidth();
double x0 = this.x0 + size.getWidth() + border;
double y0 = this.y0 + size.getHeight() + border;
model.beginUpdate();
try
{
double tmp = 0;
mxGeometry last = null;
int childCount = model.getChildCount(parent);
for (int i = 0; i < childCount; i++)
{
Object child = model.getChildAt(parent, i);
if (!isVertexIgnored(child) && isVertexMovable(child))
{
mxGeometry geo = model.getGeometry(child);
if (geo != null)
{
geo = (mxGeometry) geo.clone();
if (wrap != 0 && last != null)
{
if ((horizontal && last.getX()
+ last.getWidth() + geo.getWidth() + 2
* spacing > wrap)
|| (!horizontal && last.getY()
+ last.getHeight()
+ geo.getHeight() + 2 * spacing > wrap))
{
last = null;
if (horizontal)
{
y0 += tmp + spacing;
}
else
{
x0 += tmp + spacing;
}
tmp = 0;
}
}
tmp = Math.max(tmp, (horizontal) ? geo
.getHeight() : geo.getWidth());
if (last != null)
{
if (horizontal)
{
geo.setX(last.getX() + last.getWidth()
+ spacing);
}
else
{
geo.setY(last.getY() + last.getHeight()
+ spacing);
}
}
else
{
if (horizontal)
{
geo.setX(x0);
}
else
{
geo.setY(y0);
}
}
if (horizontal)
{
geo.setY(y0);
}
else
{
geo.setX(x0);
}
if (fill && fillValue > 0)
{
if (horizontal)
{
geo.setHeight(fillValue);
}
else
{
geo.setWidth(fillValue);
}
}
model.setGeometry(child, geo);
last = geo;
}
}
}
if (resizeParent && pgeo != null && last != null
&& !graph.isCellCollapsed(parent))
{
pgeo = (mxGeometry) pgeo.clone();
if (horizontal)
{
pgeo.setWidth(last.getX() + last.getWidth() + spacing);
}
else
{
pgeo
.setHeight(last.getY() + last.getHeight()
+ spacing);
}
model.setGeometry(parent, pgeo);
}
}
finally
{
model.endUpdate();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy