Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kityminder-core
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
吴志俊
kityminder-core
Commits
e2ac6d1e
Commit
e2ac6d1e
authored
Jun 04, 2014
by
techird
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
stash
parent
e3974368
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
373 additions
and
105 deletions
+373
-105
.jsbeautifyrc
.jsbeautifyrc
+7
-4
.jscsrc
.jscsrc
+103
-0
重构方案.md
doc/重构方案.md
+115
-4
layout.js
src/core/layout.js
+0
-0
minder.js
src/core/minder.js
+10
-18
minder.node.js
src/core/minder.node.js
+17
-17
node.js
src/core/node.js
+3
-62
render.js
src/core/render.js
+0
-0
theme.js
src/core/theme.js
+118
-0
No files found.
.jsbeautifyrc
View file @
e2ac6d1e
{
"indent_size": 4,
"indent_char": " ",
"indent_level": 0,
"indent_with_tabs": false,
"preserve_newlines": true,
"max_preserve_newlines": 4,
"max_preserve_newlines": 10,
"jslint_happy": false,
"space_in_paren": false,
"jslint_happy": true,
"brace_style": "collapse",
"keep_array_indentation": false,
"keep_function_indentation": false,
"space_before_conditional": false,
"break_chained_methods": false,
"eval_code": false,
"unescape_strings": false,
"break_chained_methods": false,
"e4x": false,
"wrap_line_length": 0
}
\ No newline at end of file
.jscsrc
0 → 100644
View file @
e2ac6d1e
/**
* FEX Style Guide (Javascript)
*
* TODO:
*
* 1. 找不到选项:每行只允许一个语句
* 2. 找不到选项:块状代码需要用大括号括起来
*/
{
// 缩进「MUST」使用 4 个空格
"validateIndentation": 4,
// 大括号(块状代码)前「MUST」使用空格
"requireSpaceBeforeBlockStatements": true,
// 下列关键字「MUST」使用空格
"requireSpaceAfterKeywords": ["if", "else", "for", "while",
"do", "try", "catch", "finally"
],
// `,` 和 `;` 前面不允许「MUST NOT」使用空格。
"requireLeftStickedOperators": [",", ";"],
// 二元运算符前后「MUST」使用空格
"requireSpaceBeforeBinaryOperators": [
"+",
"-",
"*",
"/",
"=",
"==",
"===",
"!=",
"!==",
"|",
"||",
"&",
"&&"
],
"requireSpaceAfterBinaryOperators": [
"+",
"-",
"*",
"/",
"=",
"==",
"===",
"!=",
"!==",
"|",
"||",
"&",
"&&",
":"
],
// 一元运算符与操作对象间「MUST NOT」使用空格
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
// 函数参数小括号前「MUST NOT」使用空格
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
// 小括号里面「MUST NOT」使用空格
"disallowSpacesInsideParentheses": true,
// 行尾「MUST NOT」使用空格
"disallowTrailingWhitespace": true,
// 每行「MUST NOT」超过 120 个字符
"maximumLineLength": 120,
// 一下操作符「MUST NOT」放在一行的最前面,需要放在上一行的后面
"requireOperatorBeforeLineBreak": [
"?",
"+",
"-",
"/",
"*",
"=",
"==",
"===",
"!=",
"!==",
">",
">=",
"<",
"<=",
",",
";",
"&&",
"&",
"||",
"|"
],
// 字符串统一「MUST」使用单引号
"validateQuoteMarks": "'",
// 「MUST NOT」使用多行字符串
"disallowMultipleLineStrings": true
}
\ No newline at end of file
doc/重构方案.md
View file @
e2ac6d1e
...
...
@@ -9,18 +9,129 @@ KityMinder 渲染和布局重构方案
为了不产生误会,下面约定一些词汇的意思。
样式:对节点或脑图其他内容的外观的描述。
渲染:对节点的绘制的过程。渲染参照的坐标系是节点画布的坐标系。
布局:对节点定位的过程,发生在渲染之后。定位使用的坐标系是脑图画布的坐标系。
节点树多边形:表示一个节点以及其子树所占的多边形区域。
### Layout
## 样式、渲染和布局的梳理
### Theme
负责注册和管理样式。
注册样式:
```
js
KityMinder
.
registerTheme
(
'default'
,
{
'root-padding'
:
[
30
,
20
],
'root-color'
:
'black'
,
'root-background'
:
'#A4c5c0'
,
'root-stroke'
:
'none'
,
'root-radius'
:
4
,
'root-space'
:
[
10
,
5
],
'root-font-family'
:
'Arial'
,
'root-font-size'
:
14
,
'main-connect-width'
:
2
,
'main-connect-color'
:
'white'
,
'main-connect-type'
:
'arc'
,
'sub-connect-type'
:
'fold'
...
});
```
切换样式:
Layout
```
js
minder
.
useTheme
(
'default'
);
```
读取样式:
```
js
minder
.
getStyle
(
'root-radius'
);
// returns 4
```
```
js
node
.
getStyle
(
'radius'
);
// node.getType() 返回 'root', 会自动拼接样式项,返回 4
node
.
getStyle
(
'padding-left'
);
// returns 20 发现结尾是 '-left'、'-right' 等的会自动找到样式表描述的数组按照 CSS 的方式查找值
```
### Render
### Connect
Render 负责渲染工作。
对于一个节点,有两个渲染容器(以前是多个),一个是通过
`getContentGroup()`
来获取的内容容器,一个是通过
`getDecorationGroup()`
来获得的装饰容器。布局的时候,内容容器最终决定该节点的渲染大小,装饰容器里的内容会被忽略。
节点的渲染分步进行,按顺序描述是:
`center`
,
`left`
,
`right`
,
`top`
,
`bottom`
。之前渲染这五个步骤是通过事件的形式来通知,每次渲染都清除了原本的内容重新创建节点,造成性能浪费。修改渲染的机制,改成从模块直接注册渲染的节:
```
js
KityMinder
.
registerModule
(
'MyModule'
,
{
commands
:
{
...
},
events
:
{
...
},
renderers
:
{
left
:
kity
.
createClass
(
'MyRenderer'
,
{
base
:
Renderer
,
create
:
function
(
node
)
{
this
.
content
=
new
kity
.
Group
();
// 添加元素
node
.
getContentGroup
().
addShape
(
this
.
content
);
},
update
:
function
(
node
)
{
var
content
=
this
.
content
;
// update content
// 需要返回更新后内容所占的矩形区域,简单的返回形式是 return this.content.getRenderBox();
return
{
x
:
30
,
y
:
-
30
,
width
:
24
,
height
:
24
};
}
}
}
});
```
用
`renderers`
节来描述渲染器,节的
`key`
指定渲染器使用的阶段,节的
`value`
给出渲染器的类。渲染器需要继承
`Renderer`
类,并且实现两个抽象方法:
`create()`
和
`update()`
。
`create`
方法只会在节点创建的时候调用一次,此时应该创建渲染所需要的元素,并且附加到节点上。
`update`
方法会在节点需要重新渲染的时候被调用,此时可以选择隐藏、显示或更新元素。
在渲染过程中,节点提供下述信息:
-
`node.getStyle(name)`
获得节点当前的某个样式描述
-
`node.getContentBox()`
获得节点当前已渲染的内容在节点的 ConentGroup 的坐标系中所占的矩形区域。
-
`node.getType()`
获得节点的类型('root' | 'main' | 'sub')
要触发一个节点的渲染,直接调用 'node.render()' 即可。
### Layout
Layout 负责布局工作,布局一般发生在渲染之后。对一个节点的布局,指的是排列其子树。
允许多种布局,布局注册的方式如下:
```
js
KityMinder
.
registerLayout
(
'default'
,
kity
.
createClass
(
'DefaultLayout'
,
{
base
:
Layout
,
doLayout
:
function
(
node
)
{
// do layout
}
}));
```
让节点布局的方式是调用节点的
`node.layout([name])`
方法。该方法的执行过程如下:
-
调用
`node.getLayout()`
获得节点的布局名称
-
如果节点中的 data 包含布局名称,返回该布局名称,否则下一步
-
如果节点是根节点,返回 KityMinder.getDefaultLayout()
-
返回父节点的
`getLayout()`
-
根据布局名称获得相应的布局方法,把节点作为参数传进去调用
### Expander
src/core/layout.js
0 → 100644
View file @
e2ac6d1e
src/core/minder.js
View file @
e2ac6d1e
...
...
@@ -22,14 +22,14 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
return
val
===
null
||
val
===
undefined
?
this
.
_options
[
key
]
:
val
;
}
else
{
val
=
this
.
getPreferences
();
if
(
val
)
{
return
utils
.
extend
(
val
,
this
.
_options
,
true
)
}
else
{
if
(
val
)
{
return
utils
.
extend
(
val
,
this
.
_options
,
true
);
}
else
{
return
this
.
_options
;
}
}
},
setDefaultOptions
:
function
(
key
,
val
,
cover
)
{
setDefaultOptions
:
function
(
key
,
val
,
cover
)
{
var
obj
=
{};
if
(
Utils
.
isString
(
key
)
)
{
obj
[
key
]
=
val
;
...
...
@@ -40,7 +40,7 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
},
setOptions
:
function
(
key
,
val
)
{
this
.
setPreferences
(
key
,
val
)
this
.
setPreferences
(
key
,
val
)
;
},
_initMinder
:
function
()
{
...
...
@@ -89,7 +89,7 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
addShortcutKeys
:
function
(
cmd
,
keys
)
{
var
obj
=
{},
km
=
this
;
if
(
keys
)
{
obj
[
cmd
]
=
keys
obj
[
cmd
]
=
keys
;
}
else
{
obj
=
cmd
;
}
...
...
@@ -99,7 +99,7 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
},
getShortcutKey
:
function
(
cmdName
)
{
return
this
.
_shortcutkeys
[
cmdName
]
return
this
.
_shortcutkeys
[
cmdName
]
;
},
_bindshortcutKeys
:
function
()
{
var
me
=
this
,
...
...
@@ -115,7 +115,7 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
break
;
case
'alt'
:
if
(
e
.
altKey
)
{
return
true
return
true
;
}
break
;
case
'shift'
:
...
...
@@ -127,7 +127,7 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
if
(
keyCode
==
keymap
[
key
]
)
{
return
true
;
}
return
false
return
false
;
}
me
.
on
(
'keydown'
,
function
(
e
)
{
...
...
@@ -227,11 +227,3 @@ var Minder = KityMinder.Minder = kity.createClass( "KityMinder", {
me
.
fire
(
'interactchange'
);
}
}
);
\ No newline at end of file
/**
* @include <minder.data.js>
* @include <minder.event.js>
* @include <minder.module.js>
* @include <minder.node.js>
* @include <minder.select.js>
*/
\ No newline at end of file
src/core/minder.node.js
View file @
e2ac6d1e
kity
.
extendClass
(
Minder
,
{
kity
.
extendClass
(
Minder
,
{
getRoot
:
function
()
{
getRoot
:
function
()
{
return
this
.
_root
;
},
setRoot
:
function
(
root
)
{
setRoot
:
function
(
root
)
{
this
.
_root
=
root
;
},
handelNodeInsert
:
function
(
node
)
{
handelNodeInsert
:
function
(
node
)
{
var
rc
=
this
.
_rc
;
// node.traverse( function ( current ) {
// rc.addShape( current.getRenderContainer() );
// } );
rc
.
addShape
(
node
.
getRenderContainer
()
);
rc
.
addShape
(
node
.
getRenderContainer
()
);
},
handelNodeRemove
:
function
(
node
)
{
handelNodeRemove
:
function
(
node
)
{
var
rc
=
this
.
_rc
;
node
.
traverse
(
function
(
current
)
{
rc
.
removeShape
(
current
.
getRenderContainer
()
);
}
);
node
.
traverse
(
function
(
current
)
{
rc
.
removeShape
(
current
.
getRenderContainer
()
);
});
},
renderNodes
:
function
(
nodes
)
{
renderNodes
:
function
(
nodes
)
{
var
km
=
this
;
if
(
nodes
instanceof
Array
)
{
if
(
nodes
.
length
===
0
)
return
false
;
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
km
.
renderNode
(
nodes
[
i
]
);
if
(
nodes
instanceof
Array
)
{
if
(
nodes
.
length
===
0
)
return
false
;
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
km
.
renderNode
(
nodes
[
i
]
);
}
}
else
{
km
.
renderNode
(
nodes
);
km
.
renderNode
(
nodes
);
}
},
getMinderTitle
:
function
()
{
getMinderTitle
:
function
()
{
return
this
.
getRoot
().
getText
();
}
}
);
\ No newline at end of file
});
\ No newline at end of file
src/core/node.js
View file @
e2ac6d1e
...
...
@@ -9,62 +9,8 @@ var MinderNode = KityMinder.MinderNode = kity.createClass( "MinderNode", {
}
else
{
this
.
setData
(
options
);
}
this
.
_createShapeDom
();
this
.
setData
(
"layout"
,
{}
);
},
_createShapeDom
:
function
()
{
this
.
rc
=
new
kity
.
Group
();
this
.
rc
.
addClass
(
'km-minderNode'
);
this
.
rc
.
minderNode
=
this
;
this
.
_createBgGroup
();
this
.
_createContGroup
();
},
_createGroup
:
function
(
type
)
{
var
g
=
new
kity
.
Group
();
g
.
setData
(
'rctype'
,
type
);
this
.
rc
.
appendShape
(
g
);
},
_createBgGroup
:
function
()
{
this
.
_createGroup
(
'bgrc'
);
},
_createContGroup
:
function
()
{
this
.
_createGroup
(
'contrc'
);
},
getContRc
:
function
()
{
var
groups
=
this
.
rc
.
getShapesByType
(
'group'
),
result
;
Utils
.
each
(
groups
,
function
(
i
,
p
)
{
if
(
p
.
getData
(
'rctype'
)
==
'contrc'
)
{
result
=
p
;
return
false
;
}
}
);
return
result
;
},
getBgRc
:
function
()
{
var
groups
=
this
.
rc
.
getShapesByType
(
'group'
),
result
;
Utils
.
each
(
groups
,
function
(
i
,
p
)
{
if
(
p
.
getData
(
'rctype'
)
==
'bgrc'
)
{
result
=
p
;
return
false
;
}
}
);
return
result
;
},
setPoint
:
function
(
x
,
y
)
{
if
(
arguments
.
length
<
2
)
{
this
.
setData
(
"point"
,
x
);
}
else
{
this
.
setData
(
'point'
,
{
x
:
x
,
y
:
y
}
);
}
},
getPoint
:
function
()
{
return
this
.
getData
(
'point'
);
},
setType
:
function
(
type
)
{
this
.
setData
(
'type'
,
type
);
},
...
...
@@ -186,26 +132,21 @@ var MinderNode = KityMinder.MinderNode = kity.createClass( "MinderNode", {
if
(
index
>=
0
)
{
removed
=
this
.
children
.
splice
(
index
,
1
)[
0
];
removed
.
parent
=
null
;
// this.handelRemove( removed );
}
},
// handelRemove: function ( node ) {
// var root = this.getRoot();
// if ( root.tnh ) {
// root.tnh.handelNodeRemove.call( root.tnh, node );
// }
// },
getChild
:
function
(
index
)
{
return
this
.
children
[
index
];
},
getFirstChild
:
function
()
{
return
this
.
children
[
0
];
},
getLastChild
:
function
()
{
return
this
.
children
[
this
.
children
.
length
-
1
];
},
getData
:
function
(
name
)
{
if
(
name
===
undefined
)
{
return
this
.
data
;
...
...
src/core/render.js
0 → 100644
View file @
e2ac6d1e
src/core/theme.js
0 → 100644
View file @
e2ac6d1e
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
];
}
};
Utils
.
extend
(
KityMinder
,
{
_themes
:
{},
/**
* 注册一个主题
*
* @param {String} name 主题的名称
* @param {Plain} theme 主题的样式描述
*
* @example
* KityMinder.registerTheme('default', {
* 'root-color': 'red',
* 'root-stroke': 'none',
* 'root-padding': [10, 20]
* });
*/
registerTheme
:
function
(
name
,
theme
)
{
KityMinder
.
_themes
[
name
]
=
theme
;
// 首个注册的主题为默认主题
if
(
!
KityMinder
.
_defaultTheme
)
KityMinder
.
_defaultTheme
=
name
;
}
});
kity
.
extendClass
(
Minder
,
{
/**
* 切换脑图实例上的主题
* @param {String} name 要使用的主题的名称
*/
useTheme
:
function
(
name
)
{
if
(
!
KityMinder
.
_theme
[
name
])
{
return
false
;
}
this
.
_theme
=
name
;
this
.
getRoot
().
traverse
(
function
(
node
)
{
node
.
render
();
});
this
.
getRoot
().
layout
();
},
/**
* 获取脑图实例上的当前主题
* @return {[type]} [description]
*/
getTheme
:
function
()
{
return
this
.
_theme
||
KityMinder
.
_defaultTheme
;
},
/**
* 获得脑图实例上的样式
* @param {String} item 样式名称
*/
getStyle
:
function
(
item
)
{
var
theme
=
KityMinder
.
_theme
[
this
.
getTheme
()];
var
segment
,
dir
,
selector
,
value
,
matcher
;
if
(
item
in
theme
)
return
theme
[
item
];
// 尝试匹配 CSS 数组形式的值
// 比如 item 为 'pading-left'
// theme 里有 {'padding': [10, 20]} 的定义,则可以返回 20
segment
=
item
.
split
(
'-'
);
if
(
segment
.
length
<
2
)
return
;
dir
=
segment
.
pop
();
item
=
segment
.
join
(
'-'
);
if
(
item
in
theme
)
{
value
=
theme
[
item
];
if
(
!
isNaN
(
value
))
return
value
;
if
(
Utils
.
isArray
(
value
)
&&
(
matcher
=
cssLikeValueMatcher
[
dir
]))
{
return
matcher
(
value
);
}
}
return
null
;
}
});
kity
.
extendClass
(
Node
,
{
/**
* 获得节点的样式
* @param {String} name 样式名称
*/
getStyle
:
function
(
name
)
{
var
minder
=
this
.
minder
,
value
;
if
(
!
this
.
minder
)
return
null
;
value
=
minder
.
getStyle
(
name
);
return
value
!==
null
?
value
:
minder
.
getStyle
(
this
.
getType
()
+
'-'
+
name
);
}
});
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment