1. 概览

mxGraphModel继承自mxEventSource以实现graph model。graph model是负责存储graph数据结构的包装器。graph model充当事务包装器,其中包含所有更改的事件通知,而cell包含用于更新实际数据结构的原子操作。

1.1 图层

模型中的cell层次结构必须具有顶级根cell,其中包含图层(通常是一个默认图层),而这些图层又包含图层的顶级cell。这意味着每个cell都包含在一个图层中。如果不需要图层,则应将所有新cell添加到默认图层。

图层可用于隐藏和显示cell组,或用于将cell组放置在显示中的其他cell之上。要识别图层,可以使用isLayer方法。如果给定cell的父级是模型的根,则返回true。

1.2 事件

有关详细信息,参阅事件部分。有一组新事件可用于跟踪事件发生的变化。这些事件称为初始beginUpdate的startEdit,为每个执行的更改执行,endEdit为endUpdate执行。执行的事件包含一个名为change的属性,表示执行后的更改。

1.3 编码模型

使用如下代码编码graph model,这将创建一个包含所有模型信息的XML节点:

var enc = new mxCodec();
var node = enc.encode(graph.getModel());

对于更改的编码,需要graph model监听器来编码来自给定更改数组的每个更改:

model.addListener(mxEvent.CHANGE, function(sender, evt) {var changes = evt.getProperty('edit').changes;var nodes = [];var codec = new mxCodec();for (var i = 0; i < changes.length; i++) {nodes.push(codec.encode(changes[i]));}// do something with the nodes
});

对于解码和执行更改,编解码器需要一个查找功能,允许它按如下方式解析单元ID:

var codec = new mxCodec();
codec.lookup = function(id) {return model.getCell(id);
}

对于每个编码的变化(由节点表示),可以使用以下代码来执行解码并创建变更对象:

var changes = [];
var change = codec.decode(node);
change.model = model;
change.execute();
changes.push(change);

然后可以使用模型如下调度更改:

var edit = new mxUndoableEdit(model, false);
edit.changes = changes;edit.notify = function() {edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit', edit, 'changes', edit.changes));edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,'edit', edit, 'changes', edit.changes));
}model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
model.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit', edit, 'changes', changes));

2. 构造

mxGraphModel的构造函数如下:

/*** root - 表示根cell的mxCell*/
function mxGraphModel(root) {this.currentEdit = this.createUndoableEdit();if (root != null) {this.setRoot(root);} else {this.clear();}
}

mxGraphModel与mxGraph一样,都是采用原型链方式继承自mxEventSource:

mxGraphModel.prototype = new mxEventSource();
mxGraphModel.prototype.constructor = mxGraphModel;

3. 原型属性

下面列举一些重要的原型属性:

// 保存根cell,而根cell又包含表示图层作为子cell的cell。也就是说,图中的实际元素应该存在于第三代cell中
mxGraphModel.prototype.root = null;// 从id到cell的map
mxGraphModel.prototype.cells = null;// 指定下一个被创建的id。初始值为0
mxGraphModel.prototype.nextId = 0;// 保存当前事务的更改。如果事务已关闭,则使用createUndoableEdit为此变量创建新对象
mxGraphModel.prototype.currentEdit = null;// 计算嵌套事务的深度。每次调用beginUpdate都会增加这个数字,每次调用endUpdate都会减少它
// 当计数器达到0时,事务将关闭并触发相应的事件。初始值为0
mxGraphModel.prototype.updateLevel = 0;

4. 原型方法

mxGraphModel中有许多原型方法和类,这里选择一些了解其联系及实现

4.1 创建根cell

创建根cell有两种方式,第一种就是在创建mxGraphModel时指定一个cell作为根cell,如果没有指定,则使用第二种方法,如下所示。

调用createRoot方法创建一个根cell,然后设置为当前model的根cell,并会触发根cell更改的事件:

/*** 调用createRoot创建一个根cell*/
mxGraphModel.prototype.clear = function () {this.setRoot(this.createRoot());
};/*** 使用默认图层(第一个cell)创建新的根cell*/
mxGraphModel.prototype.createRoot = function () {var cell = new mxCell();cell.insert(new mxCell());return cell;
};/*** 使用mxRootChange设置模型的root,并将更改添加到当前事务。* 这将重置模型中的所有数据结构,并且是清除现有模型的首选方法。返回新根。** root - 根cell*/
mxGraphModel.prototype.setRoot = function (root) {this.execute(new mxRootChange(this, root));return root;
};/*** 如果需要,执行给定的编辑并触发事件。编辑对象需要一个被调用的执行函数。编辑将添加到beginUpdate* 和endUpdate调用之间的currentEdit,以便在此执行是单个事务时触发事件,即如果没有调用* endUpdate之前没有调用startUpdate调用。此实现在执行给定更改之前触发execute事件。* * change - 描述更改的对象。*/
mxGraphModel.prototype.execute = function (change) {change.execute();this.beginUpdate();this.currentEdit.add(change);this.fireEvent(new mxEventObject(mxEvent.EXECUTE, 'change', change));// 新的全局执行事件this.fireEvent(new mxEventObject(mxEvent.EXECUTED, 'change', change));this.endUpdate();
};

设置新的根cell时,是通过创建一个新的mxRootChange来实现的:

/*** 更改模型中的根的操作。* 通过构造函数指定模型中根的更改。*/
function mxRootChange(model, root) {this.model = model;this.root = root;this.previous = root;
}/*** 使用mxGraphModel.rootChanged执行根的更改*/
mxRootChange.prototype.execute = function () {this.root = this.previous;this.previous = this.model.rootChanged(this.previous);
};/*** 内部回调以更改模型的根并更新内部数据结构,例如cells和nextId。返回先前的根。** root - 根cell*/
mxGraphModel.prototype.rootChanged = function (root) {var oldRoot = this.root;this.root = root;// 重置计数器和数据结构this.nextId = 0;this.cells = null;this.cellAdded(root);return oldRoot;
};

4.2 事务管理

mxGraphModel的事务管理简单而强大,主要通过beginUpdate和endUpdate实现:

/*** 将updateLevel加1。事件通知排队,直到updateLevel使用endUpdate减到0。*/
mxGraphModel.prototype.beginUpdate = function () {this.updateLevel++;this.fireEvent(new mxEventObject(mxEvent.BEGIN_UPDATE));if (this.updateLevel === 1) {this.fireEvent(new mxEventObject(mxEvent.START_EDIT));}
};/*** 将updateLevel减1,并在updateLevel减到0时触发undo事件。此函数通过调用currentEdit* 上的notify方法间接触发change事件,然后使用createUndoableEdit创建新的currentEdit。** 每次编辑时只会触发一次undo事件,而每当调用notify函数时,都会触发change事件,即在编辑的* 撤消和重做时触发。*/
mxGraphModel.prototype.endUpdate = function () {this.updateLevel--;if (this.updateLevel === 0) {this.fireEvent(new mxEventObject(mxEvent.END_EDIT));}if (!this.endingUpdate) {this.endingUpdate = this.updateLevel === 0;this.fireEvent(new mxEventObject(mxEvent.END_UPDATE, 'edit', this.currentEdit));try {if (this.endingUpdate && !this.currentEdit.isEmpty()) {this.fireEvent(new mxEventObject(mxEvent.BEFORE_UNDO, 'edit', this.currentEdit));var tmp = this.currentEdit;this.currentEdit = this.createUndoableEdit();tmp.notify();this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', tmp));}} finally {this.endingUpdate = false;}}
};/*** 创建一个新的mxUndoableEdit,它实现notify方法以通过mxUndoableEdit的源触发change和notify事件。** significant - 可选布尔值,指定要创建的编辑是否重要。默认为true。*/
mxGraphModel.prototype.createUndoableEdit = function (significant) {var edit = new mxUndoableEdit(this, (significant != null) ? significant : true);edit.notify = function () {// LATER: Remove changes property (deprecated)edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit', edit, 'changes', edit.changes));edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,'edit', edit, 'changes', edit.changes));};return edit;
};

【mxGraph】源码学习:(6)mxGraphModel相关推荐

  1. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

  2. Shiro源码学习之一

    一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...

  3. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  4. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  5. 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制

    Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...

  6. jQuery源码学习之Callbacks

    jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...

  7. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  8. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

  9. Vuex源码学习(五)加工后的module

    没有看过moduleCollection那可不行!Vuex源码学习(四)module与moduleCollection 感谢提出代码块和截图建议的小伙伴 代码块和截图的区别: 代码块部分希望大家按照我 ...

  10. 我的angularjs源码学习之旅2——依赖注入

    依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...

最新文章

  1. 华昊中天获国投创业等机构数亿元投资,专注抗肿瘤小分子化学药物研发...
  2. bzoj 4753: [Jsoi2016]最佳团体
  3. linux下shell编程
  4. C++中对象的构造顺序和析构顺序
  5. 高年薪的Web前端工程师经常思考哪些问题?
  6. java闰年的年份,Java案例-判断给定年份是闰年
  7. 前端学习(2482):关于接口的调错
  8. php array第一张图片_PHP array_udiff() 函数
  9. [转载] Java是不是面向对象的程序
  10. 信息学奥赛C++语言: 输出矩形
  11. 使用rust编译linux,在 Ubuntu 上为 CentOS 编译 Rust 程序,
  12. android 实现异步加载图片,Android中ImageView异步加载图片类
  13. C#昵图素材下载器源码可下我图、包图、千图等(带数据库)
  14. 小技巧 - LeetCode 如何查看他人耗时更优的代码答案?
  15. 中小型园区网典型配置
  16. Unity中自制Animation+播放完毕相应事件
  17. Shell攻关之shell基础
  18. 【10639 Hello Kitty】
  19. Java8 stream特性之一:List转Map方案(返回某个属性或对象本身)
  20. 量子计算机芯片电原理图,量子计算机新进展:量子光学芯片电路

热门文章

  1. 北京智能机器人为游客指路;日本研发出可识别背影的人工智能
  2. 如何对C盘进行扩容重新分区?
  3. java实战我爱自学网,白银java教程我要自学网
  4. 【数据库】浅析Innodb的聚集索引与非聚集索引
  5. 牛客网 多校3 I三角形(皮克定理)
  6. 互联网数据分析--指标和维度
  7. 易语言.用修改注册表的方式来关闭win10自带的杀毒软件
  8. 学习笔记 Tianmao 篇 materialRefreshLayout 下拉刷新 控件的使用
  9. 【easyui】之DataGrid数据显示
  10. python微信自动发送信息脚本