Package com.mxgraph.layout

Source Code of com.mxgraph.layout.mxGraphLayout

/**
* Copyright (c) 2008-2009, JGraph Ltd
*/
package com.mxgraph.layout;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxGraph.mxICellVisitor;
import com.mxgraph.view.mxGraphView;

/**
* Abstract bass class for layouts
*/
public abstract class mxGraphLayout implements mxIGraphLayout
{

  /**
   * Holds the enclosing graph.
   */
  protected mxGraph graph;

  /**
   * The parent cell of the layout, if any
   */
  protected Object parent;

  /**
   * Boolean indicating if the bounding box of the label should be used if
   * its available. Default is true.
   */
  protected boolean useBoundingBox = true;

  /**
   * Constructs a new fast organic layout for the specified graph.
   */
  public mxGraphLayout(mxGraph graph)
  {
    this.graph = graph;
  }

  public void execute(Object parent)
  {
    this.parent = parent;
  }

  /* (non-Javadoc)
   * @see com.mxgraph.layout.mxIGraphLayout#move(java.lang.Object, double, double)
   */
  public void moveCell(Object cell, double x, double y)
  {
    // TODO: Map the position to a child index for
    // the cell to be placed closest to the position
  }

  /**
   * Returns the associated graph.
   */
  public mxGraph getGraph()
  {
    return graph;
  }

  /**
   * Returns the constraint for the given key and cell. This implementation
   * always returns the value for the given key in the style of the given
   * cell.
   *
   * @param key Key of the constraint to be returned.
   * @param cell Cell whose constraint should be returned.
   */
  public Object getConstraint(Object key, Object cell)
  {
    return getConstraint(key, cell, null, false);
  }

  /**
   * Returns the constraint for the given key and cell. The optional edge and
   * source arguments are used to return inbound and outgoing routing-
   * constraints for the given edge and vertex. This implementation always
   * returns the value for the given key in the style of the given cell.
   *
   * @param key Key of the constraint to be returned.
   * @param cell Cell whose constraint should be returned.
   * @param edge Optional cell that represents the connection whose constraint
   * should be returned. Default is null.
   * @param source Optional boolean that specifies if the connection is incoming
   * or outgoing. Default is false.
   */
  public Object getConstraint(Object key, Object cell, Object edge,
      boolean source)
  {
    mxCellState state = graph.getView().getState(cell);
    Map<String, Object> style = (state != null) ? state.getStyle() : graph
        .getCellStyle(cell);

    return (style != null) ? style.get(key) : null;
  }

  /**
   * @return the useBoundingBox
   */
  public boolean isUseBoundingBox()
  {
    return useBoundingBox;
  }

  /**
   * @param useBoundingBox the useBoundingBox to set
   */
  public void setUseBoundingBox(boolean useBoundingBox)
  {
    this.useBoundingBox = useBoundingBox;
  }

  /**
   * Returns true if the given vertex may be moved by the layout.
   *
   * @param vertex Object that represents the vertex to be tested.
   * @return Returns true if the vertex can be moved.
   */
  public boolean isVertexMovable(Object vertex)
  {
    return graph.isCellMovable(vertex);
  }

  /**
   * Returns true if the given vertex has no connected edges.
   *
   * @param vertex Object that represents the vertex to be tested.
   * @return Returns true if the vertex should be ignored.
   */
  public boolean isVertexIgnored(Object vertex)
  {
    return !graph.getModel().isVertex(vertex)
        || !graph.isCellVisible(vertex);
  }

  /**
   * Returns true if the given edge has no source or target terminal.
   *
   * @param edge Object that represents the edge to be tested.
   * @return Returns true if the edge should be ignored.
   */
  public boolean isEdgeIgnored(Object edge)
  {
    mxIGraphModel model = graph.getModel();

    return !model.isEdge(edge) || !graph.isCellVisible(edge)
        || model.getTerminal(edge, true) == null
        || model.getTerminal(edge, false) == null;
  }

  /**
   * Disables or enables the edge style of the given edge.
   */
  public void setEdgeStyleEnabled(Object edge, boolean value)
  {
    graph.setCellStyles(mxConstants.STYLE_NOEDGESTYLE, (value) ? "0" : "1",
        new Object[] { edge });
  }

  /**
   * Disables or enables orthogonal end segments of the given edge
   */
  public void setOrthogonalEdge(Object edge, boolean value)
  {
    graph.setCellStyles(mxConstants.STYLE_ORTHOGONAL, (value) ? "1" : "0",
        new Object[] { edge });
  }

  public mxPoint getParentOffset(Object parent)
  {
    mxPoint result = new mxPoint();

    if (parent != null && parent != this.parent)
    {
      mxIGraphModel model = graph.getModel();

      if (model.isAncestor(this.parent, parent))
      {
        mxGeometry parentGeo = model.getGeometry(parent);

        while (parent != this.parent)
        {
          result.setX(result.getX() + parentGeo.getX());
          result.setY(result.getY() + parentGeo.getY());

          parent = model.getParent(parent);;
          parentGeo = model.getGeometry(parent);
        }
      }
    }

    return result;
  }

  /**
   * Sets the control points of the given edge to the given
   * list of mxPoints. Set the points to null to remove all
   * existing points for an edge.
   */
  public void setEdgePoints(Object edge, List<mxPoint> points)
  {
    mxIGraphModel model = graph.getModel();
    mxGeometry geometry = model.getGeometry(edge);

    if (geometry == null)
    {
      geometry = new mxGeometry();
      geometry.setRelative(true);
    }
    else
    {
      geometry = (mxGeometry) geometry.clone();
    }

    if (this.parent != null && points != null)
    {
      Object parent = graph.getModel().getParent(edge);

        mxPoint parentOffset = getParentOffset(parent);

        for (mxPoint point : points)
        {
          point.setX(point.getX() - parentOffset.getX());
          point.setY(point.getY() - parentOffset.getY());
        }

    }

    geometry.setPoints(points);
    model.setGeometry(edge, geometry);
  }

  /**
   * Returns an <mxRectangle> that defines the bounds of the given cell
   * or the bounding box if <useBoundingBox> is true.
   */
  public mxRectangle getVertexBounds(Object vertex)
  {
    mxRectangle geo = graph.getModel().getGeometry(vertex);

    // Checks for oversize label bounding box and corrects
    // the return value accordingly
    if (useBoundingBox)
    {
      mxCellState state = graph.getView().getState(vertex);

      if (state != null)
      {
        double scale = graph.getView().getScale();
        mxRectangle tmp = state.getBoundingBox();

        double dx0 = (tmp.getX() - state.getX()) / scale;
        double dy0 = (tmp.getY() - state.getY()) / scale;
        double dx1 = (tmp.getX() + tmp.getWidth() - state.getX() - state
            .getWidth()) / scale;
        double dy1 = (tmp.getY() + tmp.getHeight() - state.getY() - state
            .getHeight()) / scale;

        geo = new mxRectangle(geo.getX() + dx0, geo.getY() + dy0,
            geo.getWidth() - dx0 + dx1, geo.getHeight() + -dy0
                + dy1);
      }
    }

    if (this.parent != null)
    {
      Object parent = graph.getModel().getParent(vertex);
      geo = (mxRectangle) geo.clone();

      if (parent != null && parent != this.parent)
      {
        mxPoint parentOffset = getParentOffset(parent);
        geo.setX(geo.getX() + parentOffset.getX());
        geo.setY(geo.getY() + parentOffset.getY());
      }
    }

    return new mxRectangle(geo);
  }

  /**
   * Sets the new position of the given cell taking into account the size of
   * the bounding box if <useBoundingBox> is true. The change is only carried
   * out if the new location is not equal to the existing location, otherwise
   * the geometry is not replaced with an updated instance. The new or old
   * bounds are returned (including overlapping labels).
   *
   * Parameters:
   *
   * cell - <mxCell> whose geometry is to be set.
   * x - Integer that defines the x-coordinate of the new location.
   * y - Integer that defines the y-coordinate of the new location.
   */
  public mxRectangle setVertexLocation(Object vertex, double x, double y)
  {
    mxIGraphModel model = graph.getModel();
    mxGeometry geometry = model.getGeometry(vertex);
    mxRectangle result = null;

    if (geometry != null)
    {
      result = new mxRectangle(x, y, geometry.getWidth(),
          geometry.getHeight());

      mxGraphView graphView = graph.getView();

      // Checks for oversize labels and offset the result
      if (useBoundingBox)
      {
        mxCellState state = graphView.getState(vertex);

        if (state != null)
        {
          double scale = graph.getView().getScale();
          mxRectangle box = state.getBoundingBox();

          if (state.getBoundingBox().getX() < state.getX())
          {
            x += (state.getX() - box.getX()) / scale;
            result.setWidth(box.getWidth());
          }
          if (state.getBoundingBox().getY() < state.getY())
          {
            y += (state.getY() - box.getY()) / scale;
            result.setHeight(box.getHeight());
          }
        }
      }

      if (this.parent != null)
      {
        Object parent = model.getParent(vertex);

        if (parent != null && parent != this.parent)
        {
          mxPoint parentOffset = getParentOffset(parent);

          x = x - parentOffset.getX();
          y = y - parentOffset.getY();
        }
      }

      if (geometry.getX() != x || geometry.getY() != y)
      {
        geometry = (mxGeometry) geometry.clone();
        geometry.setX(x);
        geometry.setY(y);

        model.setGeometry(vertex, geometry);
      }
    }

    return result;
  }
 
  /**
   * Updates the bounds of the given groups to include all children. Call
   * this with the groups in parent to child order, top-most group first, eg.
   *
   * arrangeGroups(graph, mxUtils.sortCells(Arrays.asList(
   *   new Object[] { v1, v3 }), true).toArray(), 10);
   * @param groups the groups to adjust
   * @param border the border applied to the adjusted groups
   */
  public void arrangeGroups(Object[] groups, int border)
  {
    graph.getModel().beginUpdate();
    try
    {
      for (int i = groups.length - 1; i >= 0; i--)
      {
        Object group = groups[i];
        Object[] children = graph.getChildVertices(group);
        mxRectangle bounds = graph.getBoundingBoxFromGeometry(children);

        mxGeometry geometry = graph.getCellGeometry(group);
        double left = 0;
        double top = 0;
       
        // Adds the size of the title area for swimlanes
        if (this.graph.isSwimlane(group))
        {
          mxRectangle size = graph.getStartSize(group);
          left = size.getWidth();
          top = size.getHeight();
        }
       
        if (bounds != null && geometry != null)
        {
          geometry = (mxGeometry) geometry.clone();
          geometry.setX(geometry.getX() + bounds.getX() - border - left);
          geometry.setY(geometry.getY() + bounds.getY() - border - top);
          geometry.setWidth(bounds.getWidth() + 2 * border + left);
          geometry.setHeight(bounds.getHeight() + 2 * border + top);
          graph.getModel().setGeometry(group, geometry);
          graph.moveCells(children, border + left - bounds.getX(),
              border + top - bounds.getY());
        }
      }
    }
    finally
    {
      graph.getModel().endUpdate();
    }
  }
}
TOP

Related Classes of com.mxgraph.layout.mxGraphLayout

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.