接上篇, 接着学习 kityminder. css
== core/keyreceiver.js == node
extend class Minder {
init-hook(): 构造时设置选项, 侦听 'paperrender' 事件, 以调用 _initKeyReceiver()
_initKeyReceiver(): 建立 DOM 元素 <input class='km-receiver'>, 添加到容器 <div> 中.
在此 <input> 上侦听 keydown, keyup, keypress 等多个事件, 而后转给 minder 对象处理.
看起来彷佛是用于专门接收 key 事件的, 也许容器不方便接收 key 事件?
事件 on_focus(): 设置上面的 <input> 为 focus.
彷佛是将 <div> 的 focus,blur 同步给 <input>.
} 算法
== core/module.js == 数组
闭包变量: _modules = {}, 注释为已注册的模块. promise
对外提供函数 Module.register(name, module): 注册一个模块.
如今对什么是模块的概念不太清晰, 另 seajs 也是加载模块, 那么有区别? 闭包
extend class Minder { // 注释: 模块声明周期维护.
init-hook(): 调用 _initModules()
_initModules(): 某种(预先?)模块加载机制, 可能先要注册模块, 而后这里在 minder 构造时完成一些加载工做.
还涉及 command, event, renderer, shortcut 等等, 稍后细研究吧.
_garbage(): 删掉全部子节点, 等于清空文档?
destroy(): 清空文档, for-each(modules).destroy(this)
reset(): 清空, for-each(modules).reset(this); 至关于每模块提供 destroy, reset 方法可被调用.
} app
实际查看了一下, 在 minder 对象中有一个 _modules{}, 里面有 Arrange, Clipboard, Connect, ...
大约 30 个模块? ._query 为 null, ._rendererClasses 有 left,right,top 等几个. ._commands 前面
遇到过. ide
模块看起来是一种扩展功能的机制, 稍后须要更深刻看看. 函数
== core/readonly.js : 只读模式支持 == 工具
extend class Minder {
init-hook(): 若是选项有 readonly, 则设置为 disabled.
disable(): 禁用命令. 对命令对象的 query 方法包装(修饰)一下, 在 readonly 状态下返回 null/0.
产生 'readonly' 事件. 设置状态 _status='readonly'
enable(): 恢复命令. 去掉 query command 的包装. 设置状态为 'normal'.
}
由此知道 minder._status 表示的文档状态是 normal, readonly 等几种.
== core/render.js ==
class Renderer {
ctor(node): this.node = node; 问题: 一个实例对应一个 node? 这里 node 是什么?
create(node): throw ('not impl') 也许设计由派生的子类来实现.
update(): draw(), place()
draw(): throw 'not impl'; 也许子类实现.
place(): throw 'not impl'; 也许子类实现.
还有一些方法略, 大体可认为是一个接口声明, 几个主要?功能可能须要子类实现, 因此应该有(数个?)实现子类?
}
extend class Minder {
renderNodeBatch(nodes): 与 node render 机制有关, 如今理解不了, 须要稍后.
renderNode(node): render 单个节点. 彷佛有或建立 node renderers[],
而后 for-each(renderer).do_sth()
在 render 以前产生 'beforerender' 事件, 以后产生 'noderender' 事件.
}
实际查看了一下例子, root._renderers[] 含11项, 分别是 TextRenderer, PriorityRenderer 等等.
root 的几个子节点每一个也都有 _renderers[], 也都是 11 项... 每一个节点都要建立这么多吗?
在 minder._rendererClasses{} 彷佛保存有 name=>renderers[] 的映射.
extend class MinderNode {
render(): 即 minder.renderNode(此节点)
renderTree(): 即 minder.renderNodeBatch(全部子孙节点)
getRenderer(type): 获得该 type 的 renderer. 这里 type 有哪些须要后续了解.
getContentBox(): 可能每一个 node 对应有一个 content-box, 对应类为 kity.Box()
getRenderBox(): 相关概念有 renderer, content-box, transform-matrix 等. 暂不清楚.
}
另外一个小问题, 在建立 node._renderers[] 的时候, 是用 new Renderer(node), 但查看时倒是不一样的
Renderer 子类(如 TextRenderer, ImageRenderer等), 那么 new 发生了什么?
Renderer 是一个重要的概念, 咱们须要更多学习...
== core/connect.js ==
闭包变量 _connectProviders{} 注释为: 连线提供方.
这里注册一个 'default' 的 connect-provider. 细节稍后.
extend class MinderNode {
getConnect(): 注释为获取当前节点的连线类型. 缺省返回 'default', 可能名字对应 connect-provider
getConnectProider(): 根据名字找该名字的 connect-provider.
getConnection(): 获得当前节点的连线对象. 实际查看这个对象是一个 Path 类的实例.
}
extend class Minder {
getConnectContainer(): 获得对应成员变量.
createConnect(node): 建立 node._connection = kity.Path 对象, 更新 connect.
removeConnect(node): 遍历?删除全部子孙节点的 ?
updateConnect(node): 获得相关对象: parent(node), connection(kity.Path), connect-provider,
调用 provider() 方法对 node<--connect-->parent 创建连线吧. 猜想 default connect-provider
就用简单曲线连起来. 这样连线应对应一个 path 对象, 具体怎么曲线由 provider 计算...
}
register module Connect {
init(): 彷佛是建立一个 <g> 元素, 用于容纳全部连线的 <path>.
events: { // 回顾 module.js , 这里至关于侦听以下事件.
on 'nodeattach': 建立 connect.
on 'nodedetach': 删除 connect.
on 'layoutapply layoutfinish noderender': 更新 connect.
}
}
这里正好能够回顾一下 module, 了解注册模块要作什么, 如今已知模块可侦听一些事件.
查看 km._eventCallbacks{}, 里面有多种事件对应的 callback[].
== core/layout.js ==
闭包变量 _layouts{}, 用于注册 name->layout 的映射.
经过查看, 里面有 bottom, filetree-xxx, fish-bone-xxx, mind 等多种布局实现(子类).
缺省 layout 为 'mind'.
// 此类不少注释摘抄过来: 布局基类, 具体布局(子类)须要从该类派生.
class Layout {
doLayout(): 子类须要实现的布局算法. 该算法输入一个节点, 排布该节点的子节点(相对父节点的变换)
注释给出的例子中最后是 child.setLayoutTransform(transform-matrix), 即要给出最终变换矩阵.
align(): 对齐指定的节点. 根据对齐到哪个边, 产生新的变换 matrix (叠加一个平移变换).
stack(): ?多是将一组节点沿某个 axis(轴) 叠成一排(列)?
move(): 平移一组节点.
getBranchBox(): 获取给定的节点[]所占的布局区域 (box?), 是单个node box 的总的 merge. (UnionRect)
getTreeBox(): 工具方法:计算给定的节点的子树所占的布局区域. 彷佛意思是包含全部子节点的 box.
getOrderHint(): 可能由子类实现. 这里返回一个空数组.
}
// 注释: 布局支持池子管理 (什么是池子...?)
extend class Minder {
init-hook(): 调用刷新 refresh()?
getLayoutList(): ?
getLayoutInstance(name): 建立指定名字的 layout 实现(子)类.
}
// 注释: MinderNode 上的布局支持.
extend class MinderNode {
get/setLayout(): 得到当前节点的布局名称. 若是未给出就使用父节点的 layout, 直到缺省为 'mind'.
layout(name): 设置指定 name 的布局, 并调用 minder.layout()
get/setLayoutTransform(): 获取当前节点相对于父节点的布局变换. (返回是一个 matrix)
getGlobalLayoutTransformPreview(): 第一轮布局计算后, 得到的全局布局位置. (返回合并后的 matrix?)
getLayoutPointPreview(): ?
get/setGlobalLayoutTransform(): 得到节点相对于全局的布局变换. (?)
set(): 相对于全局的变换(冗余优化), 暂不明白.
get/setVertexIn(p): 多是设置连线的进入点?
get/setVertexOut(p): 多是设置连线的出点?
getLayoutVertexIn(): 对 in 点用 global-layout-transform 进行变换?
getLayoutVertextOut(): 对 out 点 xxx 变换.
get/setLayoutVectorIn(): 获取/设置某种向量 (kity.Vector?)
get/setLayoutVectorOut(): 也许是入点/出点方向向量?
getLayoutBox(): 对 content-box 进行 glt 变换.
getLayoutPoint(): 获得布局原点?
get/set/has/resetLayoutOffset(): 获取/设置布局相关的一个点 (kity.Point).
get/isLayoutRoot():
}
extend class Minder {
layout(): 清空前次layout; 第一轮布局, 第二布局; 应用布局结果; 发布 layout 事件.
会递归调用子节点的 layout(). 彷佛实际用 layout-instance.doLayout() 实质布局.
refresh(): 多是彻底重绘/重布局. 发布事件, 以及 interact-change().
applyLayoutResult(): 彷佛应用动画给更新, 若是过复杂则不动画.
}
布局是重点功能, 稍后回来再回顾.
== core/theme.js ==
闭包变量 _themes{}, 估计存放支持的全部 theme. 查看了一下大约有20种, 大约是颜色+样式组合.
数据形式像 css. 在 src/theme/ 下面有 6 个 js, 用于注册多种 theme.
extend class Minder {
static getThemeList(): 即获取 _themes{}.
init-hook: 设置(缺省) theme.
useTheme(): 切换脑图实例上的主题.
实验: 在控制台上执行 km.useTheme('fresh-green') 果真变为绿色主题~
get/setTheme(): 获取/设置主题, 发布事件.
getStyle(): 得到脑图实例上的样式. 可能像 css 方式访问.
getNodeStyle(): 获取指定节点的样式.
}
extend class MinderNode {
getStyle(): 等价于 minder.getNodeStyle(this)
}
register module Theme {
选项略;
commands: { 为 minder 添加命令 ThemeCommand }
}
如今仍是未彻底理解 register module, 是否这些注册等也均可以用 init-hook 等方式完成?
== core/template.js 显示模板(形式) ==
闭包变量 _templates{}. 查看一下大体有 6 种: default,filetree, fish-bone, ...
这里 template 应是指图的形式, 如缺省,鱼骨图,文件树等.
extend class Minder {
static getTemplateList(): 即获取 _templates{}
use/get/setTemplate(): 切换到该形式.
getTheme(): 被这里修改了.
}
extend class MinderNode {
getLayout(): 这里修改/加强了原 getLayout() 方法, 根据 template 是否支持.
getConnect(): 相似的修改.
}
register module TemplateModule {
添加 template 命令, 容许切换显示形式(模板).
}
== core/promise.js ==
这多是外部某个 js 代码, 因不了解 promise 的意图, 暂时先跳过.
== core/_boxv.js ==
调试工具, 为 kity.Box 提供一个可视化的渲染. 当 url 中含特定 boxv 时.
extend class kity.Box {
visualization get: 设置 vrect 大小.
}
extend class Minder {
init-hook: 注册事件.
on event paperrender: 建立调试用 vrect, 在上面改变大小. 有空作作实验.
}
== core/patch.js 打补丁 ==
extend class Minder {
applyPatches(): 应用所给补丁[]. 如今不了解在补丁什么...?
}
这里结束了 core/*.js 小节, 下面是 module/*.js 部分. 那就放下一篇笔记吧.