Commit 5e20101c authored by Akikonata's avatar Akikonata

Merge branch 'dev' of https://github.com/fex-team/kityminder into dev

parents 2c77fc41 434b240c
( function ( utils ) {
(function(utils) {
var content = '<div class="image-content" style="padding:20px;width:360px;">';
content += '<style>';
content += '.kmui-dialog-<%= container %> input{';
......@@ -36,39 +36,39 @@
KM.registerWidget( 'image', {
KM.registerWidget('image', {
tpl: content,
initContent: function ( km ) {
var lang = km.getLang( 'dialogs.image' ),
initContent: function(km) {
var lang = km.getLang('dialogs.image'),
html;
if ( lang ) {
html = $.parseTmpl( this.tpl, utils.extend( {
if (lang) {
html = $.parseTmpl(this.tpl, utils.extend({
'container': 'image'
}, lang ) );
}, lang));
}
this.root().html( html );
this.root().html(html);
},
initEvent: function ( km, $w ) {
$w.find( '#image_insert' ).on( 'click', function () {
km.execCommand( 'image', $w.find( '#image_href' ).val() );
initEvent: function(km, $w) {
$w.find('#image_insert').on('click', function() {
km.execCommand('image', $w.find('#image_href').val());
$w.kmui().hide();
} );
$w.find( '#image_href' ).on( 'keydown', function ( e ) {
if ( e.keyCode === 13 ) {
km.execCommand( 'image', $w.find( '#image_href' ).val() );
});
$w.find('#image_href').on('keydown', function(e) {
if (e.keyCode === 13) {
km.execCommand('image', $w.find('#image_href').val());
$w.kmui().hide();
}
} ).on('input', function() {
$w.find('#image_preview').attr('src', $w.find( '#image_href' ).val());
}).on('input', function() {
$w.find('#image_preview').attr('src', $w.find('#image_href').val());
});
var url = km.queryCommandValue( 'image' );
var $input = $w.find( '#image_href' );
$input.val( url || 'http://' );
if(url) $w.find('#image_preview').attr('src', url);
setTimeout( function () {
var url = km.queryCommandValue('image');
var $input = $w.find('#image_href');
$input.val(url || 'http://');
if (url) $w.find('#image_preview').attr('src', url);
setTimeout(function() {
$input.focus();
} );
});
},
width: 400
} );
} )( KM.Utils );
\ No newline at end of file
});
})(KM.Utils);
\ No newline at end of file
......@@ -59,6 +59,7 @@
'module/nodetext.js',
'module/hyperlink.js',
'module/expand.js',
'module/arrange.js',
'ui/jquery-ui-1.10.4.custom.min.js',
'ui/widget.js',
'ui/button.js',
......
......@@ -58,7 +58,6 @@
<a href="https://github.com/fex-team/kityminder/issues/new" target="_blank">Bug</a> |
<a href="mailto:kity@baidu.com" target="_blank">Contact Us</a>
</p>
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdMini":"2","bdMiniList":[],"bdPic":"","bdStyle":"1","bdSize":"32"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
</body>
<script>
// create km instance
......
Subproject commit 437d9c160a7961a3843cce3d9e2b01f64090f0df
Subproject commit 9e420efd89ba672f5389e21069eb0009e52ad7b1
var keymap = KityMinder.keymap = {
var keymap = KityMinder.keymap = (function(origin) {
var ret = {};
for (var key in origin) {
if (origin.hasOwnProperty(key)) {
ret[key] = origin[key];
ret[key.toLowerCase()] = origin[key];
}
}
return ret;
})({
'Backspace': 8,
'Tab': 9,
'Enter': 13,
......@@ -37,7 +46,7 @@ var keymap = KityMinder.keymap = {
'=': 187,
'-': 189,
"b": 66,
'b': 66,
'i': 73,
//回退
'z': 90,
......@@ -68,7 +77,7 @@ var keymap = KityMinder.keymap = {
38: 1,
39: 1,
40: 1,
113:1
113: 1
},
'isSelectedNodeKey': {
//上下左右
......@@ -79,4 +88,4 @@ var keymap = KityMinder.keymap = {
13: 1,
9: 1
}
};
\ No newline at end of file
});
\ No newline at end of file
......@@ -30,6 +30,18 @@ kity.extendClass(MinderNode, {
return layout;
},
getOrder: function() {
return this.getData('order') || this.getIndex();
},
setOrder: function(order) {
return this.setData('order', order);
},
getOrderHint: function(refer) {
return this.getLayoutInstance().getOrderHint(this);
},
getLayoutInstance: function() {
var LayoutClass = KityMinder._layout[this.getLayout()];
var layout = new LayoutClass();
......@@ -89,10 +101,10 @@ kity.extendClass(MinderNode, {
},
setLayoutOffset: function(p) {
this.setData('layout_' + this.getLayout() + '_offset', {
this.setData('layout_' + this.getLayout() + '_offset', p ? {
x: p.x,
y: p.y
});
} : null);
return this;
},
......@@ -147,11 +159,13 @@ kity.extendClass(Minder, {
layoutNode(this.getRoot());
return this.applyLayoutResult(duration);
this.applyLayoutResult(this.getRoot(), duration);
return this.fire('layout');
},
applyLayoutResult: function(duration) {
var root = this.getRoot();
applyLayoutResult: function(root, duration) {
root = root || this.getRoot();
var me = this;
function apply(node, pMatrix) {
......@@ -205,8 +219,7 @@ kity.extendClass(Minder, {
}
}
apply(root, new kity.Matrix());
this.fire('layout');
apply(root, root.parent ? root.parent.getGlobalLayoutTransform() : new kity.Matrix());
return this;
},
});
......@@ -291,5 +304,9 @@ var Layout = kity.createClass('Layout', {
box = g.mergeBox(box, matrix.transformBox(treeBox));
}
return box;
},
getOrderHint: function(node) {
return [];
}
});
\ No newline at end of file
......@@ -13,7 +13,7 @@ kity.extendClass( Minder, {
},
// TODO: mousemove lazy bind
_bindPaperEvents: function () {
this._paper.on( 'click dblclick mousedown contextmenu mouseup mousemove mousewheel DOMMouseScroll touchstart touchmove touchend', this._firePharse.bind( this ) );
this._paper.on( 'click dblclick mousedown contextmenu mouseup mousemove mousewheel DOMMouseScroll touchstart touchmove touchend dragenter dragleave drop', this._firePharse.bind( this ) );
if ( window ) {
window.addEventListener( 'resize', this._firePharse.bind( this ) );
window.addEventListener( 'blur', this._firePharse.bind( this ) );
......
......@@ -293,19 +293,22 @@ var MinderNode = KityMinder.MinderNode = kity.createClass('MinderNode', {
});
MinderNode.getCommonAncestor = function(nodeA, nodeB) {
if (nodeA instanceof Array) {
return MinderNode.getCommonAncestor.apply(this, nodeA);
}
switch (arguments.length) {
case 1:
return nodeA;
return nodeA.parent;
case 2:
if (nodeA.contains(nodeB)) {
if (nodeA.isAncestorOf(nodeB)) {
return nodeA;
}
if (nodeB.contains(nodeA)) {
if (nodeB.isAncestorOf(nodeA)) {
return nodeB;
}
var ancestor = nodeA.parent;
while (ancestor && !ancestor.contains(nodeB)) {
while (ancestor && !ancestor.isAncestorOf(nodeB)) {
ancestor = ancestor.parent;
}
return ancestor;
......
......@@ -24,12 +24,6 @@ var Renderer = KityMinder.Renderer = kity.createClass('Renderer', {
}
});
kity.extendClass(MinderNode, {
getContentBox: function() {
return this._contentBox;
}
});
kity.extendClass(Minder, {
_createRendererForNode: function(node) {
......@@ -122,17 +116,7 @@ kity.extendClass(MinderNode, {
return null;
},
getContentBox: function() {
return this.parent && this.parent.isCollapsed() ? {
x: 0,
y: 0,
width: 0,
height: 0,
left: 0,
top: 0,
bottom: 0,
right: 0,
cx: 0,
cy: 0
} : this._contentBox;
//if (!this._contentBox) this.render();
return this.parent && this.parent.isCollapsed() ? new kity.Box() : this._contentBox;
}
});
\ No newline at end of file
......@@ -13,7 +13,7 @@ KityMinder.registerConnectProvider('default', function(node, parent, connection)
var start, end, vector;
var abs = Math.abs;
var pathData = [];
var side = box.cx > pBox.cx ? 'right' : 'left';
var side = node.getLayoutVector().x > 0 ? 'right' : 'left';
node.getMinder().getPaper().addResource(connectMarker);
......@@ -38,30 +38,24 @@ KityMinder.registerConnectProvider('default', function(node, parent, connection)
var radius = node.getStyle('connect-radius');
var underY = box.bottom + 2;
var p1, p2, p3, p4, v12;
var isTop = parent.children.length > 1 && node.getIndex() === 0;
var startY = parent.getType() == 'sub' ? pBox.bottom + 2 : pBox.cy;
var p1, p2, p3, mx;
if (side == 'right') {
p1 = new kity.Point(pBox.right + parent.getStyle('margin-right'), pBox.cy);
p3 = new kity.Point(box.left, underY);
p4 = new kity.Point(box.right, underY);
p2 = p3.offset(-radius, isTop ? radius : -radius);
p1 = new kity.Point(pBox.right + 10, startY);
p2 = new kity.Point(box.left, underY);
p3 = new kity.Point(box.right + 10.5, underY);
} else {
p1 = new kity.Point(pBox.left - parent.getStyle('margin-left'), pBox.cy);
p3 = new kity.Point(box.right, underY);
p4 = new kity.Point(box.left, underY);
p2 = p3.offset(radius, isTop ? radius : -radius);
p1 = new kity.Point(pBox.left - 10, startY);
p2 = new kity.Point(box.right, underY);
p3 = new kity.Point(box.left - 10.5, underY);
}
v12 = kity.Vector.fromPoints(p1, p2);
mx = (p1.x + p2.x) / 2;
pathData.push('M', p1);
//pathData.push('L', p2);
// rx, ry, xr, laf, sf, p
var sf = +(side == 'right' && isTop || side == 'left' && !isTop);
pathData.push('C', mx, p1.y, mx, p2.y, p2);
pathData.push('L', p3);
pathData.push('L', p4);
//var ex = side == 'right' ? (start.x + radius) : (start.x - radius);
connection.setMarker(null);
......
......@@ -78,11 +78,13 @@ KityMinder.registerLayout('default', kity.createClass({
x = nodeContentBox.right - childContentBox.left;
x += parent.getStyle('margin-right') + child.getStyle('margin-left');
// 设置布局矢量
child.setLayoutVector(new kity.Vector(childContentBox.right, childContentBox.cy));
} else {
x = nodeContentBox.left - childContentBox.right;
x -= parent.getStyle('margin-left') + child.getStyle('margin-right');
// 设置布局矢量
child.setLayoutVector(new kity.Vector(childContentBox.left, childContentBox.cy));
}
......@@ -93,6 +95,7 @@ KityMinder.registerLayout('default', kity.createClass({
y += children[i].getStyle('margin-top');
}
// 设置布局结果
transform = new kity.Matrix().translate(x, y);
child.setLayoutTransform(transform);
......@@ -110,32 +113,34 @@ KityMinder.registerLayout('default', kity.createClass({
}
},
getLayoutContextPoints: function(node) {
var points = [];
var siblings = node.parent && node.parent.children;
var g = KityMinder.Geometry;
if (!siblings) return points;
siblings.forEach(function(sibling) {
if (sibling == node) return;
var index = sibling.getIndex();
var box = node.getLayoutBox();
// top order hint
points.push({
type: 'order',
index: index,
area: {
x: box.x,
y: box.top - 2,
width: box.width,
height: node.getStyle('margin-top')
},
hint: ['M', ]
});
getOrderHint: function(node) {
var hint = [];
var box = node.getLayoutBox();
var offset = node.getLevel() > 1 ? 3 : 5;
hint.push({
type: 'up',
node: node,
area: {
x: box.x,
y: box.top - node.getStyle('margin-top') - offset,
width: box.width,
height: node.getStyle('margin-top')
},
path: ['M', box.x, box.top - offset, 'L', box.right, box.top - offset]
});
return points;
hint.push({
type: 'down',
node: node,
area: {
x: box.x,
y: box.bottom + offset,
width: box.width,
height: node.getStyle('margin-bottom')
},
path: ['M', box.x, box.bottom + offset, 'L', box.right, box.bottom + offset]
});
return hint;
}
}));
\ No newline at end of file
kity.extendClass(MinderNode, {
arrange: function(index) {
var parent = this.parent;
if (!parent) return;
var sibling = parent.children;
if (index < 0 || index >= sibling.length) return;
sibling.splice(this.getIndex(), 1);
sibling.splice(index, 0, this);
return this;
}
});
function asc(nodeA, nodeB) {
return nodeA.getIndex() - nodeB.getIndex();
}
function desc(nodeA, nodeB) {
return -asc(nodeA, nodeB);
}
var ArrangeUpCommand = kity.createClass('ArrangeUpCommand', {
base: Command,
execute: function(km) {
var nodes = km.getSelectedNodes();
nodes.sort(asc);
var lastIndexes = nodes.map(function(node) {
return node.getIndex();
});
nodes.forEach(function(node, index) {
node.arrange(lastIndexes[index] - 1);
});
km.layout(300);
}
});
var ArrangeDownCommand = kity.createClass('ArrangeUpCommand', {
base: Command,
execute: function(km) {
var nodes = km.getSelectedNodes();
nodes.sort(desc);
var lastIndexes = nodes.map(function(node) {
return node.getIndex();
});
nodes.forEach(function(node, index) {
node.arrange(lastIndexes[index] + 1);
});
km.layout(300);
}
});
var ArrangeCommand = kity.createClass('ArrangeCommand', {
base: Command,
execute: function(km, nodes, index) {
nodes = nodes && nodes.slice() || km.getSelectedNodes().slice();
if (!nodes.length) return;
var ancestor = MinderNode.getCommonAncestor(nodes);
if (ancestor != nodes[0].parent) return;
var indexed = nodes.map(function(node) {
return {
index: node.getIndex(),
node: node
};
});
var asc = Math.min.apply(Math, indexed.map(function(one) { return one.index; })) >= index;
indexed.sort(function(a, b) {
return asc ? (b.index - a.index) : (a.index - b.index);
});
indexed.forEach(function(one) {
one.node.arrange(index);
});
km.layout(300);
}
});
KityMinder.registerModule('ArrangeModule', {
commands: {
'arrangeup': ArrangeUpCommand,
'arrangedown': ArrangeDownCommand,
'arrange': ArrangeCommand
},
addShortcutKeys: {
'arrangeup': 'alt+Up',
'arrangedown': 'alt+Down'
}
});
\ No newline at end of file
var GM = KityMinder.Geometry;
// 矩形的变形动画定义
var AreaAnimator = kity.createClass('AreaAnimator', {
base: kity.Animator,
constructor: function(startArea, endArea) {
startArea.opacity = 0;
endArea.opacity = 0.8;
this.callBase(startArea, endArea, function(target, value) {
target.setPosition(value.x, value.y);
target.setSize(value.width, value.height);
target.setOpacity(value.opacity);
});
}
});
var MoveToParentCommand = kity.createClass('MoveToParentCommand', {
base: Command,
......@@ -31,10 +19,51 @@ var MoveToParentCommand = kity.createClass('MoveToParentCommand', {
}
});
var DropHinter = kity.createClass('DropHinter', {
base: kity.Group,
constructor: function() {
this.callBase();
this.rect = new kity.Rect();
this.addShape(this.rect);
},
function boxMapper(node) {
return node.getLayoutBox();
}
render: function(target) {
this.setVisible(!!target);
if (target) {
this.rect
.setBox(target.getLayoutBox())
.setRadius(target.getStyle('radius') || 0)
.stroke(
target.getStyle('drop-hint-color') || 'yellow',
target.getStyle('drop-hint-width') || 2
);
}
}
});
var OrderHinter = kity.createClass('OrderHinter', {
base: kity.Group,
constructor: function() {
this.callBase();
this.area = new kity.Rect();
this.path = new kity.Path();
this.addShapes([this.area, this.path]);
},
render: function(hint) {
this.setVisible(!!hint);
if (hint) {
this.area.setBox(hint.area);
this.area.fill(hint.node.getStyle('order-hint-area-color') || 'rgba(0, 255, 0, .5)');
this.path.setPathData(hint.path);
this.path.stroke(
hint.node.getStyle('order-hint-path-color') || '#0f0',
hint.node.getStyle('order-hint-path-width') || 1);
}
}
});
// 对拖动对象的一个替代盒子,控制整个拖放的逻辑,包括:
// 1. 从节点列表计算出拖动部分
......@@ -43,6 +72,9 @@ var TreeDragger = kity.createClass('TreeDragger', {
constructor: function(minder) {
this._minder = minder;
this._dropHinter = new DropHinter();
this._orderHinter = new OrderHinter();
minder.getRenderContainer().addShapes([this._dropHinter, this._orderHinter]);
},
dragStart: function(position) {
......@@ -74,22 +106,51 @@ var TreeDragger = kity.createClass('TreeDragger', {
for (var i = 0; i < this._dragSources.length; i++) {
this._dragSources[i].setLayoutOffset(this._dragSourceOffsets[i].offset(movement));
minder.applyLayoutResult(this._dragSources[i]);
}
minder.layout();
this._orderTest();
//this._dropTest();
//this._updateDropHint();
if (!this._dropTest()) {
this._orderTest();
} else {
this._renderOrderHint(this._orderSucceedHint = null);
}
},
dragEnd: function() {
this._startPosition = null;
if (!this._dragMode) {
return;
}
if (this._dropSucceedTarget) {
this._dragSources.forEach(function(source) {
source.setLayoutOffset(null);
});
this._minder.execCommand('movetoparent', this._dragSources, this._dropSucceedTarget);
} else if (this._orderSucceedHint) {
var hint = this._orderSucceedHint;
var index = hint.node.getIndex();
var sourceIndexes = this._dragSources.map(function(source) {
// 顺便干掉布局偏移
source.setLayoutOffset(null);
return source.getIndex();
});
var maxIndex = Math.max.apply(Math, sourceIndexes);
var minIndex = Math.min.apply(Math, sourceIndexes);
if (index < minIndex && hint.type == 'down') index++;
if (index > maxIndex && hint.type == 'up') index--;
hint.node.setLayoutOffset(null);
this._minder.execCommand('arrange', this._dragSources, index);
this._renderOrderHint(null);
}
this._leaveDragMode();
},
......@@ -103,7 +164,9 @@ var TreeDragger = kity.createClass('TreeDragger', {
this._startPosition = null;
return false;
}
this._fadeDragSources(0.5);
this._calcDropTargets();
this._calcOrderHints();
this._dragMode = true;
return true;
},
......@@ -123,6 +186,12 @@ var TreeDragger = kity.createClass('TreeDragger', {
});
},
_fadeDragSources: function(opacity) {
this._dragSources.forEach(function(source) {
source.getRenderContainer().fxOpacity(opacity, 200);
});
},
// 计算拖放目标可以释放的节点列表(释放意味着成为其子树),存在这条限制规则:
// - 不能拖放到拖放目标的子树上(允许拖放到自身,因为多选的情况下可以把其它节点加入)
......@@ -149,46 +218,39 @@ var TreeDragger = kity.createClass('TreeDragger', {
}
this._dropTargets = findAvailableParents(this._dragSources, this._minder.getRoot());
this._dropTargetBoxes = this._dropTargets.map(boxMapper);
this._dropTargetBoxes = this._dropTargets.map(function(source) {
return source.getLayoutBox();
});
},
_shrink: function() {
// 合并所有拖放源图形的矩形即可
function calcSourceArea(boxArray) {
var area = boxArray.pop();
while (boxArray.length) {
area = GM.mergeBox(area, boxArray.pop());
}
return {
x: area.left,
y: area.top,
width: area.width,
height: area.height
};
}
// 从焦点发散出一个固定的矩形即可
function calcFocusArea(focusPoint) {
var width = 80,
height = 30;
return {
x: focusPoint.x - width / 2,
y: focusPoint.y - height / 2,
width: width,
height: height
};
_calcOrderHints: function() {
var sources = this._dragSources;
var ancestor = MinderNode.getCommonAncestor(sources);
if (ancestor == sources[0]) ancestor = sources[0].parent;
if (sources.length === 0 || ancestor != sources[0].parent) {
this._orderHints = [];
return;
}
var sourceArea = calcSourceArea(this._dragSources.map(boxMapper));
var focusArea = calcFocusArea(this._startPosition);
var animator = new AreaAnimator(sourceArea, focusArea);
animator.start(this._rect, 400, 'easeOutQuint');
var siblings = ancestor.children;
this._orderHints = siblings.reduce(function(hint, sibling) {
if (sources.indexOf(sibling) == -1) {
hint = hint.concat(sibling.getOrderHint());
}
return hint;
}, []);
},
_leaveDragMode: function() {
// this.remove();
this._fadeDragSources(1);
this._dragMode = false;
this._dropSucceedTarget = null;
// this._removeDropHint();
this._orderSucceedHint = null;
this._renderDropHint(null);
this._renderOrderHint(null);
},
_drawForDragMode: function() {
......@@ -197,64 +259,62 @@ var TreeDragger = kity.createClass('TreeDragger', {
this._minder.getRenderContainer().addShape(this);
},
// 此处可用线段树优化,但考虑到节点不多,必要性不到,就用暴力测试
_dropTest: function() {
var dragBox = this.getRenderBox(),
test;
_boxTest: function(targets, targetBoxMapper, judge) {
var sourceBoxes = this._dragSources.map(function(source) {
return source.getLayoutBox();
});
this._dropSucceedTarget = null;
for (var i = 0; i < this._dropTargetBoxes.length; i++) {
test = this._dropTargetBoxes[i];
if (GM.isBoxIntersect(dragBox, test)) {
this._dropSucceedTarget = this._dropTargets[i];
return;
var i, j, target, sourceBox, targetBox;
judge = judge || function(intersectBox, sourceBox, targetBox) {
return intersectBox;
};
for (i = 0; i < targets.length; i++) {
target = targets[i];
targetBox = targetBoxMapper.call(this, target, i);
for (j = 0; j < sourceBoxes.length; j++) {
sourceBox = sourceBoxes[j];
var intersectBox = GM.getIntersectBox(sourceBox, targetBox);
if (judge(intersectBox, sourceBox, targetBox)) {
return target;
}
}
}
},
_updateDropHint: function() {
var target = this._dropSucceedTarget,
lastTarget = this._lastSucceedTarget;
if (target && target == lastTarget) return;
if (lastTarget) {
this._removeDropStyle(lastTarget);
}
if (target) {
this._addDropStyle(target);
}
this._lastSucceedTarget = target;
},
_removeDropHint: function() {
var lastTarget = this._lastSucceedTarget;
if (lastTarget) {
this._removeDropStyle(lastTarget);
}
return null;
},
_removeDropStyle: function(node) {
this._rect.stroke('#3399ff', 1);
_dropTest: function() {
this._dropSucceedTarget = this._boxTest(this._dropTargets, function(target, i) {
return this._dropTargetBoxes[i];
}, function(intersectBox, sourceBox, targetBox) {
function area(box) {
return box.width * box.height;
}
return intersectBox && area(intersectBox) > 0.5 * Math.min(area(sourceBox), area(targetBox));
});
this._renderDropHint(this._dropSucceedTarget);
return !!this._dropSucceedTarget;
},
_addDropStyle: function(node) {
node.getRenderContainer().fxScale(1.25, 1.25, 150, 'ease').fxScale(0.8, 0.8, 150, 'ease');
_orderTest: function() {
this._orderSucceedHint = this._boxTest(this._orderHints, function(hint) {
return hint.area;
});
this._renderOrderHint(this._orderSucceedHint);
return !!this._orderSucceedHint;
},
_renderDropHint: function(target) {
this._dropHinter.render(target);
},
_orderTest: function() {
if (this._dragSources.length > 1) return false;
var source = this._dragSources[0];
var sourceBox = source.getLayoutBox();
var contextPoints = source.getLayoutContextPoints();
var contextPoint;
for (var i = 0; i < contextPoints.length; i++) {
contextPoint = contextPoints[i];
if (contextPoint.type != 'order') continue;
if (GM.isBoxIntersect(contextPoint.area, sourceBox)) {
console.log(contextPoint);
}
}
_renderOrderHint: function(hint) {
this._orderHinter.render(hint);
}
});
......@@ -277,6 +337,8 @@ KityMinder.registerModule('DragTree', function() {
},
'mouseup': function(e) {
dragger.dragEnd(e.getPosition(this.getRenderContainer()));
e.stopPropagation();
this.fire('contentchange');
}
},
commands: {
......
KityMinder.registerModule( "DropFile", function () {
KityMinder.registerModule('DropFile', function() {
var social,
draftManager,
importing = false;
var social,
draftManager,
importing = false;
function init() {
var container = this.getPaper().getContainer();
container.addEventListener( 'dragover', onDragOver );
container.addEventListener( 'drop', onDrop.bind( this ) );
}
function init() {
var container = this.getPaper().getContainer();
container.addEventListener('dragover', onDragOver);
container.addEventListener('drop', onDrop.bind(this));
}
function onDragOver( e ) {
e.preventDefault();
e.stopPropagation();
e.dataTransfer.dropEffect = 'copy';
}
function onDragOver(e) {
e.preventDefault();
e.stopPropagation();
e.dataTransfer.dropEffect = 'copy';
}
function onDrop( e ) {
e.preventDefault();
e.stopPropagation();
var minder = this;
function onDrop(e) {
e.preventDefault();
e.stopPropagation();
var minder = this;
if ( kity.Browser.ie && Number( kity.Browser.version ) < 10 ) {
alert( '文件导入对IE浏览器仅支持10以上版本' );
return;
}
if (kity.Browser.ie && Number(kity.Browser.version) < 10) {
alert('文件导入对IE浏览器仅支持10以上版本');
return;
}
var files = e.dataTransfer.files;
var files = e.dataTransfer.files;
if ( files ) {
var file = files[ 0 ];
var ext = file.type || ( /(.)\w+$/ ).exec( file.name )[ 0 ];
if (files) {
var file = files[0];
var ext = file.type || (/(.)\w+$/).exec(file.name)[0];
console.log(ext);
if ( ( /xmind/g ).test( ext ) ) { //xmind zip
importSync( minder, file, 'xmind' );
} else if ( ( /mmap/g ).test( ext ) ) { // mindmanager zip
importSync( minder, file, 'mindmanager' );
} else if ( ( /mm/g ).test( ext ) ) { //freemind xml
importAsync( minder, file, 'freemind' );
} else { // txt json
importAsync( minder, file );
}
}
}
if ((/xmind/g).test(ext)) { //xmind zip
importSync(minder, file, 'xmind');
} else if ((/mmap/g).test(ext)) { // mindmanager zip
importSync(minder, file, 'mindmanager');
} else if ((/mm/g).test(ext)) { //freemind xml
importAsync(minder, file, 'freemind');
} else if (/km/.test(ext)) { // txt json
importAsync(minder, file, 'json');
} else if (/txt/.test(ext)) {
importAsync(minder, file, 'plain');
}
}
}
function afterImport() {
if ( !importing ) return;
createDraft( this );
social.setRemotePath( null, false );
this.execCommand( 'camera', this.getRoot() );
setTimeout( function () {
social.watchChanges( true );
}, 10 );
importing = false;
}
function afterImport() {
if (!importing) return;
createDraft(this);
social.setRemotePath(null, false);
this.execCommand('camera', this.getRoot());
setTimeout(function() {
social.watchChanges(true);
}, 10);
importing = false;
}
// 同步加载文件
function importSync( minder, file, protocal ) {
social = social || window.social;
social.watchChanges( false );
importing = true;
minder.importData( file, protocal ); //zip文件的import是同步的
}
// 同步加载文件
function importSync(minder, file, protocal) {
social = social || window.social;
social.watchChanges(false);
importing = true;
minder.importData(file, protocal); //zip文件的import是同步的
}
// 异步加载文件
function importAsync( minder, file, protocal ) {
var reader = new FileReader();
reader.onload = function ( e ) {
importSync( minder, e.target.result, protocal );
};
reader.readAsText( file );
}
// 异步加载文件
function importAsync(minder, file, protocal) {
var reader = new FileReader();
reader.onload = function(e) {
importSync(minder, e.target.result, protocal);
};
reader.readAsText(file);
}
function createDraft( minder ) {
draftManager = window.draftManager || ( window.draftManager = new window.DraftManager( minder ) );
draftManager.create();
}
function createDraft(minder) {
draftManager = window.draftManager || (window.draftManager = new window.DraftManager(minder));
draftManager.create();
}
return {
events: {
'ready': init,
'import': afterImport
}
};
} );
\ No newline at end of file
return {
events: {
'ready': init,
'import': afterImport
}
};
});
\ No newline at end of file
......@@ -179,7 +179,7 @@ KityMinder.registerModule('TextEditModule', function() {
if (browser.ipad) {
receiver.container.focus();
}
}else{
} else {
//当选中节点后,输入状态准备
var node = e.getTargetNode();
if (node) {
......
......@@ -4,7 +4,10 @@ KityMinder.registerModule("fontmodule", function() {
}
KityMinder.TextRenderer.registerStyleHook(function(node, text) {
text.fill(getNodeDataOrStyle(node, 'color'));
var dataColor = node.getData('color');
var selectedColor = node.getStyle('selected-color');
var styleColor = node.getStyle('color');
text.fill(dataColor || (node.isSelected() ? selectedColor : styleColor));
text.setFont({
family: getNodeDataOrStyle(node, 'font-family'),
size: getNodeDataOrStyle(node, 'font-size')
......
......@@ -84,16 +84,24 @@ KityMinder.Geometry = (function() {
};
g.isPointInsideBox = function(p, b) {
uniformBox(b);
var ranges = g.getBoxRange(b);
return g.isNumberInRange(p.x, ranges.x) && g.isNumberInRange(p.y, ranges.y);
};
g.isBoxIntersect = function(b1, b2) {
g.getIntersectBox = function(b1, b2) {
uniformBox(b1);
uniformBox(b2);
var minx = max(b1.left, b2.left),
miny = max(b1.top, b2.top),
maxx = min(b1.right, b2.right),
maxy = min(b1.bottom, b2.bottom);
return minx < maxx && miny < maxy;
return minx < maxx && miny < maxy ? wrapBox({
left: minx,
right: maxx,
top: miny,
bottom: maxy
}) : null;
};
g.snapToSharp = function(unknown) {
......
KityMinder.registerModule( "image", function () {
function loadImageSize( url, callback ) {
var img = document.createElement( 'img' );
img.onload = function () {
callback( img.width, img.height );
KityMinder.registerModule('image', function() {
function loadImageSize(url, callback) {
var img = document.createElement('img');
img.onload = function() {
callback(img.width, img.height);
};
img.onerror = function () {
callback( null );
img.onerror = function() {
callback(null);
};
img.src = url;
}
function fitImageSize( width, height, maxWidth, maxHeight ) {
function fitImageSize(width, height, maxWidth, maxHeight) {
var ratio = width / height,
fitRatio = maxWidth / maxHeight;
// 宽高比大于最大尺寸的宽高比,以宽度为标准适应
if ( ratio > fitRatio && width > maxWidth ) {
if (ratio > fitRatio && width > maxWidth) {
width = maxWidth;
height = maxWidth / ratio;
} else if(height > maxHeight) {
} else if (height > maxHeight) {
height = maxHeight;
width = maxHeight / ratio;
}
......@@ -28,104 +28,118 @@ KityMinder.registerModule( "image", function () {
height: height
};
}
return {
"defaultOptions": {
"maxImageWidth": 200,
"maxImageHeight": 200
var ImageCommand = kity.createClass('ImageCommand', {
base: Command,
execute: function(km, url) {
var nodes = km.getSelectedNodes();
loadImageSize(url, function(width, height) {
if (!width) return;
utils.each(nodes, function(i, n) {
var size = fitImageSize(
width, height,
km.getOptions('maxImageWidth'),
km.getOptions('maxImageHeight'));
n.setData('image', url);
n.setData('imageSize', size);
n.render();
});
km.layout(300);
});
},
"commands": {
"image": kity.createClass( "ImageCommand", {
base: Command,
execute: function ( km, url ) {
var nodes = km.getSelectedNodes();
loadImageSize( url, function ( width, height ) {
if ( !width ) return;
utils.each( nodes, function ( i, n ) {
n.setData( 'image', url );
n.setData( 'imageWidth', width );
n.setData( 'imageHeight', height );
km.updateLayout( n );
} );
} );
},
queryState: function ( km ) {
var nodes = km.getSelectedNodes(),
result = 0;
if ( nodes.length === 0 ) {
return -1;
}
utils.each( nodes, function ( i, n ) {
if ( n && n.getData( 'image' ) ) {
result = 0;
return false;
}
} );
return result;
},
queryValue: function ( km ) {
var node = km.getSelectedNode();
return node.getData( 'image' );
queryState: function(km) {
var nodes = km.getSelectedNodes(),
result = 0;
if (nodes.length === 0) {
return -1;
}
utils.each(nodes, function(i, n) {
if (n && n.getData('image')) {
result = 0;
return false;
}
} ),
"removeimage": kity.createClass( "RemoveImageCommand", {
base: Command,
execute: function ( km ) {
var nodes = km.getSelectedNodes();
utils.each( nodes, function ( i, n ) {
n.setData( 'image' );
km.updateLayout( n );
} );
},
queryState: function ( km ) {
var nodes = km.getSelectedNodes();
if ( nodes.length == 0 ) {
return -1;
}
var image = false;
utils.each( nodes, function ( i, n ) {
if ( n.getData( 'image' ) ) {
image = true;
return false;
}
} );
if ( image ) {
return 0;
}
return -1;
});
return result;
},
queryValue: function(km) {
var node = km.getSelectedNode();
return node.getData('image');
}
});
var RemoveImageCommand = kity.createClass('RemoveImageCommand', {
base: Command,
execute: function(km) {
var nodes = km.getSelectedNodes();
utils.each(nodes, function(i, n) {
n.setData('image').render();
});
km.layout(300);
},
queryState: function(km) {
var nodes = km.getSelectedNodes();
if (nodes.length === 0) {
return -1;
}
var image = false;
utils.each(nodes, function(i, n) {
if (n.getData('image')) {
image = true;
return false;
}
} )
});
if (image) {
return 0;
}
return -1;
}
});
var ImageRenderer = kity.createClass('ImageRenderer', {
base: KityMinder.Renderer,
create: function(node) {
return new kity.Image();
},
"events": {
"RenderNodeTop": function ( e ) {
var node = e.node,
url = node.getData( 'image' );
var link, img, size, currentBox;
if ( url ) {
shouldRender: function(node) {
return node.getData('image');
},
size = fitImageSize(
node.getData( 'imageWidth' ),
node.getData( 'imageHeight' ),
this.getOptions( 'maxImageWidth' ),
this.getOptions( 'maxImageHeight' ) );
update: function(image, node, box) {
var url = node.getData('image');
var size = node.getData('imageSize');
var spaceTop = node.getStyle('space-top');
img = new kity.Image( url, size.width, size.height );
if (!size) return;
link = new kity.HyperLink( url );
link.addShape( img );
link.setTarget( '_blank' );
link.setStyle( 'cursor', 'pointer' );
image
.setUrl(url)
.setX(box.cx - size.width / 2)
.setY(box.y - size.height - spaceTop)
.setWidth(size.width)
.setHeight(size.height);
currentBox = node.getContRc().getBoundaryBox();
node.getContRc().addShape( link.setTranslate( 0, currentBox.y - size.height ) );
return new kity.Box(image.getX(), image.getY(), size.width, size.height);
}
});
}
}
return {
'defaultOptions': {
'maxImageWidth': 200,
'maxImageHeight': 200
},
'commands': {
'image': ImageCommand,
'removeimage': RemoveImageCommand
},
'renderers': {
'top': ImageRenderer
}
};
} );
\ No newline at end of file
});
\ No newline at end of file
......@@ -9,7 +9,7 @@ KityMinder.registerModule("KeyboardModule", function() {
var pointIndexes = [],
p;
root.traverse(function(node) {
p = node.getRenderContainer().getRenderBox('top');
p = node.getLayoutBox();
// bugfix: 不应导航到收起的节点(判断其尺寸是否存在)
if (p.width && p.height) {
......@@ -127,11 +127,10 @@ KityMinder.registerModule("KeyboardModule", function() {
km.select(nextNode, true);
}
}
return {
'events': {
'contentchange': function() {
'contentchange layoutfinish': function() {
buildPositionNetwork(this.getRoot());
},
'normal.keydown': function(e) {
......@@ -142,7 +141,11 @@ KityMinder.registerModule("KeyboardModule", function() {
this.receiver.keydownNode = node;
switch (e.originEvent.keyCode) {
var keyEvent = e.originEvent;
if (keyEvent.altKey || keyEvent.ctrlKey || keyEvent.metaKey || keyEvent.shiftKey) return;
switch (keyEvent.keyCode) {
case keys.Enter:
this.execCommand('AppendSiblingNode', lang.topic);
e.preventDefault();
......
KityMinder.registerModule("Select", function() {
KityMinder.registerModule('Select', function() {
var minder = this;
var g = KityMinder.Geometry;
......@@ -67,8 +67,8 @@ KityMinder.registerModule("Select", function() {
// 计算选中范围
minder.getRoot().traverse(function(node) {
var renderBox = node.getRenderContainer().getRenderBox("top");
if (g.isBoxIntersect(renderBox, marquee)) {
var renderBox = node.getRenderContainer().getRenderBox('top');
if (g.getIntersectBox(renderBox, marquee)) {
selectedNodes.push(node);
}
});
......@@ -90,7 +90,7 @@ KityMinder.registerModule("Select", function() {
};
})();
var lastDownNode = null;
var lastDownNode = null, lastDownPosition = null;
return {
'events': {
'normal.mousedown textedit.mousedown': function(e) {
......@@ -122,6 +122,7 @@ KityMinder.registerModule("Select", function() {
// 不能马上变为单选,因为可能是需要拖动选中的多个节点
else if (!this.isSingleSelect()) {
lastDownNode = downNode;
lastDownPosition = e.getPosition(this.getRenderContainer());
}
},
'normal.mousemove textedit.mousemove': marqueeActivator.selectMove,
......@@ -130,7 +131,9 @@ KityMinder.registerModule("Select", function() {
// 如果 mouseup 发生在 lastDownNode 外,是无需理会的
if (upNode && upNode == lastDownNode) {
this.select(lastDownNode, true);
var upPosition = e.getPosition(this.getRenderContainer());
var movement = kity.Vector.fromPoints(lastDownPosition, upPosition);
if (movement.length() < 1) this.select(lastDownNode, true);
lastDownNode = null;
}
......
......@@ -13,7 +13,7 @@ KityMinder.registerTheme('default', {
'main-stroke': 'none',
'main-font-size': 16,
'main-padding': [6, 20],
'main-margin': [30, 10],
'main-margin': 20,
'main-radius': 10,
'main-space': 5,
......@@ -22,7 +22,7 @@ KityMinder.registerTheme('default', {
'sub-stroke': 'white',
'sub-font-size': 12,
'sub-padding': [5, 10],
'sub-margin': 10,
'sub-margin': [15, 20],
'sub-tree-margin': 30,
'sub-radius': 5,
'sub-space': 5,
......@@ -31,5 +31,15 @@ KityMinder.registerTheme('default', {
'connect-width': 2,
'connect-radius': 5,
'selected-background': 'rgb(254, 219, 0)'
'selected-background': 'rgb(254, 219, 0)',
'selected-color': 'black',
'drop-hint-color': 'yellow',
'sub-drop-hint-width': 2,
'main-drop-hint-width': 4,
'root-drop-hint-width': 4,
'order-hint-area-color': 'rgba(0, 255, 0, .5)',
'order-hint-path-color': '#0f0',
'order-hint-path-width': 2
});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment