接上篇继续学习. 本段都是 seajs require(module/*.js) 的, 看起来是按照字母顺序 a-z 排列的, 所以应没什么互相依赖性.
考虑到前面有很多细节都略过, 或不懂, 在学习过程中可能还要不断回顾,复习过去的一些东西...
== module/arrange.js ==
用伪代码摘要如下:
extend class MinderNode { arrange(index): 似乎是把自己节点排到指定的 index 位置, 用于下面前移/后移等命令. } // 向上调整选中节点的位置, 对应快捷键: Alt+UP. 从界面反应上看, 是将节点在父节点中的顺序前移一位. class ArrangeUpCommand : Command { execute(): 设置所有选中节点的 index--; 调用 layout(300). 这里 300 可能指时间延迟? queryState(): 判断是否可执行, 依据是有任意被选中节点(一或多个都可). } class ArrangeDownCommand : Command { execute(), queryState(): 类似于 ArrangeUpCommand. 只是 index++ 所以`下移'. } // 调整选中节点的位置. class ArrangeCommand : Command { execute(): 似乎是调整一组有共同父节点的子节点到指定位置? } register module ArrangeModule { commands: 上面三个 cmd. contextmenu: 这里需要回顾 register module 那里如何处理 contextmenu 键的. 回顾: module.js 中没有 contextmenu 部分, 也许 kityminder-edit 版里面才有. commandShortcutKeys: 快捷键->命令. 如: alt+up->arrangeup alt+down->arrangedown }
综上所述, arrange 用于节点(前后)顺序(order, index)调整.
== module/basestyle.js ==
有些代码注释很少, 可能程序员太忙了...?
// 加粗选中的节点: Ctrl+B. 实验了一下, 加粗之后切换不回来了... class boldCommand : Command { execute(): toggle font-weight 数据(样式), 然后 render(), layout(). queryState(): 返回 nodes 节点 font-weight 状态. } // 加斜体于选中的节点: Ctrl+I. 我看和 bold 差不多, 就先略去. class italicCommand : Command { } register module basestylemodule { commands: bold->boldCommand, italic->italicCommand. commandShortcutKeys: ctrl+b->bold, ctrl+i->italic 映射. }
这里引用了 TextRenderer, 还对其注册了 style-hook, 即依赖于 module/text.js 模块, 稍后回顾.
== module/clipboard.js ==
// 复制当前选中的节点 (Ctrl+C) class CopyCommand : Command { execute(): 看起来应该是获得选中节点(?ancestors), 然后放入到(内部的)剪切板(对象). } // 剪切当前选中的节点 (Ctrl+X) class CutCommand : Command { execute(): 先 copy(), 然后 remove selected nodes. } // 粘贴已复制的节点到每一个当前选中的节点上. class PasteCommand : Command { execute(): 粘贴. 内部闭包变量 _clipboardNodes[] 当做剪贴板, 被 copy/cut 的节点放这里. 实际 paste 即是将 copied nodes 都 clone() 一份, appendTo 当前被选中节点. } register module ClipboardModule { commands & shortcut: copy,cut,paste 关于原生 clipboard 支持以及 event 暂时略. }
== module/dragtree.js ==
// 矩形的变形动画定义. class MoveToParentCommand : Command { execute(): 似乎是改变节点的父节点, 或顺序(移动节点). } // 这里 drop-hinter 大致应是 drag-node 时放下位置的那个元素(新父元素). class DropHinter : kity.Group { ctor(): 在此实例的 <g> 元素中添加 <rect> 元素. render(): 设置 <rect> 元素的大小,样式等, 显示出来. } // 排列节点的新的顺序的提示位置. class OrderHinter : kity.Group { ctor(): 在此实例 <g> 元素中添加 <rect>,<path>. render(): 设置子元素样式, 显示出来. } // 注释: 对拖动对象的一个替代盒子, 控制整个拖放的逻辑. // 1. 从节点列表计算出拖动部分. // 2. 计算可以 drop 的节点, 产生 drop 交互提示. class TreeDragger { ctor(): 创建 drop-hinter, order-hinter 并添加到 render-container of minder 中. // dragStart(), dragMove(), dragEnd(): 这三个函数应对应 drag 三个事件. dragStart(): 记录开始位置 start-position. dragMove(): 计算移动偏移, 设置被移动 node 的 layout-offset 属性(可能专用于拖动?)... 检测 order/drop-hinter 条件以及显示. dragEnd(): 有一个 _fadeDragSource() 调用, 可能是将节点透明度恢复? 调用以重新 layout(), 发布事件. _enterDragMode(): 进入拖放模式. 从 dragMove() 调用, 设置一些属性和状态. _leaveDragMode(): 离开. 清除一些属性. _calcDragSources(): 从选中的节点计算拖放源. 这里算法可简单参考(单父节点构成的的树容易一些). _fadeDragSources(opacity): 设置节点透明度. _calcDropTargets(): 计算拖放目标可以释放的节点列表 (即可以作为父节点(of 被拖动节点)). _calcOrderHints(): 应是计算新位置的, 暂时略. // 还有几个辅助函数, 暂时略吧... } register module DragTree { init(): 创建 dragger 对象. 这里全局只有一个 dragger 对象? events: // 细节略去一些. mousedown(): 调用 dragger.dragStart(). mousemove(): 调用 dragger.dragMove(). mouseup(): 调用 dragger.dragEnd(). commands: MoveToParentCommand. }
Drag 是 UI 交互中非常重要的一部分, 值得仔细参考.
== module/expand.js ==
// 将展开的操作和状态读取接口拓展到 MinderNode 上 extend class MinderNode { expand(): 展开节点. collapse(): 收起节点. isExpanded(), isCollapsed(): 判断展开/收起状态. } // 展开当前选中的节点, (根据参数)保证其可见. class ExpandCommand : Command { execute(): 展开所有祖先节点, 渲染, 重布局. } // 展开到指定的层级. class ExpandToLevelCommand : Command { execute(): 遍历节点, 如果 level (树深度, 即层级) 小于指定则展开,否则收起. } // 收起当前节点的子树 class CollapseCommand : Command { execute(): 收起节点, 渲染, (重)布局. 类似于 ExpandCommand. } class Expander : kity.Group { ctor(): 构造节点前面的圆框 +/- 号(用 <circle>&<path> 元素), 用于当做展开/收起按钮. 当然还要对该节点绑定事件于 mousedown, mouseup, click, dblclick. setState(): 切换状态, 更新显示为 + 或 - 符号. 这两个符号是用 path-data 程序中产生的... } // 这里需要回顾 Renderer 类, 那里 create() 等方法需要子类实现. class ExpanderRenderer : Renderer { create(node): 为所给 node 创建一个 Expander. update(): 暂时不理解, 稍后看. } register module Expand { commands: expand->ExpandCommand, expandtolevel, collapse... events: 侦听事件 layoutapply, beforerender, keydown 等做一些(?包装)处理. 还相当于添加了快捷键 '/', Alt+`, Alt+1(2,3,4,5,6). renderers: outside->ExpanderRenderer. 可能需要理解整个 renderer 机制才能明白. 现在猜是多个 render 组合产生最终结果. contextmenu: core 版里面可能没有, 先略. }
TODO: font.js 引用 text.js, 看 text.js 之后再回来看 font.js.
== module/hyperlink.js ==
// 为选中的节点添加超链接. class hyperlink : Command { execute(url, tilte): for-each (node) node.data .{ .link = url, .title = title } queryValue(): 返回 json 格式的超链接数据. } class hyperlinkrender : Renderer { create(): 似乎创建出 link 的 outline shape, link shape <path> 元素. 在元素上还加上事件 mouseover, mouseout. 但是否用 css 也能做到呢? update(): 看起来 Renderer 应该是两阶段工作, 首先是创建 shape, 然后发生变化时, 调用 update() 设置/更新位置. } register module hyperlink { commands: hyperlink, renderers: hyperlinkrender, }