UNPKG

@7polo/kityminder-core

Version:
295 lines (266 loc) 10.6 kB
define(function(require, exports, module) { var kity = require('../core/kity'); var utils = require('../core/utils'); var keymap = require('../core/keymap'); var MinderNode = require('../core/node'); var Command = require('../core/command'); var Module = require('../core/module'); var Renderer = require('../core/render'); 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.callBase2(kity.Group, 'constructor', []); 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) { var target = this.node; target.addEventListener('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(); }); target.addEventListener('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 }] }; }); });