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
518eec4e
Commit
518eec4e
authored
Apr 23, 2015
by
techird
Browse files
Options
Browse Files
Download
Plain Diff
1.4.0
parents
fe784d12
51eaa58a
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
303 additions
and
418 deletions
+303
-418
README.md
README.md
+8
-2
bower.json
bower.json
+17
-2
_boxv.js
src/core/_boxv.js
+34
-0
command.js
src/core/command.js
+1
-6
data.js
src/core/data.js
+8
-10
layout.js
src/core/layout.js
+6
-18
node.js
src/core/node.js
+43
-1
patch.js
src/core/patch.js
+110
-0
select.js
src/core/select.js
+5
-1
theme.js
src/core/theme.js
+1
-0
kityminder.js
src/kityminder.js
+3
-1
btree.js
src/layout/btree.js
+1
-1
clipboard.js
src/module/clipboard.js
+1
-1
expand.js
src/module/expand.js
+30
-2
history.js
src/module/history.js
+0
-352
keynav.js
src/module/keynav.js
+23
-14
node.js
src/module/node.js
+10
-5
priority.js
src/module/priority.js
+1
-1
select.js
src/module/select.js
+1
-1
No files found.
README.md
View file @
518eec4e
...
...
@@ -9,12 +9,12 @@ KityMinder 是一款强大的脑图可视化/编辑工具,由百度 FEX 团队
*
包括脑图数据的可视化展示(Json 格式)
*
包括简单的编辑功能(节点创建、编辑、删除)。更加强大编辑功能的 KityMinder 编辑器请移步
[
kityminder-editor
](
https://github.com/fex-team/kityminder-editor
)
*
不包含第三方格式(FreeMind、XMind、MindManager
、纯文本、Markdown 等)的支持,可以加载
[
kityminder-protocol
](
https://github.com/fex-team/kityminder
-protocol
)
来扩展第三方格式支持。
*
不包含第三方格式(FreeMind、XMind、MindManager
)的支持,可以加载
[
kityminder-protocol
](
https://github.com/fex-team/kityminder-third-party
-protocol
)
来扩展第三方格式支持。
*
不包含文件存储的支持,需要自行实现存储。可参照
[
百度脑图
](
https://github.com/fex-team/naotu.baidu.com
)
中的开源的 fio + 百度网盘方案进行实现。
## 使用
可以参考
[
example.html
](
example.html
)
进行使用
,代码类似:
可以参考
[
example.html
](
example.html
)
进行使用
。
```
js
<
div
id
=
"minder-container"
><
/div
>
...
...
@@ -59,6 +59,12 @@ npm install
grunt
```
想偷懒?可以用下面这个一行安装脚本:
```
bash
https://gist.githubusercontent.com/techird/72b420c7ea05154ce821/raw/6416f2709ce82a3a0d86a50763de1ce3ca7f3ca2/setup-km-core
```
## 联系我们
问题和建议反馈:
[
Github Issues
](
https://github.com/fex-team/kityminder-core/issues
)
...
...
bower.json
View file @
518eec4e
...
...
@@ -2,7 +2,7 @@
"name"
:
"kityminder-core"
,
"title"
:
"Kity Minder Core"
,
"description"
:
"Powerful online mind graphic visualization and editor (command based)"
,
"version"
:
"1.4.
0
"
,
"version"
:
"1.4.
1
"
,
"main"
:
[
"release/kityminder.core.min.js"
,
"release/kityminder.core.css"
...
...
@@ -30,4 +30,19 @@
"name"
:
"Baidu FEX"
,
"url"
:
"http://fex.baidu.com"
}
],
"bugs"
:
{
"url"
:
"https://github.com/fex-team/kityminder-core/issues"
},
"repository"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/fex-team/kityminder-core.git"
},
"author"
:
{
"name"
:
"Baidu FEX"
,
"url"
:
"http://fex.baidu.com"
},
"dependencies"
:
{
"json-diff"
:
"*"
}
}
src/core/_boxv.js
0 → 100644
View file @
518eec4e
/**
* @fileOverview
*
* 调试工具:为 kity.Box 提供一个可视化的渲染
*
* @author: techird
* @copyright: Baidu FEX, 2014
*/
define
(
function
(
require
,
exports
,
module
)
{
var
kity
=
require
(
'./kity'
);
var
Minder
=
require
(
'./minder'
);
if
(
location
.
href
.
indexOf
(
'boxv'
)
!=
-
1
)
{
var
vrect
;
Object
.
defineProperty
(
kity
.
Box
.
prototype
,
'visualization'
,
{
get
:
function
()
{
if
(
!
vrect
)
return
null
;
return
vrect
.
setBox
(
this
);
}
});
Minder
.
registerInitHook
(
function
()
{
this
.
on
(
'paperrender'
,
function
()
{
vrect
=
new
kity
.
Rect
();
vrect
.
fill
(
'rgba(200, 200, 200, .5)'
);
vrect
.
stroke
(
'orange'
);
this
.
getRenderContainer
().
addShape
(
vrect
);
});
});
}
});
\ No newline at end of file
src/core/command.js
View file @
518eec4e
...
...
@@ -134,23 +134,18 @@ define(function(require, exports, module) {
return
false
;
}
if
(
!
this
.
_hasEnterExecCommand
&&
cmd
.
isNeedUndo
()
)
{
if
(
!
this
.
_hasEnterExecCommand
)
{
this
.
_hasEnterExecCommand
=
true
;
stoped
=
this
.
_fire
(
new
MinderEvent
(
'beforeExecCommand'
,
eventParams
,
true
));
if
(
!
stoped
)
{
//保存场景
this
.
_fire
(
new
MinderEvent
(
'saveScene'
));
this
.
_fire
(
new
MinderEvent
(
'preExecCommand'
,
eventParams
,
false
));
result
=
cmd
.
execute
.
apply
(
cmd
,
[
me
].
concat
(
cmdArgs
));
this
.
_fire
(
new
MinderEvent
(
'execCommand'
,
eventParams
,
false
));
//保存场景
this
.
_fire
(
new
MinderEvent
(
'saveScene'
));
if
(
cmd
.
isContentChanged
())
{
this
.
_firePharse
(
new
MinderEvent
(
'contentchange'
));
}
...
...
src/core/data.js
View file @
518eec4e
...
...
@@ -46,12 +46,10 @@ define(function(require, exports, module) {
var
exported
=
{};
exported
.
data
=
node
.
getData
();
var
childNodes
=
node
.
getChildren
();
if
(
childNodes
.
length
)
{
exported
.
children
=
[];
for
(
var
i
=
0
;
i
<
childNodes
.
length
;
i
++
)
{
exported
.
children
.
push
(
exportNode
(
childNodes
[
i
]));
}
}
return
exported
;
}
...
...
@@ -63,7 +61,7 @@ define(function(require, exports, module) {
json
.
theme
=
this
.
getTheme
();
json
.
version
=
Minder
.
version
;
return
json
;
return
JSON
.
parse
(
JSON
.
stringify
(
json
))
;
},
/**
...
...
@@ -140,7 +138,7 @@ define(function(require, exports, module) {
*
* @param {string} protocol 指定的数据协议(默认内置五种数据协议 `json`、`text`、`markdown`、`svg` 和 `png`)
*/
exportData
:
function
(
protocolName
)
{
exportData
:
function
(
protocolName
,
option
)
{
var
json
,
protocol
;
json
=
this
.
exportJson
();
...
...
@@ -161,7 +159,7 @@ define(function(require, exports, module) {
protocol
:
protocol
}));
return
Promise
.
resolve
(
protocol
.
encode
(
json
,
this
));
return
Promise
.
resolve
(
protocol
.
encode
(
json
,
this
,
option
));
},
/**
...
...
@@ -174,7 +172,7 @@ define(function(require, exports, module) {
* @param {string} protocol 指定的用于解析数据的数据协议(默认内置三种数据协议 `json`、`text` 和 `markdown` 的支持)
* @param {any} data 要导入的数据
*/
importData
:
function
(
protocolName
,
data
)
{
importData
:
function
(
protocolName
,
data
,
option
)
{
var
json
,
protocol
;
var
minder
=
this
;
...
...
@@ -196,7 +194,7 @@ define(function(require, exports, module) {
// 导入前抛事件
this
.
_fire
(
new
MinderEvent
(
'beforeimport'
,
params
));
return
Promise
.
resolve
(
protocol
.
decode
(
data
,
this
)).
then
(
function
(
json
)
{
return
Promise
.
resolve
(
protocol
.
decode
(
data
,
this
,
option
)).
then
(
function
(
json
)
{
minder
.
importJson
(
json
);
return
json
;
});
...
...
src/core/layout.js
View file @
518eec4e
...
...
@@ -34,7 +34,7 @@ define(function(require, exports, module) {
* children[i].setLayoutTransform(new kity.Matrix().translate(x, y));
* }
*/
doLayout
:
function
(
node
)
{
doLayout
:
function
(
parent
,
children
)
{
throw
new
Error
(
'Not Implement: Layout.doLayout()'
);
},
...
...
@@ -234,10 +234,6 @@ define(function(require, exports, module) {
return
this
.
parent
.
getLayoutInstance
().
getOrderHint
(
this
);
},
getExpandPosition
:
function
()
{
return
this
.
getLayoutInstance
().
getExpandPosition
();
},
/**
* 获取当前节点相对于父节点的布局变换
*/
...
...
@@ -255,7 +251,7 @@ define(function(require, exports, module) {
var
matrix
=
this
.
getLayoutTransform
();
var
offset
=
this
.
getLayoutOffset
();
if
(
offset
)
{
matrix
.
translate
(
offset
.
x
,
offset
.
y
);
matrix
=
matrix
.
clone
()
.
translate
(
offset
.
x
,
offset
.
y
);
}
return
pMatrix
.
merge
(
matrix
);
},
...
...
@@ -359,16 +355,10 @@ define(function(require, exports, module) {
setLayoutOffset
:
function
(
p
)
{
if
(
!
this
.
parent
)
return
this
;
if
(
p
&&
!
this
.
hasLayoutOffset
())
{
var
m
=
this
.
getLayoutTransform
().
m
;
p
=
p
.
offset
(
m
.
e
,
m
.
f
);
this
.
setLayoutTransform
(
null
);
}
this
.
setData
(
'layout_'
+
this
.
parent
.
getLayout
()
+
'_offset'
,
p
?
{
x
:
p
.
x
,
y
:
p
.
y
}
:
null
);
}
:
undefined
);
return
this
;
},
...
...
@@ -421,7 +411,7 @@ define(function(require, exports, module) {
var
childrenInFlow
=
node
.
getChildren
().
filter
(
function
(
child
)
{
return
!
child
.
hasLayoutOffset
();
});
layout
.
doLayout
(
node
,
childrenInFlow
,
round
);
layout
.
doLayout
(
node
,
node
.
getChildren
()
,
round
);
}
// 第一轮布局
...
...
@@ -471,7 +461,7 @@ define(function(require, exports, module) {
}
function
apply
(
node
,
pMatrix
)
{
var
matrix
=
node
.
getLayoutTransform
().
merge
(
pMatrix
);
var
matrix
=
node
.
getLayoutTransform
().
merge
(
pMatrix
.
clone
()
);
var
lastMatrix
=
node
.
getGlobalLayoutTransform
()
||
new
kity
.
Matrix
();
var
offset
=
node
.
getLayoutOffset
();
...
...
@@ -480,7 +470,6 @@ define(function(require, exports, module) {
matrix
.
m
.
e
=
Math
.
round
(
matrix
.
m
.
e
);
matrix
.
m
.
f
=
Math
.
round
(
matrix
.
m
.
f
);
// 如果当前有动画,停止动画
if
(
node
.
_layoutTimeline
)
{
node
.
_layoutTimeline
.
stop
();
...
...
@@ -518,10 +507,9 @@ define(function(require, exports, module) {
apply
(
node
.
children
[
i
],
matrix
);
}
}
apply
(
root
,
root
.
parent
?
root
.
parent
.
getGlobalLayoutTransform
()
:
new
kity
.
Matrix
());
return
this
;
}
,
}
});
module
.
exports
=
Layout
;
...
...
src/core/node.js
View file @
518eec4e
...
...
@@ -72,6 +72,16 @@ define(function(require, exports, module) {
return
this
.
parent
;
},
getSiblings
:
function
()
{
var
children
=
this
.
parent
.
children
;
var
siblings
=
[];
var
self
=
this
;
children
.
forEach
(
function
(
child
)
{
if
(
child
!=
self
)
siblings
.
push
(
child
);
});
return
siblings
;
},
/**
* 获得节点的深度
*/
...
...
@@ -122,7 +132,16 @@ define(function(require, exports, module) {
},
setData
:
function
(
key
,
value
)
{
if
(
typeof
key
==
'object'
)
{
var
data
=
key
;
for
(
key
in
data
)
if
(
data
.
hasOwnProperty
(
key
))
{
this
.
data
[
key
]
=
data
[
key
];
}
}
else
{
this
.
data
[
key
]
=
value
;
}
return
this
;
},
/**
...
...
@@ -305,6 +324,29 @@ define(function(require, exports, module) {
root
.
minder
=
this
;
},
getAllNode
:
function
()
{
var
nodes
=
[];
this
.
getRoot
().
traverse
(
function
(
node
)
{
nodes
.
push
(
node
);
});
return
nodes
;
},
getNodeById
:
function
(
id
)
{
return
this
.
getNodesById
([
id
])[
0
];
},
getNodesById
:
function
(
ids
)
{
var
nodes
=
this
.
getAllNode
();
var
result
=
[];
nodes
.
forEach
(
function
(
node
)
{
if
(
ids
.
indexOf
(
node
.
getData
(
'id'
))
!=
-
1
)
{
result
.
push
(
node
);
}
});
return
result
;
},
createNode
:
function
(
textOrData
,
parent
,
index
)
{
var
node
=
new
MinderNode
(
textOrData
);
this
.
fire
(
'nodecreate'
,
{
...
...
src/core/patch.js
0 → 100644
View file @
518eec4e
/**
* @fileOverview
*
* 打补丁
*
* @author: techird
* @copyright: Baidu FEX, 2014
*/
define
(
function
(
require
,
exports
,
module
)
{
var
kity
=
require
(
'./kity'
);
var
Minder
=
require
(
'./minder'
);
function
insertNode
(
minder
,
info
,
parent
,
index
)
{
parent
=
minder
.
createNode
(
info
.
data
,
parent
,
index
);
info
.
children
.
forEach
(
function
(
childInfo
,
index
)
{
insertNode
(
minder
,
childInfo
,
parent
,
index
);
});
return
parent
;
}
function
applyPatch
(
minder
,
patch
)
{
// patch.op - 操作,包括 remove, add, replace
// patch.path - 路径,如 '/root/children/1/data'
// patch.value - 数据,如 { text: "思路" }
var
path
=
patch
.
path
.
split
(
'/'
);
path
.
shift
();
var
changed
=
path
.
shift
();
var
node
;
if
(
changed
==
'root'
)
{
var
dataIndex
=
path
.
indexOf
(
'data'
);
if
(
dataIndex
>
-
1
)
{
changed
=
'data'
;
var
dataPath
=
path
.
splice
(
dataIndex
+
1
);
patch
.
dataPath
=
dataPath
;
}
else
{
changed
=
'node'
;
}
node
=
minder
.
getRoot
();
var
segment
,
index
;
while
(
segment
=
path
.
shift
())
{
if
(
segment
==
'children'
)
continue
;
if
(
typeof
index
!=
'undefined'
)
node
=
node
.
getChild
(
index
);
index
=
+
segment
;
}
patch
.
index
=
index
;
patch
.
node
=
node
;
}
var
express
=
patch
.
express
=
[
changed
,
patch
.
op
].
join
(
'.'
);
switch
(
express
)
{
case
'theme.replace'
:
minder
.
useTheme
(
patch
.
value
);
break
;
case
'template.replace'
:
minder
.
useTemplate
(
patch
.
value
);
break
;
case
'node.add'
:
insertNode
(
minder
,
patch
.
value
,
patch
.
node
,
patch
.
index
).
renderTree
();
minder
.
layout
();
break
;
case
'node.remove'
:
minder
.
removeNode
(
patch
.
node
.
getChild
(
patch
.
index
));
minder
.
layout
();
break
;
case
'data.add'
:
case
'data.replace'
:
case
'data.remove'
:
var
data
=
patch
.
node
.
data
;
var
field
;
path
=
patch
.
dataPath
.
slice
();
while
(
data
&&
path
.
length
>
1
)
{
field
=
path
.
shift
();
if
(
field
in
data
)
{
data
=
data
[
field
];
}
else
if
(
patch
.
op
!=
'remove'
)
{
data
=
data
[
field
]
=
{};
}
}
if
(
data
)
{
field
=
path
.
shift
();
data
[
field
]
=
patch
.
value
;
}
if
(
field
==
'expandState'
)
{
node
.
renderTree
();
}
else
{
node
.
render
();
}
minder
.
layout
();
}
minder
.
fire
(
'patch'
,
{
'patch'
:
patch
}
);
}
kity
.
extendClass
(
Minder
,
{
applyPatches
:
function
(
patches
)
{
for
(
var
i
=
0
;
i
<
patches
.
length
;
i
++
)
{
applyPatch
(
this
,
patches
[
i
]);
}
this
.
fire
(
'contentchange'
);
return
this
;
}
});
});
\ No newline at end of file
src/core/select.js
View file @
518eec4e
...
...
@@ -80,7 +80,11 @@ define(function(require, exports, module) {
this
.
renderChangedSelection
(
lastSelect
);
return
this
;
},
selectById
:
function
(
ids
,
isSingleSelect
)
{
ids
=
utils
.
isArray
(
ids
)
?
ids
:
[
ids
];
var
nodes
=
this
.
getNodesById
(
ids
);
return
this
.
select
(
nodes
,
isSingleSelect
);
},
//当前选区中的节点在给定的节点范围内的保留选中状态,
//没在给定范围的取消选中,给定范围中的但没在当前选中范围的也做选中效果
toggleSelect
:
function
(
node
)
{
...
...
src/core/theme.js
View file @
518eec4e
...
...
@@ -64,6 +64,7 @@ define(function(require, exports, module) {
},
setTheme
:
function
(
name
)
{
if
(
name
&&
!
_themes
[
name
])
throw
new
Error
(
'Theme '
+
name
+
' not exists!'
);
var
lastTheme
=
this
.
_theme
;
this
.
_theme
=
name
||
null
;
var
container
=
this
.
getRenderTarget
();
...
...
src/kityminder.js
View file @
518eec4e
...
...
@@ -39,6 +39,8 @@ define(function(require, exports, module) {
kityminder
.
Theme
=
require
(
'./core/theme'
);
kityminder
.
Template
=
require
(
'./core/template'
);
kityminder
.
Promise
=
require
(
'./core/promise'
);
require
(
'./core/_boxv'
);
require
(
'./core/patch'
);
// 模块依赖
require
(
'./module/arrange'
);
...
...
@@ -47,7 +49,6 @@ define(function(require, exports, module) {
require
(
'./module/dragtree'
);
require
(
'./module/expand'
);
require
(
'./module/font'
);
require
(
'./module/history'
);
require
(
'./module/hyperlink'
);
require
(
'./module/image'
);
require
(
'./module/keynav'
);
...
...
@@ -81,6 +82,7 @@ define(function(require, exports, module) {
require
(
'./theme/fresh'
);
require
(
'./theme/fish'
);
require
(
'./theme/snow'
);
require
(
'./theme/wire'
);
require
(
'./connect/arc'
);
require
(
'./connect/bezier'
);
...
...
src/layout/btree.js
View file @
518eec4e
...
...
@@ -112,7 +112,7 @@ define(function(require, exports, module) {
this
.
stack
(
children
,
oppsite
[
axis
]);
var
bbox
=
this
.
getBranchBox
(
children
);
var
xAdjust
,
yAdjust
;
var
xAdjust
=
0
,
yAdjust
=
0
;
if
(
axis
==
'x'
)
{
xAdjust
=
pbox
[
name
];
...
...
src/module/clipboard.js
View file @
518eec4e
...
...
@@ -29,7 +29,7 @@ define(function(require, exports, module) {
function
sendToClipboard
(
nodes
)
{
if
(
!
nodes
.
length
)
return
;
nodes
.
sort
(
function
(
a
,
b
)
{
return
b
.
getIndex
()
-
a
.
getIndex
();
return
a
.
getIndex
()
-
b
.
getIndex
();
});
_clipboardNodes
=
nodes
.
map
(
function
(
node
)
{
return
node
.
clone
();
...
...
src/module/expand.js
View file @
518eec4e
...
...
@@ -77,7 +77,8 @@ define(function(require, exports, module) {
},
queryState
:
function
(
km
)
{
return
km
.
getSelectedNode
()
?
0
:
-
1
;
var
node
=
km
.
getSelectedNode
();
return
node
&&
!
node
.
isRoot
()
&&
!
node
.
isExpanded
()
?
0
:
-
1
;
}
});
...
...
@@ -100,6 +101,31 @@ define(function(require, exports, module) {
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
,
...
...
@@ -175,10 +201,12 @@ define(function(require, exports, module) {
this
.
expander
.
setTranslate
(
position
);
}
});
return
{
commands
:
{
'expand'
:
ExpandCommand
,
'expandtolevel'
:
ExpandToLevelCommand
'expandtolevel'
:
ExpandToLevelCommand
,
'collapse'
:
CollapseCommand
},
events
:
{
'layoutapply'
:
function
(
e
)
{
...
...
src/module/history.js
deleted
100644 → 0
View file @
fe784d12
define
(
function
(
require
,
exports
,
module
)
{
var
kity
=
require
(
'../core/kity'
);
var
utils
=
require
(
'../core/utils'
);
var
Minder
=
require
(
'../core/minder'
);
var
MinderNode
=
require
(
'../core/node'
);
var
Command
=
require
(
'../core/command'
);
var
Module
=
require
(
'../core/module'
);
function
compareObject
(
source
,
target
)
{
var
tmp
;
if
(
isEmptyObject
(
source
)
!==
isEmptyObject
(
target
))
{
return
false
;
}
if
(
getObjectLength
(
source
)
!=
getObjectLength
(
target
))
{
return
false
;
}
for
(
var
p
in
source
)
{
if
(
source
.
hasOwnProperty
(
p
))
{
tmp
=
source
[
p
];
if
(
target
[
p
]
===
undefined
)
{
return
false
;
}
if
(
utils
.
isObject
(
tmp
)
||
utils
.
isArray
(
tmp
))
{
if
(
utils
.
isObject
(
target
[
p
])
!==
utils
.
isObject
(
tmp
))
{
return
false
;
}
if
(
utils
.
isArray
(
tmp
)
!==
utils
.
isArray
(
target
[
p
]))
{
return
false
;
}
if
(
compareObject
(
tmp
,
target
[
p
])
===
false
)
{
return
false
;
}
}
else
{
if
(
tmp
!=
target
[
p
])
{
return
false
;
}
}
}
}
return
true
;
}
function
getObjectLength
(
obj
)
{
if
(
utils
.
isArray
(
obj
)
||
utils
.
isString
(
obj
))
return
obj
.
length
;
var
count
=
0
;
for
(
var
key
in
obj
)
if
(
obj
.
hasOwnProperty
(
key
))
count
++
;
return
count
;
}
function
isEmptyObject
(
obj
)
{
if
(
obj
===
null
||
obj
===
undefined
)
return
true
;
if
(
utils
.
isArray
(
obj
)
||
utils
.
isString
(
obj
))
return
obj
.
length
===
0
;
for
(
var
key
in
obj
)
if
(
obj
.
hasOwnProperty
(
key
))
return
false
;
return
true
;
}
function
getValueByIndex
(
data
,
index
)
{
var
initIndex
=
0
,
result
=
0
;
data
.
forEach
(
function
(
arr
,
i
)
{
if
(
initIndex
+
arr
.
length
>=
index
)
{
if
(
index
-
initIndex
==
arr
.
length
)
{
if
(
arr
.
length
==
1
&&
arr
[
0
].
width
===
0
)
{
initIndex
++
;
return
;
}
result
=
{
x
:
arr
[
arr
.
length
-
1
].
x
+
arr
[
arr
.
length
-
1
].
width
,
y
:
arr
[
arr
.
length
-
1
].
y
};
}
else
{
result
=
arr
[
index
-
initIndex
];
}
return
false
;
}
else
{
initIndex
+=
arr
.
length
+
(
arr
.
length
==
1
&&
arr
[
0
].
width
===
0
?
0
:
1
);
}
});
return
result
;
}
function
getNodeIndex
(
node
,
ignoreTextNode
)
{
var
preNode
=
node
,
i
=
0
;
while
(
preNode
=
preNode
.
previousSibling
)
{
if
(
ignoreTextNode
&&
preNode
.
nodeType
==
3
)
{
if
(
preNode
.
nodeType
!=
preNode
.
nextSibling
.
nodeType
)
{
i
++
;
}
continue
;
}
i
++
;
}
return
i
;
}
var
km
=
this
;
var
Scene
=
kity
.
createClass
(
'Scene'
,
{
constructor
:
function
(
root
,
inputStatus
)
{
this
.
data
=
root
.
clone
();
this
.
inputStatus
=
inputStatus
;
},
getData
:
function
()
{
return
this
.
data
;
},
cloneData
:
function
()
{
return
this
.
getData
().
clone
();
},
equals
:
function
(
scene
)
{
return
this
.
getData
().
compareTo
(
scene
.
getData
());
},
isInputStatus
:
function
()
{
return
this
.
inputStatus
;
},
setInputStatus
:
function
(
status
)
{
this
.
inputStatus
=
status
;
}
});
var
HistoryManager
=
kity
.
createClass
(
'HistoryManager'
,
{
constructor
:
function
(
km
)
{
this
.
list
=
[];
this
.
index
=
0
;
this
.
hasUndo
=
false
;
this
.
hasRedo
=
false
;
this
.
km
=
km
;
},
undo
:
function
()
{
if
(
this
.
hasUndo
)
{
var
currentScene
=
this
.
list
[
this
.
index
];
//如果是输入文字时的保存,直接回复当前场景
if
(
currentScene
&&
currentScene
.
isInputStatus
())
{
this
.
saveScene
();
this
.
restore
(
--
this
.
index
);
currentScene
.
setInputStatus
(
false
);
return
;
}
if
(
this
.
list
.
length
==
1
)
{
this
.
restore
(
0
);
return
;
}
if
(
!
this
.
list
[
this
.
index
-
1
]
&&
this
.
list
.
length
==
1
)
{
this
.
reset
();
return
;
}
while
(
this
.
list
[
this
.
index
].
equals
(
this
.
list
[
this
.
index
-
1
]))
{
this
.
index
--
;
if
(
this
.
index
===
0
)
{
return
this
.
restore
(
0
);
}
}
this
.
restore
(
--
this
.
index
);
}
},
redo
:
function
()
{
if
(
this
.
hasRedo
)
{
while
(
this
.
list
[
this
.
index
].
equals
(
this
.
list
[
this
.
index
+
1
]))
{
this
.
index
++
;
if
(
this
.
index
==
this
.
list
.
length
-
1
)
{
return
this
.
restore
(
this
.
index
);
}
}
this
.
restore
(
++
this
.
index
);
}
},
partialRenewal
:
function
(
target
)
{
var
selectedNodes
=
[];
function
compareNode
(
source
,
target
)
{
if
(
source
.
getText
()
!=
target
.
getText
())
{
return
false
;
}
if
(
compareObject
(
source
.
getData
(),
target
.
getData
())
===
false
)
{
return
false
;
}
return
true
;
}
function
appendChildNode
(
parent
,
child
)
{
if
(
child
.
isSelected
())
{
selectedNodes
.
push
(
child
);
}
km
.
appendNode
(
child
,
parent
);
child
.
render
();
var
children
=
child
.
children
.
slice
();
for
(
var
i
=
0
,
ci
;
ci
=
children
[
i
++
];)
{
appendChildNode
(
child
,
ci
);
}
}
function
traverseNode
(
srcNode
,
tagNode
)
{
if
(
compareNode
(
srcNode
,
tagNode
)
===
false
)
{
srcNode
.
setValue
(
tagNode
);
}
//todo,这里有性能问题,变成全部render了
srcNode
.
render
();
if
(
srcNode
.
isSelected
())
{
selectedNodes
.
push
(
srcNode
);
}
for
(
var
i
=
0
,
j
=
0
,
si
,
tj
;
(
si
=
srcNode
.
children
[
i
],
tj
=
tagNode
.
children
[
j
],
si
||
tj
);
i
++
,
j
++
)
{
if
(
si
&&
!
tj
)
{
i
--
;
km
.
removeNode
(
si
);
}
else
if
(
!
si
&&
tj
)
{
j
--
;
appendChildNode
(
srcNode
,
tj
);
}
else
{
traverseNode
(
si
,
tj
);
}
}
}
var
km
=
this
.
km
;
traverseNode
(
km
.
getRoot
(),
target
);
km
.
layout
(
200
);
km
.
select
(
selectedNodes
,
true
);
selectedNodes
=
[];
},
restore
:
function
(
index
)
{
index
=
index
===
undefined
?
this
.
index
:
index
;
var
scene
=
this
.
list
[
index
];
this
.
partialRenewal
(
scene
.
cloneData
());
this
.
update
();
this
.
km
.
fire
(
'restoreScene'
);
this
.
km
.
fire
(
'contentChange'
);
},
getScene
:
function
(
inputStatus
)
{
return
new
Scene
(
this
.
km
.
getRoot
(),
inputStatus
);
},
saveScene
:
function
(
inputStatus
)
{
var
currentScene
=
this
.
getScene
(
inputStatus
);
var
lastScene
=
this
.
list
[
this
.
index
];
if
(
lastScene
&&
lastScene
.
equals
(
currentScene
))
{
if
(
inputStatus
)
{
lastScene
.
setInputStatus
(
true
);
this
.
update
();
}
return
;
}
this
.
list
=
this
.
list
.
slice
(
0
,
this
.
index
+
1
);
this
.
list
.
push
(
currentScene
);
//如果大于最大数量了,就把最前的剔除
if
(
this
.
list
.
length
>
this
.
km
.
getOption
(
'maxUndoCount'
))
{
this
.
list
.
shift
();
}
this
.
index
=
this
.
list
.
length
-
1
;
//跟新undo/redo状态
this
.
update
();
},
update
:
function
()
{
this
.
hasRedo
=
!!
this
.
list
[
this
.
index
+
1
];
this
.
hasUndo
=
!!
this
.
list
[
this
.
index
-
1
];
var
currentScene
=
this
.
list
[
this
.
index
];
if
(
currentScene
&&
currentScene
.
isInputStatus
())
{
this
.
hasUndo
=
true
;
}
},
reset
:
function
()
{
this
.
list
=
[];
this
.
index
=
0
;
this
.
hasUndo
=
false
;
this
.
hasRedo
=
false
;
}
});
Module
.
register
(
'HistoryModule'
,
function
()
{
//为km实例添加history管理
this
.
historyManager
=
new
HistoryManager
(
this
);
return
{
defaultOptions
:
{
maxUndoCount
:
20
,
maxInputCount
:
20
},
'commands'
:
{
/**
* @command Undo
* @description 回退上一步操作
* @state
* 0: 当前有可回退的内容
* -1: 当前没有可回退的内容
*/
'undo'
:
kity
.
createClass
(
'UndoCommand'
,
{
base
:
Command
,
execute
:
function
(
km
)
{
km
.
historyManager
.
undo
();
},
queryState
:
function
(
km
)
{
return
km
.
historyManager
.
hasUndo
?
0
:
-
1
;
},
isNeedUndo
:
function
()
{
return
false
;
}
}),
/**
* @command Redo
* @description 重做下一步已回退的操作
* @state
* 0: 当前有可重做的内容
* -1: 当前没有可重做的内容
*/
'redo'
:
kity
.
createClass
(
'RedoCommand'
,
{
base
:
Command
,
execute
:
function
(
km
)
{
km
.
historyManager
.
redo
();
},
queryState
:
function
(
km
)
{
return
km
.
historyManager
.
hasRedo
?
0
:
-
1
;
},
isNeedUndo
:
function
()
{
return
false
;
}
})
},
commandShortcutKeys
:
{
'undo'
:
'ctrl+z'
,
//undo
'redo'
:
'ctrl+y'
//redo
},
'events'
:
{
'saveScene'
:
function
(
e
)
{
this
.
historyManager
.
saveScene
(
e
.
inputStatus
);
},
'import'
:
function
()
{
this
.
historyManager
.
reset
();
}
}
};
});
});
\ No newline at end of file
src/module/keynav.js
View file @
518eec4e
...
...
@@ -31,8 +31,7 @@ define(function(require, exports, module) {
bottom
:
p
.
y
+
p
.
height
,
width
:
p
.
width
,
height
:
p
.
height
,
node
:
node
,
text
:
node
.
getText
()
node
:
node
});
}
});
...
...
@@ -57,10 +56,19 @@ define(function(require, exports, module) {
else
if
(
yDist
<
0
)
dist
=
xDist
;
else
dist
=
sqrt
(
xDist
*
xDist
+
yDist
*
yDist
);
return
{
cx
:
dist
,
cy
:
dist
};
var
node1
=
box1
.
node
;
var
node2
=
box2
.
node
;
// sibling
if
(
node1
.
parent
==
node2
.
parent
)
{
dist
/=
10
;
}
// parent
if
(
node2
.
parent
==
node1
)
{
dist
/=
5
;
}
return
dist
;
}
function
findClosestPointsFor
(
pointIndexes
,
iFind
)
{
...
...
@@ -78,9 +86,9 @@ define(function(require, exports, module) {
// left check
if
(
current
.
right
<
find
.
left
)
{
if
(
!
most
.
left
||
dist
.
cx
<
most
.
left
.
dist
)
{
if
(
!
most
.
left
||
dist
<
most
.
left
.
dist
)
{
most
.
left
=
{
dist
:
dist
.
cx
,
dist
:
dist
,
node
:
current
.
node
};
}
...
...
@@ -88,9 +96,9 @@ define(function(require, exports, module) {
// right check
if
(
current
.
left
>
find
.
right
)
{
if
(
!
most
.
right
||
dist
.
cx
<
most
.
right
.
dist
)
{
if
(
!
most
.
right
||
dist
<
most
.
right
.
dist
)
{
most
.
right
=
{
dist
:
dist
.
cx
,
dist
:
dist
,
node
:
current
.
node
};
}
...
...
@@ -98,9 +106,9 @@ define(function(require, exports, module) {
// top check
if
(
current
.
bottom
<
find
.
top
)
{
if
(
!
most
.
top
||
dist
.
cy
<
most
.
top
.
dist
)
{
if
(
!
most
.
top
||
dist
<
most
.
top
.
dist
)
{
most
.
top
=
{
dist
:
dist
.
cy
,
dist
:
dist
,
node
:
current
.
node
};
}
...
...
@@ -108,9 +116,9 @@ define(function(require, exports, module) {
// bottom check
if
(
current
.
top
>
find
.
bottom
)
{
if
(
!
most
.
down
||
dist
.
cy
<
most
.
down
.
dist
)
{
if
(
!
most
.
down
||
dist
<
most
.
down
.
dist
)
{
most
.
down
=
{
dist
:
dist
.
cy
,
dist
:
dist
,
node
:
current
.
node
};
}
...
...
@@ -153,6 +161,7 @@ define(function(require, exports, module) {
[
'left'
,
'right'
,
'up'
,
'down'
].
forEach
(
function
(
key
)
{
if
(
e
.
isShortcutKey
(
key
))
{
navigateTo
(
minder
,
key
==
'up'
?
'top'
:
key
);
e
.
preventDefault
();
}
});
}
...
...
src/module/node.js
View file @
518eec4e
...
...
@@ -23,10 +23,15 @@ define(function(require, exports, module) {
if
(
!
parent
)
{
return
null
;
}
parent
.
expand
();
var
node
=
km
.
createNode
(
text
,
parent
);
km
.
select
(
node
,
true
);
if
(
parent
.
isExpanded
())
{
node
.
render
();
}
else
{
parent
.
expand
();
parent
.
renderTree
();
}
km
.
layout
(
600
);
},
queryState
:
function
(
km
)
{
...
...
@@ -90,7 +95,7 @@ define(function(require, exports, module) {
},
queryState
:
function
(
km
)
{
var
selectedNode
=
km
.
getSelectedNode
();
return
selectedNode
?
0
:
-
1
;
return
selectedNode
&&
!
selectedNode
.
isRoot
()
?
0
:
-
1
;
}
});
...
...
@@ -115,7 +120,7 @@ define(function(require, exports, module) {
},
queryState
:
function
(
km
)
{
var
nodes
=
km
.
getSelectedNodes
();
if
(
!
nodes
.
length
)
return
;
if
(
!
nodes
.
length
)
return
-
1
;
var
parent
=
nodes
[
0
].
parent
;
if
(
!
parent
)
return
-
1
;
for
(
var
i
=
1
;
i
<
nodes
.
length
;
i
++
)
{
...
...
src/module/priority.js
View file @
518eec4e
...
...
@@ -117,7 +117,7 @@ define(function(require, exports, module) {
});
return
{
'commands'
:
{
'priority'
:
PriorityCommand
,
'priority'
:
PriorityCommand
},
'renderers'
:
{
left
:
kity
.
createClass
(
'PriorityRenderer'
,
{
...
...
src/module/select.js
View file @
518eec4e
...
...
@@ -132,7 +132,7 @@ define(function(require, exports, module) {
// 点中了节点,并且按了 shift 键:
// 被点中的节点切换选中状态
else
if
(
e
.
originEvent
.
shiftKey
)
{
else
if
(
e
.
isShortcutKey
(
'Ctrl'
)
)
{
this
.
toggleSelect
(
downNode
);
}
...
...
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