Package com.mxgraph.sharing

Source Code of com.mxgraph.sharing.mxSharedGraphModel

/**
* Copyright (c) 2007-2012, JGraph Ltd
*/
package com.mxgraph.sharing;

import java.util.LinkedList;

import org.w3c.dom.Node;

import com.mxgraph.io.mxCodec;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxGraphModel.mxChildChange;
import com.mxgraph.model.mxICell;
import com.mxgraph.model.mxIGraphModel.mxAtomicGraphModelChange;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxUndoableEdit;
import com.mxgraph.util.mxXmlUtils;

/**
* Implements a diagram that may be shared among multiple sessions.
*/
public class mxSharedGraphModel extends mxSharedState
{

  /**
   *
   */
  protected mxGraphModel model;

  /**
   *
   */
  protected mxCodec codec = new mxCodec()
  {
    public Object lookup(String id)
    {
      return model.getCell(id);
    }
  };

  /**
   * Whether remote changes should be significant in the
   * local command history. Default is true.
   */
  protected boolean significantRemoteChanges = true;

  /**
   * Constructs a new diagram with the given model.
   *
   * @param model Initial model of the diagram.
   */
  public mxSharedGraphModel(mxGraphModel model)
  {
    super(null); // Overrides getState
    this.model = model;
  }

  /**
   * @return the model
   */
  public mxGraphModel getModel()
  {
    return model;
  }

  /**
   * @return the significantRemoteChanges
   */
  public boolean isSignificantRemoteChanges()
  {
    return significantRemoteChanges;
  }

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

  /**
   * Returns the initial state of the diagram.
   */
  public String getState()
  {
    return mxXmlUtils.getXml(codec.encode(model));
  }

  /**
   *
   */
  public synchronized void addDelta(String edits)
  {
    // Edits are not added to the history. They are sent straight out to
    // all sessions and the model is updated so the next session will get
    // these edits via the new state of the model in getState.
  }

  /**
   *
   */
  protected String processEdit(Node node)
  {
    mxAtomicGraphModelChange[] changes = decodeChanges(node.getFirstChild());

    if (changes.length > 0)
    {
      mxUndoableEdit edit = createUndoableEdit(changes);

      // No notify event here to avoid the edit from being encoded and transmitted
      // LATER: Remove changes property (deprecated)
      model.fireEvent(new mxEventObject(mxEvent.CHANGE, "edit", edit,
          "changes", changes));
      model.fireEvent(new mxEventObject(mxEvent.UNDO, "edit", edit));
      fireEvent(new mxEventObject(mxEvent.FIRED, "edit", edit));
    }

    return super.processEdit(node);
  }

  /**
   * Creates a new mxUndoableEdit that implements the notify function to fire
   * a change and notify event via the model.
   */
  protected mxUndoableEdit createUndoableEdit(
      mxAtomicGraphModelChange[] changes)
  {
    mxUndoableEdit edit = new mxUndoableEdit(this, significantRemoteChanges)
    {
      public void dispatch()
      {
        // LATER: Remove changes property (deprecated)
        ((mxGraphModel) source).fireEvent(new mxEventObject(
            mxEvent.CHANGE, "edit", this, "changes", changes));
        ((mxGraphModel) source).fireEvent(new mxEventObject(
            mxEvent.NOTIFY, "edit", this, "changes", changes));
      }
    };

    for (int i = 0; i < changes.length; i++)
    {
      edit.add(changes[i]);
    }

    return edit;
  }

  /**
   * Adds removed cells to the codec object lookup for references to the removed
   * cells after this point in time.
   */
  protected mxAtomicGraphModelChange[] decodeChanges(Node node)
  {
    // Updates the document in the existing codec
    codec.setDocument(node.getOwnerDocument());

    LinkedList<mxAtomicGraphModelChange> changes = new LinkedList<mxAtomicGraphModelChange>();

    while (node != null)
    {
      Object change;

      if (node.getNodeName().equals("mxRootChange"))
      {
        // Handles the special case were no ids should be
        // resolved in the existing model. This change will
        // replace all registered ids and cells from the
        // model and insert a new cell hierarchy instead.
        mxCodec tmp = new mxCodec(node.getOwnerDocument());
        change = tmp.decode(node);
      }
      else
      {
        change = codec.decode(node);
      }

      if (change instanceof mxAtomicGraphModelChange)
      {
        mxAtomicGraphModelChange ac = (mxAtomicGraphModelChange) change;

        ac.setModel(model);
        ac.execute();

        // Workaround for references not being resolved if cells have
        // been removed from the model prior to being referenced. This
        // adds removed cells in the codec object lookup table.
        if (ac instanceof mxChildChange
            && ((mxChildChange) ac).getParent() == null)
        {
          cellRemoved(((mxChildChange) ac).getChild());
        }

        changes.add(ac);
      }

      node = node.getNextSibling();
    }

    return changes.toArray(new mxAtomicGraphModelChange[changes.size()]);
  }

  /**
   * Adds removed cells to the codec object lookup for references to the removed
   * cells after this point in time.
   */
  public void cellRemoved(Object cell)
  {
    codec.putObject(((mxICell) cell).getId(), cell);

    int childCount = model.getChildCount(cell);

    for (int i = 0; i < childCount; i++)
    {
      cellRemoved(model.getChildAt(cell, i));
    }
  }

}
TOP

Related Classes of com.mxgraph.sharing.mxSharedGraphModel

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.