|
@@ -0,0 +1,9358 @@
|
|
|
|
+/*!
|
|
|
|
+ * ====================================================
|
|
|
|
+ * Kity Minder Core - v1.4.50 - 2018-09-17
|
|
|
|
+ * https://github.com/fex-team/kityminder-core
|
|
|
|
+ * GitHub: https://github.com/fex-team/kityminder-core.git
|
|
|
|
+ * Copyright (c) 2018 Baidu FEX; Licensed BSD-3-Clause
|
|
|
|
+ * ====================================================
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+(function () {
|
|
|
|
+var _p = {
|
|
|
|
+ r: function(index) {
|
|
|
|
+ if (_p[index].inited) {
|
|
|
|
+ return _p[index].value;
|
|
|
|
+ }
|
|
|
|
+ if (typeof _p[index].value === "function") {
|
|
|
|
+ var module = {
|
|
|
|
+ exports: {}
|
|
|
|
+ }, returnValue = _p[index].value(null, module.exports, module);
|
|
|
|
+ _p[index].inited = true;
|
|
|
|
+ _p[index].value = returnValue;
|
|
|
|
+ if (returnValue !== undefined) {
|
|
|
|
+ return returnValue;
|
|
|
|
+ } else {
|
|
|
|
+ for (var key in module.exports) {
|
|
|
|
+ if (module.exports.hasOwnProperty(key)) {
|
|
|
|
+ _p[index].inited = true;
|
|
|
|
+ _p[index].value = module.exports;
|
|
|
|
+ return module.exports;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ _p[index].inited = true;
|
|
|
|
+ return _p[index].value;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/arc.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 圆弧连线
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[0] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ var connectMarker = new kity.Marker().pipe(function() {
|
|
|
|
+ var r = 7;
|
|
|
|
+ var dot = new kity.Circle(r - 1);
|
|
|
|
+ this.addShape(dot);
|
|
|
|
+ this.setRef(r - 1, 0).setViewBox(-r, -r, r + r, r + r).setWidth(r).setHeight(r);
|
|
|
|
+ this.dot = dot;
|
|
|
|
+ this.node.setAttribute("markerUnits", "userSpaceOnUse");
|
|
|
|
+ });
|
|
|
|
+ connect.register("arc", function(node, parent, connection, width, color) {
|
|
|
|
+ var box = node.getLayoutBox(), pBox = parent.getLayoutBox();
|
|
|
|
+ var start, end, vector;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var pathData = [];
|
|
|
|
+ var side = box.x > pBox.x ? "right" : "left";
|
|
|
|
+ node.getMinder().getPaper().addResource(connectMarker);
|
|
|
|
+ start = new kity.Point(pBox.cx, pBox.cy);
|
|
|
|
+ end = side == "left" ? new kity.Point(box.right + 2, box.cy) : new kity.Point(box.left - 2, box.cy);
|
|
|
|
+ vector = kity.Vector.fromPoints(start, end);
|
|
|
|
+ pathData.push("M", start);
|
|
|
|
+ pathData.push("A", abs(vector.x), abs(vector.y), 0, 0, vector.x * vector.y > 0 ? 0 : 1, end);
|
|
|
|
+ connection.setMarker(connectMarker);
|
|
|
|
+ connectMarker.dot.fill(color);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/arc_tp.js
|
|
|
|
+/**
|
|
|
|
+ *
|
|
|
|
+ * 圆弧连线
|
|
|
|
+ *
|
|
|
|
+ * @author: along
|
|
|
|
+ * @copyright: bpd729@163.com , 2015
|
|
|
|
+ */
|
|
|
|
+_p[1] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ var connectMarker = new kity.Marker().pipe(function() {
|
|
|
|
+ var r = 7;
|
|
|
|
+ var dot = new kity.Circle(r - 1);
|
|
|
|
+ this.addShape(dot);
|
|
|
|
+ this.setRef(r - 1, 0).setViewBox(-r, -r, r + r, r + r).setWidth(r).setHeight(r);
|
|
|
|
+ this.dot = dot;
|
|
|
|
+ this.node.setAttribute("markerUnits", "userSpaceOnUse");
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * 天盘图连线除了连接当前节点和前一个节点外, 还需要渲染当前节点和后一个节点的连接, 防止样式上的断线
|
|
|
|
+ * 这是天盘图与其余的模板不同的地方
|
|
|
|
+ */
|
|
|
|
+ connect.register("arc_tp", function(node, parent, connection, width, color) {
|
|
|
|
+ var end_box = node.getLayoutBox(), start_box = parent.getLayoutBox();
|
|
|
|
+ var index = node.getIndex();
|
|
|
|
+ var nextNode = parent.getChildren()[index + 1];
|
|
|
|
+ if (node.getIndex() > 0) {
|
|
|
|
+ start_box = parent.getChildren()[index - 1].getLayoutBox();
|
|
|
|
+ }
|
|
|
|
+ var start, end, vector;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var pathData = [];
|
|
|
|
+ var side = end_box.x > start_box.x ? "right" : "left";
|
|
|
|
+ node.getMinder().getPaper().addResource(connectMarker);
|
|
|
|
+ start = new kity.Point(start_box.cx, start_box.cy);
|
|
|
|
+ end = new kity.Point(end_box.cx, end_box.cy);
|
|
|
|
+ var jl = Math.sqrt(Math.pow(start.x - end.x, 2) + Math.pow(start.y - end.y, 2));
|
|
|
|
+ //两圆中心点距离
|
|
|
|
+ jl = node.getIndex() == 0 ? jl * .4 : jl;
|
|
|
|
+ vector = kity.Vector.fromPoints(start, end);
|
|
|
|
+ pathData.push("M", start);
|
|
|
|
+ pathData.push("A", jl, jl, 0, 0, 1, end);
|
|
|
|
+ connection.setMarker(connectMarker);
|
|
|
|
+ connectMarker.dot.fill(color);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ // 设置下一个的节点的连接线
|
|
|
|
+ if (nextNode && nextNode.getConnection()) {
|
|
|
|
+ var nextConnection = nextNode.getConnection();
|
|
|
|
+ var next_end_box = nextNode.getLayoutBox();
|
|
|
|
+ var next_end = new kity.Point(next_end_box.cx, next_end_box.cy);
|
|
|
|
+ var jl2 = Math.sqrt(Math.pow(end.x - next_end.x, 2) + Math.pow(end.y - next_end.y, 2));
|
|
|
|
+ //两圆中心点距离
|
|
|
|
+ pathData = [];
|
|
|
|
+ pathData.push("M", end);
|
|
|
|
+ pathData.push("A", jl2, jl2, 0, 0, 1, next_end);
|
|
|
|
+ nextConnection.setMarker(connectMarker);
|
|
|
|
+ connectMarker.dot.fill(color);
|
|
|
|
+ nextConnection.setPathData(pathData);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/bezier.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 提供折线相连的方法
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[2] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ connect.register("bezier", function(node, parent, connection) {
|
|
|
|
+ // 连线起点和终点
|
|
|
|
+ var po = parent.getLayoutVertexOut(), pi = node.getLayoutVertexIn();
|
|
|
|
+ // 连线矢量和方向
|
|
|
|
+ var v = parent.getLayoutVectorOut().normalize();
|
|
|
|
+ var r = Math.round;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var pathData = [];
|
|
|
|
+ pathData.push("M", r(po.x), r(po.y));
|
|
|
|
+ if (abs(v.x) > abs(v.y)) {
|
|
|
|
+ // x - direction
|
|
|
|
+ var hx = (pi.x + po.x) / 2;
|
|
|
|
+ pathData.push("C", hx, po.y, hx, pi.y, pi.x, pi.y);
|
|
|
|
+ } else {
|
|
|
|
+ // y - direction
|
|
|
|
+ var hy = (pi.y + po.y) / 2;
|
|
|
|
+ pathData.push("C", po.x, hy, pi.x, hy, pi.x, pi.y);
|
|
|
|
+ }
|
|
|
|
+ connection.setMarker(null);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/fish-bone-master.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 鱼骨头主干连线
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[3] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ connect.register("fish-bone-master", function(node, parent, connection) {
|
|
|
|
+ var pout = parent.getLayoutVertexOut(), pin = node.getLayoutVertexIn();
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var dy = abs(pout.y - pin.y), dx = abs(pout.x - pin.x);
|
|
|
|
+ var pathData = [];
|
|
|
|
+ pathData.push("M", pout.x, pout.y);
|
|
|
|
+ pathData.push("h", dx - dy);
|
|
|
|
+ pathData.push("L", pin.x, pin.y);
|
|
|
|
+ connection.setMarker(null);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/l.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * "L" 连线
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[4] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ connect.register("l", function(node, parent, connection) {
|
|
|
|
+ var po = parent.getLayoutVertexOut();
|
|
|
|
+ var pi = node.getLayoutVertexIn();
|
|
|
|
+ var vo = parent.getLayoutVectorOut();
|
|
|
|
+ var pathData = [];
|
|
|
|
+ var r = Math.round, abs = Math.abs;
|
|
|
|
+ pathData.push("M", po.round());
|
|
|
|
+ if (abs(vo.x) > abs(vo.y)) {
|
|
|
|
+ pathData.push("H", r(pi.x));
|
|
|
|
+ } else {
|
|
|
|
+ pathData.push("V", pi.y);
|
|
|
|
+ }
|
|
|
|
+ pathData.push("L", pi);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/poly.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 提供折线相连的方法
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[5] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ connect.register("poly", function(node, parent, connection, width) {
|
|
|
|
+ // 连线起点和终点
|
|
|
|
+ var po = parent.getLayoutVertexOut(), pi = node.getLayoutVertexIn();
|
|
|
|
+ // 连线矢量和方向
|
|
|
|
+ var v = parent.getLayoutVectorOut().normalize();
|
|
|
|
+ var r = Math.round;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var pathData = [];
|
|
|
|
+ pathData.push("M", r(po.x), r(po.y));
|
|
|
|
+ switch (true) {
|
|
|
|
+ case abs(v.x) > abs(v.y) && v.x < 0:
|
|
|
|
+ // left
|
|
|
|
+ pathData.push("h", -parent.getStyle("margin-left"));
|
|
|
|
+ pathData.push("v", pi.y - po.y);
|
|
|
|
+ pathData.push("H", pi.x);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case abs(v.x) > abs(v.y) && v.x >= 0:
|
|
|
|
+ // right
|
|
|
|
+ pathData.push("h", parent.getStyle("margin-right"));
|
|
|
|
+ pathData.push("v", pi.y - po.y);
|
|
|
|
+ pathData.push("H", pi.x);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case abs(v.x) <= abs(v.y) && v.y < 0:
|
|
|
|
+ // top
|
|
|
|
+ pathData.push("v", -parent.getStyle("margin-top"));
|
|
|
|
+ pathData.push("h", pi.x - po.x);
|
|
|
|
+ pathData.push("V", pi.y);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case abs(v.x) <= abs(v.y) && v.y >= 0:
|
|
|
|
+ // bottom
|
|
|
|
+ pathData.push("v", parent.getStyle("margin-bottom"));
|
|
|
|
+ pathData.push("h", pi.x - po.x);
|
|
|
|
+ pathData.push("V", pi.y);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ connection.setMarker(null);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/connect/under.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 下划线连线
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[6] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var connect = _p.r(11);
|
|
|
|
+ connect.register("under", function(node, parent, connection, width, color) {
|
|
|
|
+ var box = node.getLayoutBox(), pBox = parent.getLayoutBox();
|
|
|
|
+ var start, end, vector;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var pathData = [];
|
|
|
|
+ var side = box.x > pBox.x ? "right" : "left";
|
|
|
|
+ var radius = node.getStyle("connect-radius");
|
|
|
|
+ var underY = box.bottom + 3;
|
|
|
|
+ var startY = parent.getType() == "sub" ? pBox.bottom + 3 : pBox.cy;
|
|
|
|
+ var p1, p2, p3, mx;
|
|
|
|
+ if (side == "right") {
|
|
|
|
+ p1 = new kity.Point(pBox.right, startY);
|
|
|
|
+ p2 = new kity.Point(box.left - 10, underY);
|
|
|
|
+ p3 = new kity.Point(box.right, underY);
|
|
|
|
+ } else {
|
|
|
|
+ p1 = new kity.Point(pBox.left, startY);
|
|
|
|
+ p2 = new kity.Point(box.right + 10, underY);
|
|
|
|
+ p3 = new kity.Point(box.left, underY);
|
|
|
|
+ }
|
|
|
|
+ mx = (p1.x + p2.x) / 2;
|
|
|
|
+ pathData.push("M", p1);
|
|
|
|
+ pathData.push("C", mx, p1.y, mx, p2.y, p2);
|
|
|
|
+ pathData.push("L", p3);
|
|
|
|
+ connection.setMarker(null);
|
|
|
|
+ connection.setPathData(pathData);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/_boxv.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 调试工具:为 kity.Box 提供一个可视化的渲染
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[7] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ if (location.href.indexOf("boxv") != -1) {
|
|
|
|
+ var vrect;
|
|
|
|
+ Object.defineProperty(kity.Box.prototype, "visualization", {
|
|
|
|
+ get: function() {
|
|
|
|
+ if (!vrect) return null;
|
|
|
|
+ return vrect.setBox(this);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this.on("paperrender", function() {
|
|
|
|
+ vrect = new kity.Rect();
|
|
|
|
+ vrect.fill("rgba(200, 200, 200, .5)");
|
|
|
|
+ vrect.stroke("orange");
|
|
|
|
+ this.getRenderContainer().addShape(vrect);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/animate.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 动画控制
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[8] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var animateDefaultOptions = {
|
|
|
|
+ enableAnimation: true,
|
|
|
|
+ layoutAnimationDuration: 300,
|
|
|
|
+ viewAnimationDuration: 100,
|
|
|
|
+ zoomAnimationDuration: 300
|
|
|
|
+ };
|
|
|
|
+ var resoredAnimationOptions = {};
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this.setDefaultOptions(animateDefaultOptions);
|
|
|
|
+ if (!this.getOption("enableAnimation")) {
|
|
|
|
+ this.disableAnimation();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.prototype.enableAnimation = function() {
|
|
|
|
+ for (var name in animateDefaultOptions) {
|
|
|
|
+ if (animateDefaultOptions.hasOwnProperty(name)) {
|
|
|
|
+ this.setOption(resoredAnimationOptions[name]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ Minder.prototype.disableAnimation = function() {
|
|
|
|
+ for (var name in animateDefaultOptions) {
|
|
|
|
+ if (animateDefaultOptions.hasOwnProperty(name)) {
|
|
|
|
+ resoredAnimationOptions[name] = this.getOption(name);
|
|
|
|
+ this.setOption(name, 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/command.js
|
|
|
|
+_p[9] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var MinderEvent = _p.r(13);
|
|
|
|
+ var COMMAND_STATE_NORMAL = 0;
|
|
|
|
+ var COMMAND_STATE_DISABLED = -1;
|
|
|
|
+ var COMMAND_STATE_ACTIVED = 1;
|
|
|
|
+ /**
|
|
|
|
+ * 表示一个命令,包含命令的查询及执行
|
|
|
|
+ */
|
|
|
|
+ var Command = kity.createClass("Command", {
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this._isContentChange = true;
|
|
|
|
+ this._isSelectionChange = false;
|
|
|
|
+ },
|
|
|
|
+ execute: function(minder, args) {
|
|
|
|
+ throw new Error("Not Implement: Command.execute()");
|
|
|
|
+ },
|
|
|
|
+ setContentChanged: function(val) {
|
|
|
|
+ this._isContentChange = !!val;
|
|
|
|
+ },
|
|
|
|
+ isContentChanged: function() {
|
|
|
|
+ return this._isContentChange;
|
|
|
|
+ },
|
|
|
|
+ setSelectionChanged: function(val) {
|
|
|
|
+ this._isSelectionChange = !!val;
|
|
|
|
+ },
|
|
|
|
+ isSelectionChanged: function() {
|
|
|
|
+ return this._isContentChange;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return COMMAND_STATE_NORMAL;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ return 0;
|
|
|
|
+ },
|
|
|
|
+ isNeedUndo: function() {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Command.STATE_NORMAL = COMMAND_STATE_NORMAL;
|
|
|
|
+ Command.STATE_ACTIVE = COMMAND_STATE_ACTIVED;
|
|
|
|
+ Command.STATE_DISABLED = COMMAND_STATE_DISABLED;
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _getCommand: function(name) {
|
|
|
|
+ return this._commands[name.toLowerCase()];
|
|
|
|
+ },
|
|
|
|
+ _queryCommand: function(name, type, args) {
|
|
|
|
+ var cmd = this._getCommand(name);
|
|
|
|
+ if (cmd) {
|
|
|
|
+ var queryCmd = cmd["query" + type];
|
|
|
|
+ if (queryCmd) return queryCmd.apply(cmd, [ this ].concat(args));
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method queryCommandState()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 查询指定命令的状态
|
|
|
|
+ *
|
|
|
|
+ * @grammar queryCommandName(name) => {number}
|
|
|
|
+ *
|
|
|
|
+ * @param {string} name 要查询的命令名称
|
|
|
|
+ *
|
|
|
|
+ * @return {number}
|
|
|
|
+ * -1: 命令不存在或命令当前不可用
|
|
|
|
+ * 0: 命令可用
|
|
|
|
+ * 1: 命令当前可用并且已经执行过
|
|
|
|
+ */
|
|
|
|
+ queryCommandState: function(name) {
|
|
|
|
+ return this._queryCommand(name, "State", [].slice.call(arguments, 1));
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method queryCommandValue()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 查询指定命令当前的执行值
|
|
|
|
+ *
|
|
|
|
+ * @grammar queryCommandValue(name) => {any}
|
|
|
|
+ *
|
|
|
|
+ * @param {string} name 要查询的命令名称
|
|
|
|
+ *
|
|
|
|
+ * @return {any}
|
|
|
|
+ * 如果命令不存在,返回 undefined
|
|
|
|
+ * 不同命令具有不同返回值,具体请查看 [Command](command) 章节
|
|
|
|
+ */
|
|
|
|
+ queryCommandValue: function(name) {
|
|
|
|
+ return this._queryCommand(name, "Value", [].slice.call(arguments, 1));
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method execCommand()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 执行指定的命令。
|
|
|
|
+ *
|
|
|
|
+ * @grammar execCommand(name, args...)
|
|
|
|
+ *
|
|
|
|
+ * @param {string} name 要执行的命令名称
|
|
|
|
+ * @param {argument} args 要传递给命令的其它参数
|
|
|
|
+ */
|
|
|
|
+ execCommand: function(name) {
|
|
|
|
+ if (!name) return null;
|
|
|
|
+ name = name.toLowerCase();
|
|
|
|
+ var cmdArgs = [].slice.call(arguments, 1), cmd, stoped, result, eventParams;
|
|
|
|
+ var me = this;
|
|
|
|
+ cmd = this._getCommand(name);
|
|
|
|
+ eventParams = {
|
|
|
|
+ command: cmd,
|
|
|
|
+ commandName: name.toLowerCase(),
|
|
|
|
+ commandArgs: cmdArgs
|
|
|
|
+ };
|
|
|
|
+ if (!cmd || !~this.queryCommandState(name)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (!this._hasEnterExecCommand) {
|
|
|
|
+ this._hasEnterExecCommand = true;
|
|
|
|
+ stoped = this._fire(new MinderEvent("beforeExecCommand", eventParams, true));
|
|
|
|
+ if (!stoped) {
|
|
|
|
+ this._fire(new MinderEvent("preExecCommand", eventParams, false));
|
|
|
|
+ result = cmd.execute.apply(cmd, [ me ].concat(cmdArgs));
|
|
|
|
+ this._fire(new MinderEvent("execCommand", eventParams, false));
|
|
|
|
+ if (cmd.isContentChanged()) {
|
|
|
|
+ this._firePharse(new MinderEvent("contentchange"));
|
|
|
|
+ }
|
|
|
|
+ this._interactChange();
|
|
|
|
+ }
|
|
|
|
+ this._hasEnterExecCommand = false;
|
|
|
|
+ } else {
|
|
|
|
+ result = cmd.execute.apply(cmd, [ me ].concat(cmdArgs));
|
|
|
|
+ if (!this._hasEnterExecCommand) {
|
|
|
|
+ this._interactChange();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result === undefined ? null : result;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = Command;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/compatibility.js
|
|
|
|
+_p[10] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ function compatibility(json) {
|
|
|
|
+ var version = json.version || (json.root ? "1.4.0" : "1.1.3");
|
|
|
|
+ switch (version) {
|
|
|
|
+ case "1.1.3":
|
|
|
|
+ c_113_120(json);
|
|
|
|
+
|
|
|
|
+ /* falls through */
|
|
|
|
+ case "1.2.0":
|
|
|
|
+ case "1.2.1":
|
|
|
|
+ c_120_130(json);
|
|
|
|
+
|
|
|
|
+ /* falls through */
|
|
|
|
+ case "1.3.0":
|
|
|
|
+ case "1.3.1":
|
|
|
|
+ case "1.3.2":
|
|
|
|
+ case "1.3.3":
|
|
|
|
+ case "1.3.4":
|
|
|
|
+ case "1.3.5":
|
|
|
|
+ /* falls through */
|
|
|
|
+ c_130_140(json);
|
|
|
|
+ }
|
|
|
|
+ return json;
|
|
|
|
+ }
|
|
|
|
+ function traverse(node, fn) {
|
|
|
|
+ fn(node);
|
|
|
|
+ if (node.children) node.children.forEach(function(child) {
|
|
|
|
+ traverse(child, fn);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /* 脑图数据升级 */
|
|
|
|
+ function c_120_130(json) {
|
|
|
|
+ traverse(json, function(node) {
|
|
|
|
+ var data = node.data;
|
|
|
|
+ delete data.layout_bottom_offset;
|
|
|
|
+ delete data.layout_default_offset;
|
|
|
|
+ delete data.layout_filetree_offset;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 脑图数据升级
|
|
|
|
+ * v1.1.3 => v1.2.0
|
|
|
|
+ * */
|
|
|
|
+ function c_113_120(json) {
|
|
|
|
+ // 原本的布局风格
|
|
|
|
+ var ocs = json.data.currentstyle;
|
|
|
|
+ delete json.data.currentstyle;
|
|
|
|
+ // 为 1.2 选择模板,同时保留老版本文件的皮肤
|
|
|
|
+ if (ocs == "bottom") {
|
|
|
|
+ json.template = "structure";
|
|
|
|
+ json.theme = "snow";
|
|
|
|
+ } else if (ocs == "default") {
|
|
|
|
+ json.template = "default";
|
|
|
|
+ json.theme = "classic";
|
|
|
|
+ }
|
|
|
|
+ traverse(json, function(node) {
|
|
|
|
+ var data = node.data;
|
|
|
|
+ // 升级优先级、进度图标
|
|
|
|
+ if ("PriorityIcon" in data) {
|
|
|
|
+ data.priority = data.PriorityIcon;
|
|
|
|
+ delete data.PriorityIcon;
|
|
|
|
+ }
|
|
|
|
+ if ("ProgressIcon" in data) {
|
|
|
|
+ data.progress = 1 + (data.ProgressIcon - 1 << 1);
|
|
|
|
+ delete data.ProgressIcon;
|
|
|
|
+ }
|
|
|
|
+ // 删除过时属性
|
|
|
|
+ delete data.point;
|
|
|
|
+ delete data.layout;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ function c_130_140(json) {
|
|
|
|
+ json.root = {
|
|
|
|
+ data: json.data,
|
|
|
|
+ children: json.children
|
|
|
|
+ };
|
|
|
|
+ delete json.data;
|
|
|
|
+ delete json.children;
|
|
|
|
+ }
|
|
|
|
+ return compatibility;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/connect.js
|
|
|
|
+_p[11] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ // 连线提供方
|
|
|
|
+ var _connectProviders = {};
|
|
|
|
+ function register(name, provider) {
|
|
|
|
+ _connectProviders[name] = provider;
|
|
|
|
+ }
|
|
|
|
+ register("default", function(node, parent, connection) {
|
|
|
|
+ connection.setPathData([ "M", parent.getLayoutVertexOut(), "L", node.getLayoutVertexIn() ]);
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ /**
|
|
|
|
+ * @private
|
|
|
|
+ * @method getConnect()
|
|
|
|
+ * @for MinderNode
|
|
|
|
+ * @description 获取当前节点的连线类型
|
|
|
|
+ *
|
|
|
|
+ * @grammar getConnect() => {string}
|
|
|
|
+ */
|
|
|
|
+ getConnect: function() {
|
|
|
|
+ return this.data.connect || "default";
|
|
|
|
+ },
|
|
|
|
+ getConnectProvider: function() {
|
|
|
|
+ return _connectProviders[this.getConnect()] || _connectProviders["default"];
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @private
|
|
|
|
+ * @method getConnection()
|
|
|
|
+ * @for MinderNode
|
|
|
|
+ * @description 获取当前节点的连线对象
|
|
|
|
+ *
|
|
|
|
+ * @grammar getConnection() => {kity.Path}
|
|
|
|
+ */
|
|
|
|
+ getConnection: function() {
|
|
|
|
+ return this._connection || null;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ getConnectContainer: function() {
|
|
|
|
+ return this._connectContainer;
|
|
|
|
+ },
|
|
|
|
+ createConnect: function(node) {
|
|
|
|
+ if (node.isRoot()) return;
|
|
|
|
+ var connection = new kity.Path();
|
|
|
|
+ node._connection = connection;
|
|
|
|
+ this._connectContainer.addShape(connection);
|
|
|
|
+ this.updateConnect(node);
|
|
|
|
+ },
|
|
|
|
+ removeConnect: function(node) {
|
|
|
|
+ var me = this;
|
|
|
|
+ node.traverse(function(node) {
|
|
|
|
+ me._connectContainer.removeShape(node._connection);
|
|
|
|
+ node._connection = null;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ updateConnect: function(node) {
|
|
|
|
+ var connection = node._connection;
|
|
|
|
+ var parent = node.parent;
|
|
|
|
+ if (!parent || !connection) return;
|
|
|
|
+ if (parent.isCollapsed()) {
|
|
|
|
+ connection.setVisible(false);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ connection.setVisible(true);
|
|
|
|
+ var provider = node.getConnectProvider();
|
|
|
|
+ var strokeColor = node.getStyle("connect-color") || "white", strokeWidth = node.getStyle("connect-width") || 2;
|
|
|
|
+ connection.stroke(strokeColor, strokeWidth);
|
|
|
|
+ provider(node, parent, connection, strokeWidth, strokeColor);
|
|
|
|
+ if (strokeWidth % 2 === 0) {
|
|
|
|
+ connection.setTranslate(.5, .5);
|
|
|
|
+ } else {
|
|
|
|
+ connection.setTranslate(0, 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("Connect", {
|
|
|
|
+ init: function() {
|
|
|
|
+ this._connectContainer = new kity.Group().setId(utils.uuid("minder_connect_group"));
|
|
|
|
+ this.getRenderContainer().prependShape(this._connectContainer);
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ nodeattach: function(e) {
|
|
|
|
+ this.createConnect(e.node);
|
|
|
|
+ },
|
|
|
|
+ nodedetach: function(e) {
|
|
|
|
+ this.removeConnect(e.node);
|
|
|
|
+ },
|
|
|
|
+ "layoutapply layoutfinish noderender": function(e) {
|
|
|
|
+ this.updateConnect(e.node);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ exports.register = register;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/data.js
|
|
|
|
+_p[12] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var MinderEvent = _p.r(13);
|
|
|
|
+ var compatibility = _p.r(10);
|
|
|
|
+ var Promise = _p.r(25);
|
|
|
|
+ var protocols = {};
|
|
|
|
+ function registerProtocol(name, protocol) {
|
|
|
|
+ protocols[name] = protocol;
|
|
|
|
+ for (var pname in protocols) {
|
|
|
|
+ if (protocols.hasOwnProperty(pname)) {
|
|
|
|
+ protocols[pname] = protocols[pname];
|
|
|
|
+ protocols[pname].name = pname;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ function getRegisterProtocol(name) {
|
|
|
|
+ return name === undefined ? protocols : protocols[name] || null;
|
|
|
|
+ }
|
|
|
|
+ exports.registerProtocol = registerProtocol;
|
|
|
|
+ exports.getRegisterProtocol = getRegisterProtocol;
|
|
|
|
+ // 导入导出
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ // 自动导入
|
|
|
|
+ setup: function(target) {
|
|
|
|
+ if (typeof target == "string") {
|
|
|
|
+ target = document.querySelector(target);
|
|
|
|
+ }
|
|
|
|
+ if (!target) return;
|
|
|
|
+ var protocol = target.getAttribute("minder-data-type");
|
|
|
|
+ if (protocol in protocols) {
|
|
|
|
+ var data = target.textContent;
|
|
|
|
+ target.textContent = null;
|
|
|
|
+ this.renderTo(target);
|
|
|
|
+ this.importData(protocol, data);
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method exportJson()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description
|
|
|
|
+ * 导出当前脑图数据为 JSON 对象,导出的数据格式请参考 [Data](data) 章节。
|
|
|
|
+ * @grammar exportJson() => {plain}
|
|
|
|
+ */
|
|
|
|
+ exportJson: function() {
|
|
|
|
+ /* 导出 node 上整棵树的数据为 JSON */
|
|
|
|
+ function exportNode(node) {
|
|
|
|
+ var exported = {};
|
|
|
|
+ exported.data = node.getData();
|
|
|
|
+ var childNodes = node.getChildren();
|
|
|
|
+ exported.children = [];
|
|
|
|
+ for (var i = 0; i < childNodes.length; i++) {
|
|
|
|
+ exported.children.push(exportNode(childNodes[i]));
|
|
|
|
+ }
|
|
|
|
+ return exported;
|
|
|
|
+ }
|
|
|
|
+ var json = {
|
|
|
|
+ root: exportNode(this.getRoot())
|
|
|
|
+ };
|
|
|
|
+ json.template = this.getTemplate();
|
|
|
|
+ json.theme = this.getTheme();
|
|
|
|
+ json.version = Minder.version;
|
|
|
|
+ return JSON.parse(JSON.stringify(json));
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * function Text2Children(MinderNode, String)
|
|
|
|
+ * @param {MinderNode} node 要导入数据的节点
|
|
|
|
+ * @param {String} text 导入的text数据
|
|
|
|
+ * @Desc: 用于批量插入子节点,并不会修改被插入的父节点
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.21
|
|
|
|
+ * @example: 用于批量导入如下类型的节点
|
|
|
|
+ * 234
|
|
|
|
+ * 3456346 asadf
|
|
|
|
+ * 12312414
|
|
|
|
+ * wereww
|
|
|
|
+ * 12314
|
|
|
|
+ * 1231412
|
|
|
|
+ * 13123
|
|
|
|
+ */
|
|
|
|
+ Text2Children: function(node, text) {
|
|
|
|
+ if (!(node instanceof kityminder.Node)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var children = [], jsonMap = {}, level = 0;
|
|
|
|
+ var LINE_SPLITTER = /\r|\n|\r\n/, TAB_REGEXP = /^(\t|\x20{4})/;
|
|
|
|
+ var lines = text.split(LINE_SPLITTER), line = "", jsonNode, i = 0;
|
|
|
|
+ var minder = this;
|
|
|
|
+ function isEmpty(line) {
|
|
|
|
+ return line === "" && !/\S/.test(line);
|
|
|
|
+ }
|
|
|
|
+ function getNode(line) {
|
|
|
|
+ return {
|
|
|
|
+ data: {
|
|
|
|
+ text: line.replace(/^(\t|\x20{4})+/, "").replace(/(\t|\x20{4})+$/, "")
|
|
|
|
+ },
|
|
|
|
+ children: []
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function getLevel(text) {
|
|
|
|
+ var level = 0;
|
|
|
|
+ while (TAB_REGEXP.test(text)) {
|
|
|
|
+ text = text.replace(TAB_REGEXP, "");
|
|
|
|
+ level++;
|
|
|
|
+ }
|
|
|
|
+ return level;
|
|
|
|
+ }
|
|
|
|
+ function addChild(parent, node) {
|
|
|
|
+ parent.children.push(node);
|
|
|
|
+ }
|
|
|
|
+ function importChildren(node, children) {
|
|
|
|
+ for (var i = 0, l = children.length; i < l; i++) {
|
|
|
|
+ var childNode = minder.createNode(null, node);
|
|
|
|
+ childNode.setData("text", children[i].data.text || "");
|
|
|
|
+ importChildren(childNode, children[i].children);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ while ((line = lines[i++]) !== undefined) {
|
|
|
|
+ line = line.replace(/ /g, "");
|
|
|
|
+ if (isEmpty(line)) continue;
|
|
|
|
+ level = getLevel(line);
|
|
|
|
+ jsonNode = getNode(line);
|
|
|
|
+ if (level === 0) {
|
|
|
|
+ jsonMap = {};
|
|
|
|
+ children.push(jsonNode);
|
|
|
|
+ jsonMap[0] = children[children.length - 1];
|
|
|
|
+ } else {
|
|
|
|
+ if (!jsonMap[level - 1]) {
|
|
|
|
+ throw new Error("Invalid local format");
|
|
|
|
+ }
|
|
|
|
+ addChild(jsonMap[level - 1], jsonNode);
|
|
|
|
+ jsonMap[level] = jsonNode;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ importChildren(node, children);
|
|
|
|
+ minder.refresh();
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method exportNode(MinderNode)
|
|
|
|
+ * @param {MinderNode} node 当前要被导出的节点
|
|
|
|
+ * @return {Object} 返回只含有data和children的Object
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.22
|
|
|
|
+ */
|
|
|
|
+ exportNode: function(node) {
|
|
|
|
+ var exported = {};
|
|
|
|
+ exported.data = node.getData();
|
|
|
|
+ var childNodes = node.getChildren();
|
|
|
|
+ exported.children = [];
|
|
|
|
+ for (var i = 0; i < childNodes.length; i++) {
|
|
|
|
+ exported.children.push(this.exportNode(childNodes[i]));
|
|
|
|
+ }
|
|
|
|
+ return exported;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method importNode()
|
|
|
|
+ * @description 根据纯json {data, children}数据转换成为脑图节点
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.20
|
|
|
|
+ */
|
|
|
|
+ importNode: function(node, json) {
|
|
|
|
+ var data = json.data;
|
|
|
|
+ node.data = {};
|
|
|
|
+ for (var field in data) {
|
|
|
|
+ node.setData(field, data[field]);
|
|
|
|
+ }
|
|
|
|
+ var childrenTreeData = json.children || [];
|
|
|
|
+ for (var i = 0; i < childrenTreeData.length; i++) {
|
|
|
|
+ var childNode = this.createNode(null, node);
|
|
|
|
+ this.importNode(childNode, childrenTreeData[i]);
|
|
|
|
+ }
|
|
|
|
+ return node;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method importJson()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 导入脑图数据,数据为 JSON 对象,具体的数据字段形式请参考 [Data](data) 章节。
|
|
|
|
+ *
|
|
|
|
+ * @grammar importJson(json) => {this}
|
|
|
|
+ *
|
|
|
|
+ * @param {plain} json 要导入的数据
|
|
|
|
+ */
|
|
|
|
+ importJson: function(json) {
|
|
|
|
+ if (!json) return;
|
|
|
|
+ /**
|
|
|
|
+ * @event preimport
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @when 导入数据之前
|
|
|
|
+ */
|
|
|
|
+ this._fire(new MinderEvent("preimport", null, false));
|
|
|
|
+ // 删除当前所有节点
|
|
|
|
+ while (this._root.getChildren().length) {
|
|
|
|
+ this.removeNode(this._root.getChildren()[0]);
|
|
|
|
+ }
|
|
|
|
+ json = compatibility(json);
|
|
|
|
+ this.importNode(this._root, json.root);
|
|
|
|
+ this.setTemplate(json.template || "default");
|
|
|
|
+ this.setTheme(json.theme || null);
|
|
|
|
+ this.refresh();
|
|
|
|
+ /**
|
|
|
|
+ * @event import,contentchange,interactchange
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @when 导入数据之后
|
|
|
|
+ */
|
|
|
|
+ this.fire("import");
|
|
|
|
+ this._firePharse({
|
|
|
|
+ type: "contentchange"
|
|
|
|
+ });
|
|
|
|
+ this._interactChange();
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method exportData()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 使用指定使用的数据协议,导入脑图数据
|
|
|
|
+ *
|
|
|
|
+ * @grammar exportData(protocol) => Promise<data>
|
|
|
|
+ *
|
|
|
|
+ * @param {string} protocol 指定的数据协议(默认内置五种数据协议 `json`、`text`、`markdown`、`svg` 和 `png`)
|
|
|
|
+ */
|
|
|
|
+ exportData: function(protocolName, option) {
|
|
|
|
+ var json, protocol;
|
|
|
|
+ json = this.exportJson();
|
|
|
|
+ // 指定了协议进行导出,需要检测协议是否支持
|
|
|
|
+ if (protocolName) {
|
|
|
|
+ protocol = protocols[protocolName];
|
|
|
|
+ if (!protocol || !protocol.encode) {
|
|
|
|
+ return Promise.reject(new Error("Not supported protocol:" + protocolName));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 导出前抛个事件
|
|
|
|
+ this._fire(new MinderEvent("beforeexport", {
|
|
|
|
+ json: json,
|
|
|
|
+ protocolName: protocolName,
|
|
|
|
+ protocol: protocol
|
|
|
|
+ }));
|
|
|
|
+ return Promise.resolve(protocol.encode(json, this, option));
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method importData()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 使用指定的数据协议,导入脑图数据,覆盖当前实例的脑图
|
|
|
|
+ *
|
|
|
|
+ * @grammar importData(protocol, callback) => Promise<json>
|
|
|
|
+ *
|
|
|
|
+ * @param {string} protocol 指定的用于解析数据的数据协议(默认内置三种数据协议 `json`、`text` 和 `markdown` 的支持)
|
|
|
|
+ * @param {any} data 要导入的数据
|
|
|
|
+ */
|
|
|
|
+ importData: function(protocolName, data, option) {
|
|
|
|
+ var json, protocol;
|
|
|
|
+ var minder = this;
|
|
|
|
+ // 指定了协议进行导入,需要检测协议是否支持
|
|
|
|
+ if (protocolName) {
|
|
|
|
+ protocol = protocols[protocolName];
|
|
|
|
+ if (!protocol || !protocol.decode) {
|
|
|
|
+ return Promise.reject(new Error("Not supported protocol:" + protocolName));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var params = {
|
|
|
|
+ local: data,
|
|
|
|
+ protocolName: protocolName,
|
|
|
|
+ protocol: protocol
|
|
|
|
+ };
|
|
|
|
+ // 导入前抛事件
|
|
|
|
+ this._fire(new MinderEvent("beforeimport", params));
|
|
|
|
+ return Promise.resolve(protocol.decode(data, this, option)).then(function(json) {
|
|
|
|
+ minder.importJson(json);
|
|
|
|
+ return json;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method decodeData()
|
|
|
|
+ * @for Minder
|
|
|
|
+ * @description 使用指定的数据协议,解析为脑图数据,与 importData 的区别在于:不覆盖当前实例的脑图
|
|
|
|
+ *
|
|
|
|
+ * @grammar decodeData(protocol, callback) => Promise<json>
|
|
|
|
+ *
|
|
|
|
+ * @param {string} protocol 指定的用于解析数据的数据协议(默认内置三种数据协议 `json`、`text` 和 `markdown` 的支持)
|
|
|
|
+ * @param {any} data 要导入的数据
|
|
|
|
+ */
|
|
|
|
+ decodeData: function(protocolName, data, option) {
|
|
|
|
+ var json, protocol;
|
|
|
|
+ var minder = this;
|
|
|
|
+ // 指定了协议进行导入,需要检测协议是否支持
|
|
|
|
+ if (protocolName) {
|
|
|
|
+ protocol = protocols[protocolName];
|
|
|
|
+ if (!protocol || !protocol.decode) {
|
|
|
|
+ return Promise.reject(new Error("Not supported protocol:" + protocolName));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var params = {
|
|
|
|
+ local: data,
|
|
|
|
+ protocolName: protocolName,
|
|
|
|
+ protocol: protocol
|
|
|
|
+ };
|
|
|
|
+ // 导入前抛事件
|
|
|
|
+ this._fire(new MinderEvent("beforeimport", params));
|
|
|
|
+ return Promise.resolve(protocol.decode(data, this, option));
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/event.js
|
|
|
|
+_p[13] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ /**
|
|
|
|
+ * @class MinderEvent
|
|
|
|
+ * @description 表示一个脑图中发生的事件
|
|
|
|
+ */
|
|
|
|
+ var MinderEvent = kity.createClass("MindEvent", {
|
|
|
|
+ constructor: function(type, params, canstop) {
|
|
|
|
+ params = params || {};
|
|
|
|
+ if (params.getType && params.getType() == "ShapeEvent") {
|
|
|
|
+ /**
|
|
|
|
+ * @property kityEvent
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 如果事件是从一个 kity 的事件派生的,会有 kityEvent 属性指向原来的 kity 事件
|
|
|
|
+ * @type {KityEvent}
|
|
|
|
+ */
|
|
|
|
+ this.kityEvent = params;
|
|
|
|
+ /**
|
|
|
|
+ * @property originEvent
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 如果事件是从原声 Dom 事件派生的(如 click、mousemove 等),会有 originEvent 指向原来的 Dom 事件
|
|
|
|
+ * @type {DomEvent}
|
|
|
|
+ */
|
|
|
|
+ this.originEvent = params.originEvent;
|
|
|
|
+ } else if (params.target && params.preventDefault) {
|
|
|
|
+ this.originEvent = params;
|
|
|
|
+ } else {
|
|
|
|
+ kity.Utils.extend(this, params);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @property type
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 事件的类型,如 `click`、`contentchange` 等
|
|
|
|
+ * @type {string}
|
|
|
|
+ */
|
|
|
|
+ this.type = type;
|
|
|
|
+ this._canstop = canstop || false;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method getPosition()
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 如果事件是从一个 kity 事件派生的,会有 `getPosition()` 获取事件发生的坐标
|
|
|
|
+ *
|
|
|
|
+ * @grammar getPosition(refer) => {kity.Point}
|
|
|
|
+ *
|
|
|
|
+ * @param {string|kity.Shape} refer
|
|
|
|
+ * 参照的坐标系,
|
|
|
|
+ * `"screen"` - 以浏览器屏幕为参照坐标系
|
|
|
|
+ * `"minder"` - (默认)以脑图画布为参照坐标系
|
|
|
|
+ * `{kity.Shape}` - 指定以某个 kity 图形为参照坐标系
|
|
|
|
+ */
|
|
|
|
+ getPosition: function(refer) {
|
|
|
|
+ if (!this.kityEvent) return;
|
|
|
|
+ if (!refer || refer == "minder") {
|
|
|
|
+ return this.kityEvent.getPosition(this.minder.getRenderContainer());
|
|
|
|
+ }
|
|
|
|
+ return this.kityEvent.getPosition.call(this.kityEvent, refer);
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method getTargetNode()
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 当发生的事件是鼠标事件时,获取事件位置命中的脑图节点
|
|
|
|
+ *
|
|
|
|
+ * @grammar getTargetNode() => {MinderNode}
|
|
|
|
+ */
|
|
|
|
+ getTargetNode: function() {
|
|
|
|
+ var findShape = this.kityEvent && this.kityEvent.targetShape;
|
|
|
|
+ if (!findShape) return null;
|
|
|
|
+ while (!findShape.minderNode && findShape.container) {
|
|
|
|
+ findShape = findShape.container;
|
|
|
|
+ }
|
|
|
|
+ var node = findShape.minderNode;
|
|
|
|
+ if (node && findShape.getOpacity() < 1) return null;
|
|
|
|
+ return node || null;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method stopPropagation()
|
|
|
|
+ * @for MinderEvent
|
|
|
|
+ * @description 当发生的事件是鼠标事件时,获取事件位置命中的脑图节点
|
|
|
|
+ *
|
|
|
|
+ * @grammar getTargetNode() => {MinderNode}
|
|
|
|
+ */
|
|
|
|
+ stopPropagation: function() {
|
|
|
|
+ this._stoped = true;
|
|
|
|
+ },
|
|
|
|
+ stopPropagationImmediately: function() {
|
|
|
|
+ this._immediatelyStoped = true;
|
|
|
|
+ this._stoped = true;
|
|
|
|
+ },
|
|
|
|
+ shouldStopPropagation: function() {
|
|
|
|
+ return this._canstop && this._stoped;
|
|
|
|
+ },
|
|
|
|
+ shouldStopPropagationImmediately: function() {
|
|
|
|
+ return this._canstop && this._immediatelyStoped;
|
|
|
|
+ },
|
|
|
|
+ preventDefault: function() {
|
|
|
|
+ this.originEvent.preventDefault();
|
|
|
|
+ },
|
|
|
|
+ isRightMB: function() {
|
|
|
|
+ var isRightMB = false;
|
|
|
|
+ if (!this.originEvent) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if ("which" in this.originEvent) isRightMB = this.originEvent.which == 3; else if ("button" in this.originEvent) isRightMB = this.originEvent.button == 2;
|
|
|
|
+ return isRightMB;
|
|
|
|
+ },
|
|
|
|
+ getKeyCode: function() {
|
|
|
|
+ var evt = this.originEvent;
|
|
|
|
+ return evt.keyCode || evt.which;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.registerInitHook(function(option) {
|
|
|
|
+ this._initEvents();
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initEvents: function() {
|
|
|
|
+ this._eventCallbacks = {};
|
|
|
|
+ },
|
|
|
|
+ _resetEvents: function() {
|
|
|
|
+ this._initEvents();
|
|
|
|
+ this._bindEvents();
|
|
|
|
+ },
|
|
|
|
+ _bindEvents: function() {
|
|
|
|
+ /* jscs:disable maximumLineLength */
|
|
|
|
+ this._paper.on("click dblclick mousedown contextmenu mouseup mousemove mouseover mousewheel DOMMouseScroll touchstart touchmove touchend dragenter dragleave drop", this._firePharse.bind(this));
|
|
|
|
+ if (window) {
|
|
|
|
+ window.addEventListener("resize", this._firePharse.bind(this));
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @method dispatchKeyEvent
|
|
|
|
+ * @description 派发键盘(相关)事件到脑图实例上,让实例的模块处理
|
|
|
|
+ * @grammar dispatchKeyEvent(e) => {this}
|
|
|
|
+ * @param {Event} e 原生的 Dom 事件对象
|
|
|
|
+ */
|
|
|
|
+ dispatchKeyEvent: function(e) {
|
|
|
|
+ this._firePharse(e);
|
|
|
|
+ },
|
|
|
|
+ _firePharse: function(e) {
|
|
|
|
+ var beforeEvent, preEvent, executeEvent;
|
|
|
|
+ if (e.type == "DOMMouseScroll") {
|
|
|
|
+ e.type = "mousewheel";
|
|
|
|
+ e.wheelDelta = e.originEvent.wheelDelta = e.originEvent.detail * -10;
|
|
|
|
+ e.wheelDeltaX = e.originEvent.mozMovementX;
|
|
|
|
+ e.wheelDeltaY = e.originEvent.mozMovementY;
|
|
|
|
+ }
|
|
|
|
+ beforeEvent = new MinderEvent("before" + e.type, e, true);
|
|
|
|
+ if (this._fire(beforeEvent)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ preEvent = new MinderEvent("pre" + e.type, e, true);
|
|
|
|
+ executeEvent = new MinderEvent(e.type, e, true);
|
|
|
|
+ if (this._fire(preEvent) || this._fire(executeEvent)) this._fire(new MinderEvent("after" + e.type, e, false));
|
|
|
|
+ },
|
|
|
|
+ _interactChange: function(e) {
|
|
|
|
+ var me = this;
|
|
|
|
+ if (me._interactScheduled) return;
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ me._fire(new MinderEvent("interactchange"));
|
|
|
|
+ me._interactScheduled = false;
|
|
|
|
+ }, 100);
|
|
|
|
+ me._interactScheduled = true;
|
|
|
|
+ },
|
|
|
|
+ _listen: function(type, callback) {
|
|
|
|
+ var callbacks = this._eventCallbacks[type] || (this._eventCallbacks[type] = []);
|
|
|
|
+ callbacks.push(callback);
|
|
|
|
+ },
|
|
|
|
+ _fire: function(e) {
|
|
|
|
+ /**
|
|
|
|
+ * @property minder
|
|
|
|
+ * @description 产生事件的 Minder 对象
|
|
|
|
+ * @for MinderShape
|
|
|
|
+ * @type {Minder}
|
|
|
|
+ */
|
|
|
|
+ e.minder = this;
|
|
|
|
+ var status = this.getStatus();
|
|
|
|
+ var callbacks = this._eventCallbacks[e.type.toLowerCase()] || [];
|
|
|
|
+ if (status) {
|
|
|
|
+ callbacks = callbacks.concat(this._eventCallbacks[status + "." + e.type.toLowerCase()] || []);
|
|
|
|
+ }
|
|
|
|
+ if (callbacks.length === 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var lastStatus = this.getStatus();
|
|
|
|
+ for (var i = 0; i < callbacks.length; i++) {
|
|
|
|
+ callbacks[i].call(this, e);
|
|
|
|
+ /* this.getStatus() != lastStatus ||*/
|
|
|
|
+ if (e.shouldStopPropagationImmediately()) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return e.shouldStopPropagation();
|
|
|
|
+ },
|
|
|
|
+ on: function(name, callback) {
|
|
|
|
+ var km = this;
|
|
|
|
+ name.split(/\s+/).forEach(function(n) {
|
|
|
|
+ km._listen(n.toLowerCase(), callback);
|
|
|
|
+ });
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ off: function(name, callback) {
|
|
|
|
+ var types = name.split(/\s+/);
|
|
|
|
+ var i, j, callbacks, removeIndex;
|
|
|
|
+ for (i = 0; i < types.length; i++) {
|
|
|
|
+ callbacks = this._eventCallbacks[types[i].toLowerCase()];
|
|
|
|
+ if (callbacks) {
|
|
|
|
+ removeIndex = null;
|
|
|
|
+ for (j = 0; j < callbacks.length; j++) {
|
|
|
|
+ if (callbacks[j] == callback) {
|
|
|
|
+ removeIndex = j;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (removeIndex !== null) {
|
|
|
|
+ callbacks.splice(removeIndex, 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ fire: function(type, params) {
|
|
|
|
+ var e = new MinderEvent(type, params);
|
|
|
|
+ this._fire(e);
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = MinderEvent;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/focus.js
|
|
|
|
+_p[14] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this.on("beforemousedown", function(e) {
|
|
|
|
+ this.focus();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ this.on("paperrender", function() {
|
|
|
|
+ this.focus();
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ focus: function() {
|
|
|
|
+ if (!this.isFocused()) {
|
|
|
|
+ var renderTarget = this._renderTarget;
|
|
|
|
+ renderTarget.classList.add("focus");
|
|
|
|
+ this.renderNodeBatch(this.getSelectedNodes());
|
|
|
|
+ }
|
|
|
|
+ this.fire("focus");
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ blur: function() {
|
|
|
|
+ if (this.isFocused()) {
|
|
|
|
+ var renderTarget = this._renderTarget;
|
|
|
|
+ renderTarget.classList.remove("focus");
|
|
|
|
+ this.renderNodeBatch(this.getSelectedNodes());
|
|
|
|
+ }
|
|
|
|
+ this.fire("blur");
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ isFocused: function() {
|
|
|
|
+ var renderTarget = this._renderTarget;
|
|
|
|
+ return renderTarget && renderTarget.classList.contains("focus");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/keymap.js
|
|
|
|
+_p[15] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var keymap = {
|
|
|
|
+ Backspace: 8,
|
|
|
|
+ Tab: 9,
|
|
|
|
+ Enter: 13,
|
|
|
|
+ Shift: 16,
|
|
|
|
+ Control: 17,
|
|
|
|
+ Alt: 18,
|
|
|
|
+ CapsLock: 20,
|
|
|
|
+ Esc: 27,
|
|
|
|
+ Spacebar: 32,
|
|
|
|
+ PageUp: 33,
|
|
|
|
+ PageDown: 34,
|
|
|
|
+ End: 35,
|
|
|
|
+ Home: 36,
|
|
|
|
+ Insert: 45,
|
|
|
|
+ Left: 37,
|
|
|
|
+ Up: 38,
|
|
|
|
+ Right: 39,
|
|
|
|
+ Down: 40,
|
|
|
|
+ direction: {
|
|
|
|
+ 37: 1,
|
|
|
|
+ 38: 1,
|
|
|
|
+ 39: 1,
|
|
|
|
+ 40: 1
|
|
|
|
+ },
|
|
|
|
+ Del: 46,
|
|
|
|
+ NumLock: 144,
|
|
|
|
+ Cmd: 91,
|
|
|
|
+ CmdFF: 224,
|
|
|
|
+ F1: 112,
|
|
|
|
+ F2: 113,
|
|
|
|
+ F3: 114,
|
|
|
|
+ F4: 115,
|
|
|
|
+ F5: 116,
|
|
|
|
+ F6: 117,
|
|
|
|
+ F7: 118,
|
|
|
|
+ F8: 119,
|
|
|
|
+ F9: 120,
|
|
|
|
+ F10: 121,
|
|
|
|
+ F11: 122,
|
|
|
|
+ F12: 123,
|
|
|
|
+ "`": 192,
|
|
|
|
+ "=": 187,
|
|
|
|
+ "-": 189,
|
|
|
|
+ "/": 191,
|
|
|
|
+ ".": 190,
|
|
|
|
+ controlKeys: {
|
|
|
|
+ 16: 1,
|
|
|
|
+ 17: 1,
|
|
|
|
+ 18: 1,
|
|
|
|
+ 20: 1,
|
|
|
|
+ 91: 1,
|
|
|
|
+ 224: 1
|
|
|
|
+ },
|
|
|
|
+ notContentChange: {
|
|
|
|
+ 13: 1,
|
|
|
|
+ 9: 1,
|
|
|
|
+ 33: 1,
|
|
|
|
+ 34: 1,
|
|
|
|
+ 35: 1,
|
|
|
|
+ 36: 1,
|
|
|
|
+ 16: 1,
|
|
|
|
+ 17: 1,
|
|
|
|
+ 18: 1,
|
|
|
|
+ 20: 1,
|
|
|
|
+ 91: 1,
|
|
|
|
+ //上下左右
|
|
|
|
+ 37: 1,
|
|
|
|
+ 38: 1,
|
|
|
|
+ 39: 1,
|
|
|
|
+ 40: 1,
|
|
|
|
+ 113: 1,
|
|
|
|
+ 114: 1,
|
|
|
|
+ 115: 1,
|
|
|
|
+ 144: 1,
|
|
|
|
+ 27: 1
|
|
|
|
+ },
|
|
|
|
+ isSelectedNodeKey: {
|
|
|
|
+ //上下左右
|
|
|
|
+ 37: 1,
|
|
|
|
+ 38: 1,
|
|
|
|
+ 39: 1,
|
|
|
|
+ 40: 1,
|
|
|
|
+ 13: 1,
|
|
|
|
+ 9: 1
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ // 小写适配
|
|
|
|
+ for (var key in keymap) {
|
|
|
|
+ if (keymap.hasOwnProperty(key)) {
|
|
|
|
+ keymap[key.toLowerCase()] = keymap[key];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var aKeyCode = 65;
|
|
|
|
+ var aCharCode = "a".charCodeAt(0);
|
|
|
|
+ // letters
|
|
|
|
+ "abcdefghijklmnopqrstuvwxyz".split("").forEach(function(letter) {
|
|
|
|
+ keymap[letter] = aKeyCode + (letter.charCodeAt(0) - aCharCode);
|
|
|
|
+ });
|
|
|
|
+ // numbers
|
|
|
|
+ var n = 9;
|
|
|
|
+ do {
|
|
|
|
+ keymap[n.toString()] = n + 48;
|
|
|
|
+ } while (--n);
|
|
|
|
+ module.exports = keymap;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/keyreceiver.js
|
|
|
|
+_p[16] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ function listen(element, type, handler) {
|
|
|
|
+ type.split(" ").forEach(function(name) {
|
|
|
|
+ element.addEventListener(name, handler, false);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ Minder.registerInitHook(function(option) {
|
|
|
|
+ this.setDefaultOptions({
|
|
|
|
+ enableKeyReceiver: true
|
|
|
|
+ });
|
|
|
|
+ if (this.getOption("enableKeyReceiver")) {
|
|
|
|
+ this.on("paperrender", function() {
|
|
|
|
+ this._initKeyReceiver();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initKeyReceiver: function() {
|
|
|
|
+ if (this._keyReceiver) return;
|
|
|
|
+ var receiver = this._keyReceiver = document.createElement("input");
|
|
|
|
+ receiver.classList.add("km-receiver");
|
|
|
|
+ var renderTarget = this._renderTarget;
|
|
|
|
+ renderTarget.appendChild(receiver);
|
|
|
|
+ var minder = this;
|
|
|
|
+ listen(receiver, "keydown keyup keypress copy paste blur focus input", function(e) {
|
|
|
|
+ switch (e.type) {
|
|
|
|
+ case "blur":
|
|
|
|
+ minder.blur();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "focus":
|
|
|
|
+ minder.focus();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "input":
|
|
|
|
+ receiver.value = null;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ minder._firePharse(e);
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ this.on("focus", function() {
|
|
|
|
+ receiver.select();
|
|
|
|
+ receiver.focus();
|
|
|
|
+ });
|
|
|
|
+ this.on("blur", function() {
|
|
|
|
+ receiver.blur();
|
|
|
|
+ });
|
|
|
|
+ if (this.isFocused()) {
|
|
|
|
+ receiver.select();
|
|
|
|
+ receiver.focus();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/kity.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * Kity 引入
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[17] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ module.exports = window.kity;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/layout.js
|
|
|
|
+_p[18] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var MinderEvent = _p.r(13);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var _layouts = {};
|
|
|
|
+ var _defaultLayout;
|
|
|
|
+ function register(name, layout) {
|
|
|
|
+ _layouts[name] = layout;
|
|
|
|
+ _defaultLayout = _defaultLayout || name;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @class Layout 布局基类,具体布局需要从该类派生
|
|
|
|
+ */
|
|
|
|
+ var Layout = kity.createClass("Layout", {
|
|
|
|
+ /**
|
|
|
|
+ * @abstract
|
|
|
|
+ *
|
|
|
|
+ * 子类需要实现的布局算法,该算法输入一个节点,排布该节点的子节点(相对父节点的变换)
|
|
|
|
+ *
|
|
|
|
+ * @param {MinderNode} node 需要布局的节点
|
|
|
|
+ *
|
|
|
|
+ * @example
|
|
|
|
+ *
|
|
|
|
+ * doLayout: function(node) {
|
|
|
|
+ * var children = node.getChildren();
|
|
|
|
+ * // layout calculation
|
|
|
|
+ * children[i].setLayoutTransform(new kity.Matrix().translate(x, y));
|
|
|
|
+ * }
|
|
|
|
+ */
|
|
|
|
+ doLayout: function(parent, children) {
|
|
|
|
+ throw new Error("Not Implement: Layout.doLayout()");
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 对齐指定的节点
|
|
|
|
+ *
|
|
|
|
+ * @param {Array<MinderNode>} nodes 要对齐的节点
|
|
|
|
+ * @param {string} border 对齐边界,允许取值 left, right, top, bottom
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+ align: function(nodes, border, offset) {
|
|
|
|
+ var me = this;
|
|
|
|
+ offset = offset || 0;
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ var tbox = me.getTreeBox([ node ]);
|
|
|
|
+ var matrix = node.getLayoutTransform();
|
|
|
|
+ switch (border) {
|
|
|
|
+ case "left":
|
|
|
|
+ return matrix.translate(offset - tbox.left, 0);
|
|
|
|
+
|
|
|
|
+ case "right":
|
|
|
|
+ return matrix.translate(offset - tbox.right, 0);
|
|
|
|
+
|
|
|
|
+ case "top":
|
|
|
|
+ return matrix.translate(0, offset - tbox.top);
|
|
|
|
+
|
|
|
|
+ case "bottom":
|
|
|
|
+ return matrix.translate(0, offset - tbox.bottom);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ stack: function(nodes, axis, distance) {
|
|
|
|
+ var me = this;
|
|
|
|
+ var position = 0;
|
|
|
|
+ distance = distance || function(node, next, axis) {
|
|
|
|
+ return node.getStyle({
|
|
|
|
+ x: "margin-right",
|
|
|
|
+ y: "margin-bottom"
|
|
|
|
+ }[axis]) + next.getStyle({
|
|
|
|
+ x: "margin-left",
|
|
|
|
+ y: "margin-top"
|
|
|
|
+ }[axis]);
|
|
|
|
+ };
|
|
|
|
+ nodes.forEach(function(node, index, nodes) {
|
|
|
|
+ var tbox = me.getTreeBox([ node ]);
|
|
|
|
+ var size = {
|
|
|
|
+ x: tbox.width,
|
|
|
|
+ y: tbox.height
|
|
|
|
+ }[axis];
|
|
|
|
+ var offset = {
|
|
|
|
+ x: tbox.left,
|
|
|
|
+ y: tbox.top
|
|
|
|
+ }[axis];
|
|
|
|
+ var matrix = node.getLayoutTransform();
|
|
|
|
+ if (axis == "x") {
|
|
|
|
+ matrix.translate(position - offset, 0);
|
|
|
|
+ } else {
|
|
|
|
+ matrix.translate(0, position - offset);
|
|
|
|
+ }
|
|
|
|
+ position += size;
|
|
|
|
+ if (nodes[index + 1]) position += distance(node, nodes[index + 1], axis);
|
|
|
|
+ });
|
|
|
|
+ return position;
|
|
|
|
+ },
|
|
|
|
+ move: function(nodes, dx, dy) {
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ node.getLayoutTransform().translate(dx, dy);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 工具方法:获取给点的节点所占的布局区域
|
|
|
|
+ *
|
|
|
|
+ * @param {MinderNode[]} nodes 需要计算的节点
|
|
|
|
+ *
|
|
|
|
+ * @return {Box} 计算结果
|
|
|
|
+ */
|
|
|
|
+ getBranchBox: function(nodes) {
|
|
|
|
+ var box = new kity.Box();
|
|
|
|
+ var i, node, matrix, contentBox;
|
|
|
|
+ for (i = 0; i < nodes.length; i++) {
|
|
|
|
+ node = nodes[i];
|
|
|
|
+ matrix = node.getLayoutTransform();
|
|
|
|
+ contentBox = node.getContentBox();
|
|
|
|
+ box = box.merge(matrix.transformBox(contentBox));
|
|
|
|
+ }
|
|
|
|
+ return box;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 工具方法:计算给定的节点的子树所占的布局区域
|
|
|
|
+ *
|
|
|
|
+ * @param {MinderNode} nodes 需要计算的节点
|
|
|
|
+ *
|
|
|
|
+ * @return {Box} 计算的结果
|
|
|
|
+ */
|
|
|
|
+ getTreeBox: function(nodes) {
|
|
|
|
+ var i, node, matrix, treeBox;
|
|
|
|
+ var box = new kity.Box();
|
|
|
|
+ if (!(nodes instanceof Array)) nodes = [ nodes ];
|
|
|
|
+ for (i = 0; i < nodes.length; i++) {
|
|
|
|
+ node = nodes[i];
|
|
|
|
+ matrix = node.getLayoutTransform();
|
|
|
|
+ treeBox = node.getContentBox();
|
|
|
|
+ if (node.isExpanded() && node.children.length) {
|
|
|
|
+ treeBox = treeBox.merge(this.getTreeBox(node.children));
|
|
|
|
+ }
|
|
|
|
+ box = box.merge(matrix.transformBox(treeBox));
|
|
|
|
+ }
|
|
|
|
+ return box;
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: function(node) {
|
|
|
|
+ return [];
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Layout.register = register;
|
|
|
|
+ Minder.registerInitHook(function(options) {
|
|
|
|
+ this.refresh();
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * 布局支持池子管理
|
|
|
|
+ */
|
|
|
|
+ utils.extend(Minder, {
|
|
|
|
+ getLayoutList: function() {
|
|
|
|
+ return _layouts;
|
|
|
|
+ },
|
|
|
|
+ getLayoutInstance: function(name) {
|
|
|
|
+ var LayoutClass = _layouts[name];
|
|
|
|
+ if (!LayoutClass) throw new Error("Missing Layout: " + name);
|
|
|
|
+ var layout = new LayoutClass();
|
|
|
|
+ return layout;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * MinderNode 上的布局支持
|
|
|
|
+ */
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ /**
|
|
|
|
+ * 获得当前节点的布局名称
|
|
|
|
+ *
|
|
|
|
+ * @return {String}
|
|
|
|
+ */
|
|
|
|
+ getLayout: function() {
|
|
|
|
+ var layout = this.getData("layout");
|
|
|
|
+ layout = layout || (this.isRoot() ? _defaultLayout : this.parent.getLayout());
|
|
|
|
+ return layout;
|
|
|
|
+ },
|
|
|
|
+ setLayout: function(name) {
|
|
|
|
+ if (name) {
|
|
|
|
+ if (name == "inherit") {
|
|
|
|
+ this.setData("layout");
|
|
|
|
+ } else {
|
|
|
|
+ this.setData("layout", name);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ layout: function(name) {
|
|
|
|
+ this.setLayout(name).getMinder().layout();
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ getLayoutInstance: function() {
|
|
|
|
+ return Minder.getLayoutInstance(this.getLayout());
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: function(refer) {
|
|
|
|
+ return this.parent.getLayoutInstance().getOrderHint(this);
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取当前节点相对于父节点的布局变换
|
|
|
|
+ */
|
|
|
|
+ getLayoutTransform: function() {
|
|
|
|
+ return this._layoutTransform || new kity.Matrix();
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 第一轮布局计算后,获得的全局布局位置
|
|
|
|
+ *
|
|
|
|
+ * @return {[type]} [description]
|
|
|
|
+ */
|
|
|
|
+ getGlobalLayoutTransformPreview: function() {
|
|
|
|
+ var pMatrix = this.parent ? this.parent.getLayoutTransform() : new kity.Matrix();
|
|
|
|
+ var matrix = this.getLayoutTransform();
|
|
|
|
+ var offset = this.getLayoutOffset();
|
|
|
|
+ if (offset) {
|
|
|
|
+ matrix = matrix.clone().translate(offset.x, offset.y);
|
|
|
|
+ }
|
|
|
|
+ return pMatrix.merge(matrix);
|
|
|
|
+ },
|
|
|
|
+ getLayoutPointPreview: function() {
|
|
|
|
+ return this.getGlobalLayoutTransformPreview().transformPoint(new kity.Point());
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取节点相对于全局的布局变换
|
|
|
|
+ */
|
|
|
|
+ getGlobalLayoutTransform: function() {
|
|
|
|
+ if (this._globalLayoutTransform) {
|
|
|
|
+ return this._globalLayoutTransform;
|
|
|
|
+ } else if (this.parent) {
|
|
|
|
+ return this.parent.getGlobalLayoutTransform();
|
|
|
|
+ } else {
|
|
|
|
+ return new kity.Matrix();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 设置当前节点相对于父节点的布局变换
|
|
|
|
+ */
|
|
|
|
+ setLayoutTransform: function(matrix) {
|
|
|
|
+ this._layoutTransform = matrix;
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 设置当前节点相对于全局的布局变换(冗余优化)
|
|
|
|
+ */
|
|
|
|
+ setGlobalLayoutTransform: function(matrix) {
|
|
|
|
+ this.getRenderContainer().setMatrix(this._globalLayoutTransform = matrix);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ setVertexIn: function(p) {
|
|
|
|
+ this._vertexIn = p;
|
|
|
|
+ },
|
|
|
|
+ setVertexOut: function(p) {
|
|
|
|
+ this._vertexOut = p;
|
|
|
|
+ },
|
|
|
|
+ getVertexIn: function() {
|
|
|
|
+ return this._vertexIn || new kity.Point();
|
|
|
|
+ },
|
|
|
|
+ getVertexOut: function() {
|
|
|
|
+ return this._vertexOut || new kity.Point();
|
|
|
|
+ },
|
|
|
|
+ getLayoutVertexIn: function() {
|
|
|
|
+ return this.getGlobalLayoutTransform().transformPoint(this.getVertexIn());
|
|
|
|
+ },
|
|
|
|
+ getLayoutVertexOut: function() {
|
|
|
|
+ return this.getGlobalLayoutTransform().transformPoint(this.getVertexOut());
|
|
|
|
+ },
|
|
|
|
+ setLayoutVectorIn: function(v) {
|
|
|
|
+ this._layoutVectorIn = v;
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ setLayoutVectorOut: function(v) {
|
|
|
|
+ this._layoutVectorOut = v;
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ getLayoutVectorIn: function() {
|
|
|
|
+ return this._layoutVectorIn || new kity.Vector();
|
|
|
|
+ },
|
|
|
|
+ getLayoutVectorOut: function() {
|
|
|
|
+ return this._layoutVectorOut || new kity.Vector();
|
|
|
|
+ },
|
|
|
|
+ getLayoutBox: function() {
|
|
|
|
+ var matrix = this.getGlobalLayoutTransform();
|
|
|
|
+ return matrix.transformBox(this.getContentBox());
|
|
|
|
+ },
|
|
|
|
+ getLayoutPoint: function() {
|
|
|
|
+ var matrix = this.getGlobalLayoutTransform();
|
|
|
|
+ return matrix.transformPoint(new kity.Point());
|
|
|
|
+ },
|
|
|
|
+ getLayoutOffset: function() {
|
|
|
|
+ if (!this.parent) return new kity.Point();
|
|
|
|
+ // 影响当前节点位置的是父节点的布局
|
|
|
|
+ var data = this.getData("layout_" + this.parent.getLayout() + "_offset");
|
|
|
|
+ if (data) return new kity.Point(data.x, data.y);
|
|
|
|
+ return new kity.Point();
|
|
|
|
+ },
|
|
|
|
+ setLayoutOffset: function(p) {
|
|
|
|
+ if (!this.parent) return this;
|
|
|
|
+ this.setData("layout_" + this.parent.getLayout() + "_offset", p ? {
|
|
|
|
+ x: p.x,
|
|
|
|
+ y: p.y
|
|
|
|
+ } : undefined);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ hasLayoutOffset: function() {
|
|
|
|
+ return !!this.getData("layout_" + this.parent.getLayout() + "_offset");
|
|
|
|
+ },
|
|
|
|
+ resetLayoutOffset: function() {
|
|
|
|
+ return this.setLayoutOffset(null);
|
|
|
|
+ },
|
|
|
|
+ getLayoutRoot: function() {
|
|
|
|
+ if (this.isLayoutRoot()) {
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ return this.parent.getLayoutRoot();
|
|
|
|
+ },
|
|
|
|
+ isLayoutRoot: function() {
|
|
|
|
+ return this.getData("layout") || this.isRoot();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * Minder 上的布局支持
|
|
|
|
+ */
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ layout: function() {
|
|
|
|
+ var duration = this.getOption("layoutAnimationDuration");
|
|
|
|
+ this.getRoot().traverse(function(node) {
|
|
|
|
+ // clear last results
|
|
|
|
+ node.setLayoutTransform(null);
|
|
|
|
+ });
|
|
|
|
+ function layoutNode(node, round) {
|
|
|
|
+ // layout all children first
|
|
|
|
+ // 剪枝:收起的节点无需计算
|
|
|
|
+ if (node.isExpanded() || true) {
|
|
|
|
+ node.children.forEach(function(child) {
|
|
|
|
+ layoutNode(child, round);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ var layout = node.getLayoutInstance();
|
|
|
|
+ // var childrenInFlow = node.getChildren().filter(function(child) {
|
|
|
|
+ // return !child.hasLayoutOffset();
|
|
|
|
+ // });
|
|
|
|
+ layout.doLayout(node, node.getChildren(), round);
|
|
|
|
+ }
|
|
|
|
+ // 第一轮布局
|
|
|
|
+ layoutNode(this.getRoot(), 1);
|
|
|
|
+ // 第二轮布局
|
|
|
|
+ layoutNode(this.getRoot(), 2);
|
|
|
|
+ var minder = this;
|
|
|
|
+ this.applyLayoutResult(this.getRoot(), duration, function() {
|
|
|
|
+ /**
|
|
|
|
+ * 当节点>200, 不使用动画时, 此处逻辑变为同步逻辑, 外部minder.on事件无法
|
|
|
|
+ * 被提前录入, 因此增加setTimeout
|
|
|
|
+ * @author Naixor
|
|
|
|
+ */
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ minder.fire("layoutallfinish");
|
|
|
|
+ }, 0);
|
|
|
|
+ });
|
|
|
|
+ return this.fire("layout");
|
|
|
|
+ },
|
|
|
|
+ refresh: function() {
|
|
|
|
+ this.getRoot().renderTree();
|
|
|
|
+ this.layout().fire("contentchange")._interactChange();
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ applyLayoutResult: function(root, duration, callback) {
|
|
|
|
+ root = root || this.getRoot();
|
|
|
|
+ var me = this;
|
|
|
|
+ var complex = root.getComplex();
|
|
|
|
+ function consume() {
|
|
|
|
+ if (!--complex) {
|
|
|
|
+ if (callback) {
|
|
|
|
+ callback();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 节点复杂度大于 100,关闭动画
|
|
|
|
+ if (complex > 200) duration = 0;
|
|
|
|
+ function applyMatrix(node, matrix) {
|
|
|
|
+ node.setGlobalLayoutTransform(matrix);
|
|
|
|
+ me.fire("layoutapply", {
|
|
|
|
+ node: node,
|
|
|
|
+ matrix: matrix
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ function apply(node, pMatrix) {
|
|
|
|
+ var matrix = node.getLayoutTransform().merge(pMatrix.clone());
|
|
|
|
+ var lastMatrix = node.getGlobalLayoutTransform() || new kity.Matrix();
|
|
|
|
+ var offset = node.getLayoutOffset();
|
|
|
|
+ matrix.translate(offset.x, offset.y);
|
|
|
|
+ matrix.m.e = Math.round(matrix.m.e);
|
|
|
|
+ matrix.m.f = Math.round(matrix.m.f);
|
|
|
|
+ // 如果当前有动画,停止动画
|
|
|
|
+ if (node._layoutTimeline) {
|
|
|
|
+ node._layoutTimeline.stop();
|
|
|
|
+ node._layoutTimeline = null;
|
|
|
|
+ }
|
|
|
|
+ // 如果要求以动画形式来更新,创建动画
|
|
|
|
+ if (duration) {
|
|
|
|
+ node._layoutTimeline = new kity.Animator(lastMatrix, matrix, applyMatrix).start(node, duration, "ease").on("finish", function() {
|
|
|
|
+ //可能性能低的时候会丢帧,手动添加一帧
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ applyMatrix(node, matrix);
|
|
|
|
+ me.fire("layoutfinish", {
|
|
|
|
+ node: node,
|
|
|
|
+ matrix: matrix
|
|
|
|
+ });
|
|
|
|
+ consume();
|
|
|
|
+ }, 150);
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ applyMatrix(node, matrix);
|
|
|
|
+ me.fire("layoutfinish", {
|
|
|
|
+ node: node,
|
|
|
|
+ matrix: matrix
|
|
|
|
+ });
|
|
|
|
+ consume();
|
|
|
|
+ }
|
|
|
|
+ for (var i = 0; i < node.children.length; i++) {
|
|
|
|
+ apply(node.children[i], matrix);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ apply(root, root.parent ? root.parent.getGlobalLayoutTransform() : new kity.Matrix());
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = Layout;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/minder.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * KityMinder 类,暴露在 window 上的唯一变量
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[19] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var _initHooks = [];
|
|
|
|
+ var Minder = kity.createClass("Minder", {
|
|
|
|
+ constructor: function(options) {
|
|
|
|
+ this._options = utils.extend({}, options);
|
|
|
|
+ var initHooks = _initHooks.slice();
|
|
|
|
+ var initHook;
|
|
|
|
+ while (initHooks.length) {
|
|
|
|
+ initHook = initHooks.shift();
|
|
|
|
+ if (typeof initHook == "function") {
|
|
|
|
+ initHook.call(this, this._options);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ this.fire("finishInitHook");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.version = "1.4.43";
|
|
|
|
+ Minder.registerInitHook = function(hook) {
|
|
|
|
+ _initHooks.push(hook);
|
|
|
|
+ };
|
|
|
|
+ module.exports = Minder;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/module.js
|
|
|
|
+_p[20] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ /* 已注册的模块 */
|
|
|
|
+ var _modules = {};
|
|
|
|
+ exports.register = function(name, module) {
|
|
|
|
+ _modules[name] = module;
|
|
|
|
+ };
|
|
|
|
+ /* 模块初始化 */
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this._initModules();
|
|
|
|
+ });
|
|
|
|
+ // 模块声明周期维护
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initModules: function() {
|
|
|
|
+ var modulesPool = _modules;
|
|
|
|
+ var modulesToLoad = this._options.modules || utils.keys(modulesPool);
|
|
|
|
+ this._commands = {};
|
|
|
|
+ this._query = {};
|
|
|
|
+ this._modules = {};
|
|
|
|
+ this._rendererClasses = {};
|
|
|
|
+ var i, name, type, module, moduleDeals, dealCommands, dealEvents, dealRenderers;
|
|
|
|
+ var me = this;
|
|
|
|
+ for (i = 0; i < modulesToLoad.length; i++) {
|
|
|
|
+ name = modulesToLoad[i];
|
|
|
|
+ if (!modulesPool[name]) continue;
|
|
|
|
+ // 执行模块初始化,抛出后续处理对象
|
|
|
|
+ if (typeof modulesPool[name] == "function") {
|
|
|
|
+ moduleDeals = modulesPool[name].call(me);
|
|
|
|
+ } else {
|
|
|
|
+ moduleDeals = modulesPool[name];
|
|
|
|
+ }
|
|
|
|
+ this._modules[name] = moduleDeals;
|
|
|
|
+ if (!moduleDeals) continue;
|
|
|
|
+ if (moduleDeals.defaultOptions) {
|
|
|
|
+ me.setDefaultOptions(moduleDeals.defaultOptions);
|
|
|
|
+ }
|
|
|
|
+ if (moduleDeals.init) {
|
|
|
|
+ moduleDeals.init.call(me, this._options);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @Desc: 判断是否支持原生clipboard事件,如果支持,则对pager添加其监听
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.20
|
|
|
|
+ */
|
|
|
|
+ /**
|
|
|
|
+ * 由于当前脑图解构问题,clipboard暂时全权交由玩不托管
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.24
|
|
|
|
+ */
|
|
|
|
+ // if (name === 'ClipboardModule' && this.supportClipboardEvent && !kity.Browser.gecko) {
|
|
|
|
+ // var on = function () {
|
|
|
|
+ // var clipBoardReceiver = this.clipBoardReceiver || document;
|
|
|
|
+ // if (document.addEventListener) {
|
|
|
|
+ // clipBoardReceiver.addEventListener.apply(this, arguments);
|
|
|
|
+ // } else {
|
|
|
|
+ // arguments[0] = 'on' + arguments[0];
|
|
|
|
+ // clipBoardReceiver.attachEvent.apply(this, arguments);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // for (var command in moduleDeals.clipBoardEvents) {
|
|
|
|
+ // on(command, moduleDeals.clipBoardEvents[command]);
|
|
|
|
+ // }
|
|
|
|
+ // };
|
|
|
|
+ // command加入命令池子
|
|
|
|
+ dealCommands = moduleDeals.commands;
|
|
|
|
+ for (name in dealCommands) {
|
|
|
|
+ this._commands[name.toLowerCase()] = new dealCommands[name]();
|
|
|
|
+ }
|
|
|
|
+ // 绑定事件
|
|
|
|
+ dealEvents = moduleDeals.events;
|
|
|
|
+ if (dealEvents) {
|
|
|
|
+ for (type in dealEvents) {
|
|
|
|
+ me.on(type, dealEvents[type]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 渲染器
|
|
|
|
+ dealRenderers = moduleDeals.renderers;
|
|
|
|
+ if (dealRenderers) {
|
|
|
|
+ for (type in dealRenderers) {
|
|
|
|
+ this._rendererClasses[type] = this._rendererClasses[type] || [];
|
|
|
|
+ if (utils.isArray(dealRenderers[type])) {
|
|
|
|
+ this._rendererClasses[type] = this._rendererClasses[type].concat(dealRenderers[type]);
|
|
|
|
+ } else {
|
|
|
|
+ this._rendererClasses[type].push(dealRenderers[type]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //添加模块的快捷键
|
|
|
|
+ if (moduleDeals.commandShortcutKeys) {
|
|
|
|
+ this.addCommandShortcutKeys(moduleDeals.commandShortcutKeys);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ _garbage: function() {
|
|
|
|
+ this.clearSelect();
|
|
|
|
+ while (this._root.getChildren().length) {
|
|
|
|
+ this._root.removeChild(0);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ destroy: function() {
|
|
|
|
+ var modules = this._modules;
|
|
|
|
+ this._resetEvents();
|
|
|
|
+ this._garbage();
|
|
|
|
+ for (var key in modules) {
|
|
|
|
+ if (!modules[key].destroy) continue;
|
|
|
|
+ modules[key].destroy.call(this);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ reset: function() {
|
|
|
|
+ var modules = this._modules;
|
|
|
|
+ this._garbage();
|
|
|
|
+ for (var key in modules) {
|
|
|
|
+ if (!modules[key].reset) continue;
|
|
|
|
+ modules[key].reset.call(this);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/node.js
|
|
|
|
+_p[21] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ /**
|
|
|
|
+ * @class MinderNode
|
|
|
|
+ *
|
|
|
|
+ * 表示一个脑图节点
|
|
|
|
+ */
|
|
|
|
+ var MinderNode = kity.createClass("MinderNode", {
|
|
|
|
+ /**
|
|
|
|
+ * 创建一个游离的脑图节点
|
|
|
|
+ *
|
|
|
|
+ * @param {String|Object} textOrData
|
|
|
|
+ * 节点的初始数据或文本
|
|
|
|
+ */
|
|
|
|
+ constructor: function(textOrData) {
|
|
|
|
+ // 指针
|
|
|
|
+ this.parent = null;
|
|
|
|
+ this.root = this;
|
|
|
|
+ this.children = [];
|
|
|
|
+ // 数据
|
|
|
|
+ this.data = {
|
|
|
|
+ id: utils.guid(),
|
|
|
|
+ created: +new Date()
|
|
|
|
+ };
|
|
|
|
+ // 绘图容器
|
|
|
|
+ this.initContainers();
|
|
|
|
+ if (utils.isString(textOrData)) {
|
|
|
|
+ this.setText(textOrData);
|
|
|
|
+ } else if (utils.isObject(textOrData)) {
|
|
|
|
+ utils.extend(this.data, textOrData);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ initContainers: function() {
|
|
|
|
+ this.rc = new kity.Group().setId(utils.uuid("minder_node"));
|
|
|
|
+ this.rc.minderNode = this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 判断节点是否根节点
|
|
|
|
+ */
|
|
|
|
+ isRoot: function() {
|
|
|
|
+ return this.root === this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 判断节点是否叶子
|
|
|
|
+ */
|
|
|
|
+ isLeaf: function() {
|
|
|
|
+ return this.children.length === 0;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取节点的根节点
|
|
|
|
+ */
|
|
|
|
+ getRoot: function() {
|
|
|
|
+ return this.root || this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得节点的父节点
|
|
|
|
+ */
|
|
|
|
+ getParent: function() {
|
|
|
|
+ return this.parent;
|
|
|
|
+ },
|
|
|
|
+ getSiblings: function() {
|
|
|
|
+ var children = this.parent.children;
|
|
|
|
+ var siblings = [];
|
|
|
|
+ var self = this;
|
|
|
|
+ children.forEach(function(child) {
|
|
|
|
+ if (child != self) siblings.push(child);
|
|
|
|
+ });
|
|
|
|
+ return siblings;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得节点的深度
|
|
|
|
+ */
|
|
|
|
+ getLevel: function() {
|
|
|
|
+ var level = 0, ancestor = this.parent;
|
|
|
|
+ while (ancestor) {
|
|
|
|
+ level++;
|
|
|
|
+ ancestor = ancestor.parent;
|
|
|
|
+ }
|
|
|
|
+ return level;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得节点的复杂度(即子树中节点的数量)
|
|
|
|
+ */
|
|
|
|
+ getComplex: function() {
|
|
|
|
+ var complex = 0;
|
|
|
|
+ this.traverse(function() {
|
|
|
|
+ complex++;
|
|
|
|
+ });
|
|
|
|
+ return complex;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得节点的类型(root|main|sub)
|
|
|
|
+ */
|
|
|
|
+ getType: function(type) {
|
|
|
|
+ this.type = [ "root", "main", "sub" ][Math.min(this.getLevel(), 2)];
|
|
|
|
+ return this.type;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 判断当前节点是否被测试节点的祖先
|
|
|
|
+ * @param {MinderNode} test 被测试的节点
|
|
|
|
+ */
|
|
|
|
+ isAncestorOf: function(test) {
|
|
|
|
+ var ancestor = test.parent;
|
|
|
|
+ while (ancestor) {
|
|
|
|
+ if (ancestor == this) return true;
|
|
|
|
+ ancestor = ancestor.parent;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ },
|
|
|
|
+ getData: function(key) {
|
|
|
|
+ return key ? this.data[key] : this.data;
|
|
|
|
+ },
|
|
|
|
+ setData: function(key, value) {
|
|
|
|
+ if (typeof key == "object") {
|
|
|
|
+ var data = key;
|
|
|
|
+ for (key in data) if (data.hasOwnProperty(key)) {
|
|
|
|
+ this.data[key] = data[key];
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ this.data[key] = value;
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 设置节点的文本数据
|
|
|
|
+ * @param {String} text 文本数据
|
|
|
|
+ */
|
|
|
|
+ setText: function(text) {
|
|
|
|
+ return this.data.text = text;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取节点的文本数据
|
|
|
|
+ * @return {String}
|
|
|
|
+ */
|
|
|
|
+ getText: function() {
|
|
|
|
+ return this.data.text || null;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 先序遍历当前节点树
|
|
|
|
+ * @param {Function} fn 遍历函数
|
|
|
|
+ */
|
|
|
|
+ preTraverse: function(fn, excludeThis) {
|
|
|
|
+ var children = this.getChildren();
|
|
|
|
+ if (!excludeThis) fn(this);
|
|
|
|
+ for (var i = 0; i < children.length; i++) {
|
|
|
|
+ children[i].preTraverse(fn);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 后序遍历当前节点树
|
|
|
|
+ * @param {Function} fn 遍历函数
|
|
|
|
+ */
|
|
|
|
+ postTraverse: function(fn, excludeThis) {
|
|
|
|
+ var children = this.getChildren();
|
|
|
|
+ for (var i = 0; i < children.length; i++) {
|
|
|
|
+ children[i].postTraverse(fn);
|
|
|
|
+ }
|
|
|
|
+ if (!excludeThis) fn(this);
|
|
|
|
+ },
|
|
|
|
+ traverse: function(fn, excludeThis) {
|
|
|
|
+ return this.postTraverse(fn, excludeThis);
|
|
|
|
+ },
|
|
|
|
+ getChildren: function() {
|
|
|
|
+ return this.children;
|
|
|
|
+ },
|
|
|
|
+ getIndex: function() {
|
|
|
|
+ return this.parent ? this.parent.children.indexOf(this) : -1;
|
|
|
|
+ },
|
|
|
|
+ insertChild: function(node, index) {
|
|
|
|
+ if (index === undefined) {
|
|
|
|
+ index = this.children.length;
|
|
|
|
+ }
|
|
|
|
+ if (node.parent) {
|
|
|
|
+ node.parent.removeChild(node);
|
|
|
|
+ }
|
|
|
|
+ node.parent = this;
|
|
|
|
+ node.root = this.root;
|
|
|
|
+ this.children.splice(index, 0, node);
|
|
|
|
+ },
|
|
|
|
+ appendChild: function(node) {
|
|
|
|
+ return this.insertChild(node);
|
|
|
|
+ },
|
|
|
|
+ prependChild: function(node) {
|
|
|
|
+ return this.insertChild(node, 0);
|
|
|
|
+ },
|
|
|
|
+ removeChild: function(elem) {
|
|
|
|
+ var index = elem, removed;
|
|
|
|
+ if (elem instanceof MinderNode) {
|
|
|
|
+ index = this.children.indexOf(elem);
|
|
|
|
+ }
|
|
|
|
+ if (index >= 0) {
|
|
|
|
+ removed = this.children.splice(index, 1)[0];
|
|
|
|
+ removed.parent = null;
|
|
|
|
+ removed.root = removed;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ clearChildren: function() {
|
|
|
|
+ this.children = [];
|
|
|
|
+ },
|
|
|
|
+ getChild: function(index) {
|
|
|
|
+ return this.children[index];
|
|
|
|
+ },
|
|
|
|
+ getRenderContainer: function() {
|
|
|
|
+ return this.rc;
|
|
|
|
+ },
|
|
|
|
+ getCommonAncestor: function(node) {
|
|
|
|
+ return MinderNode.getCommonAncestor(this, node);
|
|
|
|
+ },
|
|
|
|
+ contains: function(node) {
|
|
|
|
+ return this == node || this.isAncestorOf(node);
|
|
|
|
+ },
|
|
|
|
+ clone: function() {
|
|
|
|
+ var cloned = new MinderNode();
|
|
|
|
+ cloned.data = utils.clone(this.data);
|
|
|
|
+ this.children.forEach(function(child) {
|
|
|
|
+ cloned.appendChild(child.clone());
|
|
|
|
+ });
|
|
|
|
+ return cloned;
|
|
|
|
+ },
|
|
|
|
+ compareTo: function(node) {
|
|
|
|
+ if (!utils.comparePlainObject(this.data, node.data)) return false;
|
|
|
|
+ if (!utils.comparePlainObject(this.temp, node.temp)) return false;
|
|
|
|
+ if (this.children.length != node.children.length) return false;
|
|
|
|
+ var i = 0;
|
|
|
|
+ while (this.children[i]) {
|
|
|
|
+ if (!this.children[i].compareTo(node.children[i])) return false;
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ getMinder: function() {
|
|
|
|
+ return this.getRoot().minder;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ MinderNode.getCommonAncestor = function(nodeA, nodeB) {
|
|
|
|
+ if (nodeA instanceof Array) {
|
|
|
|
+ return MinderNode.getCommonAncestor.apply(this, nodeA);
|
|
|
|
+ }
|
|
|
|
+ switch (arguments.length) {
|
|
|
|
+ case 1:
|
|
|
|
+ return nodeA.parent || nodeA;
|
|
|
|
+
|
|
|
|
+ case 2:
|
|
|
|
+ if (nodeA.isAncestorOf(nodeB)) {
|
|
|
|
+ return nodeA;
|
|
|
|
+ }
|
|
|
|
+ if (nodeB.isAncestorOf(nodeA)) {
|
|
|
|
+ return nodeB;
|
|
|
|
+ }
|
|
|
|
+ var ancestor = nodeA.parent;
|
|
|
|
+ while (ancestor && !ancestor.isAncestorOf(nodeB)) {
|
|
|
|
+ ancestor = ancestor.parent;
|
|
|
|
+ }
|
|
|
|
+ return ancestor;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ return Array.prototype.reduce.call(arguments, function(prev, current) {
|
|
|
|
+ return MinderNode.getCommonAncestor(prev, current);
|
|
|
|
+ }, nodeA);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ getRoot: function() {
|
|
|
|
+ return this._root;
|
|
|
|
+ },
|
|
|
|
+ setRoot: function(root) {
|
|
|
|
+ this._root = root;
|
|
|
|
+ root.minder = this;
|
|
|
|
+ },
|
|
|
|
+ getAllNode: function() {
|
|
|
|
+ var nodes = [];
|
|
|
|
+ this.getRoot().traverse(function(node) {
|
|
|
|
+ nodes.push(node);
|
|
|
|
+ });
|
|
|
|
+ return nodes;
|
|
|
|
+ },
|
|
|
|
+ getNodeById: function(id) {
|
|
|
|
+ return this.getNodesById([ id ])[0];
|
|
|
|
+ },
|
|
|
|
+ getNodesById: function(ids) {
|
|
|
|
+ var nodes = this.getAllNode();
|
|
|
|
+ var result = [];
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ if (ids.indexOf(node.getData("id")) != -1) {
|
|
|
|
+ result.push(node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return result;
|
|
|
|
+ },
|
|
|
|
+ createNode: function(textOrData, parent, index) {
|
|
|
|
+ var node = new MinderNode(textOrData);
|
|
|
|
+ this.fire("nodecreate", {
|
|
|
|
+ node: node,
|
|
|
|
+ parent: parent,
|
|
|
|
+ index: index
|
|
|
|
+ });
|
|
|
|
+ this.appendNode(node, parent, index);
|
|
|
|
+ return node;
|
|
|
|
+ },
|
|
|
|
+ appendNode: function(node, parent, index) {
|
|
|
|
+ if (parent) parent.insertChild(node, index);
|
|
|
|
+ this.attachNode(node);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ removeNode: function(node) {
|
|
|
|
+ if (node.parent) {
|
|
|
|
+ node.parent.removeChild(node);
|
|
|
|
+ this.detachNode(node);
|
|
|
|
+ this.fire("noderemove", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ attachNode: function(node) {
|
|
|
|
+ var rc = this.getRenderContainer();
|
|
|
|
+ node.traverse(function(current) {
|
|
|
|
+ current.attached = true;
|
|
|
|
+ rc.addShape(current.getRenderContainer());
|
|
|
|
+ });
|
|
|
|
+ rc.addShape(node.getRenderContainer());
|
|
|
|
+ this.fire("nodeattach", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ detachNode: function(node) {
|
|
|
|
+ var rc = this.getRenderContainer();
|
|
|
|
+ node.traverse(function(current) {
|
|
|
|
+ current.attached = false;
|
|
|
|
+ rc.removeShape(current.getRenderContainer());
|
|
|
|
+ });
|
|
|
|
+ this.fire("nodedetach", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ getMinderTitle: function() {
|
|
|
|
+ return this.getRoot().getText();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = MinderNode;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/option.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 提供脑图选项支持
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[22] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ Minder.registerInitHook(function(options) {
|
|
|
|
+ this._defaultOptions = {};
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ setDefaultOptions: function(options) {
|
|
|
|
+ utils.extend(this._defaultOptions, options);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ getOption: function(key) {
|
|
|
|
+ if (key) {
|
|
|
|
+ return key in this._options ? this._options[key] : this._defaultOptions[key];
|
|
|
|
+ } else {
|
|
|
|
+ return utils.extend({}, this._defaultOptions, this._options);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ setOption: function(key, value) {
|
|
|
|
+ this._options[key] = value;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/paper.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 初始化渲染容器
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[23] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this._initPaper();
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initPaper: function() {
|
|
|
|
+ this._paper = new kity.Paper();
|
|
|
|
+ this._paper._minder = this;
|
|
|
|
+ this._paper.getNode().ondragstart = function(e) {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ };
|
|
|
|
+ this._paper.shapeNode.setAttribute("transform", "translate(0.5, 0.5)");
|
|
|
|
+ this._addRenderContainer();
|
|
|
|
+ this.setRoot(this.createNode());
|
|
|
|
+ if (this._options.renderTo) {
|
|
|
|
+ this.renderTo(this._options.renderTo);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ _addRenderContainer: function() {
|
|
|
|
+ this._rc = new kity.Group().setId(utils.uuid("minder"));
|
|
|
|
+ this._paper.addShape(this._rc);
|
|
|
|
+ },
|
|
|
|
+ renderTo: function(target) {
|
|
|
|
+ if (typeof target == "string") {
|
|
|
|
+ target = document.querySelector(target);
|
|
|
|
+ }
|
|
|
|
+ if (target) {
|
|
|
|
+ if (target.tagName.toLowerCase() == "script") {
|
|
|
|
+ var newTarget = document.createElement("div");
|
|
|
|
+ newTarget.id = target.id;
|
|
|
|
+ newTarget.class = target.class;
|
|
|
|
+ target.parentNode.insertBefore(newTarget, target);
|
|
|
|
+ target.parentNode.removeChild(target);
|
|
|
|
+ target = newTarget;
|
|
|
|
+ }
|
|
|
|
+ target.classList.add("km-view");
|
|
|
|
+ this._paper.renderTo(this._renderTarget = target);
|
|
|
|
+ this._bindEvents();
|
|
|
|
+ this.fire("paperrender");
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ getRenderContainer: function() {
|
|
|
|
+ return this._rc;
|
|
|
|
+ },
|
|
|
|
+ getPaper: function() {
|
|
|
|
+ return this._paper;
|
|
|
|
+ },
|
|
|
|
+ getRenderTarget: function() {
|
|
|
|
+ return this._renderTarget;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/patch.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 打补丁
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[24] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ function insertNode(minder, info, parent, index) {
|
|
|
|
+ parent = minder.createNode(info.data, parent, index);
|
|
|
|
+ info.children.forEach(function(childInfo, index) {
|
|
|
|
+ insertNode(minder, childInfo, parent, index);
|
|
|
|
+ });
|
|
|
|
+ return parent;
|
|
|
|
+ }
|
|
|
|
+ function applyPatch(minder, patch) {
|
|
|
|
+ // patch.op - 操作,包括 remove, add, replace
|
|
|
|
+ // patch.path - 路径,如 '/root/children/1/data'
|
|
|
|
+ // patch.value - 数据,如 { text: "思路" }
|
|
|
|
+ var path = patch.path.split("/");
|
|
|
|
+ path.shift();
|
|
|
|
+ var changed = path.shift();
|
|
|
|
+ var node;
|
|
|
|
+ if (changed == "root") {
|
|
|
|
+ var dataIndex = path.indexOf("data");
|
|
|
|
+ if (dataIndex > -1) {
|
|
|
|
+ changed = "data";
|
|
|
|
+ var dataPath = path.splice(dataIndex + 1);
|
|
|
|
+ patch.dataPath = dataPath;
|
|
|
|
+ } else {
|
|
|
|
+ changed = "node";
|
|
|
|
+ }
|
|
|
|
+ node = minder.getRoot();
|
|
|
|
+ var segment, index;
|
|
|
|
+ while (segment = path.shift()) {
|
|
|
|
+ if (segment == "children") continue;
|
|
|
|
+ if (typeof index != "undefined") node = node.getChild(index);
|
|
|
|
+ index = +segment;
|
|
|
|
+ }
|
|
|
|
+ patch.index = index;
|
|
|
|
+ patch.node = node;
|
|
|
|
+ }
|
|
|
|
+ var express = patch.express = [ changed, patch.op ].join(".");
|
|
|
|
+ switch (express) {
|
|
|
|
+ case "theme.replace":
|
|
|
|
+ minder.useTheme(patch.value);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "template.replace":
|
|
|
|
+ minder.useTemplate(patch.value);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "node.add":
|
|
|
|
+ insertNode(minder, patch.value, patch.node, patch.index).renderTree();
|
|
|
|
+ minder.layout();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "node.remove":
|
|
|
|
+ minder.removeNode(patch.node.getChild(patch.index));
|
|
|
|
+ minder.layout();
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "data.add":
|
|
|
|
+ case "data.replace":
|
|
|
|
+ case "data.remove":
|
|
|
|
+ var data = patch.node.data;
|
|
|
|
+ var field;
|
|
|
|
+ path = patch.dataPath.slice();
|
|
|
|
+ while (data && path.length > 1) {
|
|
|
|
+ field = path.shift();
|
|
|
|
+ if (field in data) {
|
|
|
|
+ data = data[field];
|
|
|
|
+ } else if (patch.op != "remove") {
|
|
|
|
+ data = data[field] = {};
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (data) {
|
|
|
|
+ field = path.shift();
|
|
|
|
+ data[field] = patch.value;
|
|
|
|
+ }
|
|
|
|
+ if (field == "expandState") {
|
|
|
|
+ node.renderTree();
|
|
|
|
+ } else {
|
|
|
|
+ node.render();
|
|
|
|
+ }
|
|
|
|
+ minder.layout();
|
|
|
|
+ }
|
|
|
|
+ minder.fire("patch", {
|
|
|
|
+ patch: patch
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ applyPatches: function(patches) {
|
|
|
|
+ for (var i = 0; i < patches.length; i++) {
|
|
|
|
+ applyPatch(this, patches[i]);
|
|
|
|
+ }
|
|
|
|
+ this.fire("contentchange");
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/promise.js
|
|
|
|
+_p[25] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ /*!
|
|
|
|
+ ** Thenable -- Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable
|
|
|
|
+ ** Copyright (c) 2013-2014 Ralf S. Engelschall <http://engelschall.com>
|
|
|
|
+ ** Licensed under The MIT License <http://opensource.org/licenses/MIT>
|
|
|
|
+ ** Source-Code distributed on <http://github.com/rse/thenable>
|
|
|
|
+ */
|
|
|
|
+ /* promise states [Promises/A+ 2.1] */
|
|
|
|
+ var STATE_PENDING = 0;
|
|
|
|
+ /* [Promises/A+ 2.1.1] */
|
|
|
|
+ var STATE_FULFILLED = 1;
|
|
|
|
+ /* [Promises/A+ 2.1.2] */
|
|
|
|
+ var STATE_REJECTED = 2;
|
|
|
|
+ /* [Promises/A+ 2.1.3] */
|
|
|
|
+ /* promise object constructor */
|
|
|
|
+ var Promise = function(executor) {
|
|
|
|
+ /* optionally support non-constructor/plain-function call */
|
|
|
|
+ if (!(this instanceof Promise)) return new Promise(executor);
|
|
|
|
+ /* initialize object */
|
|
|
|
+ this.id = "Thenable/1.0.7";
|
|
|
|
+ this.state = STATE_PENDING;
|
|
|
|
+ /* initial state */
|
|
|
|
+ this.fulfillValue = undefined;
|
|
|
|
+ /* initial value */
|
|
|
|
+ /* [Promises/A+ 1.3, 2.1.2.2] */
|
|
|
|
+ this.rejectReason = undefined;
|
|
|
|
+ /* initial reason */
|
|
|
|
+ /* [Promises/A+ 1.5, 2.1.3.2] */
|
|
|
|
+ this.onFulfilled = [];
|
|
|
|
+ /* initial handlers */
|
|
|
|
+ this.onRejected = [];
|
|
|
|
+ /* initial handlers */
|
|
|
|
+ /* support optional executor function */
|
|
|
|
+ if (typeof executor === "function") executor.call(this, this.fulfill.bind(this), this.reject.bind(this));
|
|
|
|
+ };
|
|
|
|
+ /* Promise API methods */
|
|
|
|
+ Promise.prototype = {
|
|
|
|
+ /* promise resolving methods */
|
|
|
|
+ fulfill: function(value) {
|
|
|
|
+ return deliver(this, STATE_FULFILLED, "fulfillValue", value);
|
|
|
|
+ },
|
|
|
|
+ reject: function(value) {
|
|
|
|
+ return deliver(this, STATE_REJECTED, "rejectReason", value);
|
|
|
|
+ },
|
|
|
|
+ /* 'The then Method' [Promises/A+ 1.1, 1.2, 2.2] */
|
|
|
|
+ then: function(onFulfilled, onRejected) {
|
|
|
|
+ var curr = this;
|
|
|
|
+ var next = new Promise();
|
|
|
|
+ /* [Promises/A+ 2.2.7] */
|
|
|
|
+ curr.onFulfilled.push(resolver(onFulfilled, next, "fulfill"));
|
|
|
|
+ /* [Promises/A+ 2.2.2/2.2.6] */
|
|
|
|
+ curr.onRejected.push(resolver(onRejected, next, "reject"));
|
|
|
|
+ /* [Promises/A+ 2.2.3/2.2.6] */
|
|
|
|
+ execute(curr);
|
|
|
|
+ return next;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ Promise.all = function(arr) {
|
|
|
|
+ return new Promise(function(resolve, reject) {
|
|
|
|
+ var len = arr.length, i = 0, res = 0, results = [];
|
|
|
|
+ if (len === 0) {
|
|
|
|
+ resolve(results);
|
|
|
|
+ }
|
|
|
|
+ while (i < len) {
|
|
|
|
+ arr[i].then(function(result) {
|
|
|
|
+ results.push(result);
|
|
|
|
+ if (++res === len) {
|
|
|
|
+ resolve(results);
|
|
|
|
+ }
|
|
|
|
+ }, function(val) {
|
|
|
|
+ reject(val);
|
|
|
|
+ });
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ /* deliver an action */
|
|
|
|
+ var deliver = function(curr, state, name, value) {
|
|
|
|
+ if (curr.state === STATE_PENDING) {
|
|
|
|
+ curr.state = state;
|
|
|
|
+ /* [Promises/A+ 2.1.2.1, 2.1.3.1] */
|
|
|
|
+ curr[name] = value;
|
|
|
|
+ /* [Promises/A+ 2.1.2.2, 2.1.3.2] */
|
|
|
|
+ execute(curr);
|
|
|
|
+ }
|
|
|
|
+ return curr;
|
|
|
|
+ };
|
|
|
|
+ /* execute all handlers */
|
|
|
|
+ var execute = function(curr) {
|
|
|
|
+ if (curr.state === STATE_FULFILLED) execute_handlers(curr, "onFulfilled", curr.fulfillValue); else if (curr.state === STATE_REJECTED) execute_handlers(curr, "onRejected", curr.rejectReason);
|
|
|
|
+ };
|
|
|
|
+ /* execute particular set of handlers */
|
|
|
|
+ var execute_handlers = function(curr, name, value) {
|
|
|
|
+ /* global process: true */
|
|
|
|
+ /* global setImmediate: true */
|
|
|
|
+ /* global setTimeout: true */
|
|
|
|
+ /* short-circuit processing */
|
|
|
|
+ if (curr[name].length === 0) return;
|
|
|
|
+ /* iterate over all handlers, exactly once */
|
|
|
|
+ var handlers = curr[name];
|
|
|
|
+ curr[name] = [];
|
|
|
|
+ /* [Promises/A+ 2.2.2.3, 2.2.3.3] */
|
|
|
|
+ var func = function() {
|
|
|
|
+ for (var i = 0; i < handlers.length; i++) handlers[i](value);
|
|
|
|
+ };
|
|
|
|
+ /* execute procedure asynchronously */
|
|
|
|
+ /* [Promises/A+ 2.2.4, 3.1] */
|
|
|
|
+ if (typeof process === "object" && typeof process.nextTick === "function") process.nextTick(func); else if (typeof setImmediate === "function") setImmediate(func); else setTimeout(func, 0);
|
|
|
|
+ };
|
|
|
|
+ /* generate a resolver function */
|
|
|
|
+ var resolver = function(cb, next, method) {
|
|
|
|
+ return function(value) {
|
|
|
|
+ if (typeof cb !== "function") /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */
|
|
|
|
+ next[method].call(next, value); else {
|
|
|
|
+ var result;
|
|
|
|
+ try {
|
|
|
|
+ if (value instanceof Promise) {
|
|
|
|
+ result = value.then(cb);
|
|
|
|
+ } else result = cb(value);
|
|
|
|
+ } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */
|
|
|
|
+ catch (e) {
|
|
|
|
+ next.reject(e);
|
|
|
|
+ /* [Promises/A+ 2.2.7.2] */
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ resolve(next, result);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ };
|
|
|
|
+ /* 'Promise Resolution Procedure' */
|
|
|
|
+ /* [Promises/A+ 2.3] */
|
|
|
|
+ var resolve = function(promise, x) {
|
|
|
|
+ /* sanity check arguments */
|
|
|
|
+ /* [Promises/A+ 2.3.1] */
|
|
|
|
+ if (promise === x) {
|
|
|
|
+ promise.reject(new TypeError("cannot resolve promise with itself"));
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ /* surgically check for a 'then' method
|
|
|
|
+ (mainly to just call the 'getter' of 'then' only once) */
|
|
|
|
+ var then;
|
|
|
|
+ if (typeof x === "object" && x !== null || typeof x === "function") {
|
|
|
|
+ try {
|
|
|
|
+ then = x.then;
|
|
|
|
+ } /* [Promises/A+ 2.3.3.1, 3.5] */
|
|
|
|
+ catch (e) {
|
|
|
|
+ promise.reject(e);
|
|
|
|
+ /* [Promises/A+ 2.3.3.2] */
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /* handle own Thenables [Promises/A+ 2.3.2]
|
|
|
|
+ and similar 'thenables' [Promises/A+ 2.3.3] */
|
|
|
|
+ if (typeof then === "function") {
|
|
|
|
+ var resolved = false;
|
|
|
|
+ try {
|
|
|
|
+ /* call retrieved 'then' method */
|
|
|
|
+ /* [Promises/A+ 2.3.3.3] */
|
|
|
|
+ then.call(x, /* resolvePromise */
|
|
|
|
+ /* [Promises/A+ 2.3.3.3.1] */
|
|
|
|
+ function(y) {
|
|
|
|
+ if (resolved) return;
|
|
|
|
+ resolved = true;
|
|
|
|
+ /* [Promises/A+ 2.3.3.3.3] */
|
|
|
|
+ if (y === x) /* [Promises/A+ 3.6] */
|
|
|
|
+ promise.reject(new TypeError("circular thenable chain")); else resolve(promise, y);
|
|
|
|
+ }, /* rejectPromise */
|
|
|
|
+ /* [Promises/A+ 2.3.3.3.2] */
|
|
|
|
+ function(r) {
|
|
|
|
+ if (resolved) return;
|
|
|
|
+ resolved = true;
|
|
|
|
+ /* [Promises/A+ 2.3.3.3.3] */
|
|
|
|
+ promise.reject(r);
|
|
|
|
+ });
|
|
|
|
+ } catch (e) {
|
|
|
|
+ if (!resolved) /* [Promises/A+ 2.3.3.3.3] */
|
|
|
|
+ promise.reject(e);
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ /* handle other values */
|
|
|
|
+ promise.fulfill(x);
|
|
|
|
+ };
|
|
|
|
+ Promise.resolve = function(value) {
|
|
|
|
+ return new Promise(function(resolve) {
|
|
|
|
+ resolve(value);
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ Promise.reject = function(reason) {
|
|
|
|
+ return new Promise(function(resolve, reject) {
|
|
|
|
+ reject(reason);
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ /* export API */
|
|
|
|
+ module.exports = Promise;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/readonly.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 只读模式支持
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[26] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderEvent = _p.r(13);
|
|
|
|
+ Minder.registerInitHook(function(options) {
|
|
|
|
+ if (options.readOnly) {
|
|
|
|
+ this.setDisabled();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ disable: function() {
|
|
|
|
+ var me = this;
|
|
|
|
+ //禁用命令
|
|
|
|
+ me.bkqueryCommandState = me.queryCommandState;
|
|
|
|
+ me.bkqueryCommandValue = me.queryCommandValue;
|
|
|
|
+ me.queryCommandState = function(type) {
|
|
|
|
+ var cmd = this._getCommand(type);
|
|
|
|
+ if (cmd && cmd.enableReadOnly) {
|
|
|
|
+ return me.bkqueryCommandState.apply(me, arguments);
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+ };
|
|
|
|
+ me.queryCommandValue = function(type) {
|
|
|
|
+ var cmd = this._getCommand(type);
|
|
|
|
+ if (cmd && cmd.enableReadOnly) {
|
|
|
|
+ return me.bkqueryCommandValue.apply(me, arguments);
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ };
|
|
|
|
+ this.setStatus("readonly");
|
|
|
|
+ me._interactChange();
|
|
|
|
+ },
|
|
|
|
+ enable: function() {
|
|
|
|
+ var me = this;
|
|
|
|
+ if (me.bkqueryCommandState) {
|
|
|
|
+ me.queryCommandState = me.bkqueryCommandState;
|
|
|
|
+ delete me.bkqueryCommandState;
|
|
|
|
+ }
|
|
|
|
+ if (me.bkqueryCommandValue) {
|
|
|
|
+ me.queryCommandValue = me.bkqueryCommandValue;
|
|
|
|
+ delete me.bkqueryCommandValue;
|
|
|
|
+ }
|
|
|
|
+ this.setStatus("normal");
|
|
|
|
+ me._interactChange();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/render.js
|
|
|
|
+_p[27] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Renderer = kity.createClass("Renderer", {
|
|
|
|
+ constructor: function(node) {
|
|
|
|
+ this.node = node;
|
|
|
|
+ },
|
|
|
|
+ create: function(node) {
|
|
|
|
+ throw new Error("Not implement: Renderer.create()");
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ watchChange: function(data) {
|
|
|
|
+ var changed;
|
|
|
|
+ if (this.watchingData === undefined) {
|
|
|
|
+ changed = true;
|
|
|
|
+ } else if (this.watchingData != data) {
|
|
|
|
+ changed = true;
|
|
|
|
+ } else {
|
|
|
|
+ changed = false;
|
|
|
|
+ }
|
|
|
|
+ this.watchingData = data;
|
|
|
|
+ },
|
|
|
|
+ shouldDraw: function(node) {
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ update: function(shape, node, box) {
|
|
|
|
+ if (this.shouldDraw()) this.draw(shape, node);
|
|
|
|
+ return this.place(shape, node, box);
|
|
|
|
+ },
|
|
|
|
+ draw: function(shape, node) {
|
|
|
|
+ throw new Error("Not implement: Renderer.draw()");
|
|
|
|
+ },
|
|
|
|
+ place: function(shape, node, box) {
|
|
|
|
+ throw new Error("Not implement: Renderer.place()");
|
|
|
|
+ },
|
|
|
|
+ getRenderShape: function() {
|
|
|
|
+ return this._renderShape || null;
|
|
|
|
+ },
|
|
|
|
+ setRenderShape: function(shape) {
|
|
|
|
+ this._renderShape = shape;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ function createMinderExtension() {
|
|
|
|
+ function createRendererForNode(node, registered) {
|
|
|
|
+ var renderers = [];
|
|
|
|
+ [ "center", "left", "right", "top", "bottom", "outline", "outside" ].forEach(function(section) {
|
|
|
|
+ var before = "before" + section;
|
|
|
|
+ var after = "after" + section;
|
|
|
|
+ if (registered[before]) {
|
|
|
|
+ renderers = renderers.concat(registered[before]);
|
|
|
|
+ }
|
|
|
|
+ if (registered[section]) {
|
|
|
|
+ renderers = renderers.concat(registered[section]);
|
|
|
|
+ }
|
|
|
|
+ if (registered[after]) {
|
|
|
|
+ renderers = renderers.concat(registered[after]);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ node._renderers = renderers.map(function(Renderer) {
|
|
|
|
+ return new Renderer(node);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ renderNodeBatch: function(nodes) {
|
|
|
|
+ var rendererClasses = this._rendererClasses;
|
|
|
|
+ var lastBoxes = [];
|
|
|
|
+ var rendererCount = 0;
|
|
|
|
+ var i, j, renderer, node;
|
|
|
|
+ if (!nodes.length) return;
|
|
|
|
+ for (j = 0; j < nodes.length; j++) {
|
|
|
|
+ node = nodes[j];
|
|
|
|
+ if (!node._renderers) {
|
|
|
|
+ createRendererForNode(node, rendererClasses);
|
|
|
|
+ }
|
|
|
|
+ node._contentBox = new kity.Box();
|
|
|
|
+ this.fire("beforerender", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ // 所有节点渲染器数量是一致的
|
|
|
|
+ rendererCount = nodes[0]._renderers.length;
|
|
|
|
+ for (i = 0; i < rendererCount; i++) {
|
|
|
|
+ // 获取延迟盒子数据
|
|
|
|
+ for (j = 0; j < nodes.length; j++) {
|
|
|
|
+ if (typeof lastBoxes[j] == "function") {
|
|
|
|
+ lastBoxes[j] = lastBoxes[j]();
|
|
|
|
+ }
|
|
|
|
+ if (!(lastBoxes[j] instanceof kity.Box)) {
|
|
|
|
+ lastBoxes[j] = new kity.Box(lastBoxes[j]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (j = 0; j < nodes.length; j++) {
|
|
|
|
+ node = nodes[j];
|
|
|
|
+ renderer = node._renderers[i];
|
|
|
|
+ // 合并盒子
|
|
|
|
+ if (lastBoxes[j]) {
|
|
|
|
+ node._contentBox = node._contentBox.merge(lastBoxes[j]);
|
|
|
|
+ renderer.contentBox = lastBoxes[j];
|
|
|
|
+ }
|
|
|
|
+ // 判断当前上下文是否应该渲染
|
|
|
|
+ if (renderer.shouldRender(node)) {
|
|
|
|
+ // 应该渲染,但是渲染图形没创建过,需要创建
|
|
|
|
+ if (!renderer.getRenderShape()) {
|
|
|
|
+ renderer.setRenderShape(renderer.create(node));
|
|
|
|
+ if (renderer.bringToBack) {
|
|
|
|
+ node.getRenderContainer().prependShape(renderer.getRenderShape());
|
|
|
|
+ } else {
|
|
|
|
+ node.getRenderContainer().appendShape(renderer.getRenderShape());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 强制让渲染图形显示
|
|
|
|
+ renderer.getRenderShape().setVisible(true);
|
|
|
|
+ // 更新渲染图形
|
|
|
|
+ lastBoxes[j] = renderer.update(renderer.getRenderShape(), node, node._contentBox);
|
|
|
|
+ } else if (renderer.getRenderShape()) {
|
|
|
|
+ renderer.getRenderShape().setVisible(false);
|
|
|
|
+ lastBoxes[j] = null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (j = 0; j < nodes.length; j++) {
|
|
|
|
+ this.fire("noderender", {
|
|
|
|
+ node: nodes[j]
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ renderNode: function(node) {
|
|
|
|
+ var rendererClasses = this._rendererClasses;
|
|
|
|
+ var i, latestBox, renderer;
|
|
|
|
+ if (!node._renderers) {
|
|
|
|
+ createRendererForNode(node, rendererClasses);
|
|
|
|
+ }
|
|
|
|
+ this.fire("beforerender", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ node._contentBox = new kity.Box();
|
|
|
|
+ node._renderers.forEach(function(renderer) {
|
|
|
|
+ // 判断当前上下文是否应该渲染
|
|
|
|
+ if (renderer.shouldRender(node)) {
|
|
|
|
+ // 应该渲染,但是渲染图形没创建过,需要创建
|
|
|
|
+ if (!renderer.getRenderShape()) {
|
|
|
|
+ renderer.setRenderShape(renderer.create(node));
|
|
|
|
+ if (renderer.bringToBack) {
|
|
|
|
+ node.getRenderContainer().prependShape(renderer.getRenderShape());
|
|
|
|
+ } else {
|
|
|
|
+ node.getRenderContainer().appendShape(renderer.getRenderShape());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 强制让渲染图形显示
|
|
|
|
+ renderer.getRenderShape().setVisible(true);
|
|
|
|
+ // 更新渲染图形
|
|
|
|
+ latestBox = renderer.update(renderer.getRenderShape(), node, node._contentBox);
|
|
|
|
+ if (typeof latestBox == "function") latestBox = latestBox();
|
|
|
|
+ // 合并渲染区域
|
|
|
|
+ if (latestBox) {
|
|
|
|
+ node._contentBox = node._contentBox.merge(latestBox);
|
|
|
|
+ renderer.contentBox = latestBox;
|
|
|
|
+ }
|
|
|
|
+ } else if (renderer.getRenderShape()) {
|
|
|
|
+ renderer.getRenderShape().setVisible(false);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ this.fire("noderender", {
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ kity.extendClass(Minder, createMinderExtension());
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ render: function() {
|
|
|
|
+ if (!this.attached) return;
|
|
|
|
+ this.getMinder().renderNode(this);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ renderTree: function() {
|
|
|
|
+ if (!this.attached) return;
|
|
|
|
+ var list = [];
|
|
|
|
+ this.traverse(function(node) {
|
|
|
|
+ list.push(node);
|
|
|
|
+ });
|
|
|
|
+ this.getMinder().renderNodeBatch(list);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ getRenderer: function(type) {
|
|
|
|
+ var rs = this._renderers;
|
|
|
|
+ if (!rs) return null;
|
|
|
|
+ for (var i = 0; i < rs.length; i++) {
|
|
|
|
+ if (rs[i].getType() == type) return rs[i];
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ },
|
|
|
|
+ getContentBox: function() {
|
|
|
|
+ //if (!this._contentBox) this.render();
|
|
|
|
+ return this.parent && this.parent.isCollapsed() ? new kity.Box() : this._contentBox || new kity.Box();
|
|
|
|
+ },
|
|
|
|
+ getRenderBox: function(rendererType, refer) {
|
|
|
|
+ var renderer = rendererType && this.getRenderer(rendererType);
|
|
|
|
+ var contentBox = renderer ? renderer.contentBox : this.getContentBox();
|
|
|
|
+ var ctm = kity.Matrix.getCTM(this.getRenderContainer(), refer || "paper");
|
|
|
|
+ return ctm.transformBox(contentBox);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = Renderer;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/select.js
|
|
|
|
+_p[28] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this._initSelection();
|
|
|
|
+ });
|
|
|
|
+ // 选区管理
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initSelection: function() {
|
|
|
|
+ this._selectedNodes = [];
|
|
|
|
+ },
|
|
|
|
+ renderChangedSelection: function(last) {
|
|
|
|
+ var current = this.getSelectedNodes();
|
|
|
|
+ var changed = [];
|
|
|
|
+ current.forEach(function(node) {
|
|
|
|
+ if (last.indexOf(node) == -1) {
|
|
|
|
+ changed.push(node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ last.forEach(function(node) {
|
|
|
|
+ if (current.indexOf(node) == -1) {
|
|
|
|
+ changed.push(node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ if (changed.length) {
|
|
|
|
+ this._interactChange();
|
|
|
|
+ this.fire("selectionchange");
|
|
|
|
+ }
|
|
|
|
+ while (changed.length) {
|
|
|
|
+ changed.shift().render();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ getSelectedNodes: function() {
|
|
|
|
+ //不能克隆返回,会对当前选区操作,从而影响querycommand
|
|
|
|
+ return this._selectedNodes;
|
|
|
|
+ },
|
|
|
|
+ getSelectedNode: function() {
|
|
|
|
+ return this.getSelectedNodes()[0] || null;
|
|
|
|
+ },
|
|
|
|
+ removeAllSelectedNodes: function() {
|
|
|
|
+ var me = this;
|
|
|
|
+ var last = this._selectedNodes.splice(0);
|
|
|
|
+ this._selectedNodes = [];
|
|
|
|
+ this.renderChangedSelection(last);
|
|
|
|
+ return this.fire("selectionclear");
|
|
|
|
+ },
|
|
|
|
+ removeSelectedNodes: function(nodes) {
|
|
|
|
+ var me = this;
|
|
|
|
+ var last = this._selectedNodes.slice(0);
|
|
|
|
+ nodes = utils.isArray(nodes) ? nodes : [ nodes ];
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ var index;
|
|
|
|
+ if ((index = me._selectedNodes.indexOf(node)) === -1) return;
|
|
|
|
+ me._selectedNodes.splice(index, 1);
|
|
|
|
+ });
|
|
|
|
+ this.renderChangedSelection(last);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ select: function(nodes, isSingleSelect) {
|
|
|
|
+ var lastSelect = this.getSelectedNodes().slice(0);
|
|
|
|
+ if (isSingleSelect) {
|
|
|
|
+ this._selectedNodes = [];
|
|
|
|
+ }
|
|
|
|
+ var me = this;
|
|
|
|
+ nodes = utils.isArray(nodes) ? nodes : [ nodes ];
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ if (me._selectedNodes.indexOf(node) !== -1) return;
|
|
|
|
+ me._selectedNodes.unshift(node);
|
|
|
|
+ });
|
|
|
|
+ this.renderChangedSelection(lastSelect);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ selectById: function(ids, isSingleSelect) {
|
|
|
|
+ ids = utils.isArray(ids) ? ids : [ ids ];
|
|
|
|
+ var nodes = this.getNodesById(ids);
|
|
|
|
+ return this.select(nodes, isSingleSelect);
|
|
|
|
+ },
|
|
|
|
+ //当前选区中的节点在给定的节点范围内的保留选中状态,
|
|
|
|
+ //没在给定范围的取消选中,给定范围中的但没在当前选中范围的也做选中效果
|
|
|
|
+ toggleSelect: function(node) {
|
|
|
|
+ if (utils.isArray(node)) {
|
|
|
|
+ node.forEach(this.toggleSelect.bind(this));
|
|
|
|
+ } else {
|
|
|
|
+ if (node.isSelected()) this.removeSelectedNodes(node); else this.select(node);
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ isSingleSelect: function() {
|
|
|
|
+ return this._selectedNodes.length == 1;
|
|
|
|
+ },
|
|
|
|
+ getSelectedAncestors: function(includeRoot) {
|
|
|
|
+ var nodes = this.getSelectedNodes().slice(0), ancestors = [], judge;
|
|
|
|
+ // 根节点不参与计算
|
|
|
|
+ var rootIndex = nodes.indexOf(this.getRoot());
|
|
|
|
+ if (~rootIndex && !includeRoot) {
|
|
|
|
+ nodes.splice(rootIndex, 1);
|
|
|
|
+ }
|
|
|
|
+ // 判断 nodes 列表中是否存在 judge 的祖先
|
|
|
|
+ function hasAncestor(nodes, judge) {
|
|
|
|
+ for (var i = nodes.length - 1; i >= 0; --i) {
|
|
|
|
+ if (nodes[i].isAncestorOf(judge)) return true;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 按照拓扑排序
|
|
|
|
+ nodes.sort(function(node1, node2) {
|
|
|
|
+ return node1.getLevel() - node2.getLevel();
|
|
|
|
+ });
|
|
|
|
+ // 因为是拓扑有序的,所以只需往上查找
|
|
|
|
+ while (judge = nodes.pop()) {
|
|
|
|
+ if (!hasAncestor(nodes, judge)) {
|
|
|
|
+ ancestors.push(judge);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ancestors;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ isSelected: function() {
|
|
|
|
+ var minder = this.getMinder();
|
|
|
|
+ return minder && minder.getSelectedNodes().indexOf(this) != -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/shortcut.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 添加快捷键支持
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[29] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var keymap = _p.r(15);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderEvent = _p.r(13);
|
|
|
|
+ /**
|
|
|
|
+ * 计算包含 meta 键的 keycode
|
|
|
|
+ *
|
|
|
|
+ * @param {String|KeyEvent} unknown
|
|
|
|
+ */
|
|
|
|
+ function getMetaKeyCode(unknown) {
|
|
|
|
+ var CTRL_MASK = 4096;
|
|
|
|
+ var ALT_MASK = 8192;
|
|
|
|
+ var SHIFT_MASK = 16384;
|
|
|
|
+ var metaKeyCode = 0;
|
|
|
|
+ if (typeof unknown == "string") {
|
|
|
|
+ // unknown as string
|
|
|
|
+ unknown.toLowerCase().split(/\+\s*/).forEach(function(name) {
|
|
|
|
+ switch (name) {
|
|
|
|
+ case "ctrl":
|
|
|
|
+ case "cmd":
|
|
|
|
+ metaKeyCode |= CTRL_MASK;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "alt":
|
|
|
|
+ metaKeyCode |= ALT_MASK;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "shift":
|
|
|
|
+ metaKeyCode |= SHIFT_MASK;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ metaKeyCode |= keymap[name];
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ // unknown as key event
|
|
|
|
+ if (unknown.ctrlKey || unknown.metaKey) {
|
|
|
|
+ metaKeyCode |= CTRL_MASK;
|
|
|
|
+ }
|
|
|
|
+ if (unknown.altKey) {
|
|
|
|
+ metaKeyCode |= ALT_MASK;
|
|
|
|
+ }
|
|
|
|
+ if (unknown.shiftKey) {
|
|
|
|
+ metaKeyCode |= SHIFT_MASK;
|
|
|
|
+ }
|
|
|
|
+ metaKeyCode |= unknown.keyCode;
|
|
|
|
+ }
|
|
|
|
+ return metaKeyCode;
|
|
|
|
+ }
|
|
|
|
+ kity.extendClass(MinderEvent, {
|
|
|
|
+ isShortcutKey: function(keyCombine) {
|
|
|
|
+ var keyEvent = this.originEvent;
|
|
|
|
+ if (!keyEvent) return false;
|
|
|
|
+ return getMetaKeyCode(keyCombine) == getMetaKeyCode(keyEvent);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this._initShortcutKey();
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initShortcutKey: function() {
|
|
|
|
+ this._bindShortcutKeys();
|
|
|
|
+ },
|
|
|
|
+ _bindShortcutKeys: function() {
|
|
|
|
+ var map = this._shortcutKeys = {};
|
|
|
|
+ var has = "hasOwnProperty";
|
|
|
|
+ this.on("keydown", function(e) {
|
|
|
|
+ for (var keys in map) {
|
|
|
|
+ if (!map[has](keys)) continue;
|
|
|
|
+ if (e.isShortcutKey(keys)) {
|
|
|
|
+ var fn = map[keys];
|
|
|
|
+ if (fn.__statusCondition && fn.__statusCondition != this.getStatus()) return;
|
|
|
|
+ fn();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ addShortcut: function(keys, fn) {
|
|
|
|
+ var binds = this._shortcutKeys;
|
|
|
|
+ keys.split(/\|\s*/).forEach(function(combine) {
|
|
|
|
+ var parts = combine.split("::");
|
|
|
|
+ var status;
|
|
|
|
+ if (parts.length > 1) {
|
|
|
|
+ combine = parts[1];
|
|
|
|
+ status = parts[0];
|
|
|
|
+ fn.__statusCondition = status;
|
|
|
|
+ }
|
|
|
|
+ binds[combine] = fn;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ addCommandShortcutKeys: function(cmd, keys) {
|
|
|
|
+ var binds = this._commandShortcutKeys || (this._commandShortcutKeys = {});
|
|
|
|
+ var obj = {}, km = this;
|
|
|
|
+ if (keys) {
|
|
|
|
+ obj[cmd] = keys;
|
|
|
|
+ } else {
|
|
|
|
+ obj = cmd;
|
|
|
|
+ }
|
|
|
|
+ var minder = this;
|
|
|
|
+ utils.each(obj, function(keys, command) {
|
|
|
|
+ binds[command] = keys;
|
|
|
|
+ minder.addShortcut(keys, function execCommandByShortcut() {
|
|
|
|
+ /**
|
|
|
|
+ * 之前判断有问题,由 === 0 改为 !== -1
|
|
|
|
+ * @editor Naixor
|
|
|
|
+ * @Date 2015-12-2
|
|
|
|
+ */
|
|
|
|
+ if (minder.queryCommandState(command) !== -1) {
|
|
|
|
+ minder.execCommand(command);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ getCommandShortcutKey: function(cmd) {
|
|
|
|
+ var binds = this._commandShortcutKeys;
|
|
|
|
+ return binds && binds[cmd] || null;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * @Desc: 添加一个判断是否支持原生Clipboard的变量,用于对ctrl + v和ctrl + c的处理
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.20
|
|
|
|
+ */
|
|
|
|
+ supportClipboardEvent: function(window) {
|
|
|
|
+ return !!window.ClipboardEvent;
|
|
|
|
+ }(window)
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/status.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 状态切换控制
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[30] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var sf = ~window.location.href.indexOf("status");
|
|
|
|
+ var tf = ~window.location.href.indexOf("trace");
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this._initStatus();
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ _initStatus: function() {
|
|
|
|
+ this._status = "normal";
|
|
|
|
+ this._rollbackStatus = "normal";
|
|
|
|
+ },
|
|
|
|
+ setStatus: function(status, force) {
|
|
|
|
+ // 在 readonly 模式下,只有 force 为 true 才能切换回来
|
|
|
|
+ if (this._status == "readonly" && !force) return this;
|
|
|
|
+ if (status != this._status) {
|
|
|
|
+ this._rollbackStatus = this._status;
|
|
|
|
+ this._status = status;
|
|
|
|
+ this.fire("statuschange", {
|
|
|
|
+ lastStatus: this._rollbackStatus,
|
|
|
|
+ currentStatus: this._status
|
|
|
|
+ });
|
|
|
|
+ if (sf) {
|
|
|
|
+ /* global console: true */
|
|
|
|
+ console.log(window.event.type, this._rollbackStatus, "->", this._status);
|
|
|
|
+ if (tf) {
|
|
|
|
+ console.trace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ rollbackStatus: function() {
|
|
|
|
+ this.setStatus(this._rollbackStatus);
|
|
|
|
+ },
|
|
|
|
+ getRollbackStatus: function() {
|
|
|
|
+ return this._rollbackStatus;
|
|
|
|
+ },
|
|
|
|
+ getStatus: function() {
|
|
|
|
+ return this._status;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/template.js
|
|
|
|
+_p[31] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var _templates = {};
|
|
|
|
+ function register(name, supports) {
|
|
|
|
+ _templates[name] = supports;
|
|
|
|
+ }
|
|
|
|
+ exports.register = register;
|
|
|
|
+ utils.extend(Minder, {
|
|
|
|
+ getTemplateList: function() {
|
|
|
|
+ return _templates;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, function() {
|
|
|
|
+ var originGetTheme = Minder.prototype.getTheme;
|
|
|
|
+ return {
|
|
|
|
+ useTemplate: function(name, duration) {
|
|
|
|
+ this.setTemplate(name);
|
|
|
|
+ this.refresh(duration || 800);
|
|
|
|
+ },
|
|
|
|
+ getTemplate: function() {
|
|
|
|
+ return this._template || "default";
|
|
|
|
+ },
|
|
|
|
+ setTemplate: function(name) {
|
|
|
|
+ this._template = name || null;
|
|
|
|
+ },
|
|
|
|
+ getTemplateSupport: function(method) {
|
|
|
|
+ var supports = _templates[this.getTemplate()];
|
|
|
|
+ return supports && supports[method];
|
|
|
|
+ },
|
|
|
|
+ getTheme: function(node) {
|
|
|
|
+ var support = this.getTemplateSupport("getTheme") || originGetTheme;
|
|
|
|
+ return support.call(this, node);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }());
|
|
|
|
+ kity.extendClass(MinderNode, function() {
|
|
|
|
+ var originGetLayout = MinderNode.prototype.getLayout;
|
|
|
|
+ var originGetConnect = MinderNode.prototype.getConnect;
|
|
|
|
+ return {
|
|
|
|
+ getLayout: function() {
|
|
|
|
+ var support = this.getMinder().getTemplateSupport("getLayout") || originGetLayout;
|
|
|
|
+ return support.call(this, this);
|
|
|
|
+ },
|
|
|
|
+ getConnect: function() {
|
|
|
|
+ var support = this.getMinder().getTemplateSupport("getConnect") || originGetConnect;
|
|
|
|
+ return support.call(this, this);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }());
|
|
|
|
+ Module.register("TemplateModule", {
|
|
|
|
+ /**
|
|
|
|
+ * @command Template
|
|
|
|
+ * @description 设置当前脑图的模板
|
|
|
|
+ * @param {string} name 模板名称
|
|
|
|
+ * 允许使用的模板可以使用 `kityminder.Minder.getTemplateList()` 查询
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ * @return 返回当前的模板名称
|
|
|
|
+ */
|
|
|
|
+ commands: {
|
|
|
|
+ template: kity.createClass("TemplateCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, name) {
|
|
|
|
+ minder.useTemplate(name);
|
|
|
|
+ minder.execCommand("camera");
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ return minder.getTemplate() || "default";
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/theme.js
|
|
|
|
+_p[32] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var cssLikeValueMatcher = {
|
|
|
|
+ left: function(value) {
|
|
|
|
+ return 3 in value && value[3] || 1 in value && value[1] || value[0];
|
|
|
|
+ },
|
|
|
|
+ right: function(value) {
|
|
|
|
+ return 1 in value && value[1] || value[0];
|
|
|
|
+ },
|
|
|
|
+ top: function(value) {
|
|
|
|
+ return value[0];
|
|
|
|
+ },
|
|
|
|
+ bottom: function(value) {
|
|
|
|
+ return 2 in value && value[2] || value[0];
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ var _themes = {};
|
|
|
|
+ /**
|
|
|
|
+ * 注册一个主题
|
|
|
|
+ *
|
|
|
|
+ * @param {String} name 主题的名称
|
|
|
|
+ * @param {Plain} theme 主题的样式描述
|
|
|
|
+ *
|
|
|
|
+ * @example
|
|
|
|
+ * Minder.registerTheme('default', {
|
|
|
|
+ * 'root-color': 'red',
|
|
|
|
+ * 'root-stroke': 'none',
|
|
|
|
+ * 'root-padding': [10, 20]
|
|
|
|
+ * });
|
|
|
|
+ */
|
|
|
|
+ function register(name, theme) {
|
|
|
|
+ _themes[name] = theme;
|
|
|
|
+ }
|
|
|
|
+ exports.register = register;
|
|
|
|
+ utils.extend(Minder, {
|
|
|
|
+ getThemeList: function() {
|
|
|
|
+ return _themes;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ /**
|
|
|
|
+ * 切换脑图实例上的主题
|
|
|
|
+ * @param {String} name 要使用的主题的名称
|
|
|
|
+ */
|
|
|
|
+ useTheme: function(name) {
|
|
|
|
+ this.setTheme(name);
|
|
|
|
+ this.refresh(800);
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ setTheme: function(name) {
|
|
|
|
+ if (name && !_themes[name]) throw new Error("Theme " + name + " not exists!");
|
|
|
|
+ var lastTheme = this._theme;
|
|
|
|
+ this._theme = name || null;
|
|
|
|
+ var container = this.getRenderTarget();
|
|
|
|
+ if (container) {
|
|
|
|
+ container.classList.remove("km-theme-" + lastTheme);
|
|
|
|
+ if (name) {
|
|
|
|
+ container.classList.add("km-theme-" + name);
|
|
|
|
+ }
|
|
|
|
+ container.style.background = this.getStyle("background");
|
|
|
|
+ }
|
|
|
|
+ this.fire("themechange", {
|
|
|
|
+ theme: name
|
|
|
|
+ });
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取脑图实例上的当前主题
|
|
|
|
+ * @return {[type]} [description]
|
|
|
|
+ */
|
|
|
|
+ getTheme: function(node) {
|
|
|
|
+ return this._theme || this.getOption("defaultTheme") || "fresh-blue";
|
|
|
|
+ },
|
|
|
|
+ getThemeItems: function(node) {
|
|
|
|
+ var theme = this.getTheme(node);
|
|
|
|
+ return _themes[this.getTheme(node)];
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得脑图实例上的样式
|
|
|
|
+ * @param {String} item 样式名称
|
|
|
|
+ */
|
|
|
|
+ getStyle: function(item, node) {
|
|
|
|
+ var items = this.getThemeItems(node);
|
|
|
|
+ var segment, dir, selector, value, matcher;
|
|
|
|
+ if (item in items) return items[item];
|
|
|
|
+ // 尝试匹配 CSS 数组形式的值
|
|
|
|
+ // 比如 item 为 'pading-left'
|
|
|
|
+ // theme 里有 {'padding': [10, 20]} 的定义,则可以返回 20
|
|
|
|
+ segment = item.split("-");
|
|
|
|
+ if (segment.length < 2) return null;
|
|
|
|
+ dir = segment.pop();
|
|
|
|
+ item = segment.join("-");
|
|
|
|
+ if (item in items) {
|
|
|
|
+ value = items[item];
|
|
|
|
+ if (utils.isArray(value) && (matcher = cssLikeValueMatcher[dir])) {
|
|
|
|
+ return matcher(value);
|
|
|
|
+ }
|
|
|
|
+ if (!isNaN(value)) return value;
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取指定节点的样式
|
|
|
|
+ * @param {String} name 样式名称,可以不加节点类型的前缀
|
|
|
|
+ */
|
|
|
|
+ getNodeStyle: function(node, name) {
|
|
|
|
+ var value = this.getStyle(node.getType() + "-" + name, node);
|
|
|
|
+ return value !== null ? value : this.getStyle(name, node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ getStyle: function(name) {
|
|
|
|
+ return this.getMinder().getNodeStyle(this, name);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("Theme", {
|
|
|
|
+ defaultOptions: {
|
|
|
|
+ defaultTheme: "fresh-blue"
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ /**
|
|
|
|
+ * @command Theme
|
|
|
|
+ * @description 设置当前脑图的主题
|
|
|
|
+ * @param {string} name 主题名称
|
|
|
|
+ * 允许使用的主题可以使用 `kityminder.Minder.getThemeList()` 查询
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ * @return 返回当前的主题名称
|
|
|
|
+ */
|
|
|
|
+ theme: kity.createClass("ThemeCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, name) {
|
|
|
|
+ return km.useTheme(name);
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ return km.getTheme() || "default";
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Minder.registerInitHook(function() {
|
|
|
|
+ this.setTheme();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/core/utils.js
|
|
|
|
+_p[33] = {
|
|
|
|
+ value: function(require, exports) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var uuidMap = {};
|
|
|
|
+ exports.extend = kity.Utils.extend.bind(kity.Utils);
|
|
|
|
+ exports.each = kity.Utils.each.bind(kity.Utils);
|
|
|
|
+ exports.uuid = function(group) {
|
|
|
|
+ uuidMap[group] = uuidMap[group] ? uuidMap[group] + 1 : 1;
|
|
|
|
+ return group + uuidMap[group];
|
|
|
|
+ };
|
|
|
|
+ exports.guid = function() {
|
|
|
|
+ return (+new Date() * 1e6 + Math.floor(Math.random() * 1e6)).toString(36);
|
|
|
|
+ };
|
|
|
|
+ exports.trim = function(str) {
|
|
|
|
+ return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, "");
|
|
|
|
+ };
|
|
|
|
+ exports.keys = function(plain) {
|
|
|
|
+ var keys = [];
|
|
|
|
+ for (var key in plain) {
|
|
|
|
+ if (plain.hasOwnProperty(key)) {
|
|
|
|
+ keys.push(key);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return keys;
|
|
|
|
+ };
|
|
|
|
+ exports.clone = function(source) {
|
|
|
|
+ return JSON.parse(JSON.stringify(source));
|
|
|
|
+ };
|
|
|
|
+ exports.comparePlainObject = function(a, b) {
|
|
|
|
+ return JSON.stringify(a) == JSON.stringify(b);
|
|
|
|
+ };
|
|
|
|
+ exports.encodeHtml = function(str, reg) {
|
|
|
|
+ return str ? str.replace(reg || /[&<">'](?:(amp|lt|quot|gt|#39|nbsp);)?/g, function(a, b) {
|
|
|
|
+ if (b) {
|
|
|
|
+ return a;
|
|
|
|
+ } else {
|
|
|
|
+ return {
|
|
|
|
+ "<": "<",
|
|
|
|
+ "&": "&",
|
|
|
|
+ '"': """,
|
|
|
|
+ ">": ">",
|
|
|
|
+ "'": "'"
|
|
|
|
+ }[a];
|
|
|
|
+ }
|
|
|
|
+ }) : "";
|
|
|
|
+ };
|
|
|
|
+ exports.clearWhiteSpace = function(str) {
|
|
|
|
+ return str.replace(/[\u200b\t\r\n]/g, "");
|
|
|
|
+ };
|
|
|
|
+ exports.each([ "String", "Function", "Array", "Number", "RegExp", "Object" ], function(v) {
|
|
|
|
+ var toString = Object.prototype.toString;
|
|
|
|
+ exports["is" + v] = function(obj) {
|
|
|
|
+ return toString.apply(obj) == "[object " + v + "]";
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/expose-kityminder.js
|
|
|
|
+_p[34] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ module.exports = window.kityminder = _p.r(35);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/kityminder.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 默认导出(全部模块)
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[35] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kityminder = {
|
|
|
|
+ version: _p.r(19).version
|
|
|
|
+ };
|
|
|
|
+ // 核心导出,大写的部分导出类,小写的部分简单 require 一下
|
|
|
|
+ // 这里顺序是有讲究的,调整前先弄清楚依赖关系。
|
|
|
|
+ _p.r(33);
|
|
|
|
+ kityminder.Minder = _p.r(19);
|
|
|
|
+ kityminder.Command = _p.r(9);
|
|
|
|
+ kityminder.Node = _p.r(21);
|
|
|
|
+ _p.r(22);
|
|
|
|
+ _p.r(8);
|
|
|
|
+ kityminder.Event = _p.r(13);
|
|
|
|
+ kityminder.data = _p.r(12);
|
|
|
|
+ _p.r(10);
|
|
|
|
+ kityminder.KeyMap = _p.r(15);
|
|
|
|
+ _p.r(29);
|
|
|
|
+ _p.r(30);
|
|
|
|
+ _p.r(23);
|
|
|
|
+ _p.r(28);
|
|
|
|
+ _p.r(14);
|
|
|
|
+ _p.r(16);
|
|
|
|
+ kityminder.Module = _p.r(20);
|
|
|
|
+ _p.r(26);
|
|
|
|
+ kityminder.Render = _p.r(27);
|
|
|
|
+ kityminder.Connect = _p.r(11);
|
|
|
|
+ kityminder.Layout = _p.r(18);
|
|
|
|
+ kityminder.Theme = _p.r(32);
|
|
|
|
+ kityminder.Template = _p.r(31);
|
|
|
|
+ kityminder.Promise = _p.r(25);
|
|
|
|
+ _p.r(7);
|
|
|
|
+ _p.r(24);
|
|
|
|
+ // 模块依赖
|
|
|
|
+ _p.r(42);
|
|
|
|
+ _p.r(43);
|
|
|
|
+ _p.r(44);
|
|
|
|
+ _p.r(45);
|
|
|
|
+ _p.r(46);
|
|
|
|
+ _p.r(47);
|
|
|
|
+ _p.r(48);
|
|
|
|
+ _p.r(50);
|
|
|
|
+ _p.r(49);
|
|
|
|
+ _p.r(51);
|
|
|
|
+ _p.r(52);
|
|
|
|
+ _p.r(53);
|
|
|
|
+ _p.r(54);
|
|
|
|
+ _p.r(55);
|
|
|
|
+ _p.r(56);
|
|
|
|
+ _p.r(57);
|
|
|
|
+ _p.r(58);
|
|
|
|
+ _p.r(59);
|
|
|
|
+ _p.r(60);
|
|
|
|
+ _p.r(61);
|
|
|
|
+ _p.r(62);
|
|
|
|
+ _p.r(63);
|
|
|
|
+ _p.r(64);
|
|
|
|
+ _p.r(68);
|
|
|
|
+ _p.r(65);
|
|
|
|
+ _p.r(67);
|
|
|
|
+ _p.r(66);
|
|
|
|
+ _p.r(40);
|
|
|
|
+ _p.r(36);
|
|
|
|
+ _p.r(37);
|
|
|
|
+ _p.r(38);
|
|
|
|
+ _p.r(39);
|
|
|
|
+ _p.r(41);
|
|
|
|
+ _p.r(75);
|
|
|
|
+ _p.r(78);
|
|
|
|
+ _p.r(77);
|
|
|
|
+ _p.r(76);
|
|
|
|
+ _p.r(78);
|
|
|
|
+ _p.r(80);
|
|
|
|
+ _p.r(79);
|
|
|
|
+ _p.r(0);
|
|
|
|
+ _p.r(1);
|
|
|
|
+ _p.r(2);
|
|
|
|
+ _p.r(3);
|
|
|
|
+ _p.r(4);
|
|
|
|
+ _p.r(5);
|
|
|
|
+ _p.r(6);
|
|
|
|
+ _p.r(69);
|
|
|
|
+ _p.r(73);
|
|
|
|
+ _p.r(70);
|
|
|
|
+ _p.r(72);
|
|
|
|
+ _p.r(71);
|
|
|
|
+ _p.r(74);
|
|
|
|
+ module.exports = kityminder;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/btree.js
|
|
|
|
+_p[36] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ [ "left", "right", "top", "bottom" ].forEach(registerLayoutForDirection);
|
|
|
|
+ function registerLayoutForDirection(name) {
|
|
|
|
+ var axis = name == "left" || name == "right" ? "x" : "y";
|
|
|
|
+ var dir = name == "left" || name == "top" ? -1 : 1;
|
|
|
|
+ var oppsite = {
|
|
|
|
+ left: "right",
|
|
|
|
+ right: "left",
|
|
|
|
+ top: "bottom",
|
|
|
|
+ bottom: "top",
|
|
|
|
+ x: "y",
|
|
|
|
+ y: "x"
|
|
|
|
+ };
|
|
|
|
+ function getOrderHint(node) {
|
|
|
|
+ var hint = [];
|
|
|
|
+ var box = node.getLayoutBox();
|
|
|
|
+ var offset = 5;
|
|
|
|
+ if (axis == "x") {
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "up",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.top - node.getStyle("margin-top") - offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-top")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.top - offset, "L", box.right, box.top - offset ]
|
|
|
|
+ });
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "down",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.bottom + offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-bottom")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.bottom + offset, "L", box.right, box.bottom + offset ]
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "up",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.left - node.getStyle("margin-left") - offset,
|
|
|
|
+ y: box.top,
|
|
|
|
+ width: node.getStyle("margin-left"),
|
|
|
|
+ height: box.height
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.left - offset, box.top, "L", box.left - offset, box.bottom ]
|
|
|
|
+ });
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "down",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.right + offset,
|
|
|
|
+ y: box.top,
|
|
|
|
+ width: node.getStyle("margin-right"),
|
|
|
|
+ height: box.height
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.right + offset, box.top, "L", box.right + offset, box.bottom ]
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ return hint;
|
|
|
|
+ }
|
|
|
|
+ Layout.register(name, kity.createClass({
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(parent, children) {
|
|
|
|
+ var pbox = parent.getContentBox();
|
|
|
|
+ if (axis == "x") {
|
|
|
|
+ parent.setVertexOut(new kity.Point(pbox[name], pbox.cy));
|
|
|
|
+ parent.setLayoutVectorOut(new kity.Vector(dir, 0));
|
|
|
|
+ } else {
|
|
|
|
+ parent.setVertexOut(new kity.Point(pbox.cx, pbox[name]));
|
|
|
|
+ parent.setLayoutVectorOut(new kity.Vector(0, dir));
|
|
|
|
+ }
|
|
|
|
+ if (!children.length) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ children.forEach(function(child) {
|
|
|
|
+ var cbox = child.getContentBox();
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ if (axis == "x") {
|
|
|
|
+ child.setVertexIn(new kity.Point(cbox[oppsite[name]], cbox.cy));
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(dir, 0));
|
|
|
|
+ } else {
|
|
|
|
+ child.setVertexIn(new kity.Point(cbox.cx, cbox[oppsite[name]]));
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(0, dir));
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ this.align(children, oppsite[name]);
|
|
|
|
+ this.stack(children, oppsite[axis]);
|
|
|
|
+ var bbox = this.getBranchBox(children);
|
|
|
|
+ var xAdjust = 0, yAdjust = 0;
|
|
|
|
+ if (axis == "x") {
|
|
|
|
+ xAdjust = pbox[name];
|
|
|
|
+ xAdjust += dir * parent.getStyle("margin-" + name);
|
|
|
|
+ xAdjust += dir * children[0].getStyle("margin-" + oppsite[name]);
|
|
|
|
+ yAdjust = pbox.bottom;
|
|
|
|
+ yAdjust -= pbox.height / 2;
|
|
|
|
+ yAdjust -= bbox.height / 2;
|
|
|
|
+ yAdjust -= bbox.y;
|
|
|
|
+ } else {
|
|
|
|
+ xAdjust = pbox.right;
|
|
|
|
+ xAdjust -= pbox.width / 2;
|
|
|
|
+ xAdjust -= bbox.width / 2;
|
|
|
|
+ xAdjust -= bbox.x;
|
|
|
|
+ yAdjust = pbox[name];
|
|
|
|
+ yAdjust += dir * parent.getStyle("margin-" + name);
|
|
|
|
+ yAdjust += dir * children[0].getStyle("margin-" + oppsite[name]);
|
|
|
|
+ }
|
|
|
|
+ this.move(children, xAdjust, yAdjust);
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: getOrderHint
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/filetree.js
|
|
|
|
+_p[37] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ [ -1, 1 ].forEach(registerLayoutForDir);
|
|
|
|
+ function registerLayoutForDir(dir) {
|
|
|
|
+ var name = "filetree-" + (dir > 0 ? "down" : "up");
|
|
|
|
+ Layout.register(name, kity.createClass({
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(parent, children, round) {
|
|
|
|
+ var pBox = parent.getContentBox();
|
|
|
|
+ var indent = 20;
|
|
|
|
+ parent.setVertexOut(new kity.Point(pBox.left + indent, dir > 0 ? pBox.bottom : pBox.top));
|
|
|
|
+ parent.setLayoutVectorOut(new kity.Vector(0, dir));
|
|
|
|
+ if (!children.length) return;
|
|
|
|
+ children.forEach(function(child) {
|
|
|
|
+ var cbox = child.getContentBox();
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ child.setVertexIn(new kity.Point(cbox.left, cbox.cy));
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(1, 0));
|
|
|
|
+ });
|
|
|
|
+ this.align(children, "left");
|
|
|
|
+ this.stack(children, "y");
|
|
|
|
+ var xAdjust = 0;
|
|
|
|
+ xAdjust += pBox.left;
|
|
|
|
+ xAdjust += indent;
|
|
|
|
+ xAdjust += children[0].getStyle("margin-left");
|
|
|
|
+ var yAdjust = 0;
|
|
|
|
+ if (dir > 0) {
|
|
|
|
+ yAdjust += pBox.bottom;
|
|
|
|
+ yAdjust += parent.getStyle("margin-bottom");
|
|
|
|
+ yAdjust += children[0].getStyle("margin-top");
|
|
|
|
+ } else {
|
|
|
|
+ yAdjust -= this.getTreeBox(children).bottom;
|
|
|
|
+ yAdjust += pBox.top;
|
|
|
|
+ yAdjust -= parent.getStyle("margin-top");
|
|
|
|
+ yAdjust -= children[0].getStyle("margin-bottom");
|
|
|
|
+ }
|
|
|
|
+ this.move(children, xAdjust, yAdjust);
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: function(node) {
|
|
|
|
+ var hint = [];
|
|
|
|
+ var box = node.getLayoutBox();
|
|
|
|
+ var offset = node.getLevel() > 1 ? 3 : 5;
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "up",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.top - node.getStyle("margin-top") - offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-top")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.top - offset, "L", box.right, box.top - offset ]
|
|
|
|
+ });
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "down",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.bottom + offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-bottom")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.bottom + offset, "L", box.right, box.bottom + offset ]
|
|
|
|
+ });
|
|
|
|
+ return hint;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/fish-bone-master.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 鱼骨图主骨架布局
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[38] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ Layout.register("fish-bone-master", kity.createClass("FishBoneMasterLayout", {
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(parent, children, round) {
|
|
|
|
+ var upPart = [], downPart = [];
|
|
|
|
+ var child = children[0];
|
|
|
|
+ var pBox = parent.getContentBox();
|
|
|
|
+ parent.setVertexOut(new kity.Point(pBox.right, pBox.cy));
|
|
|
|
+ parent.setLayoutVectorOut(new kity.Vector(1, 0));
|
|
|
|
+ if (!child) return;
|
|
|
|
+ var cBox = child.getContentBox();
|
|
|
|
+ var pMarginRight = parent.getStyle("margin-right");
|
|
|
|
+ var cMarginLeft = child.getStyle("margin-left");
|
|
|
|
+ var cMarginTop = child.getStyle("margin-top");
|
|
|
|
+ var cMarginBottom = child.getStyle("margin-bottom");
|
|
|
|
+ children.forEach(function(child, index) {
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ var cBox = child.getContentBox();
|
|
|
|
+ if (index % 2) {
|
|
|
|
+ downPart.push(child);
|
|
|
|
+ child.setVertexIn(new kity.Point(cBox.left, cBox.top));
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(1, 1));
|
|
|
|
+ } else {
|
|
|
|
+ upPart.push(child);
|
|
|
|
+ child.setVertexIn(new kity.Point(cBox.left, cBox.bottom));
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(1, -1));
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ this.stack(upPart, "x");
|
|
|
|
+ this.stack(downPart, "x");
|
|
|
|
+ this.align(upPart, "bottom");
|
|
|
|
+ this.align(downPart, "top");
|
|
|
|
+ var xAdjust = pBox.right + pMarginRight + cMarginLeft;
|
|
|
|
+ var yAdjustUp = pBox.cy - cMarginBottom - parent.getStyle("margin-top");
|
|
|
|
+ var yAdjustDown = pBox.cy + cMarginTop + parent.getStyle("margin-bottom");
|
|
|
|
+ this.move(upPart, xAdjust, yAdjustUp);
|
|
|
|
+ this.move(downPart, xAdjust + cMarginLeft, yAdjustDown);
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/fish-bone-slave.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[39] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ Layout.register("fish-bone-slave", kity.createClass("FishBoneSlaveLayout", {
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(parent, children, round) {
|
|
|
|
+ var layout = this;
|
|
|
|
+ var abs = Math.abs;
|
|
|
|
+ var GOLD_CUT = 1 - .618;
|
|
|
|
+ var pBox = parent.getContentBox();
|
|
|
|
+ var vi = parent.getLayoutVectorIn();
|
|
|
|
+ parent.setLayoutVectorOut(vi);
|
|
|
|
+ var goldX = pBox.left + pBox.width * GOLD_CUT;
|
|
|
|
+ var pout = new kity.Point(goldX, vi.y > 0 ? pBox.bottom : pBox.top);
|
|
|
|
+ parent.setVertexOut(pout);
|
|
|
|
+ var child = children[0];
|
|
|
|
+ if (!child) return;
|
|
|
|
+ var cBox = child.getContentBox();
|
|
|
|
+ children.forEach(function(child, index) {
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(1, 0));
|
|
|
|
+ child.setVertexIn(new kity.Point(cBox.left, cBox.cy));
|
|
|
|
+ });
|
|
|
|
+ this.stack(children, "y");
|
|
|
|
+ this.align(children, "left");
|
|
|
|
+ var xAdjust = 0, yAdjust = 0;
|
|
|
|
+ xAdjust += pout.x;
|
|
|
|
+ if (parent.getLayoutVectorOut().y < 0) {
|
|
|
|
+ yAdjust -= this.getTreeBox(children).bottom;
|
|
|
|
+ yAdjust += parent.getContentBox().top;
|
|
|
|
+ yAdjust -= parent.getStyle("margin-top");
|
|
|
|
+ yAdjust -= child.getStyle("margin-bottom");
|
|
|
|
+ } else {
|
|
|
|
+ yAdjust += parent.getContentBox().bottom;
|
|
|
|
+ yAdjust += parent.getStyle("margin-bottom");
|
|
|
|
+ yAdjust += child.getStyle("margin-top");
|
|
|
|
+ }
|
|
|
|
+ this.move(children, xAdjust, yAdjust);
|
|
|
|
+ if (round == 2) {
|
|
|
|
+ children.forEach(function(child) {
|
|
|
|
+ var m = child.getLayoutTransform();
|
|
|
|
+ var cbox = child.getContentBox();
|
|
|
|
+ var pin = m.transformPoint(new kity.Point(cbox.left, 0));
|
|
|
|
+ layout.move([ child ], abs(pin.y - pout.y), 0);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/mind.js
|
|
|
|
+_p[40] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ Layout.register("mind", kity.createClass({
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(node, children) {
|
|
|
|
+ var layout = this;
|
|
|
|
+ var half = Math.ceil(node.children.length / 2);
|
|
|
|
+ var right = [];
|
|
|
|
+ var left = [];
|
|
|
|
+ children.forEach(function(child) {
|
|
|
|
+ if (child.getIndex() < half) right.push(child); else left.push(child);
|
|
|
|
+ });
|
|
|
|
+ var leftLayout = Minder.getLayoutInstance("left");
|
|
|
|
+ var rightLayout = Minder.getLayoutInstance("right");
|
|
|
|
+ leftLayout.doLayout(node, left);
|
|
|
|
+ rightLayout.doLayout(node, right);
|
|
|
|
+ var box = node.getContentBox();
|
|
|
|
+ node.setVertexOut(new kity.Point(box.cx, box.cy));
|
|
|
|
+ node.setLayoutVectorOut(new kity.Vector(0, 0));
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: function(node) {
|
|
|
|
+ var hint = [];
|
|
|
|
+ var box = node.getLayoutBox();
|
|
|
|
+ var offset = 5;
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "up",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.top - node.getStyle("margin-top") - offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-top")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.top - offset, "L", box.right, box.top - offset ]
|
|
|
|
+ });
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "down",
|
|
|
|
+ node: node,
|
|
|
|
+ area: new kity.Box({
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.bottom + offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-bottom")
|
|
|
|
+ }),
|
|
|
|
+ path: [ "M", box.x, box.bottom + offset, "L", box.right, box.bottom + offset ]
|
|
|
|
+ });
|
|
|
|
+ return hint;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/layout/tianpan.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 天盘模板
|
|
|
|
+ *
|
|
|
|
+ * @author: along
|
|
|
|
+ * @copyright: bpd729@163.com, 2015
|
|
|
|
+ */
|
|
|
|
+_p[41] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Layout = _p.r(18);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ Layout.register("tianpan", kity.createClass({
|
|
|
|
+ base: Layout,
|
|
|
|
+ doLayout: function(parent, children) {
|
|
|
|
+ if (children.length == 0) return;
|
|
|
|
+ var layout = this;
|
|
|
|
+ var pbox = parent.getContentBox();
|
|
|
|
+ var x, y, box;
|
|
|
|
+ var _theta = 5;
|
|
|
|
+ var _r = Math.max(pbox.width, 50);
|
|
|
|
+ children.forEach(function(child, index) {
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ box = layout.getTreeBox(child);
|
|
|
|
+ _r = Math.max(Math.max(box.width, box.height), _r);
|
|
|
|
+ });
|
|
|
|
+ _r = _r / 1.5 / Math.PI;
|
|
|
|
+ children.forEach(function(child, index) {
|
|
|
|
+ x = _r * (Math.cos(_theta) + Math.sin(_theta) * _theta);
|
|
|
|
+ y = _r * (Math.sin(_theta) - Math.cos(_theta) * _theta);
|
|
|
|
+ _theta += .9 - index * .02;
|
|
|
|
+ child.setLayoutVectorIn(new kity.Vector(1, 0));
|
|
|
|
+ child.setVertexIn(new kity.Point(pbox.cx, pbox.cy));
|
|
|
|
+ child.setLayoutTransform(new kity.Matrix());
|
|
|
|
+ layout.move([ child ], x, y);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ getOrderHint: function(node) {
|
|
|
|
+ var hint = [];
|
|
|
|
+ var box = node.getLayoutBox();
|
|
|
|
+ var offset = 5;
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "up",
|
|
|
|
+ node: node,
|
|
|
|
+ area: {
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.top - node.getStyle("margin-top") - offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-top")
|
|
|
|
+ },
|
|
|
|
+ path: [ "M", box.x, box.top - offset, "L", box.right, box.top - offset ]
|
|
|
|
+ });
|
|
|
|
+ hint.push({
|
|
|
|
+ type: "down",
|
|
|
|
+ node: node,
|
|
|
|
+ area: {
|
|
|
|
+ x: box.x,
|
|
|
|
+ y: box.bottom + offset,
|
|
|
|
+ width: box.width,
|
|
|
|
+ height: node.getStyle("margin-bottom")
|
|
|
|
+ },
|
|
|
|
+ path: [ "M", box.x, box.bottom + offset, "L", box.right, box.bottom + offset ]
|
|
|
|
+ });
|
|
|
|
+ return hint;
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/arrange.js
|
|
|
|
+_p[42] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ arrange: function(index) {
|
|
|
|
+ var parent = this.parent;
|
|
|
|
+ if (!parent) return;
|
|
|
|
+ var sibling = parent.children;
|
|
|
|
+ if (index < 0 || index >= sibling.length) return;
|
|
|
|
+ sibling.splice(this.getIndex(), 1);
|
|
|
|
+ sibling.splice(index, 0, this);
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ function asc(nodeA, nodeB) {
|
|
|
|
+ return nodeA.getIndex() - nodeB.getIndex();
|
|
|
|
+ }
|
|
|
|
+ function desc(nodeA, nodeB) {
|
|
|
|
+ return -asc(nodeA, nodeB);
|
|
|
|
+ }
|
|
|
|
+ function canArrange(km) {
|
|
|
|
+ var selected = km.getSelectedNode();
|
|
|
|
+ return selected && selected.parent && selected.parent.children.length > 1;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @command ArrangeUp
|
|
|
|
+ * @description 向上调整选中节点的位置
|
|
|
|
+ * @shortcut Alt + Up
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前选中了具有相同父亲的节点
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ var ArrangeUpCommand = kity.createClass("ArrangeUpCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.sort(asc);
|
|
|
|
+ var lastIndexes = nodes.map(function(node) {
|
|
|
|
+ return node.getIndex();
|
|
|
|
+ });
|
|
|
|
+ nodes.forEach(function(node, index) {
|
|
|
|
+ node.arrange(lastIndexes[index] - 1);
|
|
|
|
+ });
|
|
|
|
+ km.layout(300);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selected = km.getSelectedNode();
|
|
|
|
+ return selected ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command ArrangeDown
|
|
|
|
+ * @description 向下调整选中节点的位置
|
|
|
|
+ * @shortcut Alt + Down
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前选中了具有相同父亲的节点
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ var ArrangeDownCommand = kity.createClass("ArrangeUpCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.sort(desc);
|
|
|
|
+ var lastIndexes = nodes.map(function(node) {
|
|
|
|
+ return node.getIndex();
|
|
|
|
+ });
|
|
|
|
+ nodes.forEach(function(node, index) {
|
|
|
|
+ node.arrange(lastIndexes[index] + 1);
|
|
|
|
+ });
|
|
|
|
+ km.layout(300);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selected = km.getSelectedNode();
|
|
|
|
+ return selected ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Arrange
|
|
|
|
+ * @description 调整选中节点的位置
|
|
|
|
+ * @param {number} index 调整后节点的新位置
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前选中了具有相同父亲的节点
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ var ArrangeCommand = kity.createClass("ArrangeCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, index) {
|
|
|
|
+ var nodes = km.getSelectedNodes().slice();
|
|
|
|
+ if (!nodes.length) return;
|
|
|
|
+ var ancestor = MinderNode.getCommonAncestor(nodes);
|
|
|
|
+ if (ancestor != nodes[0].parent) return;
|
|
|
|
+ var indexed = nodes.map(function(node) {
|
|
|
|
+ return {
|
|
|
|
+ index: node.getIndex(),
|
|
|
|
+ node: node
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ var asc = Math.min.apply(Math, indexed.map(function(one) {
|
|
|
|
+ return one.index;
|
|
|
|
+ })) >= index;
|
|
|
|
+ indexed.sort(function(a, b) {
|
|
|
|
+ return asc ? b.index - a.index : a.index - b.index;
|
|
|
|
+ });
|
|
|
|
+ indexed.forEach(function(one) {
|
|
|
|
+ one.node.arrange(index);
|
|
|
|
+ });
|
|
|
|
+ km.layout(300);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selected = km.getSelectedNode();
|
|
|
|
+ return selected ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("ArrangeModule", {
|
|
|
|
+ commands: {
|
|
|
|
+ arrangeup: ArrangeUpCommand,
|
|
|
|
+ arrangedown: ArrangeDownCommand,
|
|
|
|
+ arrange: ArrangeCommand
|
|
|
|
+ },
|
|
|
|
+ contextmenu: [ {
|
|
|
|
+ command: "arrangeup"
|
|
|
|
+ }, {
|
|
|
|
+ command: "arrangedown"
|
|
|
|
+ }, {
|
|
|
|
+ divider: true
|
|
|
|
+ } ],
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ arrangeup: "normal::alt+Up",
|
|
|
|
+ arrangedown: "normal::alt+Down"
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/basestyle.js
|
|
|
|
+_p[43] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var TextRenderer = _p.r(61);
|
|
|
|
+ Module.register("basestylemodule", function() {
|
|
|
|
+ var km = this;
|
|
|
|
+ function getNodeDataOrStyle(node, name) {
|
|
|
|
+ return node.getData(name) || node.getStyle(name);
|
|
|
|
+ }
|
|
|
|
+ TextRenderer.registerStyleHook(function(node, textGroup) {
|
|
|
|
+ var fontWeight = getNodeDataOrStyle(node, "font-weight");
|
|
|
|
+ var fontStyle = getNodeDataOrStyle(node, "font-style");
|
|
|
|
+ var styleHash = [ fontWeight, fontStyle ].join("/");
|
|
|
|
+ textGroup.eachItem(function(index, item) {
|
|
|
|
+ item.setFont({
|
|
|
|
+ weight: fontWeight,
|
|
|
|
+ style: fontStyle
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ /**
|
|
|
|
+ * @command Bold
|
|
|
|
+ * @description 加粗选中的节点
|
|
|
|
+ * @shortcut Ctrl + B
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * 1: 当前已选中的节点已加粗
|
|
|
|
+ */
|
|
|
|
+ bold: kity.createClass("boldCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ if (this.queryState("bold") == 1) {
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-weight").render();
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-weight", "bold").render();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryState: function() {
|
|
|
|
+ var nodes = km.getSelectedNodes(), result = 0;
|
|
|
|
+ if (nodes.length === 0) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ if (n && n.getData("font-weight")) {
|
|
|
|
+ result = 1;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command Italic
|
|
|
|
+ * @description 加斜选中的节点
|
|
|
|
+ * @shortcut Ctrl + I
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * 1: 当前已选中的节点已加斜
|
|
|
|
+ */
|
|
|
|
+ italic: kity.createClass("italicCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ if (this.queryState("italic") == 1) {
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-style").render();
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-style", "italic").render();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryState: function() {
|
|
|
|
+ var nodes = km.getSelectedNodes(), result = 0;
|
|
|
|
+ if (nodes.length === 0) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ if (n && n.getData("font-style")) {
|
|
|
|
+ result = 1;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ bold: "ctrl+b",
|
|
|
|
+ //bold
|
|
|
|
+ italic: "ctrl+i"
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/clipboard.js
|
|
|
|
+_p[44] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ Module.register("ClipboardModule", function() {
|
|
|
|
+ var km = this, _clipboardNodes = [], _selectedNodes = [];
|
|
|
|
+ function appendChildNode(parent, child) {
|
|
|
|
+ _selectedNodes.push(child);
|
|
|
|
+ km.appendNode(child, parent);
|
|
|
|
+ child.render();
|
|
|
|
+ child.setLayoutOffset(null);
|
|
|
|
+ var children = child.children.map(function(node) {
|
|
|
|
+ return node.clone();
|
|
|
|
+ });
|
|
|
|
+ /*
|
|
|
|
+ * fixed bug: Modified on 2015.08.05
|
|
|
|
+ * 原因:粘贴递归 append 时没有清空原来父节点的子节点,而父节点被复制的时候,是连同子节点一起复制过来的
|
|
|
|
+ * 解决办法:增加了下面这一行代码
|
|
|
|
+ * by: @zhangbobell zhangbobell@163.com
|
|
|
|
+ */
|
|
|
|
+ child.clearChildren();
|
|
|
|
+ for (var i = 0, ci; ci = children[i]; i++) {
|
|
|
|
+ appendChildNode(child, ci);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ function sendToClipboard(nodes) {
|
|
|
|
+ if (!nodes.length) return;
|
|
|
|
+ nodes.sort(function(a, b) {
|
|
|
|
+ return a.getIndex() - b.getIndex();
|
|
|
|
+ });
|
|
|
|
+ _clipboardNodes = nodes.map(function(node) {
|
|
|
|
+ return node.clone();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @command Copy
|
|
|
|
+ * @description 复制当前选中的节点
|
|
|
|
+ * @shortcut Ctrl + C
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var CopyCommand = kity.createClass("CopyCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ sendToClipboard(km.getSelectedAncestors(true));
|
|
|
|
+ this.setContentChanged(false);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Cut
|
|
|
|
+ * @description 剪切当前选中的节点
|
|
|
|
+ * @shortcut Ctrl + X
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var CutCommand = kity.createClass("CutCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var ancestors = km.getSelectedAncestors();
|
|
|
|
+ if (ancestors.length === 0) return;
|
|
|
|
+ sendToClipboard(ancestors);
|
|
|
|
+ km.select(MinderNode.getCommonAncestor(ancestors), true);
|
|
|
|
+ ancestors.slice().forEach(function(node) {
|
|
|
|
+ km.removeNode(node);
|
|
|
|
+ });
|
|
|
|
+ km.layout(300);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Paste
|
|
|
|
+ * @description 粘贴已复制的节点到每一个当前选中的节点上
|
|
|
|
+ * @shortcut Ctrl + V
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var PasteCommand = kity.createClass("PasteCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ if (_clipboardNodes.length) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ if (!nodes.length) return;
|
|
|
|
+ for (var i = 0, ni; ni = _clipboardNodes[i]; i++) {
|
|
|
|
+ for (var j = 0, node; node = nodes[j]; j++) {
|
|
|
|
+ appendChildNode(node, ni.clone());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ km.select(_selectedNodes, true);
|
|
|
|
+ _selectedNodes = [];
|
|
|
|
+ km.layout(300);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNode() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @Desc: 若支持原生clipboadr事件则基于原生扩展,否则使用km的基础事件只处理节点的粘贴复制
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.20
|
|
|
|
+ */
|
|
|
|
+ if (km.supportClipboardEvent && !kity.Browser.gecko) {
|
|
|
|
+ var Copy = function(e) {
|
|
|
|
+ this.fire("beforeCopy", e);
|
|
|
|
+ };
|
|
|
|
+ var Cut = function(e) {
|
|
|
|
+ this.fire("beforeCut", e);
|
|
|
|
+ };
|
|
|
|
+ var Paste = function(e) {
|
|
|
|
+ this.fire("beforePaste", e);
|
|
|
|
+ };
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ copy: CopyCommand,
|
|
|
|
+ cut: CutCommand,
|
|
|
|
+ paste: PasteCommand
|
|
|
|
+ },
|
|
|
|
+ clipBoardEvents: {
|
|
|
|
+ copy: Copy.bind(km),
|
|
|
|
+ cut: Cut.bind(km),
|
|
|
|
+ paste: Paste.bind(km)
|
|
|
|
+ },
|
|
|
|
+ sendToClipboard: sendToClipboard
|
|
|
|
+ };
|
|
|
|
+ } else {
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ copy: CopyCommand,
|
|
|
|
+ cut: CutCommand,
|
|
|
|
+ paste: PasteCommand
|
|
|
|
+ },
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ copy: "normal::ctrl+c|",
|
|
|
|
+ cut: "normal::ctrl+x",
|
|
|
|
+ paste: "normal::ctrl+v"
|
|
|
|
+ },
|
|
|
|
+ sendToClipboard: sendToClipboard
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/dragtree.js
|
|
|
|
+_p[45] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ // 矩形的变形动画定义
|
|
|
|
+ var MoveToParentCommand = kity.createClass("MoveToParentCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, nodes, parent) {
|
|
|
|
+ var node;
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ node = nodes[i];
|
|
|
|
+ if (node.parent) {
|
|
|
|
+ node.parent.removeChild(node);
|
|
|
|
+ parent.appendChild(node);
|
|
|
|
+ node.render();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ parent.expand();
|
|
|
|
+ minder.select(nodes, true);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var DropHinter = kity.createClass("DropHinter", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.rect = new kity.Rect();
|
|
|
|
+ this.addShape(this.rect);
|
|
|
|
+ },
|
|
|
|
+ render: function(target) {
|
|
|
|
+ this.setVisible(!!target);
|
|
|
|
+ if (target) {
|
|
|
|
+ this.rect.setBox(target.getLayoutBox()).setRadius(target.getStyle("radius") || 0).stroke(target.getStyle("drop-hint-color") || "yellow", target.getStyle("drop-hint-width") || 2);
|
|
|
|
+ this.bringTop();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var OrderHinter = kity.createClass("OrderHinter", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.area = new kity.Rect();
|
|
|
|
+ this.path = new kity.Path();
|
|
|
|
+ this.addShapes([ this.area, this.path ]);
|
|
|
|
+ },
|
|
|
|
+ render: function(hint) {
|
|
|
|
+ this.setVisible(!!hint);
|
|
|
|
+ if (hint) {
|
|
|
|
+ this.area.setBox(hint.area);
|
|
|
|
+ this.area.fill(hint.node.getStyle("order-hint-area-color") || "rgba(0, 255, 0, .5)");
|
|
|
|
+ this.path.setPathData(hint.path);
|
|
|
|
+ this.path.stroke(hint.node.getStyle("order-hint-path-color") || "#0f0", hint.node.getStyle("order-hint-path-width") || 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // 对拖动对象的一个替代盒子,控制整个拖放的逻辑,包括:
|
|
|
|
+ // 1. 从节点列表计算出拖动部分
|
|
|
|
+ // 2. 计算可以 drop 的节点,产生 drop 交互提示
|
|
|
|
+ var TreeDragger = kity.createClass("TreeDragger", {
|
|
|
|
+ constructor: function(minder) {
|
|
|
|
+ this._minder = minder;
|
|
|
|
+ this._dropHinter = new DropHinter();
|
|
|
|
+ this._orderHinter = new OrderHinter();
|
|
|
|
+ minder.getRenderContainer().addShapes([ this._dropHinter, this._orderHinter ]);
|
|
|
|
+ },
|
|
|
|
+ dragStart: function(position) {
|
|
|
|
+ // 只记录开始位置,不马上开启拖放模式
|
|
|
|
+ // 这个位置同时是拖放范围收缩时的焦点位置(中心)
|
|
|
|
+ this._startPosition = position;
|
|
|
|
+ },
|
|
|
|
+ dragMove: function(position) {
|
|
|
|
+ // 启动拖放模式需要最小的移动距离
|
|
|
|
+ var DRAG_MOVE_THRESHOLD = 10;
|
|
|
|
+ if (!this._startPosition) return;
|
|
|
|
+ var movement = kity.Vector.fromPoints(this._dragPosition || this._startPosition, position);
|
|
|
|
+ var minder = this._minder;
|
|
|
|
+ this._dragPosition = position;
|
|
|
|
+ if (!this._dragMode) {
|
|
|
|
+ // 判断拖放模式是否该启动
|
|
|
|
+ if (kity.Vector.fromPoints(this._dragPosition, this._startPosition).length() < DRAG_MOVE_THRESHOLD) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!this._enterDragMode()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (var i = 0; i < this._dragSources.length; i++) {
|
|
|
|
+ this._dragSources[i].setLayoutOffset(this._dragSources[i].getLayoutOffset().offset(movement));
|
|
|
|
+ minder.applyLayoutResult(this._dragSources[i]);
|
|
|
|
+ }
|
|
|
|
+ if (!this._dropTest()) {
|
|
|
|
+ this._orderTest();
|
|
|
|
+ } else {
|
|
|
|
+ this._renderOrderHint(this._orderSucceedHint = null);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ dragEnd: function() {
|
|
|
|
+ this._startPosition = null;
|
|
|
|
+ this._dragPosition = null;
|
|
|
|
+ if (!this._dragMode) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this._fadeDragSources(1);
|
|
|
|
+ if (this._dropSucceedTarget) {
|
|
|
|
+ this._dragSources.forEach(function(source) {
|
|
|
|
+ source.setLayoutOffset(null);
|
|
|
|
+ });
|
|
|
|
+ this._minder.layout(-1);
|
|
|
|
+ this._minder.execCommand("movetoparent", this._dragSources, this._dropSucceedTarget);
|
|
|
|
+ } else if (this._orderSucceedHint) {
|
|
|
|
+ var hint = this._orderSucceedHint;
|
|
|
|
+ var index = hint.node.getIndex();
|
|
|
|
+ var sourceIndexes = this._dragSources.map(function(source) {
|
|
|
|
+ // 顺便干掉布局偏移
|
|
|
|
+ source.setLayoutOffset(null);
|
|
|
|
+ return source.getIndex();
|
|
|
|
+ });
|
|
|
|
+ var maxIndex = Math.max.apply(Math, sourceIndexes);
|
|
|
|
+ var minIndex = Math.min.apply(Math, sourceIndexes);
|
|
|
|
+ if (index < minIndex && hint.type == "down") index++;
|
|
|
|
+ if (index > maxIndex && hint.type == "up") index--;
|
|
|
|
+ hint.node.setLayoutOffset(null);
|
|
|
|
+ this._minder.execCommand("arrange", index);
|
|
|
|
+ this._renderOrderHint(null);
|
|
|
|
+ } else {
|
|
|
|
+ this._minder.fire("savescene");
|
|
|
|
+ }
|
|
|
|
+ this._minder.layout(300);
|
|
|
|
+ this._leaveDragMode();
|
|
|
|
+ this._minder.fire("contentchange");
|
|
|
|
+ },
|
|
|
|
+ // 进入拖放模式:
|
|
|
|
+ // 1. 计算拖放源和允许的拖放目标
|
|
|
|
+ // 2. 标记已启动
|
|
|
|
+ _enterDragMode: function() {
|
|
|
|
+ this._calcDragSources();
|
|
|
|
+ if (!this._dragSources.length) {
|
|
|
|
+ this._startPosition = null;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ this._fadeDragSources(.5);
|
|
|
|
+ this._calcDropTargets();
|
|
|
|
+ this._calcOrderHints();
|
|
|
|
+ this._dragMode = true;
|
|
|
|
+ this._minder.setStatus("dragtree");
|
|
|
|
+ return true;
|
|
|
|
+ },
|
|
|
|
+ // 从选中的节点计算拖放源
|
|
|
|
+ // 并不是所有选中的节点都作为拖放源,如果选中节点中存在 A 和 B,
|
|
|
|
+ // 并且 A 是 B 的祖先,则 B 不作为拖放源
|
|
|
|
+ //
|
|
|
|
+ // 计算过程:
|
|
|
|
+ // 1. 将节点按照树高排序,排序后只可能是前面节点是后面节点的祖先
|
|
|
|
+ // 2. 从后往前枚举排序的结果,如果发现枚举目标之前存在其祖先,
|
|
|
|
+ // 则排除枚举目标作为拖放源,否则加入拖放源
|
|
|
|
+ _calcDragSources: function() {
|
|
|
|
+ this._dragSources = this._minder.getSelectedAncestors();
|
|
|
|
+ },
|
|
|
|
+ _fadeDragSources: function(opacity) {
|
|
|
|
+ var minder = this._minder;
|
|
|
|
+ this._dragSources.forEach(function(source) {
|
|
|
|
+ source.getRenderContainer().setOpacity(opacity, 200);
|
|
|
|
+ source.traverse(function(node) {
|
|
|
|
+ if (opacity < 1) {
|
|
|
|
+ minder.detachNode(node);
|
|
|
|
+ } else {
|
|
|
|
+ minder.attachNode(node);
|
|
|
|
+ }
|
|
|
|
+ }, true);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ // 计算拖放目标可以释放的节点列表(释放意味着成为其子树),存在这条限制规则:
|
|
|
|
+ // - 不能拖放到拖放目标的子树上(允许拖放到自身,因为多选的情况下可以把其它节点加入)
|
|
|
|
+ //
|
|
|
|
+ // 1. 加入当前节点(初始为根节点)到允许列表
|
|
|
|
+ // 2. 对于当前节点的每一个子节点:
|
|
|
|
+ // (1) 如果是拖放目标的其中一个节点,忽略(整棵子树被剪枝)
|
|
|
|
+ // (2) 如果不是拖放目标之一,以当前子节点为当前节点,回到 1 计算
|
|
|
|
+ // 3. 返回允许列表
|
|
|
|
+ //
|
|
|
|
+ _calcDropTargets: function() {
|
|
|
|
+ function findAvailableParents(nodes, root) {
|
|
|
|
+ var availables = [], i;
|
|
|
|
+ availables.push(root);
|
|
|
|
+ root.getChildren().forEach(function(test) {
|
|
|
|
+ for (i = 0; i < nodes.length; i++) {
|
|
|
|
+ if (nodes[i] == test) return;
|
|
|
|
+ }
|
|
|
|
+ availables = availables.concat(findAvailableParents(nodes, test));
|
|
|
|
+ });
|
|
|
|
+ return availables;
|
|
|
|
+ }
|
|
|
|
+ this._dropTargets = findAvailableParents(this._dragSources, this._minder.getRoot());
|
|
|
|
+ this._dropTargetBoxes = this._dropTargets.map(function(source) {
|
|
|
|
+ return source.getLayoutBox();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ _calcOrderHints: function() {
|
|
|
|
+ var sources = this._dragSources;
|
|
|
|
+ var ancestor = MinderNode.getCommonAncestor(sources);
|
|
|
|
+ // 只有一个元素选中,公共祖先是其父
|
|
|
|
+ if (ancestor == sources[0]) ancestor = sources[0].parent;
|
|
|
|
+ if (sources.length === 0 || ancestor != sources[0].parent) {
|
|
|
|
+ this._orderHints = [];
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var siblings = ancestor.children;
|
|
|
|
+ this._orderHints = siblings.reduce(function(hint, sibling) {
|
|
|
|
+ if (sources.indexOf(sibling) == -1) {
|
|
|
|
+ hint = hint.concat(sibling.getOrderHint());
|
|
|
|
+ }
|
|
|
|
+ return hint;
|
|
|
|
+ }, []);
|
|
|
|
+ },
|
|
|
|
+ _leaveDragMode: function() {
|
|
|
|
+ this._dragMode = false;
|
|
|
|
+ this._dropSucceedTarget = null;
|
|
|
|
+ this._orderSucceedHint = null;
|
|
|
|
+ this._renderDropHint(null);
|
|
|
|
+ this._renderOrderHint(null);
|
|
|
|
+ this._minder.rollbackStatus();
|
|
|
|
+ },
|
|
|
|
+ _drawForDragMode: function() {
|
|
|
|
+ this._text.setContent(this._dragSources.length + " items");
|
|
|
|
+ this._text.setPosition(this._startPosition.x, this._startPosition.y + 5);
|
|
|
|
+ this._minder.getRenderContainer().addShape(this);
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 通过 judge 函数判断 targetBox 和 sourceBox 的位置交叉关系
|
|
|
|
+ * @param targets -- 目标节点
|
|
|
|
+ * @param targetBoxMapper -- 目标节点与对应 Box 的映射关系
|
|
|
|
+ * @param judge -- 判断函数
|
|
|
|
+ * @returns {*}
|
|
|
|
+ * @private
|
|
|
|
+ */
|
|
|
|
+ _boxTest: function(targets, targetBoxMapper, judge) {
|
|
|
|
+ var sourceBoxes = this._dragSources.map(function(source) {
|
|
|
|
+ return source.getLayoutBox();
|
|
|
|
+ });
|
|
|
|
+ var i, j, target, sourceBox, targetBox;
|
|
|
|
+ judge = judge || function(intersectBox, sourceBox, targetBox) {
|
|
|
|
+ return intersectBox && !intersectBox.isEmpty();
|
|
|
|
+ };
|
|
|
|
+ for (i = 0; i < targets.length; i++) {
|
|
|
|
+ target = targets[i];
|
|
|
|
+ targetBox = targetBoxMapper.call(this, target, i);
|
|
|
|
+ for (j = 0; j < sourceBoxes.length; j++) {
|
|
|
|
+ sourceBox = sourceBoxes[j];
|
|
|
|
+ var intersectBox = sourceBox.intersect(targetBox);
|
|
|
|
+ if (judge(intersectBox, sourceBox, targetBox)) {
|
|
|
|
+ return target;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ },
|
|
|
|
+ _dropTest: function() {
|
|
|
|
+ this._dropSucceedTarget = this._boxTest(this._dropTargets, function(target, i) {
|
|
|
|
+ return this._dropTargetBoxes[i];
|
|
|
|
+ }, function(intersectBox, sourceBox, targetBox) {
|
|
|
|
+ function area(box) {
|
|
|
|
+ return box.width * box.height;
|
|
|
|
+ }
|
|
|
|
+ if (!intersectBox) return false;
|
|
|
|
+ /*
|
|
|
|
+ * Added by zhangbobell, 2015.9.8
|
|
|
|
+ *
|
|
|
|
+ * 增加了下面一行判断,修复了循环比较中 targetBox 为折叠节点时,intersetBox 面积为 0,
|
|
|
|
+ * 而 targetBox 的 width 和 height 均为 0
|
|
|
|
+ * 此时造成了满足以下的第二个条件而返回 true
|
|
|
|
+ * */
|
|
|
|
+ if (!area(intersectBox)) return false;
|
|
|
|
+ // 面积判断,交叉面积大于其中的一半
|
|
|
|
+ if (area(intersectBox) > .5 * Math.min(area(sourceBox), area(targetBox))) return true;
|
|
|
|
+ // 有一个边完全重合的情况,也认为两个是交叉的
|
|
|
|
+ if (intersectBox.width + 1 >= Math.min(sourceBox.width, targetBox.width)) return true;
|
|
|
|
+ if (intersectBox.height + 1 >= Math.min(sourceBox.height, targetBox.height)) return true;
|
|
|
|
+ return false;
|
|
|
|
+ });
|
|
|
|
+ this._renderDropHint(this._dropSucceedTarget);
|
|
|
|
+ return !!this._dropSucceedTarget;
|
|
|
|
+ },
|
|
|
|
+ _orderTest: function() {
|
|
|
|
+ this._orderSucceedHint = this._boxTest(this._orderHints, function(hint) {
|
|
|
|
+ return hint.area;
|
|
|
|
+ });
|
|
|
|
+ this._renderOrderHint(this._orderSucceedHint);
|
|
|
|
+ return !!this._orderSucceedHint;
|
|
|
|
+ },
|
|
|
|
+ _renderDropHint: function(target) {
|
|
|
|
+ this._dropHinter.render(target);
|
|
|
|
+ },
|
|
|
|
+ _renderOrderHint: function(hint) {
|
|
|
|
+ this._orderHinter.render(hint);
|
|
|
|
+ },
|
|
|
|
+ preventDragMove: function() {
|
|
|
|
+ this._startPosition = null;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("DragTree", function() {
|
|
|
|
+ var dragger;
|
|
|
|
+ return {
|
|
|
|
+ init: function() {
|
|
|
|
+ dragger = new TreeDragger(this);
|
|
|
|
+ window.addEventListener("mouseup", function() {
|
|
|
|
+ dragger.dragEnd();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ "normal.mousedown inputready.mousedown": function(e) {
|
|
|
|
+ // 单选中根节点也不触发拖拽
|
|
|
|
+ if (e.originEvent.button) return;
|
|
|
|
+ if (e.getTargetNode() && e.getTargetNode() != this.getRoot()) {
|
|
|
|
+ dragger.dragStart(e.getPosition());
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ "normal.mousemove dragtree.mousemove": function(e) {
|
|
|
|
+ dragger.dragMove(e.getPosition());
|
|
|
|
+ },
|
|
|
|
+ "normal.mouseup dragtree.beforemouseup": function(e) {
|
|
|
|
+ dragger.dragEnd();
|
|
|
|
+ //e.stopPropagation();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ },
|
|
|
|
+ statuschange: function(e) {
|
|
|
|
+ if (e.lastStatus == "textedit" && e.currentStatus == "normal") {
|
|
|
|
+ dragger.preventDragMove();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ movetoparent: MoveToParentCommand
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/expand.js
|
|
|
|
+_p[46] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var keymap = _p.r(15);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("Expand", function() {
|
|
|
|
+ var minder = this;
|
|
|
|
+ var EXPAND_STATE_DATA = "expandState", STATE_EXPAND = "expand", STATE_COLLAPSE = "collapse";
|
|
|
|
+ // 将展开的操作和状态读取接口拓展到 MinderNode 上
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ /**
|
|
|
|
+ * 展开节点
|
|
|
|
+ * @param {Policy} policy 展开的策略,默认为 KEEP_STATE
|
|
|
|
+ */
|
|
|
|
+ expand: function() {
|
|
|
|
+ this.setData(EXPAND_STATE_DATA, STATE_EXPAND);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 收起节点
|
|
|
|
+ */
|
|
|
|
+ collapse: function() {
|
|
|
|
+ this.setData(EXPAND_STATE_DATA, STATE_COLLAPSE);
|
|
|
|
+ return this;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 判断节点当前的状态是否为展开
|
|
|
|
+ */
|
|
|
|
+ isExpanded: function() {
|
|
|
|
+ var expanded = this.getData(EXPAND_STATE_DATA) !== STATE_COLLAPSE;
|
|
|
|
+ return expanded && (this.isRoot() || this.parent.isExpanded());
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 判断节点当前的状态是否为收起
|
|
|
|
+ */
|
|
|
|
+ isCollapsed: function() {
|
|
|
|
+ return !this.isExpanded();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Expand
|
|
|
|
+ * @description 展开当前选中的节点,保证其可见
|
|
|
|
+ * @param {bool} justParents 是否只展开到父亲
|
|
|
|
+ * * `false` - (默认)保证选中的节点以及其子树可见
|
|
|
|
+ * * `true` - 只保证选中的节点可见,不展开其子树
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var ExpandCommand = kity.createClass("ExpandCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, justParents) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ if (!node) return;
|
|
|
|
+ if (justParents) {
|
|
|
|
+ node = node.parent;
|
|
|
|
+ }
|
|
|
|
+ while (node.parent) {
|
|
|
|
+ node.expand();
|
|
|
|
+ node = node.parent;
|
|
|
|
+ }
|
|
|
|
+ node.renderTree();
|
|
|
|
+ km.layout(100);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ return node && !node.isRoot() && !node.isExpanded() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command ExpandToLevel
|
|
|
|
+ * @description 展开脑图到指定的层级
|
|
|
|
+ * @param {number} level 指定展开到的层级,最少值为 1。
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 一直可用
|
|
|
|
+ */
|
|
|
|
+ var ExpandToLevelCommand = kity.createClass("ExpandToLevelCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, level) {
|
|
|
|
+ km.getRoot().traverse(function(node) {
|
|
|
|
+ if (node.getLevel() < level) node.expand();
|
|
|
|
+ if (node.getLevel() == level && !node.isLeaf()) node.collapse();
|
|
|
|
+ });
|
|
|
|
+ km.refresh(100);
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Collapse
|
|
|
|
+ * @description 收起当前节点的子树
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var CollapseCommand = kity.createClass("CollapseCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ if (!node) return;
|
|
|
|
+ node.collapse();
|
|
|
|
+ node.renderTree();
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ return node && !node.isRoot() && node.isExpanded() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var Expander = kity.createClass("Expander", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function(node) {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.radius = 6;
|
|
|
|
+ this.outline = new kity.Circle(this.radius).stroke("gray").fill("white");
|
|
|
|
+ this.sign = new kity.Path().stroke("gray");
|
|
|
|
+ this.addShapes([ this.outline, this.sign ]);
|
|
|
|
+ this.initEvent(node);
|
|
|
|
+ this.setId(utils.uuid("node_expander"));
|
|
|
|
+ this.setStyle("cursor", "pointer");
|
|
|
|
+ },
|
|
|
|
+ initEvent: function(node) {
|
|
|
|
+ this.on("mousedown", function(e) {
|
|
|
|
+ minder.select([ node ], true);
|
|
|
|
+ if (node.isExpanded()) {
|
|
|
|
+ node.collapse();
|
|
|
|
+ } else {
|
|
|
|
+ node.expand();
|
|
|
|
+ }
|
|
|
|
+ node.renderTree().getMinder().layout(100);
|
|
|
|
+ node.getMinder().fire("contentchange");
|
|
|
|
+ e.stopPropagation();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ this.on("dblclick click mouseup", function(e) {
|
|
|
|
+ e.stopPropagation();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ setState: function(state) {
|
|
|
|
+ if (state == "hide") {
|
|
|
|
+ this.setVisible(false);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.setVisible(true);
|
|
|
|
+ var pathData = [ "M", 1.5 - this.radius, 0, "L", this.radius - 1.5, 0 ];
|
|
|
|
+ if (state == STATE_COLLAPSE) {
|
|
|
|
+ pathData.push([ "M", 0, 1.5 - this.radius, "L", 0, this.radius - 1.5 ]);
|
|
|
|
+ }
|
|
|
|
+ this.sign.setPathData(pathData);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var ExpanderRenderer = kity.createClass("ExpanderRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ if (node.isRoot()) return;
|
|
|
|
+ this.expander = new Expander(node);
|
|
|
|
+ node.getRenderContainer().prependShape(this.expander);
|
|
|
|
+ node.expanderRenderer = this;
|
|
|
|
+ this.node = node;
|
|
|
|
+ return this.expander;
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return !node.isRoot();
|
|
|
|
+ },
|
|
|
|
+ update: function(expander, node, box) {
|
|
|
|
+ if (!node.parent) return;
|
|
|
|
+ var visible = node.parent.isExpanded();
|
|
|
|
+ expander.setState(visible && node.children.length ? node.getData(EXPAND_STATE_DATA) : "hide");
|
|
|
|
+ var vector = node.getLayoutVectorIn().normalize(expander.radius + node.getStyle("stroke-width"));
|
|
|
|
+ var position = node.getVertexIn().offset(vector.reverse());
|
|
|
|
+ this.expander.setTranslate(position);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ expand: ExpandCommand,
|
|
|
|
+ expandtolevel: ExpandToLevelCommand,
|
|
|
|
+ collapse: CollapseCommand
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ layoutapply: function(e) {
|
|
|
|
+ var r = e.node.getRenderer("ExpanderRenderer");
|
|
|
|
+ if (r.getRenderShape()) {
|
|
|
|
+ r.update(r.getRenderShape(), e.node);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ beforerender: function(e) {
|
|
|
|
+ var node = e.node;
|
|
|
|
+ var visible = !node.parent || node.parent.isExpanded();
|
|
|
|
+ var minder = this;
|
|
|
|
+ node.getRenderContainer().setVisible(visible);
|
|
|
|
+ if (!visible) e.stopPropagation();
|
|
|
|
+ },
|
|
|
|
+ "normal.keydown": function(e) {
|
|
|
|
+ if (this.getStatus() == "textedit") return;
|
|
|
|
+ if (e.originEvent.keyCode == keymap["/"]) {
|
|
|
|
+ var node = this.getSelectedNode();
|
|
|
|
+ if (!node || node == this.getRoot()) return;
|
|
|
|
+ var expanded = node.isExpanded();
|
|
|
|
+ this.getSelectedNodes().forEach(function(node) {
|
|
|
|
+ if (expanded) node.collapse(); else node.expand();
|
|
|
|
+ node.renderTree();
|
|
|
|
+ });
|
|
|
|
+ this.layout(100);
|
|
|
|
+ this.fire("contentchange");
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ e.stopPropagationImmediately();
|
|
|
|
+ }
|
|
|
|
+ if (e.isShortcutKey("Alt+`")) {
|
|
|
|
+ this.execCommand("expandtolevel", 9999);
|
|
|
|
+ }
|
|
|
|
+ for (var i = 1; i < 6; i++) {
|
|
|
|
+ if (e.isShortcutKey("Alt+" + i)) {
|
|
|
|
+ this.execCommand("expandtolevel", i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ outside: ExpanderRenderer
|
|
|
|
+ },
|
|
|
|
+ contextmenu: [ {
|
|
|
|
+ command: "expandtoleaf",
|
|
|
|
+ query: function() {
|
|
|
|
+ return !minder.getSelectedNode();
|
|
|
|
+ },
|
|
|
|
+ fn: function(minder) {
|
|
|
|
+ minder.execCommand("expandtolevel", 9999);
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ command: "expandtolevel1",
|
|
|
|
+ query: function() {
|
|
|
|
+ return !minder.getSelectedNode();
|
|
|
|
+ },
|
|
|
|
+ fn: function(minder) {
|
|
|
|
+ minder.execCommand("expandtolevel", 1);
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ command: "expandtolevel2",
|
|
|
|
+ query: function() {
|
|
|
|
+ return !minder.getSelectedNode();
|
|
|
|
+ },
|
|
|
|
+ fn: function(minder) {
|
|
|
|
+ minder.execCommand("expandtolevel", 2);
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ command: "expandtolevel3",
|
|
|
|
+ query: function() {
|
|
|
|
+ return !minder.getSelectedNode();
|
|
|
|
+ },
|
|
|
|
+ fn: function(minder) {
|
|
|
|
+ minder.execCommand("expandtolevel", 3);
|
|
|
|
+ }
|
|
|
|
+ }, {
|
|
|
|
+ divider: true
|
|
|
|
+ } ]
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/font.js
|
|
|
|
+_p[47] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var TextRenderer = _p.r(61);
|
|
|
|
+ function getNodeDataOrStyle(node, name) {
|
|
|
|
+ return node.getData(name) || node.getStyle(name);
|
|
|
|
+ }
|
|
|
|
+ TextRenderer.registerStyleHook(function(node, textGroup) {
|
|
|
|
+ var dataColor = node.getData("color");
|
|
|
|
+ var selectedColor = node.getStyle("selected-color");
|
|
|
|
+ var styleColor = node.getStyle("color");
|
|
|
|
+ var foreColor = dataColor || (node.isSelected() && selectedColor ? selectedColor : styleColor);
|
|
|
|
+ var fontFamily = getNodeDataOrStyle(node, "font-family");
|
|
|
|
+ var fontSize = getNodeDataOrStyle(node, "font-size");
|
|
|
|
+ textGroup.fill(foreColor);
|
|
|
|
+ textGroup.eachItem(function(index, item) {
|
|
|
|
+ item.setFont({
|
|
|
|
+ family: fontFamily,
|
|
|
|
+ size: fontSize
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ Module.register("fontmodule", {
|
|
|
|
+ commands: {
|
|
|
|
+ /**
|
|
|
|
+ * @command ForeColor
|
|
|
|
+ * @description 设置选中节点的字体颜色
|
|
|
|
+ * @param {string} color 表示颜色的字符串
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 如果只有一个节点选中,返回已选中节点的字体颜色;否则返回 'mixed'。
|
|
|
|
+ */
|
|
|
|
+ forecolor: kity.createClass("fontcolorCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, color) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("color", color);
|
|
|
|
+ n.render();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length === 0 ? -1 : 0;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ if (km.getSelectedNodes().length == 1) {
|
|
|
|
+ return km.getSelectedNodes()[0].getData("color");
|
|
|
|
+ }
|
|
|
|
+ return "mixed";
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command Background
|
|
|
|
+ * @description 设置选中节点的背景颜色
|
|
|
|
+ * @param {string} color 表示颜色的字符串
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 如果只有一个节点选中,返回已选中节点的背景颜色;否则返回 'mixed'。
|
|
|
|
+ */
|
|
|
|
+ background: kity.createClass("backgroudCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, color) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("background", color);
|
|
|
|
+ n.render();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length === 0 ? -1 : 0;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ if (km.getSelectedNodes().length == 1) {
|
|
|
|
+ return km.getSelectedNodes()[0].getData("background");
|
|
|
|
+ }
|
|
|
|
+ return "mixed";
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command FontFamily
|
|
|
|
+ * @description 设置选中节点的字体
|
|
|
|
+ * @param {string} family 表示字体的字符串
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 返回首个选中节点的字体
|
|
|
|
+ */
|
|
|
|
+ fontfamily: kity.createClass("fontfamilyCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, family) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-family", family);
|
|
|
|
+ n.render();
|
|
|
|
+ km.layout();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length === 0 ? -1 : 0;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ if (node) return node.getData("font-family");
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command FontSize
|
|
|
|
+ * @description 设置选中节点的字体大小
|
|
|
|
+ * @param {number} size 字体大小(px)
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 返回首个选中节点的字体大小
|
|
|
|
+ */
|
|
|
|
+ fontsize: kity.createClass("fontsizeCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, size) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("font-size", size);
|
|
|
|
+ n.render();
|
|
|
|
+ km.layout(300);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length === 0 ? -1 : 0;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ if (node) return node.getData("font-size");
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/hyperlink.js
|
|
|
|
+_p[48] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ // jscs:disable maximumLineLength
|
|
|
|
+ var linkShapePath = "M16.614,10.224h-1.278c-1.668,0-3.07-1.07-3.599-2.556h4.877c0.707,0,1.278-0.571,1.278-1.278V3.834 c0-0.707-0.571-1.278-1.278-1.278h-4.877C12.266,1.071,13.668,0,15.336,0h1.278c2.116,0,3.834,1.716,3.834,3.834V6.39 C20.448,8.508,18.73,10.224,16.614,10.224z M5.112,5.112c0-0.707,0.573-1.278,1.278-1.278h7.668c0.707,0,1.278,0.571,1.278,1.278 S14.765,6.39,14.058,6.39H6.39C5.685,6.39,5.112,5.819,5.112,5.112z M2.556,3.834V6.39c0,0.707,0.573,1.278,1.278,1.278h4.877 c-0.528,1.486-1.932,2.556-3.599,2.556H3.834C1.716,10.224,0,8.508,0,6.39V3.834C0,1.716,1.716,0,3.834,0h1.278 c1.667,0,3.071,1.071,3.599,2.556H3.834C3.129,2.556,2.556,3.127,2.556,3.834z";
|
|
|
|
+ Module.register("hyperlink", {
|
|
|
|
+ commands: {
|
|
|
|
+ /**
|
|
|
|
+ * @command HyperLink
|
|
|
|
+ * @description 为选中的节点添加超链接
|
|
|
|
+ * @param {string} url 超链接的 URL,设置为 null 移除
|
|
|
|
+ * @param {string} title 超链接的说明
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 返回首个选中节点的超链接信息,JSON 对象: `{url: url, title: title}`
|
|
|
|
+ */
|
|
|
|
+ hyperlink: kity.createClass("hyperlink", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, url, title) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ n.setData("hyperlink", url);
|
|
|
|
+ n.setData("hyperlinkTitle", url && title);
|
|
|
|
+ n.render();
|
|
|
|
+ });
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes(), result = 0;
|
|
|
|
+ if (nodes.length === 0) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ if (n && n.getData("hyperlink")) {
|
|
|
|
+ result = 0;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return result;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ return {
|
|
|
|
+ url: node.getData("hyperlink"),
|
|
|
|
+ title: node.getData("hyperlinkTitle")
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ right: kity.createClass("hyperlinkrender", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function() {
|
|
|
|
+ var link = new kity.HyperLink();
|
|
|
|
+ var linkshape = new kity.Path();
|
|
|
|
+ var outline = new kity.Rect(24, 22, -2, -6, 4).fill("rgba(255, 255, 255, 0)");
|
|
|
|
+ linkshape.setPathData(linkShapePath).fill("#666");
|
|
|
|
+ link.addShape(outline);
|
|
|
|
+ link.addShape(linkshape);
|
|
|
|
+ link.setTarget("_blank");
|
|
|
|
+ link.setStyle("cursor", "pointer");
|
|
|
|
+ link.on("mouseover", function() {
|
|
|
|
+ outline.fill("rgba(255, 255, 200, .8)");
|
|
|
|
+ }).on("mouseout", function() {
|
|
|
|
+ outline.fill("rgba(255, 255, 255, 0)");
|
|
|
|
+ });
|
|
|
|
+ return link;
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData("hyperlink");
|
|
|
|
+ },
|
|
|
|
+ update: function(link, node, box) {
|
|
|
|
+ var href = node.getData("hyperlink");
|
|
|
|
+ link.setHref("#");
|
|
|
|
+ var allowed = [ "^http:", "^https:", "^ftp:", "^mailto:" ];
|
|
|
|
+ for (var i = 0; i < allowed.length; i++) {
|
|
|
|
+ var regex = new RegExp(allowed[i]);
|
|
|
|
+ if (regex.test(href)) {
|
|
|
|
+ link.setHref(href);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var title = node.getData("hyperlinkTitle");
|
|
|
|
+ if (title) {
|
|
|
|
+ title = [ title, "(", href, ")" ].join("");
|
|
|
|
+ } else {
|
|
|
|
+ title = href;
|
|
|
|
+ }
|
|
|
|
+ link.node.setAttributeNS("http://www.w3.org/1999/xlink", "title", title);
|
|
|
|
+ var spaceRight = node.getStyle("space-right");
|
|
|
|
+ link.setTranslate(box.right + spaceRight + 2, -5);
|
|
|
|
+ return new kity.Box({
|
|
|
|
+ x: box.right + spaceRight,
|
|
|
|
+ y: -11,
|
|
|
|
+ width: 24,
|
|
|
|
+ height: 22
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/image-viewer.js
|
|
|
|
+_p[49] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var keymap = _p.r(15);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ Module.register("ImageViewer", function() {
|
|
|
|
+ function createEl(name, classNames, children) {
|
|
|
|
+ var el = document.createElement(name);
|
|
|
|
+ addClass(el, classNames);
|
|
|
|
+ children && children.length && children.forEach(function(child) {
|
|
|
|
+ el.appendChild(child);
|
|
|
|
+ });
|
|
|
|
+ return el;
|
|
|
|
+ }
|
|
|
|
+ function on(el, event, handler) {
|
|
|
|
+ el.addEventListener(event, handler);
|
|
|
|
+ }
|
|
|
|
+ function addClass(el, classNames) {
|
|
|
|
+ classNames && classNames.split(" ").forEach(function(className) {
|
|
|
|
+ el.classList.add(className);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ function removeClass(el, classNames) {
|
|
|
|
+ classNames && classNames.split(" ").forEach(function(className) {
|
|
|
|
+ el.classList.remove(className);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ var ImageViewer = kity.createClass("ImageViewer", {
|
|
|
|
+ constructor: function() {
|
|
|
|
+ var btnClose = createEl("button", "km-image-viewer-btn km-image-viewer-close");
|
|
|
|
+ var btnSource = createEl("button", "km-image-viewer-btn km-image-viewer-source");
|
|
|
|
+ var image = this.image = createEl("img");
|
|
|
|
+ var toolbar = this.toolbar = createEl("div", "km-image-viewer-toolbar", [ btnSource, btnClose ]);
|
|
|
|
+ var container = createEl("div", "km-image-viewer-container", [ image ]);
|
|
|
|
+ var viewer = this.viewer = createEl("div", "km-image-viewer", [ toolbar, container ]);
|
|
|
|
+ this.hotkeyHandler = this.hotkeyHandler.bind(this);
|
|
|
|
+ on(btnClose, "click", this.close.bind(this));
|
|
|
|
+ on(btnSource, "click", this.viewSource.bind(this));
|
|
|
|
+ on(image, "click", this.zoomImage.bind(this));
|
|
|
|
+ on(viewer, "contextmenu", this.toggleToolbar.bind(this));
|
|
|
|
+ on(document, "keydown", this.hotkeyHandler);
|
|
|
|
+ },
|
|
|
|
+ dispose: function() {
|
|
|
|
+ this.close();
|
|
|
|
+ document.removeEventListener("remove", this.hotkeyHandler);
|
|
|
|
+ },
|
|
|
|
+ hotkeyHandler: function(e) {
|
|
|
|
+ if (!this.actived) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (e.keyCode === keymap["esc"]) {
|
|
|
|
+ this.close();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ toggleToolbar: function(e) {
|
|
|
|
+ e && e.preventDefault();
|
|
|
|
+ this.toolbar.classList.toggle("hidden");
|
|
|
|
+ },
|
|
|
|
+ zoomImage: function(restore) {
|
|
|
|
+ var image = this.image;
|
|
|
|
+ if (typeof restore === "boolean") {
|
|
|
|
+ restore && addClass(image, "limited");
|
|
|
|
+ } else {
|
|
|
|
+ image.classList.toggle("limited");
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ viewSource: function(src) {
|
|
|
|
+ window.open(this.image.src);
|
|
|
|
+ },
|
|
|
|
+ open: function(src) {
|
|
|
|
+ var input = document.querySelector("input");
|
|
|
|
+ if (input) {
|
|
|
|
+ input.focus();
|
|
|
|
+ input.blur();
|
|
|
|
+ }
|
|
|
|
+ this.image.src = src;
|
|
|
|
+ this.zoomImage(true);
|
|
|
|
+ document.body.appendChild(this.viewer);
|
|
|
|
+ this.actived = true;
|
|
|
|
+ },
|
|
|
|
+ close: function() {
|
|
|
|
+ this.image.src = "";
|
|
|
|
+ document.body.removeChild(this.viewer);
|
|
|
|
+ this.actived = false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ init: function() {
|
|
|
|
+ this.viewer = new ImageViewer();
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ "normal.dblclick": function(e) {
|
|
|
|
+ var shape = e.kityEvent.targetShape;
|
|
|
|
+ if (shape.__KityClassName === "Image" && shape.url) {
|
|
|
|
+ this.viewer.open(shape.url);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/image.js
|
|
|
|
+_p[50] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("image", function() {
|
|
|
|
+ function loadImageSize(url, callback) {
|
|
|
|
+ var img = document.createElement("img");
|
|
|
|
+ img.onload = function() {
|
|
|
|
+ callback(img.width, img.height);
|
|
|
|
+ };
|
|
|
|
+ img.onerror = function() {
|
|
|
|
+ callback(null);
|
|
|
|
+ };
|
|
|
|
+ img.src = url;
|
|
|
|
+ }
|
|
|
|
+ function fitImageSize(width, height, maxWidth, maxHeight) {
|
|
|
|
+ var ratio = width / height, fitRatio = maxWidth / maxHeight;
|
|
|
|
+ // 宽高比大于最大尺寸的宽高比,以宽度为标准适应
|
|
|
|
+ if (width > maxWidth && ratio > fitRatio) {
|
|
|
|
+ width = maxWidth;
|
|
|
|
+ height = width / ratio;
|
|
|
|
+ } else if (height > maxHeight) {
|
|
|
|
+ height = maxHeight;
|
|
|
|
+ width = height * ratio;
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ width: width | 0,
|
|
|
|
+ height: height | 0
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @command Image
|
|
|
|
+ * @description 为选中的节点添加图片
|
|
|
|
+ * @param {string} url 图片的 URL,设置为 null 移除
|
|
|
|
+ * @param {string} title 图片的说明
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 返回首个选中节点的图片信息,JSON 对象: `{url: url, title: title}`
|
|
|
|
+ */
|
|
|
|
+ var ImageCommand = kity.createClass("ImageCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, url, title) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ loadImageSize(url, function(width, height) {
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ var size = fitImageSize(width, height, km.getOption("maxImageWidth"), km.getOption("maxImageHeight"));
|
|
|
|
+ n.setData("image", url);
|
|
|
|
+ n.setData("imageTitle", url && title);
|
|
|
|
+ n.setData("imageSize", url && size);
|
|
|
|
+ n.render();
|
|
|
|
+ });
|
|
|
|
+ km.fire("saveScene");
|
|
|
|
+ km.layout(300);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes(), result = 0;
|
|
|
|
+ if (nodes.length === 0) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ nodes.forEach(function(n) {
|
|
|
|
+ if (n && n.getData("image")) {
|
|
|
|
+ result = 0;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return result;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var node = km.getSelectedNode();
|
|
|
|
+ return {
|
|
|
|
+ url: node.getData("image"),
|
|
|
|
+ title: node.getData("imageTitle")
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var ImageRenderer = kity.createClass("ImageRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ return new kity.Image(node.getData("image"));
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData("image");
|
|
|
|
+ },
|
|
|
|
+ update: function(image, node, box) {
|
|
|
|
+ var url = node.getData("image");
|
|
|
|
+ var title = node.getData("imageTitle");
|
|
|
|
+ var size = node.getData("imageSize");
|
|
|
|
+ var spaceTop = node.getStyle("space-top");
|
|
|
|
+ if (!size) return;
|
|
|
|
+ if (title) {
|
|
|
|
+ image.node.setAttributeNS("http://www.w3.org/1999/xlink", "title", title);
|
|
|
|
+ }
|
|
|
|
+ var x = box.cx - size.width / 2;
|
|
|
|
+ var y = box.y - size.height - spaceTop;
|
|
|
|
+ image.setUrl(url).setX(x | 0).setY(y | 0).setWidth(size.width | 0).setHeight(size.height | 0);
|
|
|
|
+ return new kity.Box(x | 0, y | 0, size.width | 0, size.height | 0);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ defaultOptions: {
|
|
|
|
+ maxImageWidth: 200,
|
|
|
|
+ maxImageHeight: 200
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ image: ImageCommand
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ top: ImageRenderer
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/keynav.js
|
|
|
|
+_p[51] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var keymap = _p.r(15);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("KeyboardModule", function() {
|
|
|
|
+ var min = Math.min, max = Math.max, abs = Math.abs, sqrt = Math.sqrt, exp = Math.exp;
|
|
|
|
+ function buildPositionNetwork(root) {
|
|
|
|
+ var pointIndexes = [], p;
|
|
|
|
+ root.traverse(function(node) {
|
|
|
|
+ p = node.getLayoutBox();
|
|
|
|
+ // bugfix: 不应导航到收起的节点(判断其尺寸是否存在)
|
|
|
|
+ if (p.width && p.height) {
|
|
|
|
+ pointIndexes.push({
|
|
|
|
+ left: p.x,
|
|
|
|
+ top: p.y,
|
|
|
|
+ right: p.x + p.width,
|
|
|
|
+ bottom: p.y + p.height,
|
|
|
|
+ width: p.width,
|
|
|
|
+ height: p.height,
|
|
|
|
+ node: node
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ for (var i = 0; i < pointIndexes.length; i++) {
|
|
|
|
+ findClosestPointsFor(pointIndexes, i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 这是金泉的点子,赞!
|
|
|
|
+ // 求两个不相交矩形的最近距离
|
|
|
|
+ function getCoefedDistance(box1, box2) {
|
|
|
|
+ var xMin, xMax, yMin, yMax, xDist, yDist, dist, cx, cy;
|
|
|
|
+ xMin = min(box1.left, box2.left);
|
|
|
|
+ xMax = max(box1.right, box2.right);
|
|
|
|
+ yMin = min(box1.top, box2.top);
|
|
|
|
+ yMax = max(box1.bottom, box2.bottom);
|
|
|
|
+ xDist = xMax - xMin - box1.width - box2.width;
|
|
|
|
+ yDist = yMax - yMin - box1.height - box2.height;
|
|
|
|
+ if (xDist < 0) dist = yDist; else if (yDist < 0) dist = xDist; else dist = sqrt(xDist * xDist + yDist * yDist);
|
|
|
|
+ var node1 = box1.node;
|
|
|
|
+ var node2 = box2.node;
|
|
|
|
+ // sibling
|
|
|
|
+ if (node1.parent == node2.parent) {
|
|
|
|
+ dist /= 10;
|
|
|
|
+ }
|
|
|
|
+ // parent
|
|
|
|
+ if (node2.parent == node1) {
|
|
|
|
+ dist /= 5;
|
|
|
|
+ }
|
|
|
|
+ return dist;
|
|
|
|
+ }
|
|
|
|
+ function findClosestPointsFor(pointIndexes, iFind) {
|
|
|
|
+ var find = pointIndexes[iFind];
|
|
|
|
+ var most = {}, quad;
|
|
|
|
+ var current, dist;
|
|
|
|
+ for (var i = 0; i < pointIndexes.length; i++) {
|
|
|
|
+ if (i == iFind) continue;
|
|
|
|
+ current = pointIndexes[i];
|
|
|
|
+ dist = getCoefedDistance(current, find);
|
|
|
|
+ // left check
|
|
|
|
+ if (current.right < find.left) {
|
|
|
|
+ if (!most.left || dist < most.left.dist) {
|
|
|
|
+ most.left = {
|
|
|
|
+ dist: dist,
|
|
|
|
+ node: current.node
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // right check
|
|
|
|
+ if (current.left > find.right) {
|
|
|
|
+ if (!most.right || dist < most.right.dist) {
|
|
|
|
+ most.right = {
|
|
|
|
+ dist: dist,
|
|
|
|
+ node: current.node
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // top check
|
|
|
|
+ if (current.bottom < find.top) {
|
|
|
|
+ if (!most.top || dist < most.top.dist) {
|
|
|
|
+ most.top = {
|
|
|
|
+ dist: dist,
|
|
|
|
+ node: current.node
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // bottom check
|
|
|
|
+ if (current.top > find.bottom) {
|
|
|
|
+ if (!most.down || dist < most.down.dist) {
|
|
|
|
+ most.down = {
|
|
|
|
+ dist: dist,
|
|
|
|
+ node: current.node
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ find.node._nearestNodes = {
|
|
|
|
+ right: most.right && most.right.node || null,
|
|
|
|
+ top: most.top && most.top.node || null,
|
|
|
|
+ left: most.left && most.left.node || null,
|
|
|
|
+ down: most.down && most.down.node || null
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function navigateTo(km, direction) {
|
|
|
|
+ var referNode = km.getSelectedNode();
|
|
|
|
+ if (!referNode) {
|
|
|
|
+ km.select(km.getRoot());
|
|
|
|
+ buildPositionNetwork(km.getRoot());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!referNode._nearestNodes) {
|
|
|
|
+ buildPositionNetwork(km.getRoot());
|
|
|
|
+ }
|
|
|
|
+ var nextNode = referNode._nearestNodes[direction];
|
|
|
|
+ if (nextNode) {
|
|
|
|
+ km.select(nextNode, true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 稀释用
|
|
|
|
+ var lastFrame;
|
|
|
|
+ return {
|
|
|
|
+ events: {
|
|
|
|
+ layoutallfinish: function() {
|
|
|
|
+ var root = this.getRoot();
|
|
|
|
+ buildPositionNetwork(root);
|
|
|
|
+ },
|
|
|
|
+ "normal.keydown readonly.keydown": function(e) {
|
|
|
|
+ var minder = this;
|
|
|
|
+ [ "left", "right", "up", "down" ].forEach(function(key) {
|
|
|
|
+ if (e.isShortcutKey(key)) {
|
|
|
|
+ navigateTo(minder, key == "up" ? "top" : key);
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/layout.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 布局模块
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[52] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ /**
|
|
|
|
+ * @command Layout
|
|
|
|
+ * @description 设置选中节点的布局
|
|
|
|
+ * 允许使用的布局可以使用 `kityminder.Minder.getLayoutList()` 查询
|
|
|
|
+ * @param {string} name 布局的名称,设置为 null 则使用继承或默认的布局
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ * @return 返回首个选中节点的布局名称
|
|
|
|
+ */
|
|
|
|
+ var LayoutCommand = kity.createClass("LayoutCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, name) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ node.layout(name);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ if (node) {
|
|
|
|
+ return node.getData("layout");
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return minder.getSelectedNode() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command ResetLayout
|
|
|
|
+ * @description 重设选中节点的布局,如果当前没有选中的节点,重设整个脑图的布局
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ * @return 返回首个选中节点的布局名称
|
|
|
|
+ */
|
|
|
|
+ var ResetLayoutCommand = kity.createClass("ResetLayoutCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ if (!nodes.length) nodes = [ minder.getRoot() ];
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ node.traverse(function(child) {
|
|
|
|
+ child.resetLayoutOffset();
|
|
|
|
+ if (!child.isRoot()) {
|
|
|
|
+ child.setData("layout", null);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ minder.layout(300);
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ Module.register("LayoutModule", {
|
|
|
|
+ commands: {
|
|
|
|
+ layout: LayoutCommand,
|
|
|
|
+ resetlayout: ResetLayoutCommand
|
|
|
|
+ },
|
|
|
|
+ contextmenu: [ {
|
|
|
|
+ command: "resetlayout"
|
|
|
|
+ }, {
|
|
|
|
+ divider: true
|
|
|
|
+ } ],
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ resetlayout: "Ctrl+Shift+L"
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/node.js
|
|
|
|
+_p[53] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ /**
|
|
|
|
+ * @command AppendChildNode
|
|
|
|
+ * @description 添加子节点到选中的节点中
|
|
|
|
+ * @param {string|object} textOrData 要插入的节点的文本或数据
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var AppendChildCommand = kity.createClass("AppendChildCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, text) {
|
|
|
|
+ var parent = km.getSelectedNode();
|
|
|
|
+ if (!parent) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ var node = km.createNode(text, parent);
|
|
|
|
+ km.select(node, true);
|
|
|
|
+ if (parent.isExpanded()) {
|
|
|
|
+ node.render();
|
|
|
|
+ } else {
|
|
|
|
+ parent.expand();
|
|
|
|
+ parent.renderTree();
|
|
|
|
+ }
|
|
|
|
+ km.layout(600);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selectedNode = km.getSelectedNode();
|
|
|
|
+ return selectedNode ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command AppendSiblingNode
|
|
|
|
+ * @description 添加选中的节点的兄弟节点
|
|
|
|
+ * @param {string|object} textOrData 要添加的节点的文本或数据
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var AppendSiblingCommand = kity.createClass("AppendSiblingCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, text) {
|
|
|
|
+ var sibling = km.getSelectedNode();
|
|
|
|
+ var parent = sibling.parent;
|
|
|
|
+ if (!parent) {
|
|
|
|
+ return km.execCommand("AppendChildNode", text);
|
|
|
|
+ }
|
|
|
|
+ var node = km.createNode(text, parent, sibling.getIndex() + 1);
|
|
|
|
+ node.setGlobalLayoutTransform(sibling.getGlobalLayoutTransform());
|
|
|
|
+ km.select(node, true);
|
|
|
|
+ node.render();
|
|
|
|
+ km.layout(600);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selectedNode = km.getSelectedNode();
|
|
|
|
+ return selectedNode ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command RemoveNode
|
|
|
|
+ * @description 移除选中的节点
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var RemoveNodeCommand = kity.createClass("RemoverNodeCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ var ancestor = MinderNode.getCommonAncestor.apply(null, nodes);
|
|
|
|
+ var index = nodes[0].getIndex();
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ if (!node.isRoot()) km.removeNode(node);
|
|
|
|
+ });
|
|
|
|
+ if (nodes.length == 1) {
|
|
|
|
+ var selectBack = ancestor.children[index - 1] || ancestor.children[index];
|
|
|
|
+ km.select(selectBack || ancestor || km.getRoot(), true);
|
|
|
|
+ } else {
|
|
|
|
+ km.select(ancestor || km.getRoot(), true);
|
|
|
|
+ }
|
|
|
|
+ km.layout(600);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var selectedNode = km.getSelectedNode();
|
|
|
|
+ return selectedNode && !selectedNode.isRoot() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var AppendParentCommand = kity.createClass("AppendParentCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, text) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ nodes.sort(function(a, b) {
|
|
|
|
+ return a.getIndex() - b.getIndex();
|
|
|
|
+ });
|
|
|
|
+ var parent = nodes[0].parent;
|
|
|
|
+ var newParent = km.createNode(text, parent, nodes[0].getIndex());
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ newParent.appendChild(node);
|
|
|
|
+ });
|
|
|
|
+ newParent.setGlobalLayoutTransform(nodes[nodes.length >> 1].getGlobalLayoutTransform());
|
|
|
|
+ km.select(newParent, true);
|
|
|
|
+ km.layout(600);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ if (!nodes.length) return -1;
|
|
|
|
+ var parent = nodes[0].parent;
|
|
|
|
+ if (!parent) return -1;
|
|
|
|
+ for (var i = 1; i < nodes.length; i++) {
|
|
|
|
+ if (nodes[i].parent != parent) return -1;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("NodeModule", function() {
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ AppendChildNode: AppendChildCommand,
|
|
|
|
+ AppendSiblingNode: AppendSiblingCommand,
|
|
|
|
+ RemoveNode: RemoveNodeCommand,
|
|
|
|
+ AppendParentNode: AppendParentCommand
|
|
|
|
+ },
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ appendsiblingnode: "normal::Enter",
|
|
|
|
+ appendchildnode: "normal::Insert|Tab",
|
|
|
|
+ appendparentnode: "normal::Shift+Tab|normal::Shift+Insert",
|
|
|
|
+ removenode: "normal::Del|Backspace"
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/note.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 支持节点详细信息(HTML)格式
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[54] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("NoteModule", function() {
|
|
|
|
+ var NOTE_PATH = "M9,9H3V8h6L9,9L9,9z M9,7H3V6h6V7z M9,5H3V4h6V5z M8.5,11H2V2h8v7.5 M9,12l2-2V1H1v11";
|
|
|
|
+ /**
|
|
|
|
+ * @command Note
|
|
|
|
+ * @description 设置节点的备注信息
|
|
|
|
+ * @param {string} note 要设置的备注信息,设置为 null 则移除备注信息
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var NoteCommand = kity.createClass("NoteCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, note) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ node.setData("note", note);
|
|
|
|
+ node.render();
|
|
|
|
+ node.getMinder().layout(300);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return minder.getSelectedNodes().length === 1 ? 0 : -1;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ return node && node.getData("note");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var NoteIcon = kity.createClass("NoteIcon", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.width = 16;
|
|
|
|
+ this.height = 17;
|
|
|
|
+ this.rect = new kity.Rect(16, 17, .5, -8.5, 2).fill("transparent");
|
|
|
|
+ this.path = new kity.Path().setPathData(NOTE_PATH).setTranslate(2.5, -6.5);
|
|
|
|
+ this.addShapes([ this.rect, this.path ]);
|
|
|
|
+ this.on("mouseover", function() {
|
|
|
|
+ this.rect.fill("rgba(255, 255, 200, .8)");
|
|
|
|
+ }).on("mouseout", function() {
|
|
|
|
+ this.rect.fill("transparent");
|
|
|
|
+ });
|
|
|
|
+ this.setStyle("cursor", "pointer");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var NoteIconRenderer = kity.createClass("NoteIconRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ var icon = new NoteIcon();
|
|
|
|
+ icon.on("mousedown", function(e) {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ node.getMinder().fire("editnoterequest");
|
|
|
|
+ });
|
|
|
|
+ icon.on("mouseover", function() {
|
|
|
|
+ node.getMinder().fire("shownoterequest", {
|
|
|
|
+ node: node,
|
|
|
|
+ icon: icon
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ icon.on("mouseout", function() {
|
|
|
|
+ node.getMinder().fire("hidenoterequest", {
|
|
|
|
+ node: node,
|
|
|
|
+ icon: icon
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ return icon;
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData("note");
|
|
|
|
+ },
|
|
|
|
+ update: function(icon, node, box) {
|
|
|
|
+ var x = box.right + node.getStyle("space-left");
|
|
|
|
+ var y = box.cy;
|
|
|
|
+ icon.path.fill(node.getStyle("color"));
|
|
|
|
+ icon.setTranslate(x, y);
|
|
|
|
+ return new kity.Box(x, Math.round(y - icon.height / 2), icon.width, icon.height);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ renderers: {
|
|
|
|
+ right: NoteIconRenderer
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ note: NoteCommand
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/outline.js
|
|
|
|
+_p[55] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ var OutlineRenderer = kity.createClass("OutlineRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ var outline = new kity.Rect().setId(utils.uuid("node_outline"));
|
|
|
|
+ this.bringToBack = true;
|
|
|
|
+ return outline;
|
|
|
|
+ },
|
|
|
|
+ update: function(outline, node, box) {
|
|
|
|
+ var shape = node.getStyle("shape");
|
|
|
|
+ var paddingLeft = node.getStyle("padding-left"), paddingRight = node.getStyle("padding-right"), paddingTop = node.getStyle("padding-top"), paddingBottom = node.getStyle("padding-bottom");
|
|
|
|
+ var outlineBox = {
|
|
|
|
+ x: box.x - paddingLeft,
|
|
|
|
+ y: box.y - paddingTop,
|
|
|
|
+ width: box.width + paddingLeft + paddingRight,
|
|
|
|
+ height: box.height + paddingTop + paddingBottom
|
|
|
|
+ };
|
|
|
|
+ var radius = node.getStyle("radius");
|
|
|
|
+ // 天盘图圆形的情况
|
|
|
|
+ if (shape && shape == "circle") {
|
|
|
|
+ var p = Math.pow;
|
|
|
|
+ var r = Math.round;
|
|
|
|
+ radius = r(Math.sqrt(p(outlineBox.width, 2) + p(outlineBox.height, 2)) / 2);
|
|
|
|
+ outlineBox.x = box.cx - radius;
|
|
|
|
+ outlineBox.y = box.cy - radius;
|
|
|
|
+ outlineBox.width = 2 * radius;
|
|
|
|
+ outlineBox.height = 2 * radius;
|
|
|
|
+ }
|
|
|
|
+ var prefix = node.isSelected() ? node.getMinder().isFocused() ? "selected-" : "blur-selected-" : "";
|
|
|
|
+ outline.setPosition(outlineBox.x, outlineBox.y).setSize(outlineBox.width, outlineBox.height).setRadius(radius).fill(node.getData("background") || node.getStyle(prefix + "background") || node.getStyle("background")).stroke(node.getStyle(prefix + "stroke" || node.getStyle("stroke")), node.getStyle(prefix + "stroke-width"));
|
|
|
|
+ return new kity.Box(outlineBox);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var ShadowRenderer = kity.createClass("ShadowRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ this.bringToBack = true;
|
|
|
|
+ return new kity.Rect();
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getStyle("shadow");
|
|
|
|
+ },
|
|
|
|
+ update: function(shadow, node, box) {
|
|
|
|
+ shadow.setPosition(box.x + 4, box.y + 5).fill(node.getStyle("shadow"));
|
|
|
|
+ var shape = node.getStyle("shape");
|
|
|
|
+ if (!shape) {
|
|
|
|
+ shadow.setSize(box.width, box.height);
|
|
|
|
+ shadow.setRadius(node.getStyle("radius"));
|
|
|
|
+ } else if (shape == "circle") {
|
|
|
|
+ var width = Math.max(box.width, box.height);
|
|
|
|
+ shadow.setSize(width, width);
|
|
|
|
+ shadow.setRadius(width / 2);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var marker = new kity.Marker();
|
|
|
|
+ marker.setWidth(10);
|
|
|
|
+ marker.setHeight(12);
|
|
|
|
+ marker.setRef(0, 0);
|
|
|
|
+ marker.setViewBox(-6, -4, 8, 10);
|
|
|
|
+ marker.addShape(new kity.Path().setPathData("M-5-3l5,3,-5,3").stroke("#33ffff"));
|
|
|
|
+ var wireframeOption = /wire/.test(window.location.href);
|
|
|
|
+ var WireframeRenderer = kity.createClass("WireframeRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function() {
|
|
|
|
+ var wireframe = new kity.Group();
|
|
|
|
+ var oxy = this.oxy = new kity.Path().stroke("#f6f").setPathData("M0,-50L0,50M-50,0L50,0");
|
|
|
|
+ var box = this.wireframe = new kity.Rect().stroke("lightgreen");
|
|
|
|
+ var vectorIn = this.vectorIn = new kity.Path().stroke("#66ffff");
|
|
|
|
+ var vectorOut = this.vectorOut = new kity.Path().stroke("#66ffff");
|
|
|
|
+ vectorIn.setMarker(marker, "end");
|
|
|
|
+ vectorOut.setMarker(marker, "end");
|
|
|
|
+ return wireframe.addShapes([ oxy, box, vectorIn, vectorOut ]);
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function() {
|
|
|
|
+ return wireframeOption;
|
|
|
|
+ },
|
|
|
|
+ update: function(created, node, box) {
|
|
|
|
+ this.wireframe.setPosition(box.x, box.y).setSize(box.width, box.height);
|
|
|
|
+ var pin = node.getVertexIn();
|
|
|
|
+ var pout = node.getVertexOut();
|
|
|
|
+ var vin = node.getLayoutVectorIn().normalize(30);
|
|
|
|
+ var vout = node.getLayoutVectorOut().normalize(30);
|
|
|
|
+ this.vectorIn.setPathData([ "M", pin.offset(vin.reverse()), "L", pin ]);
|
|
|
|
+ this.vectorOut.setPathData([ "M", pout, "l", vout ]);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("OutlineModule", function() {
|
|
|
|
+ return {
|
|
|
|
+ events: !wireframeOption ? null : {
|
|
|
|
+ ready: function() {
|
|
|
|
+ this.getPaper().addResource(marker);
|
|
|
|
+ },
|
|
|
|
+ layoutallfinish: function() {
|
|
|
|
+ this.getRoot().traverse(function(node) {
|
|
|
|
+ node.getRenderer("WireframeRenderer").update(null, node, node.getContentBox());
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ outline: OutlineRenderer,
|
|
|
|
+ outside: [ ShadowRenderer, WireframeRenderer ]
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/priority.js
|
|
|
|
+_p[56] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("PriorityModule", function() {
|
|
|
|
+ var minder = this;
|
|
|
|
+ // Designed by Akikonata
|
|
|
|
+ // [MASK, BACK]
|
|
|
|
+ var PRIORITY_COLORS = [ null, [ "#FF1200", "#840023" ], // 1 - red
|
|
|
|
+ [ "#0074FF", "#01467F" ], // 2 - blue
|
|
|
|
+ [ "#00AF00", "#006300" ], // 3 - green
|
|
|
|
+ [ "#FF962E", "#B25000" ], // 4 - orange
|
|
|
|
+ [ "#A464FF", "#4720C4" ], // 5 - purple
|
|
|
|
+ [ "#A3A3A3", "#515151" ], // 6,7,8,9 - gray
|
|
|
|
+ [ "#A3A3A3", "#515151" ], [ "#A3A3A3", "#515151" ], [ "#A3A3A3", "#515151" ] ];
|
|
|
|
+ // hue from 1 to 5
|
|
|
|
+ // jscs:disable maximumLineLength
|
|
|
|
+ var BACK_PATH = "M0,13c0,3.866,3.134,7,7,7h6c3.866,0,7-3.134,7-7V7H0V13z";
|
|
|
|
+ var MASK_PATH = "M20,10c0,3.866-3.134,7-7,7H7c-3.866,0-7-3.134-7-7V7c0-3.866,3.134-7,7-7h6c3.866,0,7,3.134,7,7V10z";
|
|
|
|
+ var PRIORITY_DATA = "priority";
|
|
|
|
+ // 优先级图标的图形
|
|
|
|
+ var PriorityIcon = kity.createClass("PriorityIcon", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.setSize(20);
|
|
|
|
+ this.create();
|
|
|
|
+ this.setId(utils.uuid("node_priority"));
|
|
|
|
+ },
|
|
|
|
+ setSize: function(size) {
|
|
|
|
+ this.width = this.height = size;
|
|
|
|
+ },
|
|
|
|
+ create: function() {
|
|
|
|
+ var white, back, mask, number;
|
|
|
|
+ // 4 layer
|
|
|
|
+ white = new kity.Path().setPathData(MASK_PATH).fill("white");
|
|
|
|
+ back = new kity.Path().setPathData(BACK_PATH).setTranslate(.5, .5);
|
|
|
|
+ mask = new kity.Path().setPathData(MASK_PATH).setOpacity(.8).setTranslate(.5, .5);
|
|
|
|
+ number = new kity.Text().setX(this.width / 2 - .5).setY(this.height / 2).setTextAnchor("middle").setVerticalAlign("middle").setFontItalic(true).setFontSize(12).fill("white");
|
|
|
|
+ this.addShapes([ back, mask, number ]);
|
|
|
|
+ this.mask = mask;
|
|
|
|
+ this.back = back;
|
|
|
|
+ this.number = number;
|
|
|
|
+ },
|
|
|
|
+ setValue: function(value) {
|
|
|
|
+ var back = this.back, mask = this.mask, number = this.number;
|
|
|
|
+ var color = PRIORITY_COLORS[value];
|
|
|
|
+ if (color) {
|
|
|
|
+ back.fill(color[1]);
|
|
|
|
+ mask.fill(color[0]);
|
|
|
|
+ }
|
|
|
|
+ number.setContent(value);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Priority
|
|
|
|
+ * @description 设置节点的优先级信息
|
|
|
|
+ * @param {number} value 要设置的优先级(添加一个优先级小图标)
|
|
|
|
+ * 取值为 0 移除优先级信息;
|
|
|
|
+ * 取值为 1 - 9 设置优先级,超过 9 的优先级不渲染
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var PriorityCommand = kity.createClass("SetPriorityCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, value) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ nodes[i].setData(PRIORITY_DATA, value || null).render();
|
|
|
|
+ }
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ var val;
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ val = nodes[i].getData(PRIORITY_DATA);
|
|
|
|
+ if (val) break;
|
|
|
|
+ }
|
|
|
|
+ return val || null;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ priority: PriorityCommand
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ left: kity.createClass("PriorityRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ return new PriorityIcon();
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData(PRIORITY_DATA);
|
|
|
|
+ },
|
|
|
|
+ update: function(icon, node, box) {
|
|
|
|
+ var data = node.getData(PRIORITY_DATA);
|
|
|
|
+ var spaceLeft = node.getStyle("space-left"), x, y;
|
|
|
|
+ icon.setValue(data);
|
|
|
|
+ x = box.left - icon.width - spaceLeft;
|
|
|
|
+ y = -icon.height / 2;
|
|
|
|
+ icon.setTranslate(x, y);
|
|
|
|
+ return new kity.Box({
|
|
|
|
+ x: x,
|
|
|
|
+ y: y,
|
|
|
|
+ width: icon.width,
|
|
|
|
+ height: icon.height
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/progress.js
|
|
|
|
+_p[57] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("ProgressModule", function() {
|
|
|
|
+ var minder = this;
|
|
|
|
+ var PROGRESS_DATA = "progress";
|
|
|
|
+ // Designed by Akikonata
|
|
|
|
+ var BG_COLOR = "#FFED83";
|
|
|
|
+ var PIE_COLOR = "#43BC00";
|
|
|
|
+ var SHADOW_PATH = "M10,3c4.418,0,8,3.582,8,8h1c0-5.523-3.477-10-9-10S1,5.477,1,11h1C2,6.582,5.582,3,10,3z";
|
|
|
|
+ var SHADOW_COLOR = "#8E8E8E";
|
|
|
|
+ // jscs:disable maximumLineLength
|
|
|
|
+ var FRAME_PATH = "M10,0C4.477,0,0,4.477,0,10c0,5.523,4.477,10,10,10s10-4.477,10-10C20,4.477,15.523,0,10,0zM10,18c-4.418,0-8-3.582-8-8s3.582-8,8-8s8,3.582,8,8S14.418,18,10,18z";
|
|
|
|
+ var FRAME_GRAD = new kity.LinearGradient().pipe(function(g) {
|
|
|
|
+ g.setStartPosition(0, 0);
|
|
|
|
+ g.setEndPosition(0, 1);
|
|
|
|
+ g.addStop(0, "#fff");
|
|
|
|
+ g.addStop(1, "#ccc");
|
|
|
|
+ });
|
|
|
|
+ var CHECK_PATH = "M15.812,7.896l-6.75,6.75l-4.5-4.5L6.25,8.459l2.812,2.803l5.062-5.053L15.812,7.896z";
|
|
|
|
+ var CHECK_COLOR = "#EEE";
|
|
|
|
+ minder.getPaper().addResource(FRAME_GRAD);
|
|
|
|
+ // 进度图标的图形
|
|
|
|
+ var ProgressIcon = kity.createClass("ProgressIcon", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function(value) {
|
|
|
|
+ this.callBase();
|
|
|
|
+ this.setSize(20);
|
|
|
|
+ this.create();
|
|
|
|
+ this.setValue(value);
|
|
|
|
+ this.setId(utils.uuid("node_progress"));
|
|
|
|
+ this.translate(.5, .5);
|
|
|
|
+ },
|
|
|
|
+ setSize: function(size) {
|
|
|
|
+ this.width = this.height = size;
|
|
|
|
+ },
|
|
|
|
+ create: function() {
|
|
|
|
+ var bg, pie, shadow, frame, check;
|
|
|
|
+ bg = new kity.Circle(9).fill(BG_COLOR);
|
|
|
|
+ pie = new kity.Pie(9, 0).fill(PIE_COLOR);
|
|
|
|
+ shadow = new kity.Path().setPathData(SHADOW_PATH).setTranslate(-10, -10).fill(SHADOW_COLOR);
|
|
|
|
+ frame = new kity.Path().setTranslate(-10, -10).setPathData(FRAME_PATH).fill(FRAME_GRAD);
|
|
|
|
+ check = new kity.Path().setTranslate(-10, -10).setPathData(CHECK_PATH).fill(CHECK_COLOR);
|
|
|
|
+ this.addShapes([ bg, pie, shadow, check, frame ]);
|
|
|
|
+ this.pie = pie;
|
|
|
|
+ this.check = check;
|
|
|
|
+ },
|
|
|
|
+ setValue: function(value) {
|
|
|
|
+ this.pie.setAngle(-360 * (value - 1) / 8);
|
|
|
|
+ this.check.setVisible(value == 9);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Progress
|
|
|
|
+ * @description 设置节点的进度信息(添加一个进度小图标)
|
|
|
|
+ * @param {number} value 要设置的进度
|
|
|
|
+ * 取值为 0 移除进度信息;
|
|
|
|
+ * 取值为 1 表示未开始;
|
|
|
|
+ * 取值为 2 表示完成 1/8;
|
|
|
|
+ * 取值为 3 表示完成 2/8;
|
|
|
|
+ * 取值为 4 表示完成 3/8;
|
|
|
|
+ * 其余类推,取值为 9 表示全部完成
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ var ProgressCommand = kity.createClass("ProgressCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, value) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ nodes[i].setData(PROGRESS_DATA, value || null).render();
|
|
|
|
+ }
|
|
|
|
+ km.layout();
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(km) {
|
|
|
|
+ var nodes = km.getSelectedNodes();
|
|
|
|
+ var val;
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ val = nodes[i].getData(PROGRESS_DATA);
|
|
|
|
+ if (val) break;
|
|
|
|
+ }
|
|
|
|
+ return val || null;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNodes().length ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ progress: ProgressCommand
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ left: kity.createClass("ProgressRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ return new ProgressIcon();
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData(PROGRESS_DATA);
|
|
|
|
+ },
|
|
|
|
+ update: function(icon, node, box) {
|
|
|
|
+ var data = node.getData(PROGRESS_DATA);
|
|
|
|
+ var spaceLeft = node.getStyle("space-left");
|
|
|
|
+ var x, y;
|
|
|
|
+ icon.setValue(data);
|
|
|
|
+ x = box.left - icon.width - spaceLeft;
|
|
|
|
+ y = -icon.height / 2;
|
|
|
|
+ icon.setTranslate(x + icon.width / 2, y + icon.height / 2);
|
|
|
|
+ return new kity.Box(x, y, icon.width, icon.height);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/resource.js
|
|
|
|
+_p[58] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("Resource", function() {
|
|
|
|
+ // String Hash
|
|
|
|
+ // https://github.com/drostie/sha3-js/edit/master/blake32.min.js
|
|
|
|
+ var blake32 = function() {
|
|
|
|
+ var k, g, r, l, m, o, p, q, t, w, x;
|
|
|
|
+ x = 4 * (1 << 30);
|
|
|
|
+ k = [ 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225 ];
|
|
|
|
+ m = [ 608135816, 2242054355, 320440878, 57701188, 2752067618, 698298832, 137296536, 3964562569, 1160258022, 953160567, 3193202383, 887688300, 3232508343, 3380367581, 1065670069, 3041331479 ];
|
|
|
|
+ w = function(i) {
|
|
|
|
+ if (i < 0) {
|
|
|
|
+ i += x;
|
|
|
|
+ }
|
|
|
|
+ return ("00000000" + i.toString(16)).slice(-8);
|
|
|
|
+ };
|
|
|
|
+ o = [ [ 16, 50, 84, 118, 152, 186, 220, 254 ], [ 174, 132, 249, 109, 193, 32, 123, 53 ], [ 139, 12, 37, 223, 234, 99, 23, 73 ], [ 151, 19, 205, 235, 98, 165, 4, 143 ], [ 9, 117, 66, 250, 30, 203, 134, 211 ], [ 194, 166, 176, 56, 212, 87, 239, 145 ], [ 92, 241, 222, 164, 112, 54, 41, 184 ], [ 189, 231, 28, 147, 5, 79, 104, 162 ], [ 246, 158, 59, 128, 44, 125, 65, 90 ], [ 42, 72, 103, 81, 191, 233, 195, 13 ] ];
|
|
|
|
+ p = function(a, b, n) {
|
|
|
|
+ var s = q[a] ^ q[b];
|
|
|
|
+ q[a] = s >>> n | s << 32 - n;
|
|
|
|
+ };
|
|
|
|
+ g = function(i, a, b, c, d) {
|
|
|
|
+ var u = l + o[r][i] % 16, v = l + (o[r][i] >> 4);
|
|
|
|
+ a %= 4;
|
|
|
|
+ b = 4 + b % 4;
|
|
|
|
+ c = 8 + c % 4;
|
|
|
|
+ d = 12 + d % 4;
|
|
|
|
+ q[a] += q[b] + (t[u] ^ m[v % 16]);
|
|
|
|
+ p(d, a, 16);
|
|
|
|
+ q[c] += q[d];
|
|
|
|
+ p(b, c, 12);
|
|
|
|
+ q[a] += q[b] + (t[v] ^ m[u % 16]);
|
|
|
|
+ p(d, a, 8);
|
|
|
|
+ q[c] += q[d];
|
|
|
|
+ p(b, c, 7);
|
|
|
|
+ };
|
|
|
|
+ return function(a, b) {
|
|
|
|
+ if (!(b instanceof Array && b.length === 4)) {
|
|
|
|
+ b = [ 0, 0, 0, 0 ];
|
|
|
|
+ }
|
|
|
|
+ var c, d, e, L, f, h, j, i;
|
|
|
|
+ d = k.slice(0);
|
|
|
|
+ c = m.slice(0, 8);
|
|
|
|
+ for (r = 0; r < 4; r += 1) {
|
|
|
|
+ c[r] ^= b[r];
|
|
|
|
+ }
|
|
|
|
+ e = a.length * 16;
|
|
|
|
+ f = e % 512 > 446 || e % 512 === 0 ? 0 : e;
|
|
|
|
+ if (e % 512 === 432) {
|
|
|
|
+ a += "老";
|
|
|
|
+ } else {
|
|
|
|
+ a += "耀";
|
|
|
|
+ while (a.length % 32 !== 27) {
|
|
|
|
+ a += "\0";
|
|
|
|
+ }
|
|
|
|
+ a += "";
|
|
|
|
+ }
|
|
|
|
+ t = [];
|
|
|
|
+ for (i = 0; i < a.length; i += 2) {
|
|
|
|
+ t.push(a.charCodeAt(i) * 65536 + a.charCodeAt(i + 1));
|
|
|
|
+ }
|
|
|
|
+ t.push(0);
|
|
|
|
+ t.push(e);
|
|
|
|
+ h = t.length - 16;
|
|
|
|
+ j = 0;
|
|
|
|
+ for (l = 0; l < t.length; l += 16) {
|
|
|
|
+ j += 512;
|
|
|
|
+ L = l === h ? f : Math.min(e, j);
|
|
|
|
+ q = d.concat(c);
|
|
|
|
+ q[12] ^= L;
|
|
|
|
+ q[13] ^= L;
|
|
|
|
+ for (r = 0; r < 10; r += 1) {
|
|
|
|
+ for (i = 0; i < 8; i += 1) {
|
|
|
|
+ if (i < 4) {
|
|
|
|
+ g(i, i, i, i, i);
|
|
|
|
+ } else {
|
|
|
|
+ g(i, i, i + 1, i + 2, i + 3);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (i = 0; i < 8; i += 1) {
|
|
|
|
+ d[i] ^= b[i % 4] ^ q[i] ^ q[i + 8];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return d.map(w).join("");
|
|
|
|
+ };
|
|
|
|
+ }();
|
|
|
|
+ /**
|
|
|
|
+ * 自动使用的颜色序列
|
|
|
|
+ */
|
|
|
|
+ var RESOURCE_COLOR_SERIES = [ 51, 303, 75, 200, 157, 0, 26, 254 ].map(function(h) {
|
|
|
|
+ return kity.Color.createHSL(h, 100, 85);
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * 在 Minder 上拓展一些关于资源的支持接口
|
|
|
|
+ */
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ /**
|
|
|
|
+ * 获取字符串的哈希值
|
|
|
|
+ *
|
|
|
|
+ * @param {String} str
|
|
|
|
+ * @return {Number} hashCode
|
|
|
|
+ */
|
|
|
|
+ getHashCode: function(str) {
|
|
|
|
+ str = blake32(str);
|
|
|
|
+ var hash = 1315423911, i, ch;
|
|
|
|
+ for (i = str.length - 1; i >= 0; i--) {
|
|
|
|
+ ch = str.charCodeAt(i);
|
|
|
|
+ hash ^= (hash << 5) + ch + (hash >> 2);
|
|
|
|
+ }
|
|
|
|
+ return hash & 2147483647;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取脑图中某个资源对应的颜色
|
|
|
|
+ *
|
|
|
|
+ * 如果存在同名资源,则返回已经分配给该资源的颜色,否则分配给该资源一个颜色,并且返回
|
|
|
|
+ *
|
|
|
|
+ * 如果资源数超过颜色序列数量,返回哈希颜色
|
|
|
|
+ *
|
|
|
|
+ * @param {String} resource 资源名称
|
|
|
|
+ * @return {Color}
|
|
|
|
+ */
|
|
|
|
+ getResourceColor: function(resource) {
|
|
|
|
+ var colorMapping = this._getResourceColorIndexMapping();
|
|
|
|
+ var nextIndex;
|
|
|
|
+ if (!Object.prototype.hasOwnProperty.call(colorMapping, resource)) {
|
|
|
|
+ // 找不到找下个可用索引
|
|
|
|
+ nextIndex = this._getNextResourceColorIndex();
|
|
|
|
+ colorMapping[resource] = nextIndex;
|
|
|
|
+ }
|
|
|
|
+ // 资源过多,找不到可用索引颜色,统一返回哈希函数得到的颜色
|
|
|
|
+ return RESOURCE_COLOR_SERIES[colorMapping[resource]] || kity.Color.createHSL(Math.floor(this.getHashCode(resource) / 2147483647 * 359), 100, 85);
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获得已使用的资源的列表
|
|
|
|
+ *
|
|
|
|
+ * @return {Array}
|
|
|
|
+ */
|
|
|
|
+ getUsedResource: function() {
|
|
|
|
+ var mapping = this._getResourceColorIndexMapping();
|
|
|
|
+ var used = [], resource;
|
|
|
|
+ for (resource in mapping) {
|
|
|
|
+ if (Object.prototype.hasOwnProperty.call(mapping, resource)) {
|
|
|
|
+ used.push(resource);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return used;
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * 获取脑图下一个可用的资源颜色索引
|
|
|
|
+ *
|
|
|
|
+ * @return {int}
|
|
|
|
+ */
|
|
|
|
+ _getNextResourceColorIndex: function() {
|
|
|
|
+ // 获取现有颜色映射
|
|
|
|
+ // resource => color_index
|
|
|
|
+ var colorMapping = this._getResourceColorIndexMapping();
|
|
|
|
+ var resource, used, i;
|
|
|
|
+ used = [];
|
|
|
|
+ // 抽取已经使用的值到 used 数组
|
|
|
|
+ for (resource in colorMapping) {
|
|
|
|
+ if (Object.prototype.hasOwnProperty.call(colorMapping, resource)) {
|
|
|
|
+ used.push(colorMapping[resource]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 枚举所有的可用值,如果还没被使用,返回
|
|
|
|
+ for (i = 0; i < RESOURCE_COLOR_SERIES.length; i++) {
|
|
|
|
+ if (!~used.indexOf(i)) return i;
|
|
|
|
+ }
|
|
|
|
+ // 没有可用的颜色了
|
|
|
|
+ return -1;
|
|
|
|
+ },
|
|
|
|
+ // 获取现有颜色映射
|
|
|
|
+ // resource => color_index
|
|
|
|
+ _getResourceColorIndexMapping: function() {
|
|
|
|
+ return this._resourceColorMapping || (this._resourceColorMapping = {});
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @class 设置资源的命令
|
|
|
|
+ *
|
|
|
|
+ * @example
|
|
|
|
+ *
|
|
|
|
+ * // 设置选中节点资源为 "张三"
|
|
|
|
+ * minder.execCommand('resource', ['张三']);
|
|
|
|
+ *
|
|
|
|
+ * // 添加资源 "李四" 到选中节点
|
|
|
|
+ * var resource = minder.queryCommandValue();
|
|
|
|
+ * resource.push('李四');
|
|
|
|
+ * minder.execCommand('resource', resource);
|
|
|
|
+ *
|
|
|
|
+ * // 清除选中节点的资源
|
|
|
|
+ * minder.execCommand('resource', null);
|
|
|
|
+ */
|
|
|
|
+ var ResourceCommand = kity.createClass("ResourceCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, resource) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ if (typeof resource == "string") {
|
|
|
|
+ resource = [ resource ];
|
|
|
|
+ }
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ node.setData("resource", resource).render();
|
|
|
|
+ });
|
|
|
|
+ minder.layout(200);
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ var resource = [];
|
|
|
|
+ nodes.forEach(function(node) {
|
|
|
|
+ var nodeResource = node.getData("resource");
|
|
|
|
+ if (!nodeResource) return;
|
|
|
|
+ nodeResource.forEach(function(name) {
|
|
|
|
+ if (!~resource.indexOf(name)) {
|
|
|
|
+ resource.push(name);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ return resource;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(km) {
|
|
|
|
+ return km.getSelectedNode() ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @class 资源的覆盖图形
|
|
|
|
+ *
|
|
|
|
+ * 该类为一个资源以指定的颜色渲染一个动态的覆盖图形
|
|
|
|
+ */
|
|
|
|
+ var ResourceOverlay = kity.createClass("ResourceOverlay", {
|
|
|
|
+ base: kity.Group,
|
|
|
|
+ constructor: function() {
|
|
|
|
+ this.callBase();
|
|
|
|
+ var text, rect;
|
|
|
|
+ rect = this.rect = new kity.Rect().setRadius(4);
|
|
|
|
+ text = this.text = new kity.Text().setFontSize(12).setVerticalAlign("middle");
|
|
|
|
+ this.addShapes([ rect, text ]);
|
|
|
|
+ },
|
|
|
|
+ setValue: function(resourceName, color) {
|
|
|
|
+ var paddingX = 8, paddingY = 4, borderRadius = 4;
|
|
|
|
+ var text, box, rect;
|
|
|
|
+ text = this.text;
|
|
|
|
+ if (resourceName == this.lastResourceName) {
|
|
|
|
+ box = this.lastBox;
|
|
|
|
+ } else {
|
|
|
|
+ text.setContent(resourceName);
|
|
|
|
+ box = text.getBoundaryBox();
|
|
|
|
+ this.lastResourceName = resourceName;
|
|
|
|
+ this.lastBox = box;
|
|
|
|
+ }
|
|
|
|
+ text.setX(paddingX).fill(color.dec("l", 70));
|
|
|
|
+ rect = this.rect;
|
|
|
|
+ rect.setPosition(0, box.y - paddingY);
|
|
|
|
+ this.width = Math.round(box.width + paddingX * 2);
|
|
|
|
+ this.height = Math.round(box.height + paddingY * 2);
|
|
|
|
+ rect.setSize(this.width, this.height);
|
|
|
|
+ rect.fill(color);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @class 资源渲染器
|
|
|
|
+ */
|
|
|
|
+ var ResourceRenderer = kity.createClass("ResourceRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function(node) {
|
|
|
|
+ this.overlays = [];
|
|
|
|
+ return new kity.Group();
|
|
|
|
+ },
|
|
|
|
+ shouldRender: function(node) {
|
|
|
|
+ return node.getData("resource") && node.getData("resource").length;
|
|
|
|
+ },
|
|
|
|
+ update: function(container, node, box) {
|
|
|
|
+ var spaceRight = node.getStyle("space-right");
|
|
|
|
+ var overlays = this.overlays;
|
|
|
|
+ /* 修复 resource 数组中出现 null 的 bug
|
|
|
|
+ * @Author zhangbobell
|
|
|
|
+ * @date 2016-01-15
|
|
|
|
+ */
|
|
|
|
+ var resource = node.getData("resource").filter(function(ele) {
|
|
|
|
+ return ele !== null;
|
|
|
|
+ });
|
|
|
|
+ if (resource.length === 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var minder = node.getMinder();
|
|
|
|
+ var i, overlay, x;
|
|
|
|
+ x = 0;
|
|
|
|
+ for (i = 0; i < resource.length; i++) {
|
|
|
|
+ x += spaceRight;
|
|
|
|
+ overlay = overlays[i];
|
|
|
|
+ if (!overlay) {
|
|
|
|
+ overlay = new ResourceOverlay();
|
|
|
|
+ overlays.push(overlay);
|
|
|
|
+ container.addShape(overlay);
|
|
|
|
+ }
|
|
|
|
+ overlay.setVisible(true);
|
|
|
|
+ overlay.setValue(resource[i], minder.getResourceColor(resource[i]));
|
|
|
|
+ overlay.setTranslate(x, -1);
|
|
|
|
+ x += overlay.width;
|
|
|
|
+ }
|
|
|
|
+ while (overlay = overlays[i++]) overlay.setVisible(false);
|
|
|
|
+ container.setTranslate(box.right, 0);
|
|
|
|
+ return new kity.Box({
|
|
|
|
+ x: box.right,
|
|
|
|
+ y: Math.round(-overlays[0].height / 2),
|
|
|
|
+ width: x,
|
|
|
|
+ height: overlays[0].height
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ resource: ResourceCommand
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ right: ResourceRenderer
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/select.js
|
|
|
|
+_p[59] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("Select", function() {
|
|
|
|
+ var minder = this;
|
|
|
|
+ var rc = minder.getRenderContainer();
|
|
|
|
+ // 在实例上渲染框选矩形、计算框选范围的对象
|
|
|
|
+ var marqueeActivator = function() {
|
|
|
|
+ // 记录选区的开始位置(mousedown的位置)
|
|
|
|
+ var startPosition = null;
|
|
|
|
+ // 选区的图形
|
|
|
|
+ var marqueeShape = new kity.Path();
|
|
|
|
+ // 标记是否已经启动框选状态
|
|
|
|
+ // 并不是 mousedown 发生之后就启动框选状态,而是检测到移动了一定的距离(MARQUEE_MODE_THRESHOLD)之后
|
|
|
|
+ var marqueeMode = false;
|
|
|
|
+ var MARQUEE_MODE_THRESHOLD = 10;
|
|
|
|
+ return {
|
|
|
|
+ selectStart: function(e) {
|
|
|
|
+ // 只接受左键
|
|
|
|
+ if (e.originEvent.button || e.originEvent.altKey) return;
|
|
|
|
+ // 清理不正确状态
|
|
|
|
+ if (startPosition) {
|
|
|
|
+ return this.selectEnd();
|
|
|
|
+ }
|
|
|
|
+ startPosition = e.getPosition(rc).round();
|
|
|
|
+ },
|
|
|
|
+ selectMove: function(e) {
|
|
|
|
+ if (minder.getStatus() == "textedit") {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!startPosition) return;
|
|
|
|
+ var p1 = startPosition, p2 = e.getPosition(rc);
|
|
|
|
+ // 检测是否要进入选区模式
|
|
|
|
+ if (!marqueeMode) {
|
|
|
|
+ // 距离没达到阈值,退出
|
|
|
|
+ if (kity.Vector.fromPoints(p1, p2).length() < MARQUEE_MODE_THRESHOLD) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 已经达到阈值,记录下来并且重置选区形状
|
|
|
|
+ marqueeMode = true;
|
|
|
|
+ rc.addShape(marqueeShape);
|
|
|
|
+ marqueeShape.fill(minder.getStyle("marquee-background")).stroke(minder.getStyle("marquee-stroke")).setOpacity(.8).getDrawer().clear();
|
|
|
|
+ }
|
|
|
|
+ var marquee = new kity.Box(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y), selectedNodes = [];
|
|
|
|
+ // 使其犀利
|
|
|
|
+ marquee.left = Math.round(marquee.left);
|
|
|
|
+ marquee.top = Math.round(marquee.top);
|
|
|
|
+ marquee.right = Math.round(marquee.right);
|
|
|
|
+ marquee.bottom = Math.round(marquee.bottom);
|
|
|
|
+ // 选区形状更新
|
|
|
|
+ marqueeShape.getDrawer().pipe(function() {
|
|
|
|
+ this.clear();
|
|
|
|
+ this.moveTo(marquee.left, marquee.top);
|
|
|
|
+ this.lineTo(marquee.right, marquee.top);
|
|
|
|
+ this.lineTo(marquee.right, marquee.bottom);
|
|
|
|
+ this.lineTo(marquee.left, marquee.bottom);
|
|
|
|
+ this.close();
|
|
|
|
+ });
|
|
|
|
+ // 计算选中范围
|
|
|
|
+ minder.getRoot().traverse(function(node) {
|
|
|
|
+ var renderBox = node.getLayoutBox();
|
|
|
|
+ if (!renderBox.intersect(marquee).isEmpty()) {
|
|
|
|
+ selectedNodes.push(node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // 应用选中范围
|
|
|
|
+ minder.select(selectedNodes, true);
|
|
|
|
+ // 清除多余的东西
|
|
|
|
+ window.getSelection().removeAllRanges();
|
|
|
|
+ },
|
|
|
|
+ selectEnd: function(e) {
|
|
|
|
+ if (startPosition) {
|
|
|
|
+ startPosition = null;
|
|
|
|
+ }
|
|
|
|
+ if (marqueeMode) {
|
|
|
|
+ marqueeShape.fadeOut(200, "ease", 0, function() {
|
|
|
|
+ if (marqueeShape.remove) marqueeShape.remove();
|
|
|
|
+ });
|
|
|
|
+ marqueeMode = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }();
|
|
|
|
+ var lastDownNode = null, lastDownPosition = null;
|
|
|
|
+ return {
|
|
|
|
+ init: function() {
|
|
|
|
+ window.addEventListener("mouseup", function() {
|
|
|
|
+ marqueeActivator.selectEnd();
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ mousedown: function(e) {
|
|
|
|
+ var downNode = e.getTargetNode();
|
|
|
|
+ // 没有点中节点:
|
|
|
|
+ // 清除选中状态,并且标记选区开始位置
|
|
|
|
+ if (!downNode) {
|
|
|
|
+ this.removeAllSelectedNodes();
|
|
|
|
+ marqueeActivator.selectStart(e);
|
|
|
|
+ this.setStatus("normal");
|
|
|
|
+ } else if (e.isShortcutKey("Ctrl")) {
|
|
|
|
+ this.toggleSelect(downNode);
|
|
|
|
+ } else if (!downNode.isSelected()) {
|
|
|
|
+ this.select(downNode, true);
|
|
|
|
+ } else if (!this.isSingleSelect()) {
|
|
|
|
+ lastDownNode = downNode;
|
|
|
|
+ lastDownPosition = e.getPosition();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ mousemove: marqueeActivator.selectMove,
|
|
|
|
+ mouseup: function(e) {
|
|
|
|
+ var upNode = e.getTargetNode();
|
|
|
|
+ // 如果 mouseup 发生在 lastDownNode 外,是无需理会的
|
|
|
|
+ if (upNode && upNode == lastDownNode) {
|
|
|
|
+ var upPosition = e.getPosition();
|
|
|
|
+ var movement = kity.Vector.fromPoints(lastDownPosition, upPosition);
|
|
|
|
+ if (movement.length() < 1) this.select(lastDownNode, true);
|
|
|
|
+ lastDownNode = null;
|
|
|
|
+ }
|
|
|
|
+ // 清理一下选择状态
|
|
|
|
+ marqueeActivator.selectEnd(e);
|
|
|
|
+ },
|
|
|
|
+ //全选操作
|
|
|
|
+ "normal.keydown": function(e) {
|
|
|
|
+ if (e.isShortcutKey("ctrl+a")) {
|
|
|
|
+ var selectedNodes = [];
|
|
|
|
+ this.getRoot().traverse(function(node) {
|
|
|
|
+ selectedNodes.push(node);
|
|
|
|
+ });
|
|
|
|
+ this.select(selectedNodes, true);
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/style.js
|
|
|
|
+_p[60] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("StyleModule", function() {
|
|
|
|
+ var styleNames = [ "font-size", "font-family", "font-weight", "font-style", "background", "color" ];
|
|
|
|
+ var styleClipBoard = null;
|
|
|
|
+ function hasStyle(node) {
|
|
|
|
+ var data = node.getData();
|
|
|
|
+ for (var i = 0; i < styleNames.length; i++) {
|
|
|
|
+ if (styleNames[i] in data) return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ commands: {
|
|
|
|
+ /**
|
|
|
|
+ * @command CopyStyle
|
|
|
|
+ * @description 拷贝选中节点的当前样式,包括字体、字号、粗体、斜体、背景色、字体色
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点
|
|
|
|
+ * -1: 当前没有选中的节点
|
|
|
|
+ */
|
|
|
|
+ copystyle: kity.createClass("CopyStyleCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ var nodeData = node.getData();
|
|
|
|
+ styleClipBoard = {};
|
|
|
|
+ styleNames.forEach(function(name) {
|
|
|
|
+ if (name in nodeData) styleClipBoard[name] = nodeData[name]; else {
|
|
|
|
+ styleClipBoard[name] = null;
|
|
|
|
+ delete styleClipBoard[name];
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return styleClipBoard;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ if (nodes.length !== 1) return -1;
|
|
|
|
+ return hasStyle(nodes[0]) ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command PasteStyle
|
|
|
|
+ * @description 粘贴已拷贝的样式到选中的节点上,包括字体、字号、粗体、斜体、背景色、字体色
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点,并且已经有复制的样式
|
|
|
|
+ * -1: 当前没有选中的节点,或者没有复制的样式
|
|
|
|
+ */
|
|
|
|
+ pastestyle: kity.createClass("PastStyleCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ minder.getSelectedNodes().forEach(function(node) {
|
|
|
|
+ for (var name in styleClipBoard) {
|
|
|
|
+ if (styleClipBoard.hasOwnProperty(name)) node.setData(name, styleClipBoard[name]);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ minder.renderNodeBatch(minder.getSelectedNodes());
|
|
|
|
+ minder.layout(300);
|
|
|
|
+ return styleClipBoard;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return styleClipBoard && minder.getSelectedNodes().length ? 0 : -1;
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ /**
|
|
|
|
+ * @command ClearStyle
|
|
|
|
+ * @description 移除选中节点的样式,包括字体、字号、粗体、斜体、背景色、字体色
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前有选中的节点,并且至少有一个设置了至少一种样式
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ clearstyle: kity.createClass("ClearStyleCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ minder.getSelectedNodes().forEach(function(node) {
|
|
|
|
+ styleNames.forEach(function(name) {
|
|
|
|
+ node.setData(name);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ minder.renderNodeBatch(minder.getSelectedNodes());
|
|
|
|
+ minder.layout(300);
|
|
|
|
+ return styleClipBoard;
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ var nodes = minder.getSelectedNodes();
|
|
|
|
+ if (!nodes.length) return -1;
|
|
|
|
+ for (var i = 0; i < nodes.length; i++) {
|
|
|
|
+ if (hasStyle(nodes[i])) return 0;
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/text.js
|
|
|
|
+_p[61] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ /**
|
|
|
|
+ * 针对不同系统、不同浏览器、不同字体做居中兼容性处理
|
|
|
|
+ * 暂时未增加Linux的处理
|
|
|
|
+ */
|
|
|
|
+ var FONT_ADJUST = {
|
|
|
|
+ safari: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.17,
|
|
|
|
+ "楷体,楷体_GB2312,SimKai": -.1,
|
|
|
|
+ "隶书, SimLi": -.1,
|
|
|
|
+ "comic sans ms": -.23,
|
|
|
|
+ "impact,chicago": -.15,
|
|
|
|
+ "times new roman": -.1,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: 0
|
|
|
|
+ },
|
|
|
|
+ ie: {
|
|
|
|
+ 10: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.17,
|
|
|
|
+ "comic sans ms": -.17,
|
|
|
|
+ "impact,chicago": -.08,
|
|
|
|
+ "times new roman": .04,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: -.15
|
|
|
|
+ },
|
|
|
|
+ 11: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.17,
|
|
|
|
+ "arial,helvetica,sans-serif": -.17,
|
|
|
|
+ "comic sans ms": -.17,
|
|
|
|
+ "impact,chicago": -.08,
|
|
|
|
+ "times new roman": .04,
|
|
|
|
+ "sans-serif": -.16,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: -.15
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ edge: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.15,
|
|
|
|
+ "arial,helvetica,sans-serif": -.17,
|
|
|
|
+ "comic sans ms": -.17,
|
|
|
|
+ "impact,chicago": -.08,
|
|
|
|
+ "sans-serif": -.16,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: -.15
|
|
|
|
+ },
|
|
|
|
+ sg: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.15,
|
|
|
|
+ "arial,helvetica,sans-serif": -.05,
|
|
|
|
+ "comic sans ms": -.22,
|
|
|
|
+ "impact,chicago": -.16,
|
|
|
|
+ "times new roman": -.03,
|
|
|
|
+ "arial black,avant garde": -.22,
|
|
|
|
+ default: -.15
|
|
|
|
+ },
|
|
|
|
+ chrome: {
|
|
|
|
+ Mac: {
|
|
|
|
+ "andale mono": -.05,
|
|
|
|
+ "comic sans ms": -.3,
|
|
|
|
+ "impact,chicago": -.13,
|
|
|
|
+ "times new roman": -.1,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: 0
|
|
|
|
+ },
|
|
|
|
+ Win: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.15,
|
|
|
|
+ "arial,helvetica,sans-serif": -.02,
|
|
|
|
+ "arial black,avant garde": -.2,
|
|
|
|
+ "comic sans ms": -.2,
|
|
|
|
+ "impact,chicago": -.12,
|
|
|
|
+ "times new roman": -.02,
|
|
|
|
+ default: -.15
|
|
|
|
+ },
|
|
|
|
+ Lux: {
|
|
|
|
+ "andale mono": -.05,
|
|
|
|
+ "comic sans ms": -.3,
|
|
|
|
+ "impact,chicago": -.13,
|
|
|
|
+ "times new roman": -.1,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: 0
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ firefox: {
|
|
|
|
+ Mac: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.2,
|
|
|
|
+ "宋体,SimSun": .05,
|
|
|
|
+ "comic sans ms": -.2,
|
|
|
|
+ "impact,chicago": -.15,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ "times new roman": -.1,
|
|
|
|
+ default: .05
|
|
|
|
+ },
|
|
|
|
+ Win: {
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.16,
|
|
|
|
+ "andale mono": -.17,
|
|
|
|
+ "arial,helvetica,sans-serif": -.17,
|
|
|
|
+ "comic sans ms": -.22,
|
|
|
|
+ "impact,chicago": -.23,
|
|
|
|
+ "times new roman": -.22,
|
|
|
|
+ "sans-serif": -.22,
|
|
|
|
+ "arial black,avant garde": -.17,
|
|
|
|
+ default: -.16
|
|
|
|
+ },
|
|
|
|
+ Lux: {
|
|
|
|
+ "宋体,SimSun": -.2,
|
|
|
|
+ "微软雅黑,Microsoft YaHei": -.2,
|
|
|
|
+ "黑体, SimHei": -.2,
|
|
|
|
+ "隶书, SimLi": -.2,
|
|
|
|
+ "楷体,楷体_GB2312,SimKai": -.2,
|
|
|
|
+ "andale mono": -.2,
|
|
|
|
+ "arial,helvetica,sans-serif": -.2,
|
|
|
|
+ "comic sans ms": -.2,
|
|
|
|
+ "impact,chicago": -.2,
|
|
|
|
+ "times new roman": -.2,
|
|
|
|
+ "sans-serif": -.2,
|
|
|
|
+ "arial black,avant garde": -.2,
|
|
|
|
+ default: -.16
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ var TextRenderer = kity.createClass("TextRenderer", {
|
|
|
|
+ base: Renderer,
|
|
|
|
+ create: function() {
|
|
|
|
+ return new kity.Group().setId(utils.uuid("node_text"));
|
|
|
|
+ },
|
|
|
|
+ update: function(textGroup, node) {
|
|
|
|
+ function getDataOrStyle(name) {
|
|
|
|
+ return node.getData(name) || node.getStyle(name);
|
|
|
|
+ }
|
|
|
|
+ var nodeText = node.getText();
|
|
|
|
+ var textArr = nodeText ? nodeText.split("\n") : [ " " ];
|
|
|
|
+ var lineHeight = node.getStyle("line-height");
|
|
|
|
+ var fontSize = getDataOrStyle("font-size");
|
|
|
|
+ var fontFamily = getDataOrStyle("font-family") || "default";
|
|
|
|
+ var height = lineHeight * fontSize * textArr.length - (lineHeight - 1) * fontSize;
|
|
|
|
+ var yStart = -height / 2;
|
|
|
|
+ var Browser = kity.Browser;
|
|
|
|
+ var adjust;
|
|
|
|
+ if (Browser.chrome || Browser.opera || Browser.bd || Browser.lb === "chrome") {
|
|
|
|
+ adjust = FONT_ADJUST["chrome"][Browser.platform][fontFamily];
|
|
|
|
+ } else if (Browser.gecko) {
|
|
|
|
+ adjust = FONT_ADJUST["firefox"][Browser.platform][fontFamily];
|
|
|
|
+ } else if (Browser.sg) {
|
|
|
|
+ adjust = FONT_ADJUST["sg"][fontFamily];
|
|
|
|
+ } else if (Browser.safari) {
|
|
|
|
+ adjust = FONT_ADJUST["safari"][fontFamily];
|
|
|
|
+ } else if (Browser.ie) {
|
|
|
|
+ adjust = FONT_ADJUST["ie"][Browser.version][fontFamily];
|
|
|
|
+ } else if (Browser.edge) {
|
|
|
|
+ adjust = FONT_ADJUST["edge"][fontFamily];
|
|
|
|
+ } else if (Browser.lb) {
|
|
|
|
+ // 猎豹浏览器的ie内核兼容性模式下
|
|
|
|
+ adjust = .9;
|
|
|
|
+ }
|
|
|
|
+ textGroup.setTranslate(0, (adjust || 0) * fontSize);
|
|
|
|
+ var rBox = new kity.Box(), r = Math.round;
|
|
|
|
+ this.setTextStyle(node, textGroup);
|
|
|
|
+ var textLength = textArr.length;
|
|
|
|
+ var textGroupLength = textGroup.getItems().length;
|
|
|
|
+ var i, ci, textShape, text;
|
|
|
|
+ if (textLength < textGroupLength) {
|
|
|
|
+ for (i = textLength, ci; ci = textGroup.getItem(i); ) {
|
|
|
|
+ textGroup.removeItem(i);
|
|
|
|
+ }
|
|
|
|
+ } else if (textLength > textGroupLength) {
|
|
|
|
+ var growth = textLength - textGroupLength;
|
|
|
|
+ while (growth--) {
|
|
|
|
+ textShape = new kity.Text().setAttr("text-rendering", "inherit");
|
|
|
|
+ if (kity.Browser.ie || kity.Browser.edge) {
|
|
|
|
+ textShape.setVerticalAlign("top");
|
|
|
|
+ } else {
|
|
|
|
+ textShape.setAttr("dominant-baseline", "text-before-edge");
|
|
|
|
+ }
|
|
|
|
+ textGroup.addItem(textShape);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (i = 0, text, textShape; text = textArr[i], textShape = textGroup.getItem(i); i++) {
|
|
|
|
+ textShape.setContent(text);
|
|
|
|
+ if (kity.Browser.ie || kity.Browser.edge) {
|
|
|
|
+ textShape.fixPosition();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ this.setTextStyle(node, textGroup);
|
|
|
|
+ var textHash = node.getText() + [ "font-size", "font-name", "font-weight", "font-style" ].map(getDataOrStyle).join("/");
|
|
|
|
+ if (node._currentTextHash == textHash && node._currentTextGroupBox) return node._currentTextGroupBox;
|
|
|
|
+ node._currentTextHash = textHash;
|
|
|
|
+ return function() {
|
|
|
|
+ textGroup.eachItem(function(i, textShape) {
|
|
|
|
+ var y = yStart + i * fontSize * lineHeight;
|
|
|
|
+ textShape.setY(y);
|
|
|
|
+ var bbox = textShape.getBoundaryBox();
|
|
|
|
+ rBox = rBox.merge(new kity.Box(0, y, bbox.height && bbox.width || 1, fontSize));
|
|
|
|
+ });
|
|
|
|
+ var nBox = new kity.Box(r(rBox.x), r(rBox.y), r(rBox.width), r(rBox.height));
|
|
|
|
+ node._currentTextGroupBox = nBox;
|
|
|
|
+ return nBox;
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ setTextStyle: function(node, text) {
|
|
|
|
+ var hooks = TextRenderer._styleHooks;
|
|
|
|
+ hooks.forEach(function(hook) {
|
|
|
|
+ hook(node, text);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var TextCommand = kity.createClass({
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder, text) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ if (node) {
|
|
|
|
+ node.setText(text);
|
|
|
|
+ node.render();
|
|
|
|
+ minder.layout();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return minder.getSelectedNodes().length == 1 ? 0 : -1;
|
|
|
|
+ },
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ var node = minder.getSelectedNode();
|
|
|
|
+ return node ? node.getText() : null;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ utils.extend(TextRenderer, {
|
|
|
|
+ _styleHooks: [],
|
|
|
|
+ registerStyleHook: function(fn) {
|
|
|
|
+ TextRenderer._styleHooks.push(fn);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ kity.extendClass(MinderNode, {
|
|
|
|
+ getTextGroup: function() {
|
|
|
|
+ return this.getRenderer("TextRenderer").getRenderShape();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("text", {
|
|
|
|
+ commands: {
|
|
|
|
+ text: TextCommand
|
|
|
|
+ },
|
|
|
|
+ renderers: {
|
|
|
|
+ center: TextRenderer
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ module.exports = TextRenderer;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/view.js
|
|
|
|
+_p[62] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ var ViewDragger = kity.createClass("ViewDragger", {
|
|
|
|
+ constructor: function(minder) {
|
|
|
|
+ this._minder = minder;
|
|
|
|
+ this._enabled = false;
|
|
|
|
+ this._bind();
|
|
|
|
+ var me = this;
|
|
|
|
+ this._minder.getViewDragger = function() {
|
|
|
|
+ return me;
|
|
|
|
+ };
|
|
|
|
+ this.setEnabled(false);
|
|
|
|
+ },
|
|
|
|
+ isEnabled: function() {
|
|
|
|
+ return this._enabled;
|
|
|
|
+ },
|
|
|
|
+ setEnabled: function(value) {
|
|
|
|
+ var paper = this._minder.getPaper();
|
|
|
|
+ paper.setStyle("cursor", value ? "pointer" : "default");
|
|
|
|
+ paper.setStyle("cursor", value ? "-webkit-grab" : "default");
|
|
|
|
+ this._enabled = value;
|
|
|
|
+ },
|
|
|
|
+ timeline: function() {
|
|
|
|
+ return this._moveTimeline;
|
|
|
|
+ },
|
|
|
|
+ move: function(offset, duration) {
|
|
|
|
+ var minder = this._minder;
|
|
|
|
+ var targetPosition = this.getMovement().offset(offset);
|
|
|
|
+ this.moveTo(targetPosition, duration);
|
|
|
|
+ },
|
|
|
|
+ moveTo: function(position, duration) {
|
|
|
|
+ if (duration) {
|
|
|
|
+ var dragger = this;
|
|
|
|
+ if (this._moveTimeline) this._moveTimeline.stop();
|
|
|
|
+ this._moveTimeline = this._minder.getRenderContainer().animate(new kity.Animator(this.getMovement(), position, function(target, value) {
|
|
|
|
+ dragger.moveTo(value);
|
|
|
|
+ }), duration, "easeOutCubic").timeline();
|
|
|
|
+ this._moveTimeline.on("finish", function() {
|
|
|
|
+ dragger._moveTimeline = null;
|
|
|
|
+ });
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+ this._minder.getRenderContainer().setTranslate(position.round());
|
|
|
|
+ this._minder.fire("viewchange");
|
|
|
|
+ },
|
|
|
|
+ getMovement: function() {
|
|
|
|
+ var translate = this._minder.getRenderContainer().transform.translate;
|
|
|
|
+ return translate ? translate[0] : new kity.Point();
|
|
|
|
+ },
|
|
|
|
+ getView: function() {
|
|
|
|
+ var minder = this._minder;
|
|
|
|
+ var c = minder._lastClientSize || {
|
|
|
|
+ width: minder.getRenderTarget().clientWidth,
|
|
|
|
+ height: minder.getRenderTarget().clientHeight
|
|
|
|
+ };
|
|
|
|
+ var m = this.getMovement();
|
|
|
|
+ var box = new kity.Box(0, 0, c.width, c.height);
|
|
|
|
+ var viewMatrix = minder.getPaper().getViewPortMatrix();
|
|
|
|
+ return viewMatrix.inverse().translate(-m.x, -m.y).transformBox(box);
|
|
|
|
+ },
|
|
|
|
+ _bind: function() {
|
|
|
|
+ var dragger = this, isTempDrag = false, lastPosition = null, currentPosition = null;
|
|
|
|
+ function dragEnd(e) {
|
|
|
|
+ if (!lastPosition) return;
|
|
|
|
+ lastPosition = null;
|
|
|
|
+ e.stopPropagation();
|
|
|
|
+ // 临时拖动需要还原状态
|
|
|
|
+ if (isTempDrag) {
|
|
|
|
+ dragger.setEnabled(false);
|
|
|
|
+ isTempDrag = false;
|
|
|
|
+ if (dragger._minder.getStatus() == "hand") dragger._minder.rollbackStatus();
|
|
|
|
+ }
|
|
|
|
+ var paper = dragger._minder.getPaper();
|
|
|
|
+ paper.setStyle("cursor", dragger._minder.getStatus() == "hand" ? "-webkit-grab" : "default");
|
|
|
|
+ dragger._minder.fire("viewchanged");
|
|
|
|
+ }
|
|
|
|
+ this._minder.on("normal.mousedown normal.touchstart " + "inputready.mousedown inputready.touchstart " + "readonly.mousedown readonly.touchstart", function(e) {
|
|
|
|
+ if (e.originEvent.button == 2) {
|
|
|
|
+ e.originEvent.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ // 点击未选中的根节点临时开启
|
|
|
|
+ if (e.getTargetNode() == this.getRoot() || e.originEvent.button == 2 || e.originEvent.altKey) {
|
|
|
|
+ lastPosition = e.getPosition("view");
|
|
|
|
+ isTempDrag = true;
|
|
|
|
+ }
|
|
|
|
+ }).on("normal.mousemove normal.touchmove " + "readonly.mousemove readonly.touchmove " + "inputready.mousemove inputready.touchmove", function(e) {
|
|
|
|
+ if (e.type == "touchmove") {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ if (!isTempDrag) return;
|
|
|
|
+ var offset = kity.Vector.fromPoints(lastPosition, e.getPosition("view"));
|
|
|
|
+ if (offset.length() > 10) {
|
|
|
|
+ this.setStatus("hand", true);
|
|
|
|
+ var paper = dragger._minder.getPaper();
|
|
|
|
+ paper.setStyle("cursor", "-webkit-grabbing");
|
|
|
|
+ }
|
|
|
|
+ }).on("hand.beforemousedown hand.beforetouchstart", function(e) {
|
|
|
|
+ // 已经被用户打开拖放模式
|
|
|
|
+ if (dragger.isEnabled()) {
|
|
|
|
+ lastPosition = e.getPosition("view");
|
|
|
|
+ e.stopPropagation();
|
|
|
|
+ var paper = dragger._minder.getPaper();
|
|
|
|
+ paper.setStyle("cursor", "-webkit-grabbing");
|
|
|
|
+ }
|
|
|
|
+ }).on("hand.beforemousemove hand.beforetouchmove", function(e) {
|
|
|
|
+ if (lastPosition) {
|
|
|
|
+ currentPosition = e.getPosition("view");
|
|
|
|
+ // 当前偏移加上历史偏移
|
|
|
|
+ var offset = kity.Vector.fromPoints(lastPosition, currentPosition);
|
|
|
|
+ dragger.move(offset);
|
|
|
|
+ e.stopPropagation();
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ e.originEvent.preventDefault();
|
|
|
|
+ lastPosition = currentPosition;
|
|
|
|
+ }
|
|
|
|
+ }).on("mouseup touchend", dragEnd);
|
|
|
|
+ window.addEventListener("mouseup", dragEnd);
|
|
|
|
+ this._minder.on("contextmenu", function(e) {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ Module.register("View", function() {
|
|
|
|
+ var km = this;
|
|
|
|
+ /**
|
|
|
|
+ * @command Hand
|
|
|
|
+ * @description 切换抓手状态,抓手状态下,鼠标拖动将拖动视野,而不是创建选区
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 当前不是抓手状态
|
|
|
|
+ * 1: 当前是抓手状态
|
|
|
|
+ */
|
|
|
|
+ var ToggleHandCommand = kity.createClass("ToggleHandCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ if (minder.getStatus() != "hand") {
|
|
|
|
+ minder.setStatus("hand", true);
|
|
|
|
+ } else {
|
|
|
|
+ minder.rollbackStatus();
|
|
|
|
+ }
|
|
|
|
+ this.setContentChanged(false);
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return minder.getStatus() == "hand" ? 1 : 0;
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Camera
|
|
|
|
+ * @description 设置当前视野的中心位置到某个节点上
|
|
|
|
+ * @param {kityminder.MinderNode} focusNode 要定位的节点
|
|
|
|
+ * @param {number} duration 设置视野移动的动画时长(单位 ms),设置为 0 不使用动画
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ */
|
|
|
|
+ var CameraCommand = kity.createClass("CameraCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, focusNode) {
|
|
|
|
+ focusNode = focusNode || km.getRoot();
|
|
|
|
+ var viewport = km.getPaper().getViewPort();
|
|
|
|
+ var offset = focusNode.getRenderContainer().getRenderBox("view");
|
|
|
|
+ var dx = viewport.center.x - offset.x - offset.width / 2, dy = viewport.center.y - offset.y;
|
|
|
|
+ var dragger = km._viewDragger;
|
|
|
|
+ var duration = km.getOption("viewAnimationDuration");
|
|
|
|
+ dragger.move(new kity.Point(dx, dy), duration);
|
|
|
|
+ this.setContentChanged(false);
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command Move
|
|
|
|
+ * @description 指定方向移动当前视野
|
|
|
|
+ * @param {string} dir 移动方向
|
|
|
|
+ * 取值为 'left',视野向左移动一半
|
|
|
|
+ * 取值为 'right',视野向右移动一半
|
|
|
|
+ * 取值为 'up',视野向上移动一半
|
|
|
|
+ * 取值为 'down',视野向下移动一半
|
|
|
|
+ * @param {number} duration 视野移动的动画时长(单位 ms),设置为 0 不使用动画
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ */
|
|
|
|
+ var MoveCommand = kity.createClass("MoveCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(km, dir) {
|
|
|
|
+ var dragger = km._viewDragger;
|
|
|
|
+ var size = km._lastClientSize;
|
|
|
|
+ var duration = km.getOption("viewAnimationDuration");
|
|
|
|
+ switch (dir) {
|
|
|
|
+ case "up":
|
|
|
|
+ dragger.move(new kity.Point(0, size.height / 2), duration);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "down":
|
|
|
|
+ dragger.move(new kity.Point(0, -size.height / 2), duration);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "left":
|
|
|
|
+ dragger.move(new kity.Point(size.width / 2, 0), duration);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "right":
|
|
|
|
+ dragger.move(new kity.Point(-size.width / 2, 0), duration);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ init: function() {
|
|
|
|
+ this._viewDragger = new ViewDragger(this);
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ hand: ToggleHandCommand,
|
|
|
|
+ camera: CameraCommand,
|
|
|
|
+ move: MoveCommand
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ statuschange: function(e) {
|
|
|
|
+ this._viewDragger.setEnabled(e.currentStatus == "hand");
|
|
|
|
+ },
|
|
|
|
+ mousewheel: function(e) {
|
|
|
|
+ var dx, dy;
|
|
|
|
+ e = e.originEvent;
|
|
|
|
+ if (e.ctrlKey || e.shiftKey) return;
|
|
|
|
+ if ("wheelDeltaX" in e) {
|
|
|
|
+ dx = e.wheelDeltaX || 0;
|
|
|
|
+ dy = e.wheelDeltaY || 0;
|
|
|
|
+ } else {
|
|
|
|
+ dx = 0;
|
|
|
|
+ dy = e.wheelDelta;
|
|
|
|
+ }
|
|
|
|
+ this._viewDragger.move({
|
|
|
|
+ x: dx / 2.5,
|
|
|
|
+ y: dy / 2.5
|
|
|
|
+ });
|
|
|
|
+ var me = this;
|
|
|
|
+ clearTimeout(this._mousewheeltimer);
|
|
|
|
+ this._mousewheeltimer = setTimeout(function() {
|
|
|
|
+ me.fire("viewchanged");
|
|
|
|
+ }, 100);
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ },
|
|
|
|
+ "normal.dblclick readonly.dblclick": function(e) {
|
|
|
|
+ if (e.kityEvent.targetShape instanceof kity.Paper) {
|
|
|
|
+ this.execCommand("camera", this.getRoot(), 800);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ "paperrender finishInitHook": function() {
|
|
|
|
+ if (!this.getRenderTarget()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.execCommand("camera", null, 0);
|
|
|
|
+ this._lastClientSize = {
|
|
|
|
+ width: this.getRenderTarget().clientWidth,
|
|
|
|
+ height: this.getRenderTarget().clientHeight
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ resize: function(e) {
|
|
|
|
+ var a = {
|
|
|
|
+ width: this.getRenderTarget().clientWidth,
|
|
|
|
+ height: this.getRenderTarget().clientHeight
|
|
|
|
+ }, b = this._lastClientSize;
|
|
|
|
+ this._viewDragger.move(new kity.Point((a.width - b.width) / 2 | 0, (a.height - b.height) / 2 | 0));
|
|
|
|
+ this._lastClientSize = a;
|
|
|
|
+ },
|
|
|
|
+ "selectionchange layoutallfinish": function(e) {
|
|
|
|
+ var selected = this.getSelectedNode();
|
|
|
|
+ var minder = this;
|
|
|
|
+ /*
|
|
|
|
+ * Added by zhangbobell 2015.9.9
|
|
|
|
+ * windows 10 的 edge 浏览器在全部动画停止后,优先级图标不显示 text,
|
|
|
|
+ * 因此再次触发一次 render 事件,让浏览器重绘
|
|
|
|
+ * */
|
|
|
|
+ if (kity.Browser.edge) {
|
|
|
|
+ this.fire("paperrender");
|
|
|
|
+ }
|
|
|
|
+ if (!selected) return;
|
|
|
|
+ var dragger = this._viewDragger;
|
|
|
|
+ var timeline = dragger.timeline();
|
|
|
|
+ /*
|
|
|
|
+ * Added by zhangbobell 2015.09.25
|
|
|
|
+ * 如果之前有动画,那么就先暂时返回,等之前动画结束之后再次执行本函数
|
|
|
|
+ * 以防止 view 动画变动了位置,导致本函数执行的时候位置计算不对
|
|
|
|
+ *
|
|
|
|
+ * fixed bug : 初始化的时候中心节点位置不固定(有的时候在左上角,有的时候在中心)
|
|
|
|
+ * */
|
|
|
|
+ if (timeline) {
|
|
|
|
+ timeline.on("finish", function() {
|
|
|
|
+ minder.fire("selectionchange");
|
|
|
|
+ });
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var view = dragger.getView();
|
|
|
|
+ var focus = selected.getLayoutBox();
|
|
|
|
+ var space = 50;
|
|
|
|
+ var dx = 0, dy = 0;
|
|
|
|
+ if (focus.right > view.right) {
|
|
|
|
+ dx += view.right - focus.right - space;
|
|
|
|
+ } else if (focus.left < view.left) {
|
|
|
|
+ dx += view.left - focus.left + space;
|
|
|
|
+ }
|
|
|
|
+ if (focus.bottom > view.bottom) {
|
|
|
|
+ dy += view.bottom - focus.bottom - space;
|
|
|
|
+ }
|
|
|
|
+ if (focus.top < view.top) {
|
|
|
|
+ dy += view.top - focus.top + space;
|
|
|
|
+ }
|
|
|
|
+ if (dx || dy) dragger.move(new kity.Point(dx, dy), 100);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/module/zoom.js
|
|
|
|
+_p[63] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var utils = _p.r(33);
|
|
|
|
+ var Minder = _p.r(19);
|
|
|
|
+ var MinderNode = _p.r(21);
|
|
|
|
+ var Command = _p.r(9);
|
|
|
|
+ var Module = _p.r(20);
|
|
|
|
+ var Renderer = _p.r(27);
|
|
|
|
+ Module.register("Zoom", function() {
|
|
|
|
+ var me = this;
|
|
|
|
+ var timeline;
|
|
|
|
+ function setTextRendering() {
|
|
|
|
+ var value = me._zoomValue >= 100 ? "optimize-speed" : "geometricPrecision";
|
|
|
|
+ me.getRenderContainer().setAttr("text-rendering", value);
|
|
|
|
+ }
|
|
|
|
+ function fixPaperCTM(paper) {
|
|
|
|
+ var node = paper.shapeNode;
|
|
|
|
+ var ctm = node.getCTM();
|
|
|
|
+ var matrix = new kity.Matrix(ctm.a, ctm.b, ctm.c, ctm.d, (ctm.e | 0) + .5, (ctm.f | 0) + .5);
|
|
|
|
+ node.setAttribute("transform", "matrix(" + matrix.toString() + ")");
|
|
|
|
+ }
|
|
|
|
+ kity.extendClass(Minder, {
|
|
|
|
+ zoom: function(value) {
|
|
|
|
+ var paper = this.getPaper();
|
|
|
|
+ var viewport = paper.getViewPort();
|
|
|
|
+ viewport.zoom = value / 100;
|
|
|
|
+ viewport.center = {
|
|
|
|
+ x: viewport.center.x,
|
|
|
|
+ y: viewport.center.y
|
|
|
|
+ };
|
|
|
|
+ paper.setViewPort(viewport);
|
|
|
|
+ if (value == 100) fixPaperCTM(paper);
|
|
|
|
+ },
|
|
|
|
+ getZoomValue: function() {
|
|
|
|
+ return this._zoomValue;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ function zoomMinder(minder, value) {
|
|
|
|
+ var paper = minder.getPaper();
|
|
|
|
+ var viewport = paper.getViewPort();
|
|
|
|
+ if (!value) return;
|
|
|
|
+ setTextRendering();
|
|
|
|
+ var duration = minder.getOption("zoomAnimationDuration");
|
|
|
|
+ if (minder.getRoot().getComplex() > 200 || !duration) {
|
|
|
|
+ minder._zoomValue = value;
|
|
|
|
+ minder.zoom(value);
|
|
|
|
+ minder.fire("viewchange");
|
|
|
|
+ } else {
|
|
|
|
+ var animator = new kity.Animator({
|
|
|
|
+ beginValue: minder._zoomValue,
|
|
|
|
+ finishValue: value,
|
|
|
|
+ setter: function(target, value) {
|
|
|
|
+ target.zoom(value);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ minder._zoomValue = value;
|
|
|
|
+ if (timeline) {
|
|
|
|
+ timeline.pause();
|
|
|
|
+ }
|
|
|
|
+ timeline = animator.start(minder, duration, "easeInOutSine");
|
|
|
|
+ timeline.on("finish", function() {
|
|
|
|
+ minder.fire("viewchange");
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ minder.fire("zoom", {
|
|
|
|
+ zoom: value
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @command Zoom
|
|
|
|
+ * @description 缩放当前的视野到一定的比例(百分比)
|
|
|
|
+ * @param {number} value 设置的比例,取值 100 则为原尺寸
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 始终可用
|
|
|
|
+ */
|
|
|
|
+ var ZoomCommand = kity.createClass("Zoom", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: zoomMinder,
|
|
|
|
+ queryValue: function(minder) {
|
|
|
|
+ return minder._zoomValue;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command ZoomIn
|
|
|
|
+ * @description 放大当前的视野到下一个比例等级(百分比)
|
|
|
|
+ * @shortcut =
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 如果当前脑图的配置中还有下一个比例等级
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ var ZoomInCommand = kity.createClass("ZoomInCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ zoomMinder(minder, this.nextValue(minder));
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return +!this.nextValue(minder);
|
|
|
|
+ },
|
|
|
|
+ nextValue: function(minder) {
|
|
|
|
+ var stack = minder.getOption("zoom"), i;
|
|
|
|
+ for (i = 0; i < stack.length; i++) {
|
|
|
|
+ if (stack[i] > minder._zoomValue) return stack[i];
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ /**
|
|
|
|
+ * @command ZoomOut
|
|
|
|
+ * @description 缩小当前的视野到上一个比例等级(百分比)
|
|
|
|
+ * @shortcut -
|
|
|
|
+ * @state
|
|
|
|
+ * 0: 如果当前脑图的配置中还有上一个比例等级
|
|
|
|
+ * -1: 其它情况
|
|
|
|
+ */
|
|
|
|
+ var ZoomOutCommand = kity.createClass("ZoomOutCommand", {
|
|
|
|
+ base: Command,
|
|
|
|
+ execute: function(minder) {
|
|
|
|
+ zoomMinder(minder, this.nextValue(minder));
|
|
|
|
+ },
|
|
|
|
+ queryState: function(minder) {
|
|
|
|
+ return +!this.nextValue(minder);
|
|
|
|
+ },
|
|
|
|
+ nextValue: function(minder) {
|
|
|
|
+ var stack = minder.getOption("zoom"), i;
|
|
|
|
+ for (i = stack.length - 1; i >= 0; i--) {
|
|
|
|
+ if (stack[i] < minder._zoomValue) return stack[i];
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ },
|
|
|
|
+ enableReadOnly: true
|
|
|
|
+ });
|
|
|
|
+ return {
|
|
|
|
+ init: function() {
|
|
|
|
+ this._zoomValue = 100;
|
|
|
|
+ this.setDefaultOptions({
|
|
|
|
+ zoom: [ 10, 20, 50, 100, 200 ]
|
|
|
|
+ });
|
|
|
|
+ setTextRendering();
|
|
|
|
+ },
|
|
|
|
+ commands: {
|
|
|
|
+ zoomin: ZoomInCommand,
|
|
|
|
+ zoomout: ZoomOutCommand,
|
|
|
|
+ zoom: ZoomCommand
|
|
|
|
+ },
|
|
|
|
+ events: {
|
|
|
|
+ "normal.mousewheel readonly.mousewheel": function(e) {
|
|
|
|
+ if (!e.originEvent.ctrlKey && !e.originEvent.metaKey) return;
|
|
|
|
+ var delta = e.originEvent.wheelDelta;
|
|
|
|
+ var me = this;
|
|
|
|
+ // 稀释
|
|
|
|
+ if (Math.abs(delta) > 100) {
|
|
|
|
+ clearTimeout(this._wheelZoomTimeout);
|
|
|
|
+ } else {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this._wheelZoomTimeout = setTimeout(function() {
|
|
|
|
+ var value;
|
|
|
|
+ var lastValue = me.getPaper()._zoom || 1;
|
|
|
|
+ if (delta > 0) {
|
|
|
|
+ me.execCommand("zoomin");
|
|
|
|
+ } else if (delta < 0) {
|
|
|
|
+ me.execCommand("zoomout");
|
|
|
|
+ }
|
|
|
|
+ }, 100);
|
|
|
|
+ e.originEvent.preventDefault();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ commandShortcutKeys: {
|
|
|
|
+ zoomin: "ctrl+=",
|
|
|
|
+ zoomout: "ctrl+-"
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/protocol/json.js
|
|
|
|
+_p[64] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var data = _p.r(12);
|
|
|
|
+ data.registerProtocol("json", module.exports = {
|
|
|
|
+ fileDescription: "KityMinder 格式",
|
|
|
|
+ fileExtension: ".km",
|
|
|
|
+ dataType: "text",
|
|
|
|
+ mineType: "application/json",
|
|
|
|
+ encode: function(json) {
|
|
|
|
+ return JSON.stringify(json);
|
|
|
|
+ },
|
|
|
|
+ decode: function(local) {
|
|
|
|
+ return JSON.parse(local);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/protocol/markdown.js
|
|
|
|
+_p[65] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var data = _p.r(12);
|
|
|
|
+ var LINE_ENDING_SPLITER = /\r\n|\r|\n/;
|
|
|
|
+ var EMPTY_LINE = "";
|
|
|
|
+ var NOTE_MARK_START = "\x3c!--Note--\x3e";
|
|
|
|
+ var NOTE_MARK_CLOSE = "\x3c!--/Note--\x3e";
|
|
|
|
+ function encode(json) {
|
|
|
|
+ return _build(json, 1).join("\n");
|
|
|
|
+ }
|
|
|
|
+ function _build(node, level) {
|
|
|
|
+ var lines = [];
|
|
|
|
+ level = level || 1;
|
|
|
|
+ var sharps = _generateHeaderSharp(level);
|
|
|
|
+ lines.push(sharps + " " + node.data.text);
|
|
|
|
+ lines.push(EMPTY_LINE);
|
|
|
|
+ var note = node.data.note;
|
|
|
|
+ if (note) {
|
|
|
|
+ var hasSharp = /^#/.test(note);
|
|
|
|
+ if (hasSharp) {
|
|
|
|
+ lines.push(NOTE_MARK_START);
|
|
|
|
+ note = note.replace(/^#+/gm, function($0) {
|
|
|
|
+ return sharps + $0;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ lines.push(note);
|
|
|
|
+ if (hasSharp) {
|
|
|
|
+ lines.push(NOTE_MARK_CLOSE);
|
|
|
|
+ }
|
|
|
|
+ lines.push(EMPTY_LINE);
|
|
|
|
+ }
|
|
|
|
+ if (node.children) node.children.forEach(function(child) {
|
|
|
|
+ lines = lines.concat(_build(child, level + 1));
|
|
|
|
+ });
|
|
|
|
+ return lines;
|
|
|
|
+ }
|
|
|
|
+ function _generateHeaderSharp(level) {
|
|
|
|
+ var sharps = "";
|
|
|
|
+ while (level--) sharps += "#";
|
|
|
|
+ return sharps;
|
|
|
|
+ }
|
|
|
|
+ function decode(markdown) {
|
|
|
|
+ var json, parentMap = {}, lines, line, lineInfo, level, node, parent, noteProgress, codeBlock;
|
|
|
|
+ // 一级标题转换 `{title}\n===` => `# {title}`
|
|
|
|
+ markdown = markdown.replace(/^(.+)\n={3,}/, function($0, $1) {
|
|
|
|
+ return "# " + $1;
|
|
|
|
+ });
|
|
|
|
+ lines = markdown.split(LINE_ENDING_SPLITER);
|
|
|
|
+ // 按行分析
|
|
|
|
+ for (var i = 0; i < lines.length; i++) {
|
|
|
|
+ line = lines[i];
|
|
|
|
+ lineInfo = _resolveLine(line);
|
|
|
|
+ // 备注标记处理
|
|
|
|
+ if (lineInfo.noteClose) {
|
|
|
|
+ noteProgress = false;
|
|
|
|
+ continue;
|
|
|
|
+ } else if (lineInfo.noteStart) {
|
|
|
|
+ noteProgress = true;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 代码块处理
|
|
|
|
+ codeBlock = lineInfo.codeBlock ? !codeBlock : codeBlock;
|
|
|
|
+ // 备注条件:备注标签中,非标题定义,或标题越位
|
|
|
|
+ if (noteProgress || codeBlock || !lineInfo.level || lineInfo.level > level + 1) {
|
|
|
|
+ if (node) _pushNote(node, line);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 标题处理
|
|
|
|
+ level = lineInfo.level;
|
|
|
|
+ node = _initNode(lineInfo.content, parentMap[level - 1]);
|
|
|
|
+ parentMap[level] = node;
|
|
|
|
+ }
|
|
|
|
+ _cleanUp(parentMap[1]);
|
|
|
|
+ return parentMap[1];
|
|
|
|
+ }
|
|
|
|
+ function _initNode(text, parent) {
|
|
|
|
+ var node = {
|
|
|
|
+ data: {
|
|
|
|
+ text: text,
|
|
|
|
+ note: ""
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ if (parent) {
|
|
|
|
+ if (parent.children) parent.children.push(node); else parent.children = [ node ];
|
|
|
|
+ }
|
|
|
|
+ return node;
|
|
|
|
+ }
|
|
|
|
+ function _pushNote(node, line) {
|
|
|
|
+ node.data.note += line + "\n";
|
|
|
|
+ }
|
|
|
|
+ function _isEmpty(line) {
|
|
|
|
+ return !/\S/.test(line);
|
|
|
|
+ }
|
|
|
|
+ function _resolveLine(line) {
|
|
|
|
+ var match = /^(#+)?\s*(.*)$/.exec(line);
|
|
|
|
+ return {
|
|
|
|
+ level: match[1] && match[1].length || null,
|
|
|
|
+ content: match[2],
|
|
|
|
+ noteStart: line == NOTE_MARK_START,
|
|
|
|
+ noteClose: line == NOTE_MARK_CLOSE,
|
|
|
|
+ codeBlock: /^\s*```/.test(line)
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function _cleanUp(node) {
|
|
|
|
+ if (!/\S/.test(node.data.note)) {
|
|
|
|
+ node.data.note = null;
|
|
|
|
+ delete node.data.note;
|
|
|
|
+ } else {
|
|
|
|
+ var notes = node.data.note.split("\n");
|
|
|
|
+ while (notes.length && !/\S/.test(notes[0])) notes.shift();
|
|
|
|
+ while (notes.length && !/\S/.test(notes[notes.length - 1])) notes.pop();
|
|
|
|
+ node.data.note = notes.join("\n");
|
|
|
|
+ }
|
|
|
|
+ if (node.children) node.children.forEach(_cleanUp);
|
|
|
|
+ }
|
|
|
|
+ data.registerProtocol("markdown", module.exports = {
|
|
|
|
+ fileDescription: "Markdown/GFM 格式",
|
|
|
|
+ fileExtension: ".md",
|
|
|
|
+ mineType: "text/markdown",
|
|
|
|
+ dataType: "text",
|
|
|
|
+ encode: function(json) {
|
|
|
|
+ return encode(json.root);
|
|
|
|
+ },
|
|
|
|
+ decode: function(markdown) {
|
|
|
|
+ return decode(markdown);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/protocol/png.js
|
|
|
|
+_p[66] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var data = _p.r(12);
|
|
|
|
+ var Promise = _p.r(25);
|
|
|
|
+ var DomURL = window.URL || window.webkitURL || window;
|
|
|
|
+ function loadImage(info, callback) {
|
|
|
|
+ return new Promise(function(resolve, reject) {
|
|
|
|
+ var image = document.createElement("img");
|
|
|
|
+ image.onload = function() {
|
|
|
|
+ resolve({
|
|
|
|
+ element: this,
|
|
|
|
+ x: info.x,
|
|
|
|
+ y: info.y,
|
|
|
|
+ width: info.width,
|
|
|
|
+ height: info.height
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ image.onerror = function(err) {
|
|
|
|
+ reject(err);
|
|
|
|
+ };
|
|
|
|
+ image.crossOrigin = "anonymous";
|
|
|
|
+ image.src = info.url;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * xhrLoadImage: 通过 xhr 加载保存在 BOS 上的图片
|
|
|
|
+ * @note: BOS 上的 CORS 策略是取 headers 里面的 Origin 字段进行判断
|
|
|
|
+ * 而通过 image 的 src 的方式是无法传递 origin 的,因此需要通过 xhr 进行
|
|
|
|
+ */
|
|
|
|
+ function xhrLoadImage(info, callback) {
|
|
|
|
+ return Promise(function(resolve, reject) {
|
|
|
|
+ var xmlHttp = new XMLHttpRequest();
|
|
|
|
+ xmlHttp.open("GET", info.url + "?_=" + Date.now(), true);
|
|
|
|
+ xmlHttp.responseType = "blob";
|
|
|
|
+ xmlHttp.onreadystatechange = function() {
|
|
|
|
+ if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
|
|
|
|
+ var blob = xmlHttp.response;
|
|
|
|
+ var image = document.createElement("img");
|
|
|
|
+ image.src = DomURL.createObjectURL(blob);
|
|
|
|
+ image.onload = function() {
|
|
|
|
+ DomURL.revokeObjectURL(image.src);
|
|
|
|
+ resolve({
|
|
|
|
+ element: image,
|
|
|
|
+ x: info.x,
|
|
|
|
+ y: info.y,
|
|
|
|
+ width: info.width,
|
|
|
|
+ height: info.height
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ xmlHttp.send();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ function getSVGInfo(minder) {
|
|
|
|
+ var paper = minder.getPaper(), paperTransform, domContainer = paper.container, svgXml, svgContainer, svgDom, renderContainer = minder.getRenderContainer(), renderBox = renderContainer.getRenderBox(), width = renderBox.width + 1, height = renderBox.height + 1, blob, svgUrl, img;
|
|
|
|
+ // 保存原始变换,并且移动到合适的位置
|
|
|
|
+ paperTransform = paper.shapeNode.getAttribute("transform");
|
|
|
|
+ paper.shapeNode.setAttribute("transform", "translate(0.5, 0.5)");
|
|
|
|
+ renderContainer.translate(-renderBox.x, -renderBox.y);
|
|
|
|
+ // 获取当前的 XML 代码
|
|
|
|
+ svgXml = paper.container.innerHTML;
|
|
|
|
+ // 回复原始变换及位置
|
|
|
|
+ renderContainer.translate(renderBox.x, renderBox.y);
|
|
|
|
+ paper.shapeNode.setAttribute("transform", paperTransform);
|
|
|
|
+ // 过滤内容
|
|
|
|
+ svgContainer = document.createElement("div");
|
|
|
|
+ svgContainer.innerHTML = svgXml;
|
|
|
|
+ svgDom = svgContainer.querySelector("svg");
|
|
|
|
+ svgDom.setAttribute("width", renderBox.width + 1);
|
|
|
|
+ svgDom.setAttribute("height", renderBox.height + 1);
|
|
|
|
+ svgDom.setAttribute("style", 'font-family: Arial, "Microsoft Yahei","Heiti SC";');
|
|
|
|
+ svgContainer = document.createElement("div");
|
|
|
|
+ svgContainer.appendChild(svgDom);
|
|
|
|
+ svgXml = svgContainer.innerHTML;
|
|
|
|
+ // Dummy IE
|
|
|
|
+ svgXml = svgXml.replace(' xmlns="http://www.w3.org/2000/svg" ' + 'xmlns:NS1="" NS1:ns1:xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:NS2="" NS2:xmlns:ns1=""', "");
|
|
|
|
+ // svg 含有 符号导出报错 Entity 'nbsp' not defined ,含有控制字符触发Load Image 会触发报错
|
|
|
|
+ svgXml = svgXml.replace(/ |[\x00-\x1F\x7F-\x9F]/g, "");
|
|
|
|
+ // fix title issue in safari
|
|
|
|
+ // @ http://stackoverflow.com/questions/30273775/namespace-prefix-ns1-for-href-on-tagelement-is-not-defined-setattributens
|
|
|
|
+ svgXml = svgXml.replace(/NS\d+:title/gi, "xlink:title");
|
|
|
|
+ blob = new Blob([ svgXml ], {
|
|
|
|
+ type: "image/svg+xml"
|
|
|
|
+ });
|
|
|
|
+ svgUrl = DomURL.createObjectURL(blob);
|
|
|
|
+ //svgUrl = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgXml);
|
|
|
|
+ var imagesInfo = [];
|
|
|
|
+ // 遍历取出图片信息
|
|
|
|
+ traverse(minder.getRoot());
|
|
|
|
+ function traverse(node) {
|
|
|
|
+ var nodeData = node.data;
|
|
|
|
+ if (nodeData.image) {
|
|
|
|
+ minder.renderNode(node);
|
|
|
|
+ var nodeData = node.data;
|
|
|
|
+ var imageUrl = nodeData.image;
|
|
|
|
+ var imageSize = nodeData.imageSize;
|
|
|
|
+ var imageRenderBox = node.getRenderBox("ImageRenderer", minder.getRenderContainer());
|
|
|
|
+ var imageInfo = {
|
|
|
|
+ url: imageUrl,
|
|
|
|
+ width: imageSize.width,
|
|
|
|
+ height: imageSize.height,
|
|
|
|
+ x: -renderContainer.getBoundaryBox().x + imageRenderBox.x,
|
|
|
|
+ y: -renderContainer.getBoundaryBox().y + imageRenderBox.y
|
|
|
|
+ };
|
|
|
|
+ imagesInfo.push(imageInfo);
|
|
|
|
+ }
|
|
|
|
+ // 若节点折叠,则直接返回
|
|
|
|
+ if (nodeData.expandState === "collapse") {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ var children = node.getChildren();
|
|
|
|
+ for (var i = 0; i < children.length; i++) {
|
|
|
|
+ traverse(children[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ width: width,
|
|
|
|
+ height: height,
|
|
|
|
+ dataUrl: svgUrl,
|
|
|
|
+ xml: svgXml,
|
|
|
|
+ imagesInfo: imagesInfo
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function encode(json, minder, option) {
|
|
|
|
+ var resultCallback;
|
|
|
|
+ /* 绘制 PNG 的画布及上下文 */
|
|
|
|
+ var canvas = document.createElement("canvas");
|
|
|
|
+ var ctx = canvas.getContext("2d");
|
|
|
|
+ /* 尝试获取背景图片 URL 或背景颜色 */
|
|
|
|
+ var bgDeclare = minder.getStyle("background").toString();
|
|
|
|
+ var bgUrl = /url\(\"(.+)\"\)/.exec(bgDeclare);
|
|
|
|
+ var bgColor = kity.Color.parse(bgDeclare);
|
|
|
|
+ /* 获取 SVG 文件内容 */
|
|
|
|
+ var svgInfo = getSVGInfo(minder);
|
|
|
|
+ var width = option && option.width && option.width > svgInfo.width ? option.width : svgInfo.width;
|
|
|
|
+ var height = option && option.height && option.height > svgInfo.height ? option.height : svgInfo.height;
|
|
|
|
+ var offsetX = option && option.width && option.width > svgInfo.width ? (option.width - svgInfo.width) / 2 : 0;
|
|
|
|
+ var offsetY = option && option.height && option.height > svgInfo.height ? (option.height - svgInfo.height) / 2 : 0;
|
|
|
|
+ var svgDataUrl = svgInfo.dataUrl;
|
|
|
|
+ var imagesInfo = svgInfo.imagesInfo;
|
|
|
|
+ /* 画布的填充大小 */
|
|
|
|
+ var padding = 20;
|
|
|
|
+ canvas.width = width + padding * 2;
|
|
|
|
+ canvas.height = height + padding * 2;
|
|
|
|
+ function fillBackground(ctx, style) {
|
|
|
|
+ ctx.save();
|
|
|
|
+ ctx.fillStyle = style;
|
|
|
|
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
+ ctx.restore();
|
|
|
|
+ }
|
|
|
|
+ function drawImage(ctx, image, x, y, width, height) {
|
|
|
|
+ if (width && height) {
|
|
|
|
+ ctx.drawImage(image, x + padding, y + padding, width, height);
|
|
|
|
+ } else {
|
|
|
|
+ ctx.drawImage(image, x + padding, y + padding);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ function generateDataUrl(canvas) {
|
|
|
|
+ return canvas.toDataURL("image/png");
|
|
|
|
+ }
|
|
|
|
+ // 加载节点上的图片
|
|
|
|
+ function loadImages(imagesInfo) {
|
|
|
|
+ var imagePromises = imagesInfo.map(function(imageInfo) {
|
|
|
|
+ return xhrLoadImage(imageInfo);
|
|
|
|
+ });
|
|
|
|
+ return Promise.all(imagePromises);
|
|
|
|
+ }
|
|
|
|
+ function drawSVG() {
|
|
|
|
+ var svgData = {
|
|
|
|
+ url: svgDataUrl
|
|
|
|
+ };
|
|
|
|
+ return loadImage(svgData).then(function($image) {
|
|
|
|
+ drawImage(ctx, $image.element, offsetX, offsetY, $image.width, $image.height);
|
|
|
|
+ return loadImages(imagesInfo);
|
|
|
|
+ }).then(function($images) {
|
|
|
|
+ for (var i = 0; i < $images.length; i++) {
|
|
|
|
+ drawImage(ctx, $images[i].element, $images[i].x + offsetX, $images[i].y + offsetY, $images[i].width, $images[i].height);
|
|
|
|
+ }
|
|
|
|
+ DomURL.revokeObjectURL(svgDataUrl);
|
|
|
|
+ document.body.appendChild(canvas);
|
|
|
|
+ var pngBase64 = generateDataUrl(canvas);
|
|
|
|
+ document.body.removeChild(canvas);
|
|
|
|
+ return pngBase64;
|
|
|
|
+ }, function(err) {
|
|
|
|
+ // 这里处理 reject,出错基本上是因为跨域,
|
|
|
|
+ // 出错后依然导出,只不过没有图片。
|
|
|
|
+ alert("脑图的节点中包含跨域图片,导出的 png 中节点图片不显示,你可以替换掉这些跨域的图片并重试。");
|
|
|
|
+ DomURL.revokeObjectURL(svgDataUrl);
|
|
|
|
+ document.body.appendChild(canvas);
|
|
|
|
+ var pngBase64 = generateDataUrl(canvas);
|
|
|
|
+ document.body.removeChild(canvas);
|
|
|
|
+ return pngBase64;
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (bgUrl) {
|
|
|
|
+ var bgInfo = {
|
|
|
|
+ url: bgUrl[1]
|
|
|
|
+ };
|
|
|
|
+ return loadImage(bgInfo).then(function($image) {
|
|
|
|
+ fillBackground(ctx, ctx.createPattern($image.element, "repeat"));
|
|
|
|
+ return drawSVG();
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ fillBackground(ctx, bgColor.toString());
|
|
|
|
+ return drawSVG();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ data.registerProtocol("png", module.exports = {
|
|
|
|
+ fileDescription: "PNG 图片",
|
|
|
|
+ fileExtension: ".png",
|
|
|
|
+ mineType: "image/png",
|
|
|
|
+ dataType: "base64",
|
|
|
|
+ encode: encode
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/protocol/svg.js
|
|
|
|
+_p[67] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var data = _p.r(12);
|
|
|
|
+ /**
|
|
|
|
+ * 导出svg时删除全部svg元素中的transform
|
|
|
|
+ * @auth Naixor
|
|
|
|
+ * @method removeTransform
|
|
|
|
+ * @param {[type]} svgDom [description]
|
|
|
|
+ * @return {[type]} [description]
|
|
|
|
+ */
|
|
|
|
+ function cleanSVG(svgDom, x, y) {
|
|
|
|
+ function getTransformToElement(target, source) {
|
|
|
|
+ var matrix;
|
|
|
|
+ try {
|
|
|
|
+ matrix = source.getScreenCTM().inverse();
|
|
|
|
+ } catch (e) {
|
|
|
|
+ throw new Error("Can not inverse source element' ctm.");
|
|
|
|
+ }
|
|
|
|
+ return matrix.multiply(target.getScreenCTM());
|
|
|
|
+ }
|
|
|
|
+ function dealWithPath(d, dealWithPattern) {
|
|
|
|
+ if (!(dealWithPattern instanceof Function)) {
|
|
|
|
+ dealWithPattern = function() {};
|
|
|
|
+ }
|
|
|
|
+ var strArr = [], pattern = [], cache = [];
|
|
|
|
+ for (var i = 0, l = d.length; i < l; i++) {
|
|
|
|
+ switch (d[i]) {
|
|
|
|
+ case "M":
|
|
|
|
+ case "L":
|
|
|
|
+ case "T":
|
|
|
|
+ case "S":
|
|
|
|
+ case "A":
|
|
|
|
+ case "C":
|
|
|
|
+ case "H":
|
|
|
|
+ case "V":
|
|
|
|
+ case "Q":
|
|
|
|
+ {
|
|
|
|
+ if (cache.length) {
|
|
|
|
+ pattern.push(cache.join(""));
|
|
|
|
+ cache = [];
|
|
|
|
+ }
|
|
|
|
+ // 脑图的path格式真奇怪...偶尔就给我蹦出来一个"..V123 C..", 那空格几个意思 - -
|
|
|
|
+ if (pattern[pattern.length - 1] === ",") {
|
|
|
|
+ pattern.pop();
|
|
|
|
+ }
|
|
|
|
+ if (pattern.length) {
|
|
|
|
+ dealWithPattern(pattern);
|
|
|
|
+ strArr.push(pattern.join(""));
|
|
|
|
+ pattern = [];
|
|
|
|
+ }
|
|
|
|
+ pattern.push(d[i]);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "Z":
|
|
|
|
+ case "z":
|
|
|
|
+ {
|
|
|
|
+ pattern.push(cache.join(""), d[i]);
|
|
|
|
+ dealWithPattern(pattern);
|
|
|
|
+ strArr.push(pattern.join(""));
|
|
|
|
+ cache = [];
|
|
|
|
+ pattern = [];
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case ".":
|
|
|
|
+ case "e":
|
|
|
|
+ {
|
|
|
|
+ cache.push(d[i]);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "-":
|
|
|
|
+ {
|
|
|
|
+ if (d[i - 1] !== "e") {
|
|
|
|
+ if (cache.length) {
|
|
|
|
+ pattern.push(cache.join(""), ",");
|
|
|
|
+ }
|
|
|
|
+ cache = [];
|
|
|
|
+ }
|
|
|
|
+ cache.push("-");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case " ":
|
|
|
|
+ case ",":
|
|
|
|
+ {
|
|
|
|
+ if (cache.length) {
|
|
|
|
+ pattern.push(cache.join(""), ",");
|
|
|
|
+ cache = [];
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ {
|
|
|
|
+ if (/\d/.test(d[i])) {
|
|
|
|
+ cache.push(d[i]);
|
|
|
|
+ } else {
|
|
|
|
+ // m a c s q h v l t z情况
|
|
|
|
+ if (cache.length) {
|
|
|
|
+ pattern.push(cache.join(""), d[i]);
|
|
|
|
+ cache = [];
|
|
|
|
+ } else {
|
|
|
|
+ // 脑图的path格式真奇怪...偶尔就给我蹦出来一个"..V123 c..", 那空格几个意思 - -
|
|
|
|
+ if (pattern[pattern.length - 1] === ",") {
|
|
|
|
+ pattern.pop();
|
|
|
|
+ }
|
|
|
|
+ pattern.push(d[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (i + 1 === l) {
|
|
|
|
+ if (cache.length) {
|
|
|
|
+ pattern.push(cache.join(""));
|
|
|
|
+ }
|
|
|
|
+ dealWithPattern(pattern);
|
|
|
|
+ strArr.push(pattern.join(""));
|
|
|
|
+ cache = null;
|
|
|
|
+ pattern = null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return strArr.join("");
|
|
|
|
+ }
|
|
|
|
+ function replaceWithNode(svgNode, parentX, parentY) {
|
|
|
|
+ if (!svgNode) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (svgNode.tagName === "defs") {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (svgNode.getAttribute("fill") === "transparent") {
|
|
|
|
+ svgNode.setAttribute("fill", "none");
|
|
|
|
+ }
|
|
|
|
+ if (svgNode.getAttribute("marker-end")) {
|
|
|
|
+ svgNode.removeAttribute("marker-end");
|
|
|
|
+ }
|
|
|
|
+ parentX = parentX || 0;
|
|
|
|
+ parentY = parentY || 0;
|
|
|
|
+ if (svgNode.getAttribute("transform")) {
|
|
|
|
+ var ctm = getTransformToElement(svgNode, svgNode.parentElement);
|
|
|
|
+ parentX -= ctm.e;
|
|
|
|
+ parentY -= ctm.f;
|
|
|
|
+ svgNode.removeAttribute("transform");
|
|
|
|
+ }
|
|
|
|
+ switch (svgNode.tagName.toLowerCase()) {
|
|
|
|
+ case "g":
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "path":
|
|
|
|
+ {
|
|
|
|
+ var d = svgNode.getAttribute("d");
|
|
|
|
+ if (d) {
|
|
|
|
+ d = dealWithPath(d, function(pattern) {
|
|
|
|
+ switch (pattern[0]) {
|
|
|
|
+ case "V":
|
|
|
|
+ {
|
|
|
|
+ pattern[1] = +pattern[1] - parentY;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "H":
|
|
|
|
+ {
|
|
|
|
+ pattern[1] = +pattern[1] - parentX;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "M":
|
|
|
|
+ case "L":
|
|
|
|
+ case "T":
|
|
|
|
+ {
|
|
|
|
+ pattern[1] = +pattern[1] - parentX;
|
|
|
|
+ pattern[3] = +pattern[3] - parentY;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "Q":
|
|
|
|
+ case "S":
|
|
|
|
+ {
|
|
|
|
+ pattern[1] = +pattern[1] - parentX;
|
|
|
|
+ pattern[3] = +pattern[3] - parentY;
|
|
|
|
+ pattern[5] = +pattern[5] - parentX;
|
|
|
|
+ pattern[7] = +pattern[7] - parentY;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "A":
|
|
|
|
+ {
|
|
|
|
+ pattern[11] = +pattern[11] - parentX;
|
|
|
|
+ pattern[13] = +pattern[13] - parentY;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "C":
|
|
|
|
+ {
|
|
|
|
+ pattern[1] = +pattern[1] - parentX;
|
|
|
|
+ pattern[3] = +pattern[3] - parentY;
|
|
|
|
+ pattern[5] = +pattern[5] - parentX;
|
|
|
|
+ pattern[7] = +pattern[7] - parentY;
|
|
|
|
+ pattern[9] = +pattern[9] - parentX;
|
|
|
|
+ pattern[11] = +pattern[11] - parentY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ svgNode.setAttribute("d", d);
|
|
|
|
+ svgNode.removeAttribute("transform");
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case "image":
|
|
|
|
+ case "text":
|
|
|
|
+ {
|
|
|
|
+ if (parentX && parentY) {
|
|
|
|
+ var x = +svgNode.getAttribute("x") || 0, y = +svgNode.getAttribute("y") || 0;
|
|
|
|
+ svgNode.setAttribute("x", x - parentX);
|
|
|
|
+ svgNode.setAttribute("y", y - parentY);
|
|
|
|
+ }
|
|
|
|
+ if (svgNode.getAttribute("dominant-baseline")) {
|
|
|
|
+ svgNode.removeAttribute("dominant-baseline");
|
|
|
|
+ svgNode.setAttribute("dy", ".8em");
|
|
|
|
+ }
|
|
|
|
+ svgNode.removeAttribute("transform");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (svgNode.children) {
|
|
|
|
+ for (var i = 0, l = svgNode.children.length; i < l; i++) {
|
|
|
|
+ replaceWithNode(svgNode.children[i], parentX, parentY);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ svgDom.style.visibility = "hidden";
|
|
|
|
+ replaceWithNode(svgDom, x || 0, y || 0);
|
|
|
|
+ svgDom.style.visibility = "visible";
|
|
|
|
+ }
|
|
|
|
+ data.registerProtocol("svg", module.exports = {
|
|
|
|
+ fileDescription: "SVG 矢量图",
|
|
|
|
+ fileExtension: ".svg",
|
|
|
|
+ mineType: "image/svg+xml",
|
|
|
|
+ dataType: "text",
|
|
|
|
+ encode: function(json, minder) {
|
|
|
|
+ var paper = minder.getPaper(), paperTransform = paper.shapeNode.getAttribute("transform"), svgXml, svgContainer, svgDom, renderContainer = minder.getRenderContainer(), renderBox = renderContainer.getRenderBox(), transform = renderContainer.getTransform(), width = renderBox.width, height = renderBox.height, padding = 20;
|
|
|
|
+ paper.shapeNode.setAttribute("transform", "translate(0.5, 0.5)");
|
|
|
|
+ svgXml = paper.container.innerHTML;
|
|
|
|
+ paper.shapeNode.setAttribute("transform", paperTransform);
|
|
|
|
+ svgContainer = document.createElement("div");
|
|
|
|
+ document.body.appendChild(svgContainer);
|
|
|
|
+ svgContainer.innerHTML = svgXml;
|
|
|
|
+ svgDom = svgContainer.querySelector("svg");
|
|
|
|
+ svgDom.setAttribute("width", width + padding * 2 | 0);
|
|
|
|
+ svgDom.setAttribute("height", height + padding * 2 | 0);
|
|
|
|
+ svgDom.setAttribute("style", "background: " + minder.getStyle("background"));
|
|
|
|
+ //"font-family: Arial, Microsoft Yahei, Heiti SC; " +
|
|
|
|
+ svgDom.setAttribute("viewBox", [ 0, 0, width + padding * 2 | 0, height + padding * 2 | 0 ].join(" "));
|
|
|
|
+ tempSvgContainer = document.createElement("div");
|
|
|
|
+ cleanSVG(svgDom, renderBox.x - padding | 0, renderBox.y - padding | 0);
|
|
|
|
+ document.body.removeChild(svgContainer);
|
|
|
|
+ tempSvgContainer.appendChild(svgDom);
|
|
|
|
+ // need a xml with width and height
|
|
|
|
+ svgXml = tempSvgContainer.innerHTML;
|
|
|
|
+ // svg 含有 符号导出报错 Entity 'nbsp' not defined
|
|
|
|
+ svgXml = svgXml.replace(/ /g, " ");
|
|
|
|
+ // svg 含有 符号导出报错 Entity 'nbsp' not defined
|
|
|
|
+ return svgXml;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/protocol/text.js
|
|
|
|
+_p[68] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var data = _p.r(12);
|
|
|
|
+ var Browser = _p.r(17).Browser;
|
|
|
|
+ /**
|
|
|
|
+ * @Desc: 增加对不容浏览器下节点中文本\t匹配的处理,不同浏览器下\t无法正确匹配,导致无法使用TAB来批量导入节点
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.17
|
|
|
|
+ */
|
|
|
|
+ var LINE_ENDING = "\r", LINE_ENDING_SPLITER = /\r\n|\r|\n/, TAB_CHAR = function(Browser) {
|
|
|
|
+ if (Browser.gecko) {
|
|
|
|
+ return {
|
|
|
|
+ REGEXP: new RegExp("^(\t|" + String.fromCharCode(160, 160, 32, 160) + ")"),
|
|
|
|
+ DELETE: new RegExp("^(\t|" + String.fromCharCode(160, 160, 32, 160) + ")+")
|
|
|
|
+ };
|
|
|
|
+ } else if (Browser.ie || Browser.edge) {
|
|
|
|
+ // ie系列和edge比较特别,\t在div中会被直接转义成SPACE故只好使用SPACE来做处理
|
|
|
|
+ return {
|
|
|
|
+ REGEXP: new RegExp("^(" + String.fromCharCode(32) + "|" + String.fromCharCode(160) + ")"),
|
|
|
|
+ DELETE: new RegExp("^(" + String.fromCharCode(32) + "|" + String.fromCharCode(160) + ")+")
|
|
|
|
+ };
|
|
|
|
+ } else {
|
|
|
|
+ return {
|
|
|
|
+ REGEXP: /^(\t|\x20{4})/,
|
|
|
|
+ DELETE: /^(\t|\x20{4})+/
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }(Browser);
|
|
|
|
+ function repeat(s, n) {
|
|
|
|
+ var result = "";
|
|
|
|
+ while (n--) result += s;
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 对节点text中的换行符进行处理
|
|
|
|
+ * @method encodeWrap
|
|
|
|
+ * @param {String} nodeText MinderNode.data.text
|
|
|
|
+ * @return {String} \n -> '\n'; \\n -> '\\n'
|
|
|
|
+ */
|
|
|
|
+ function encodeWrap(nodeText) {
|
|
|
|
+ if (!nodeText) {
|
|
|
|
+ return "";
|
|
|
|
+ }
|
|
|
|
+ var textArr = [], WRAP_TEXT = [ "\\", "n" ];
|
|
|
|
+ for (var i = 0, j = 0, l = nodeText.length; i < l; i++) {
|
|
|
|
+ if (nodeText[i] === "\n" || nodeText[i] === "\r") {
|
|
|
|
+ textArr.push("\\n");
|
|
|
|
+ j = 0;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (nodeText[i] === WRAP_TEXT[j]) {
|
|
|
|
+ j++;
|
|
|
|
+ if (j === 2) {
|
|
|
|
+ j = 0;
|
|
|
|
+ textArr.push("\\\\n");
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ switch (j) {
|
|
|
|
+ case 0:
|
|
|
|
+ {
|
|
|
|
+ textArr.push(nodeText[i]);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case 1:
|
|
|
|
+ {
|
|
|
|
+ textArr.push(nodeText[i - 1], nodeText[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ j = 0;
|
|
|
|
+ }
|
|
|
|
+ return textArr.join("");
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 将文本内容中的'\n'和'\\n'分别转换成\n和\\n
|
|
|
|
+ * @method decodeWrap
|
|
|
|
+ * @param {[type]} text [description]
|
|
|
|
+ * @return {[type]} [description]
|
|
|
|
+ */
|
|
|
|
+ function decodeWrap(text) {
|
|
|
|
+ if (!text) {
|
|
|
|
+ return "";
|
|
|
|
+ }
|
|
|
|
+ var textArr = [], WRAP_TEXT = [ "\\", "\\", "n" ];
|
|
|
|
+ for (var i = 0, j = 0, l = text.length; i < l; i++) {
|
|
|
|
+ if (text[i] === WRAP_TEXT[j]) {
|
|
|
|
+ j++;
|
|
|
|
+ if (j === 3) {
|
|
|
|
+ j = 0;
|
|
|
|
+ textArr.push("\\n");
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ switch (j) {
|
|
|
|
+ case 0:
|
|
|
|
+ {
|
|
|
|
+ textArr.push(text[i]);
|
|
|
|
+ j = 0;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case 1:
|
|
|
|
+ {
|
|
|
|
+ if (text[i] === "n") {
|
|
|
|
+ textArr.push("\n");
|
|
|
|
+ } else {
|
|
|
|
+ textArr.push(text[i - 1], text[i]);
|
|
|
|
+ }
|
|
|
|
+ j = 0;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ case 2:
|
|
|
|
+ {
|
|
|
|
+ textArr.push(text[i - 2]);
|
|
|
|
+ if (text[i] !== "\\") {
|
|
|
|
+ j = 0;
|
|
|
|
+ textArr.push(text[i - 1], text[i]);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return textArr.join("");
|
|
|
|
+ }
|
|
|
|
+ function encode(json, level) {
|
|
|
|
+ var local = "";
|
|
|
|
+ level = level || 0;
|
|
|
|
+ local += repeat("\t", level);
|
|
|
|
+ local += encodeWrap(json.data.text) + LINE_ENDING;
|
|
|
|
+ if (json.children) {
|
|
|
|
+ json.children.forEach(function(child) {
|
|
|
|
+ local += encode(child, level + 1);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ return local;
|
|
|
|
+ }
|
|
|
|
+ function isEmpty(line) {
|
|
|
|
+ return !/\S/.test(line);
|
|
|
|
+ }
|
|
|
|
+ function getLevel(line) {
|
|
|
|
+ var level = 0;
|
|
|
|
+ while (TAB_CHAR.REGEXP.test(line)) {
|
|
|
|
+ line = line.replace(TAB_CHAR.REGEXP, "");
|
|
|
|
+ level++;
|
|
|
|
+ }
|
|
|
|
+ return level;
|
|
|
|
+ }
|
|
|
|
+ function getNode(line) {
|
|
|
|
+ return {
|
|
|
|
+ data: {
|
|
|
|
+ text: decodeWrap(line.replace(TAB_CHAR.DELETE, ""))
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function decode(local) {
|
|
|
|
+ var json, parentMap = {}, lines = local.split(LINE_ENDING_SPLITER), line, level, node;
|
|
|
|
+ function addChild(parent, child) {
|
|
|
|
+ var children = parent.children || (parent.children = []);
|
|
|
|
+ children.push(child);
|
|
|
|
+ }
|
|
|
|
+ for (var i = 0; i < lines.length; i++) {
|
|
|
|
+ line = lines[i];
|
|
|
|
+ if (isEmpty(line)) continue;
|
|
|
|
+ level = getLevel(line);
|
|
|
|
+ node = getNode(line);
|
|
|
|
+ if (level === 0) {
|
|
|
|
+ if (json) {
|
|
|
|
+ throw new Error("Invalid local format");
|
|
|
|
+ }
|
|
|
|
+ json = node;
|
|
|
|
+ } else {
|
|
|
|
+ if (!parentMap[level - 1]) {
|
|
|
|
+ throw new Error("Invalid local format");
|
|
|
|
+ }
|
|
|
|
+ addChild(parentMap[level - 1], node);
|
|
|
|
+ }
|
|
|
|
+ parentMap[level] = node;
|
|
|
|
+ }
|
|
|
|
+ return json;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @Desc: 增加一个将当前选中节点转换成text的方法
|
|
|
|
+ * @Editor: Naixor
|
|
|
|
+ * @Date: 2015.9.21
|
|
|
|
+ */
|
|
|
|
+ function Node2Text(node) {
|
|
|
|
+ function exportNode(node) {
|
|
|
|
+ var exported = {};
|
|
|
|
+ exported.data = node.getData();
|
|
|
|
+ var childNodes = node.getChildren();
|
|
|
|
+ exported.children = [];
|
|
|
|
+ for (var i = 0; i < childNodes.length; i++) {
|
|
|
|
+ exported.children.push(exportNode(childNodes[i]));
|
|
|
|
+ }
|
|
|
|
+ return exported;
|
|
|
|
+ }
|
|
|
|
+ if (!node) return;
|
|
|
|
+ if (/^\s*$/.test(node.data.text)) {
|
|
|
|
+ node.data.text = "分支主题";
|
|
|
|
+ }
|
|
|
|
+ return encode(exportNode(node));
|
|
|
|
+ }
|
|
|
|
+ data.registerProtocol("text", module.exports = {
|
|
|
|
+ fileDescription: "大纲文本",
|
|
|
|
+ fileExtension: ".txt",
|
|
|
|
+ dataType: "text",
|
|
|
|
+ mineType: "text/plain",
|
|
|
|
+ encode: function(json) {
|
|
|
|
+ return encode(json.root, 0);
|
|
|
|
+ },
|
|
|
|
+ decode: function(local) {
|
|
|
|
+ return decode(local);
|
|
|
|
+ },
|
|
|
|
+ Node2Text: function(node) {
|
|
|
|
+ return Node2Text(node);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/default.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 默认模板 - 脑图模板
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[69] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("default", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ if (node.getData("layout")) return node.getData("layout");
|
|
|
|
+ var level = node.getLevel();
|
|
|
|
+ // 根节点
|
|
|
|
+ if (level === 0) {
|
|
|
|
+ return "mind";
|
|
|
|
+ }
|
|
|
|
+ // 一级节点
|
|
|
|
+ if (level === 1) {
|
|
|
|
+ return node.getLayoutPointPreview().x > 0 ? "right" : "left";
|
|
|
|
+ }
|
|
|
|
+ return node.parent.getLayout();
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ if (node.getLevel() == 1) return "arc";
|
|
|
|
+ return "under";
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/filetree.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 文件夹模板
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[70] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("filetree", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ if (node.getData("layout")) return node.getData("layout");
|
|
|
|
+ if (node.isRoot()) return "bottom";
|
|
|
|
+ return "filetree-down";
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ if (node.getLevel() == 1) {
|
|
|
|
+ return "poly";
|
|
|
|
+ }
|
|
|
|
+ return "l";
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/fish-bone.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 默认模板 - 鱼骨头模板
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[71] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("fish-bone", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ if (node.getData("layout")) return node.getData("layout");
|
|
|
|
+ var level = node.getLevel();
|
|
|
|
+ // 根节点
|
|
|
|
+ if (level === 0) {
|
|
|
|
+ return "fish-bone-master";
|
|
|
|
+ }
|
|
|
|
+ // 一级节点
|
|
|
|
+ if (level === 1) {
|
|
|
|
+ return "fish-bone-slave";
|
|
|
|
+ }
|
|
|
|
+ return node.getLayoutPointPreview().y > 0 ? "filetree-up" : "filetree-down";
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ switch (node.getLevel()) {
|
|
|
|
+ case 1:
|
|
|
|
+ return "fish-bone-master";
|
|
|
|
+
|
|
|
|
+ case 2:
|
|
|
|
+ return "line";
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ return "l";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/right.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 往右布局结构模板
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[72] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("right", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ return node.getData("layout") || "right";
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ if (node.getLevel() == 1) return "arc";
|
|
|
|
+ return "bezier";
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/structure.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 组织结构图模板
|
|
|
|
+ *
|
|
|
|
+ * @author: techird
|
|
|
|
+ * @copyright: Baidu FEX, 2014
|
|
|
|
+ */
|
|
|
|
+_p[73] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("structure", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ return node.getData("layout") || "bottom";
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ return "poly";
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/template/tianpan.js
|
|
|
|
+/**
|
|
|
|
+ * @fileOverview
|
|
|
|
+ *
|
|
|
|
+ * 天盘模板
|
|
|
|
+ *
|
|
|
|
+ * @author: along
|
|
|
|
+ * @copyright: bpd729@163.com, 2015
|
|
|
|
+ */
|
|
|
|
+_p[74] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var template = _p.r(31);
|
|
|
|
+ template.register("tianpan", {
|
|
|
|
+ getLayout: function(node) {
|
|
|
|
+ if (node.getData("layout")) return node.getData("layout");
|
|
|
|
+ var level = node.getLevel();
|
|
|
|
+ // 根节点
|
|
|
|
+ if (level === 0) {
|
|
|
|
+ return "tianpan";
|
|
|
|
+ }
|
|
|
|
+ return node.parent.getLayout();
|
|
|
|
+ },
|
|
|
|
+ getConnect: function(node) {
|
|
|
|
+ return "arc_tp";
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/default.js
|
|
|
|
+_p[75] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ [ "classic", "classic-compact" ].forEach(function(name) {
|
|
|
|
+ var compact = name == "classic-compact";
|
|
|
|
+ /* jscs:disable maximumLineLength */
|
|
|
|
+ theme.register(name, {
|
|
|
|
+ background: '#3A4144 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=") repeat',
|
|
|
|
+ "root-color": "#430",
|
|
|
|
+ "root-background": "#e9df98",
|
|
|
|
+ "root-stroke": "#e9df98",
|
|
|
|
+ "root-font-size": 24,
|
|
|
|
+ "root-padding": compact ? [ 10, 25 ] : [ 15, 25 ],
|
|
|
|
+ "root-margin": compact ? [ 15, 25 ] : [ 30, 100 ],
|
|
|
|
+ "root-radius": 30,
|
|
|
|
+ "root-space": 10,
|
|
|
|
+ "root-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "main-color": "#333",
|
|
|
|
+ "main-background": "#a4c5c0",
|
|
|
|
+ "main-stroke": "#a4c5c0",
|
|
|
|
+ "main-font-size": 16,
|
|
|
|
+ "main-padding": compact ? [ 5, 15 ] : [ 6, 20 ],
|
|
|
|
+ "main-margin": compact ? [ 5, 10 ] : 20,
|
|
|
|
+ "main-radius": 10,
|
|
|
|
+ "main-space": 5,
|
|
|
|
+ "main-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "sub-color": "white",
|
|
|
|
+ "sub-background": "transparent",
|
|
|
|
+ "sub-stroke": "none",
|
|
|
|
+ "sub-font-size": 12,
|
|
|
|
+ "sub-padding": [ 5, 10 ],
|
|
|
|
+ "sub-margin": compact ? [ 5, 10 ] : [ 15, 20 ],
|
|
|
|
+ "sub-tree-margin": 30,
|
|
|
|
+ "sub-radius": 5,
|
|
|
|
+ "sub-space": 5,
|
|
|
|
+ "connect-color": "white",
|
|
|
|
+ "connect-width": 2,
|
|
|
|
+ "main-connect-width": 3,
|
|
|
|
+ "connect-radius": 5,
|
|
|
|
+ "selected-background": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-stroke": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-color": "black",
|
|
|
|
+ "marquee-background": "rgba(255,255,255,.3)",
|
|
|
|
+ "marquee-stroke": "white",
|
|
|
|
+ "drop-hint-color": "yellow",
|
|
|
|
+ "sub-drop-hint-width": 2,
|
|
|
|
+ "main-drop-hint-width": 4,
|
|
|
|
+ "root-drop-hint-width": 4,
|
|
|
|
+ "order-hint-area-color": "rgba(0, 255, 0, .5)",
|
|
|
|
+ "order-hint-path-color": "#0f0",
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": "rgb(27,171,255)",
|
|
|
|
+ "line-height": 1.5
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/fish.js
|
|
|
|
+_p[76] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ theme.register("fish", {
|
|
|
|
+ background: '#3A4144 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=") repeat',
|
|
|
|
+ "root-color": "#430",
|
|
|
|
+ "root-background": "#e9df98",
|
|
|
|
+ "root-stroke": "#e9df98",
|
|
|
|
+ "root-font-size": 24,
|
|
|
|
+ "root-padding": [ 35, 35 ],
|
|
|
|
+ "root-margin": 30,
|
|
|
|
+ "root-radius": 100,
|
|
|
|
+ "root-space": 10,
|
|
|
|
+ "root-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "main-color": "#333",
|
|
|
|
+ "main-background": "#a4c5c0",
|
|
|
|
+ "main-stroke": "#a4c5c0",
|
|
|
|
+ "main-font-size": 16,
|
|
|
|
+ "main-padding": [ 6, 20 ],
|
|
|
|
+ "main-margin": [ 20, 20 ],
|
|
|
|
+ "main-radius": 5,
|
|
|
|
+ "main-space": 5,
|
|
|
|
+ "main-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "sub-color": "black",
|
|
|
|
+ "sub-background": "white",
|
|
|
|
+ "sub-stroke": "white",
|
|
|
|
+ "sub-font-size": 12,
|
|
|
|
+ "sub-padding": [ 5, 10 ],
|
|
|
|
+ "sub-margin": [ 10 ],
|
|
|
|
+ "sub-radius": 5,
|
|
|
|
+ "sub-space": 5,
|
|
|
|
+ "connect-color": "white",
|
|
|
|
+ "connect-width": 3,
|
|
|
|
+ "main-connect-width": 3,
|
|
|
|
+ "connect-radius": 5,
|
|
|
|
+ "selected-background": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-stroke": "rgb(254, 219, 0)",
|
|
|
|
+ "marquee-background": "rgba(255,255,255,.3)",
|
|
|
|
+ "marquee-stroke": "white",
|
|
|
|
+ "drop-hint-color": "yellow",
|
|
|
|
+ "drop-hint-width": 4,
|
|
|
|
+ "order-hint-area-color": "rgba(0, 255, 0, .5)",
|
|
|
|
+ "order-hint-path-color": "#0f0",
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": "rgb(27,171,255)",
|
|
|
|
+ "line-height": 1.5
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/fresh.js
|
|
|
|
+_p[77] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var kity = _p.r(17);
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ function hsl(h, s, l) {
|
|
|
|
+ return kity.Color.createHSL(h, s, l);
|
|
|
|
+ }
|
|
|
|
+ function generate(h, compat) {
|
|
|
|
+ return {
|
|
|
|
+ background: "#fbfbfb",
|
|
|
|
+ "root-color": "white",
|
|
|
|
+ "root-background": hsl(h, 37, 60),
|
|
|
|
+ "root-stroke": hsl(h, 37, 60),
|
|
|
|
+ "root-font-size": 16,
|
|
|
|
+ "root-padding": compat ? [ 6, 12 ] : [ 12, 24 ],
|
|
|
|
+ "root-margin": compat ? 10 : [ 30, 100 ],
|
|
|
|
+ "root-radius": 5,
|
|
|
|
+ "root-space": 10,
|
|
|
|
+ "main-color": "black",
|
|
|
|
+ "main-background": hsl(h, 33, 95),
|
|
|
|
+ "main-stroke": hsl(h, 37, 60),
|
|
|
|
+ "main-stroke-width": 1,
|
|
|
|
+ "main-font-size": 14,
|
|
|
|
+ "main-padding": [ 6, 20 ],
|
|
|
|
+ "main-margin": compat ? 8 : 20,
|
|
|
|
+ "main-radius": 3,
|
|
|
|
+ "main-space": 5,
|
|
|
|
+ "sub-color": "black",
|
|
|
|
+ "sub-background": "transparent",
|
|
|
|
+ "sub-stroke": "none",
|
|
|
|
+ "sub-font-size": 12,
|
|
|
|
+ "sub-padding": compat ? [ 3, 5 ] : [ 5, 10 ],
|
|
|
|
+ "sub-margin": compat ? [ 4, 8 ] : [ 15, 20 ],
|
|
|
|
+ "sub-radius": 5,
|
|
|
|
+ "sub-space": 5,
|
|
|
|
+ "connect-color": hsl(h, 37, 60),
|
|
|
|
+ "connect-width": 1,
|
|
|
|
+ "connect-radius": 5,
|
|
|
|
+ "selected-stroke": hsl(h, 26, 30),
|
|
|
|
+ "selected-stroke-width": "3",
|
|
|
|
+ "blur-selected-stroke": hsl(h, 10, 60),
|
|
|
|
+ "marquee-background": hsl(h, 100, 80).set("a", .1),
|
|
|
|
+ "marquee-stroke": hsl(h, 37, 60),
|
|
|
|
+ "drop-hint-color": hsl(h, 26, 35),
|
|
|
|
+ "drop-hint-width": 5,
|
|
|
|
+ "order-hint-area-color": hsl(h, 100, 30).set("a", .5),
|
|
|
|
+ "order-hint-path-color": hsl(h, 100, 25),
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": hsl(h, 100, 20),
|
|
|
|
+ "line-height": 1.5
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ var plans = {
|
|
|
|
+ red: 0,
|
|
|
|
+ soil: 25,
|
|
|
|
+ green: 122,
|
|
|
|
+ blue: 204,
|
|
|
|
+ purple: 246,
|
|
|
|
+ pink: 334
|
|
|
|
+ };
|
|
|
|
+ var name;
|
|
|
|
+ for (name in plans) {
|
|
|
|
+ theme.register("fresh-" + name, generate(plans[name]));
|
|
|
|
+ theme.register("fresh-" + name + "-compat", generate(plans[name], true));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/snow.js
|
|
|
|
+_p[78] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ [ "snow", "snow-compact" ].forEach(function(name) {
|
|
|
|
+ var compact = name == "snow-compact";
|
|
|
|
+ /* jscs:disable maximumLineLength */
|
|
|
|
+ theme.register(name, {
|
|
|
|
+ background: '#3A4144 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=") repeat',
|
|
|
|
+ "root-color": "#430",
|
|
|
|
+ "root-background": "#e9df98",
|
|
|
|
+ "root-stroke": "#e9df98",
|
|
|
|
+ "root-font-size": 24,
|
|
|
|
+ "root-padding": compact ? [ 5, 10 ] : [ 15, 25 ],
|
|
|
|
+ "root-margin": compact ? 15 : 30,
|
|
|
|
+ "root-radius": 5,
|
|
|
|
+ "root-space": 10,
|
|
|
|
+ "root-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "main-color": "#333",
|
|
|
|
+ "main-background": "#a4c5c0",
|
|
|
|
+ "main-stroke": "#a4c5c0",
|
|
|
|
+ "main-font-size": 16,
|
|
|
|
+ "main-padding": compact ? [ 4, 10 ] : [ 6, 20 ],
|
|
|
|
+ "main-margin": compact ? [ 5, 10 ] : [ 20, 40 ],
|
|
|
|
+ "main-radius": 5,
|
|
|
|
+ "main-space": 5,
|
|
|
|
+ "main-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "sub-color": "black",
|
|
|
|
+ "sub-background": "white",
|
|
|
|
+ "sub-stroke": "white",
|
|
|
|
+ "sub-font-size": 12,
|
|
|
|
+ "sub-padding": [ 5, 10 ],
|
|
|
|
+ "sub-margin": compact ? [ 5, 10 ] : [ 10, 20 ],
|
|
|
|
+ "sub-radius": 5,
|
|
|
|
+ "sub-space": 5,
|
|
|
|
+ "connect-color": "white",
|
|
|
|
+ "connect-width": 2,
|
|
|
|
+ "main-connect-width": 3,
|
|
|
|
+ "connect-radius": 5,
|
|
|
|
+ "selected-background": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-stroke": "rgb(254, 219, 0)",
|
|
|
|
+ "marquee-background": "rgba(255,255,255,.3)",
|
|
|
|
+ "marquee-stroke": "white",
|
|
|
|
+ "drop-hint-color": "yellow",
|
|
|
|
+ "drop-hint-width": 4,
|
|
|
|
+ "order-hint-area-color": "rgba(0, 255, 0, .5)",
|
|
|
|
+ "order-hint-path-color": "#0f0",
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": "rgb(27,171,255)",
|
|
|
|
+ "line-height": 1.5
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/tianpan.js
|
|
|
|
+_p[79] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ [ "tianpan", "tianpan-compact" ].forEach(function(name) {
|
|
|
|
+ var compact = name == "tianpan-compact";
|
|
|
|
+ theme.register(name, {
|
|
|
|
+ background: '#3A4144 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowQzg5QTQ0NDhENzgxMUUzOENGREE4QTg0RDgzRTZDNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowQzg5QTQ0NThENzgxMUUzOENGREE4QTg0RDgzRTZDNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkMwOEQ1NDRGOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMwOEQ1NDUwOEQ3NzExRTM4Q0ZEQThBODREODNFNkM3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+e9P33AAAACVJREFUeNpisXJ0YUACTAyoAMr/+eM7EGGRZ4FQ7BycEAZAgAEAHbEGtkoQm/wAAAAASUVORK5CYII=") repeat',
|
|
|
|
+ "root-color": "#430",
|
|
|
|
+ "root-background": "#e9df98",
|
|
|
|
+ "root-stroke": "#e9df98",
|
|
|
|
+ "root-font-size": 25,
|
|
|
|
+ "root-padding": compact ? 15 : 20,
|
|
|
|
+ "root-margin": compact ? [ 15, 25 ] : 100,
|
|
|
|
+ "root-radius": 30,
|
|
|
|
+ "root-space": 10,
|
|
|
|
+ "root-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "root-shape": "circle",
|
|
|
|
+ "main-color": "#333",
|
|
|
|
+ "main-background": "#a4c5c0",
|
|
|
|
+ "main-stroke": "#a4c5c0",
|
|
|
|
+ "main-font-size": 15,
|
|
|
|
+ "main-padding": compact ? 10 : 12,
|
|
|
|
+ "main-margin": compact ? 10 : 12,
|
|
|
|
+ "main-radius": 10,
|
|
|
|
+ "main-space": 5,
|
|
|
|
+ "main-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "main-shape": "circle",
|
|
|
|
+ "sub-color": "#333",
|
|
|
|
+ "sub-background": "#99ca6a",
|
|
|
|
+ "sub-stroke": "#a4c5c0",
|
|
|
|
+ "sub-font-size": 13,
|
|
|
|
+ "sub-padding": 5,
|
|
|
|
+ "sub-margin": compact ? 6 : 10,
|
|
|
|
+ "sub-tree-margin": 30,
|
|
|
|
+ "sub-radius": 5,
|
|
|
|
+ "sub-space": 5,
|
|
|
|
+ "sub-shadow": "rgba(0, 0, 0, .25)",
|
|
|
|
+ "sub-shape": "circle",
|
|
|
|
+ "connect-color": "white",
|
|
|
|
+ "connect-width": 2,
|
|
|
|
+ "main-connect-width": 3,
|
|
|
|
+ "connect-radius": 5,
|
|
|
|
+ "selected-background": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-stroke": "rgb(254, 219, 0)",
|
|
|
|
+ "selected-color": "black",
|
|
|
|
+ "marquee-background": "rgba(255,255,255,.3)",
|
|
|
|
+ "marquee-stroke": "white",
|
|
|
|
+ "drop-hint-color": "yellow",
|
|
|
|
+ "sub-drop-hint-width": 2,
|
|
|
|
+ "main-drop-hint-width": 4,
|
|
|
|
+ "root-drop-hint-width": 4,
|
|
|
|
+ "order-hint-area-color": "rgba(0, 255, 0, .5)",
|
|
|
|
+ "order-hint-path-color": "#0f0",
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": "rgb(27,171,255)",
|
|
|
|
+ "line-height": 1.4
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//src/theme/wire.js
|
|
|
|
+_p[80] = {
|
|
|
|
+ value: function(require, exports, module) {
|
|
|
|
+ var theme = _p.r(32);
|
|
|
|
+ theme.register("wire", {
|
|
|
|
+ background: "black",
|
|
|
|
+ color: "#999",
|
|
|
|
+ stroke: "none",
|
|
|
|
+ padding: 10,
|
|
|
|
+ margin: 20,
|
|
|
|
+ "font-size": 14,
|
|
|
|
+ "connect-color": "#999",
|
|
|
|
+ "connect-width": 1,
|
|
|
|
+ "selected-background": "#999",
|
|
|
|
+ "selected-color": "black",
|
|
|
|
+ "marquee-background": "rgba(255,255,255,.3)",
|
|
|
|
+ "marquee-stroke": "white",
|
|
|
|
+ "drop-hint-color": "yellow",
|
|
|
|
+ "sub-drop-hint-width": 2,
|
|
|
|
+ "main-drop-hint-width": 4,
|
|
|
|
+ "root-drop-hint-width": 4,
|
|
|
|
+ "order-hint-area-color": "rgba(0, 255, 0, .5)",
|
|
|
|
+ "order-hint-path-color": "#0f0",
|
|
|
|
+ "order-hint-path-width": 1,
|
|
|
|
+ "text-selection-color": "rgb(27,171,255)",
|
|
|
|
+ "line-height": 1.5
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+var moduleMapping = {
|
|
|
|
+ "expose-kityminder": 34
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+function use(name) {
|
|
|
|
+ _p.r([ moduleMapping[name] ]);
|
|
|
|
+}
|
|
|
|
+use('expose-kityminder');
|
|
|
|
+})();
|