学习 kityminder 笔记(六)

接上篇, 接着学习 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 部分. 那就放下一篇笔记吧.

相关文章
相关标签/搜索