Package com.mxgraph.view

Source Code of com.mxgraph.view.mxLayoutManager

package com.mxgraph.view;

import java.awt.Point;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.mxgraph.layout.mxIGraphLayout;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.model.mxGraphModel.mxChildChange;
import com.mxgraph.model.mxGraphModel.mxGeometryChange;
import com.mxgraph.model.mxGraphModel.mxRootChange;
import com.mxgraph.model.mxGraphModel.mxTerminalChange;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxUndoableEdit;
import com.mxgraph.util.mxUtils;
import com.mxgraph.util.mxUndoableEdit.mxUndoableChange;

/**
* Implements a layout manager that updates the layout for a given transaction.
* The following example installs an automatic tree layout in a graph:
*
* <code>
* new mxLayoutManager(graph) {
*
*   mxCompactTreeLayout layout = new mxCompactTreeLayout(graph);
*  
*   public mxIGraphLayout getLayout(Object parent)
*   {
*     if (graph.getModel().getChildCount(parent) > 0) {
*       return layout;
*     }
*     return null;
*   }
* };
* </code>
*
* This class fires the following event:
*
* mxEvent.LAYOUT_CELLS fires between begin- and endUpdate after all cells have
* been layouted in layoutCells. The <code>cells</code> property contains all
* cells that have been passed to layoutCells.
*/
public class mxLayoutManager 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. Default is true.
   */
  protected boolean enabled = true;

  /**
   * Optional string that specifies the attributename to be passed to
   * mxCell.is to check if the rule applies to a cell. Default is true.
   */
  protected boolean bubbling = true;

  /**
   *
   */
  protected mxIEventListener undoHandler = new mxIEventListener()
  {
    public void invoke(Object source, mxEventObject evt)
    {
      if (isEnabled())
      {
        beforeUndo((mxUndoableEdit) evt.getProperty("edit"));
      }
    }
  };

  /**
   *
   */
  protected mxIEventListener moveHandler = new mxIEventListener()
  {
    public void invoke(Object source, mxEventObject evt)
    {
      if (isEnabled())
      {
        cellsMoved((Object[]) evt.getProperty("cells"), (Point) evt
            .getProperty("location"));
      }
    }
  };

  /**
   *
   */
  public mxLayoutManager(mxGraph graph)
  {
    setGraph(graph);
  }

  /**
   * @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 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 value the graph to set
   */
  public void setGraph(mxGraph value)
  {
    if (graph != null)
    {
      mxIGraphModel model = graph.getModel();
      model.removeListener(undoHandler);
      graph.removeListener(moveHandler);
    }

    graph = value;

    if (graph != null)
    {
      mxIGraphModel model = graph.getModel();
      model.addListener(mxEvent.BEFORE_UNDO, undoHandler);
      graph.addListener(mxEvent.MOVE_CELLS, moveHandler);
    }
  }

  /**
   *
   */
  protected mxIGraphLayout getLayout(Object parent)
  {
    return null;
  }

  /**
   *
   */
  protected void cellsMoved(Object[] cells, Point location)
  {
    if (cells != null && location != null)
    {
      mxIGraphModel model = getGraph().getModel();

      // Checks if a layout exists to take care of the moving
      for (int i = 0; i < cells.length; i++)
      {
        mxIGraphLayout layout = getLayout(model.getParent(cells[i]));

        if (layout != null)
        {
          layout.moveCell(cells[i], location.x, location.y);
        }
      }
    }
  }

  /**
   *
   */
  protected void beforeUndo(mxUndoableEdit edit)
  {
    Collection<Object> cells = getCellsForChanges(edit.getChanges());
    mxIGraphModel model = getGraph().getModel();

    if (isBubbling())
    {
      Object[] tmp = mxGraphModel.getParents(model, cells.toArray());

      while (tmp.length > 0)
      {
        cells.addAll(Arrays.asList(tmp));
        tmp = mxGraphModel.getParents(model, tmp);
      }
    }

    layoutCells(mxUtils.sortCells(cells, false).toArray());
  }

  /**
   *
   */
  protected Collection<Object> getCellsForChanges(
      List<mxUndoableChange> changes)
  {
    Set<Object> result = new HashSet<Object>();
    Iterator<mxUndoableChange> it = changes.iterator();

    while (it.hasNext())
    {
      mxUndoableChange change = it.next();

      if (change instanceof mxRootChange)
      {
        return new HashSet<Object>();
      }
      else
      {
        result.addAll(getCellsForChange(change));
      }
    }

    return result;
  }

  /**
   *
   */
  protected Collection<Object> getCellsForChange(mxUndoableChange change)
  {
    mxIGraphModel model = getGraph().getModel();
    Set<Object> result = new HashSet<Object>();

    if (change instanceof mxChildChange)
    {
      mxChildChange cc = (mxChildChange) change;
      Object parent = model.getParent(cc.getChild());

      if (cc.getChild() != null)
      {
        result.add(cc.getChild());
      }

      if (parent != null)
      {
        result.add(parent);
      }

      if (cc.getPrevious() != null)
      {
        result.add(cc.getPrevious());
      }
    }
    else if (change instanceof mxTerminalChange
        || change instanceof mxGeometryChange)
    {
      Object cell = (change instanceof mxTerminalChange) ? ((mxTerminalChange) change)
          .getCell()
          : ((mxGeometryChange) change).getCell();

      if (cell != null)
      {
        result.add(cell);
        Object parent = model.getParent(cell);

        if (parent != null)
        {
          result.add(parent);
        }
      }
    }

    return result;
  }

  /**
   *
   */
  protected void layoutCells(Object[] cells)
  {
    if (cells.length > 0)
    {
      // Invokes the layouts while removing duplicates
      mxIGraphModel model = getGraph().getModel();

      model.beginUpdate();
      try
      {
        for (int i = 0; i < cells.length; i++)
        {
          if (cells[i] != model.getRoot())
          {
            executeLayout(getLayout(cells[i]), cells[i]);
          }
        }

        fireEvent(new mxEventObject(mxEvent.LAYOUT_CELLS, "cells",
            cells));
      }
      finally
      {
        model.endUpdate();
      }
    }
  }

  /**
   *
   */
  protected void executeLayout(mxIGraphLayout layout, Object parent)
  {
    if (layout != null && parent != null)
    {
      layout.execute(parent);
    }
  }

  /**
   *
   */
  public void destroy()
  {
    setGraph(null);
  }

}
TOP

Related Classes of com.mxgraph.view.mxLayoutManager

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.