mirror of
https://bitbucket.org/wisemapping/wisemapping-open-source.git
synced 2024-08-20 04:30:42 +02:00
working on Freemind layout algorithm
This commit is contained in:
parent
ae071f7fcb
commit
d4de03d373
@ -124,6 +124,8 @@
|
||||
files="commands/AddRelationshipCommand.js"/>
|
||||
<filelist dir="${basedir}/src/main/javascript/"
|
||||
files="commands/MoveControlPointCommand.js"/>
|
||||
<filelist dir="${basedir}/src/main/javascript/"
|
||||
files="commands/freeMind/DragTopicCommand.js"/>
|
||||
|
||||
|
||||
<filelist dir="${basedir}/src/main/javascript/"
|
||||
@ -241,6 +243,7 @@
|
||||
<include>commands/RemoveNoteFromTopicCommand-min.js</include>
|
||||
<include>commands/AddRelationshipCommand-min.js</include>
|
||||
<include>commands/MoveControlPointCommand-min.js</include>
|
||||
<include>commands/freeMind/DragTopicCommand-min.js</include>
|
||||
|
||||
<include>layoutManagers/boards/Board-min.js</include>
|
||||
<include>layoutManagers/boards/freeMindBoards/Board-min.js</include>
|
||||
|
@ -87,7 +87,7 @@ mindplot.CentralTopic.prototype.updateTopicShape = function()
|
||||
{
|
||||
|
||||
};
|
||||
mindplot.CentralTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize) {
|
||||
mindplot.CentralTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize, updatePosition) {
|
||||
|
||||
// Center main topic ...
|
||||
var zeroPoint = new core.Point(0, 0);
|
||||
|
@ -103,7 +103,7 @@ mindplot.CentralTopicBoard.prototype.addBranch = function(topic)
|
||||
board.update(entry);
|
||||
};
|
||||
|
||||
mindplot.CentralTopicBoard.prototype.updateChildrenPosition = function(topic, xOffset)
|
||||
mindplot.CentralTopicBoard.prototype.updateChildrenPosition = function(topic, xOffset, modifiedTopics)
|
||||
{
|
||||
var board = this._rightBoard;
|
||||
var oldReferencePosition = board.getReferencePoint();
|
||||
|
@ -141,7 +141,7 @@ mindplot.ConnectionLine.prototype._positionateConnector = function(targetTopic)
|
||||
y = y - offset;
|
||||
|
||||
var connector = targetTopic.getShrinkConnector();
|
||||
if (targetPosition.x >= 0)
|
||||
if (Math.sign(targetPosition.x) > 0)
|
||||
{
|
||||
var x = targetTopicSize.width;
|
||||
connector.setPosition(x, y);
|
||||
|
@ -97,10 +97,6 @@ mindplot.CommandContext = new Class({
|
||||
core.assert(model, "model can not be null");
|
||||
var topic = this._designer._nodeModelToNodeGraph(model, isVisible);
|
||||
|
||||
// @todo: Is this required ?
|
||||
var designer = this._designer;
|
||||
designer.onObjectFocusEvent.attempt(topic, designer);
|
||||
|
||||
return topic;
|
||||
},
|
||||
createModel:function()
|
||||
|
@ -207,7 +207,7 @@ mindplot.DragTopic.prototype.updateDraggedTopic = function(workspace)
|
||||
command = new mindplot.commands.DragTopicCommand(topicId, dragPosition);
|
||||
command.setPosition(dragPosition);
|
||||
}
|
||||
actionRunner.execute(command)
|
||||
actionRunner.execute(command);
|
||||
};
|
||||
|
||||
mindplot.DragTopic.prototype.setBoardPosition = function(point)
|
||||
|
@ -175,20 +175,25 @@ mindplot.MainTopic.prototype.getTopicType = function()
|
||||
};
|
||||
|
||||
|
||||
mindplot.MainTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize) {
|
||||
mindplot.MainTopic.prototype._updatePositionOnChangeSize = function(oldSize, newSize, updatePosition) {
|
||||
|
||||
var xOffset = (newSize.width - oldSize.width) / 2;
|
||||
var pos = this.getPosition();
|
||||
if (core.Utils.isDefined(pos))
|
||||
{
|
||||
if (pos.x > 0)
|
||||
if(!updatePosition && this.getModel().getFinalPosition()){
|
||||
this.setPosition(this.getModel().getFinalPosition(), false);
|
||||
}
|
||||
else{
|
||||
var xOffset = Math.round((newSize.width - oldSize.width) / 2);
|
||||
var pos = this.getPosition();
|
||||
if (core.Utils.isDefined(pos))
|
||||
{
|
||||
pos.x = pos.x + xOffset;
|
||||
} else
|
||||
{
|
||||
pos.x = pos.x - xOffset;
|
||||
if (pos.x > 0)
|
||||
{
|
||||
pos.x = pos.x + xOffset;
|
||||
} else
|
||||
{
|
||||
pos.x = pos.x - xOffset;
|
||||
}
|
||||
this.setPosition(pos);
|
||||
}
|
||||
this.setPosition(pos);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -126,16 +126,16 @@ mindplot.Mindmap.prototype.hasAlreadyAdded = function(node)
|
||||
}
|
||||
};
|
||||
|
||||
mindplot.Mindmap.prototype.createNode = function(type)
|
||||
mindplot.Mindmap.prototype.createNode = function(type, id)
|
||||
{
|
||||
core.assert(type, "node type can not be null");
|
||||
return this._createNode(type);
|
||||
return this._createNode(type, id);
|
||||
};
|
||||
|
||||
mindplot.Mindmap.prototype._createNode = function(type)
|
||||
mindplot.Mindmap.prototype._createNode = function(type, id)
|
||||
{
|
||||
core.assert(type, 'Node type must be specified.');
|
||||
var result = new mindplot.NodeModel(type, this);
|
||||
var result = new mindplot.NodeModel(type, this, id);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mindplot.NodeModel = function(type, mindmap)
|
||||
mindplot.NodeModel = function(type, mindmap, id)
|
||||
{
|
||||
core.assert(type, 'Node type can not be null');
|
||||
core.assert(mindmap, 'mindmap can not be null');
|
||||
@ -29,7 +29,14 @@ mindplot.NodeModel = function(type, mindmap)
|
||||
this._notes = [];
|
||||
this._size = {width:50,height:20};
|
||||
this._position = null;
|
||||
this._id = mindplot.NodeModel._nextUUID();
|
||||
if(core.Utils.isDefined(id)){
|
||||
if(!mindplot.NodeModel._uuid || id>mindplot.NodeModel._uuid){
|
||||
mindplot.NodeModel._uuid = id;
|
||||
}
|
||||
this._id = id;
|
||||
} else {
|
||||
this._id = mindplot.NodeModel._nextUUID();
|
||||
}
|
||||
this._mindmap = mindmap;
|
||||
this._text = null;
|
||||
this._shapeType = null;
|
||||
@ -95,6 +102,9 @@ mindplot.NodeModel.prototype.getId = function()
|
||||
mindplot.NodeModel.prototype.setId = function(id)
|
||||
{
|
||||
this._id = id;
|
||||
if(mindplot.NodeModel._uuid<id){
|
||||
mindplot.NodeModel._uuid = id;
|
||||
}
|
||||
};
|
||||
|
||||
mindplot.NodeModel.prototype.getType = function()
|
||||
@ -213,6 +223,24 @@ mindplot.NodeModel.prototype.getPosition = function()
|
||||
return this._position;
|
||||
};
|
||||
|
||||
mindplot.NodeModel.prototype.setFinalPosition = function(x, y)
|
||||
{
|
||||
core.assert(core.Utils.isDefined(x), "x coordinate must be defined");
|
||||
core.assert(core.Utils.isDefined(y), "y coordinate must be defined");
|
||||
|
||||
if (!core.Utils.isDefined(this._finalPosition))
|
||||
{
|
||||
this._finalPosition = new core.Point();
|
||||
}
|
||||
this._finalPosition.x = parseInt(x);
|
||||
this._finalPosition.y = parseInt(y);
|
||||
};
|
||||
|
||||
mindplot.NodeModel.prototype.getFinalPosition = function()
|
||||
{
|
||||
return this._finalPosition;
|
||||
};
|
||||
|
||||
mindplot.NodeModel.prototype.setSize = function(width, height)
|
||||
{
|
||||
this._size.width = width;
|
||||
|
@ -516,7 +516,7 @@ mindplot.Topic.prototype.setFontFamily = function(value, updateModel)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
elem.updateNode();
|
||||
elem.updateNode(updateModel);
|
||||
};
|
||||
};
|
||||
|
||||
@ -537,7 +537,7 @@ mindplot.Topic.prototype.setFontSize = function(value, updateModel)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
elem.updateNode();
|
||||
elem.updateNode(updateModel);
|
||||
};
|
||||
};
|
||||
|
||||
@ -559,7 +559,7 @@ mindplot.Topic.prototype.setFontStyle = function(value, updateModel)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
elem.updateNode();
|
||||
elem.updateNode(updateModel);
|
||||
};
|
||||
};
|
||||
|
||||
@ -657,7 +657,7 @@ mindplot.Topic.prototype._setText = function(text, updateModel)
|
||||
{
|
||||
return function()
|
||||
{
|
||||
elem.updateNode();
|
||||
elem.updateNode(updateModel);
|
||||
};
|
||||
};
|
||||
|
||||
@ -1092,7 +1092,7 @@ mindplot.Topic.prototype._setSize = function(size)
|
||||
innerShape.setSize(size.width, size.height);
|
||||
};
|
||||
|
||||
mindplot.Topic.prototype.setSize = function(size, force)
|
||||
mindplot.Topic.prototype.setSize = function(size, force, updatePosition)
|
||||
{
|
||||
var oldSize = this.getSize();
|
||||
if (oldSize.width != size.width || oldSize.height != size.height || force)
|
||||
@ -1100,14 +1100,14 @@ mindplot.Topic.prototype.setSize = function(size, force)
|
||||
this._setSize(size);
|
||||
|
||||
// Update the figure position(ej: central topic must be centered) and children position.
|
||||
this._updatePositionOnChangeSize(oldSize, size);
|
||||
this._updatePositionOnChangeSize(oldSize, size, updatePosition);
|
||||
|
||||
mindplot.EventBus.instance.fireEvent(mindplot.EventBus.events.NodeResizeEvent,[this]);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
mindplot.Topic.prototype._updatePositionOnChangeSize = function(oldSize, newSize) {
|
||||
mindplot.Topic.prototype._updatePositionOnChangeSize = function(oldSize, newSize, updatePosition) {
|
||||
core.assert(false, "this method must be overided");
|
||||
};
|
||||
|
||||
@ -1284,7 +1284,7 @@ mindplot.Topic.prototype.createDragNode = function()
|
||||
return dragNode;
|
||||
};
|
||||
|
||||
mindplot.Topic.prototype.updateNode = function()
|
||||
mindplot.Topic.prototype.updateNode = function(updatePosition)
|
||||
{
|
||||
if(this.isInWorkspace()){
|
||||
var textShape = this.getTextShape();
|
||||
@ -1302,7 +1302,7 @@ mindplot.Topic.prototype.updateNode = function()
|
||||
}
|
||||
|
||||
var newSize = {width:width,height:height};
|
||||
this.setSize(newSize);
|
||||
this.setSize(newSize, false, updatePosition);
|
||||
|
||||
// Positionate node ...
|
||||
textShape.setPosition(iconOffset+this._offset, pos);
|
||||
|
@ -257,14 +257,14 @@ mindplot.XMLMindmapSerializer_Pela.prototype.loadFromDom = function(dom)
|
||||
mindplot.XMLMindmapSerializer_Pela.prototype._deserializeNode = function(domElem, mindmap)
|
||||
{
|
||||
var type = (domElem.getAttribute('central') != null) ? mindplot.NodeModel.CENTRAL_TOPIC_TYPE : mindplot.NodeModel.MAIN_TOPIC_TYPE;
|
||||
var topic = mindmap.createNode(type);
|
||||
|
||||
// Load attributes...
|
||||
var id = domElem.getAttribute('id');
|
||||
if(id) {
|
||||
topic.setId(id);
|
||||
id=parseInt(id);
|
||||
}
|
||||
|
||||
|
||||
var topic = mindmap.createNode(type, id);
|
||||
|
||||
var text = domElem.getAttribute('text');
|
||||
if (text) {
|
||||
topic.setText(text);
|
||||
@ -330,6 +330,7 @@ mindplot.XMLMindmapSerializer_Pela.prototype._deserializeNode = function(domElem
|
||||
if (position) {
|
||||
var pos = position.split(',');
|
||||
topic.setPosition(pos[0], pos[1]);
|
||||
topic.setFinalPosition(pos[0], pos[1]);
|
||||
}
|
||||
|
||||
//Creating icons and children nodes
|
||||
|
@ -41,6 +41,8 @@ mindplot.commands.AddTopicCommand = mindplot.Command.extend(
|
||||
|
||||
var doneFn = function(){
|
||||
// Finally, focus ...
|
||||
var designer = commandContext._designer;
|
||||
designer.onObjectFocusEvent.attempt(topic, designer);
|
||||
topic.setOnFocus(true);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright [2011] [wisemapping]
|
||||
*
|
||||
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||
* "powered by wisemapping" text requirement on every single page;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the license at
|
||||
*
|
||||
* http://www.wisemapping.org/license
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
mindplot.commands.freeMind={};
|
||||
|
||||
mindplot.commands.freeMind.DragTopicCommand = mindplot.Command.extend(
|
||||
{
|
||||
initialize: function()
|
||||
{
|
||||
this._modifiedTopics=null;
|
||||
this._id = mindplot.Command._nextUUID();
|
||||
},
|
||||
execute: function(commandContext)
|
||||
{
|
||||
var keys = this._modifiedTopics.keys();
|
||||
for(var i=0; i<keys.length; i++){
|
||||
var id = keys[i];
|
||||
var modTopic = this._modifiedTopics.get(id);
|
||||
var topic = commandContext.findTopics(parseInt(id))[0];
|
||||
|
||||
var position = topic.getPosition();
|
||||
var pos = modTopic.newPos;
|
||||
if(position.x != pos.x || position.y != pos.y){
|
||||
topic.setPosition(pos.clone(), true);
|
||||
}
|
||||
}
|
||||
},
|
||||
undoExecute: function(commandContext)
|
||||
{
|
||||
var keys = this._modifiedTopics.keys();
|
||||
for(var i=0; i<keys.length; i++){
|
||||
var id = keys[i];
|
||||
var modTopic = this._modifiedTopics.get(id);
|
||||
var topic = commandContext.findTopics(parseInt(id))[0];
|
||||
|
||||
var position = topic.getPosition();
|
||||
var pos = modTopic.originalPos;
|
||||
if(position.x != pos.x || position.y != pos.y){
|
||||
topic.setPosition(pos.clone(), true);
|
||||
}
|
||||
}
|
||||
},
|
||||
setModifiedTopics:function(modifiedTopics){
|
||||
this._modifiedTopics = modifiedTopics;
|
||||
}
|
||||
});
|
@ -6,7 +6,7 @@ mindplot.layoutManagers.BaseLayoutManager = new Class({
|
||||
|
||||
initialize: function(designer, options) {
|
||||
this.setOptions(options);
|
||||
this._boards = new Hash();
|
||||
this._createBoard();
|
||||
this._designer = designer;
|
||||
mindplot.EventBus.instance.addEvent(mindplot.EventBus.events.NodeResizeEvent,this._nodeResizeEvent.bind(this));
|
||||
mindplot.EventBus.instance.addEvent(mindplot.EventBus.events.NodeMoveEvent,this._nodeMoveEvent.bind(this));
|
||||
@ -17,26 +17,31 @@ mindplot.layoutManagers.BaseLayoutManager = new Class({
|
||||
_nodeResizeEvent:function(node){
|
||||
},
|
||||
_nodeMoveEvent:function(node){
|
||||
//todo: Usar un solo board para todos los nodos. Testear que ande el set margin cuando se mueven los nodos.
|
||||
this.getTopicBoardForTopic(node).updateChildrenPosition(node);
|
||||
var modifiedTopics = [];
|
||||
this.getTopicBoardForTopic(node).updateChildrenPosition(node, modifiedTopics);
|
||||
},
|
||||
_nodeDisconnectEvent:function(targetNode, node){
|
||||
this.getTopicBoardForTopic(targetNode).removeTopicFromBoard(node);
|
||||
var modifiedTopics = [];
|
||||
this.getTopicBoardForTopic(targetNode).removeTopicFromBoard(node,modifiedTopics);
|
||||
},
|
||||
_nodeConnectEvent:function(targetNode, node){
|
||||
this.getTopicBoardForTopic(targetNode).addBranch(node);
|
||||
var modifiedTopics = [];
|
||||
this.getTopicBoardForTopic(targetNode).addBranch(node,modifiedTopics);
|
||||
},
|
||||
_NodeRepositionateEvent:function(node){
|
||||
},
|
||||
_createBoard:function(){
|
||||
this._boards = new Hash();
|
||||
},
|
||||
getTopicBoardForTopic:function(node){
|
||||
var id = node.getId()
|
||||
var id = node.getId();
|
||||
var result = this._boards[id];
|
||||
if(!result){
|
||||
result = this.addNode(node);
|
||||
result = this._addNode(node);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
addNode:function(node){
|
||||
_addNode:function(node){
|
||||
var board = null;
|
||||
if (this._isCentralTopic(node))
|
||||
board = this._createCentralTopicBoard(node);
|
||||
|
@ -5,10 +5,14 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
initialize:function(designer, options){
|
||||
this.parent(designer, options);
|
||||
},
|
||||
_nodeConnectEvent:function(targetNode, node){
|
||||
if(!this._isCentralTopic(node)){
|
||||
this.parent(targetNode, node);
|
||||
}
|
||||
},
|
||||
registerListenersOnNode : function(topic)
|
||||
{
|
||||
var id = topic.getId();
|
||||
console.log("registering on node: "+id);
|
||||
// Register node listeners ...
|
||||
var designer = this.getDesigner();
|
||||
topic.addEventListener('onfocus', function(event)
|
||||
@ -22,11 +26,11 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
topic.addEventListener("mousedown",this._mousedownListener.bindWithEvent(this,[topic]));
|
||||
}
|
||||
|
||||
/*// Register editor events ...
|
||||
if (!this._viewMode)
|
||||
// Register editor events ...
|
||||
if (!this.getDesigner()._viewMode)
|
||||
{
|
||||
this._editor.listenEventOnNode(topic, 'dblclick', true);
|
||||
}*/
|
||||
this.getDesigner()._editor.listenEventOnNode(topic, 'dblclick', true);
|
||||
}
|
||||
|
||||
},
|
||||
_mousedownListener:function(event,topic){
|
||||
@ -38,7 +42,9 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
workSpace.enableWorkspaceEvents(false);
|
||||
|
||||
var id = topic.getId();
|
||||
console.log("down on node: "+id);
|
||||
this._command = new mindplot.commands.freeMind.DragTopicCommand();
|
||||
this._modifiedTopics = new Hash();
|
||||
|
||||
var topics = this.getDesigner()._getTopics();
|
||||
// Disable all mouse events.
|
||||
for (var i = 0; i < topics.length; i++)
|
||||
@ -53,6 +59,8 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
// Set initial position.
|
||||
// var mousePos = screen.getWorkspaceMousePosition(event);
|
||||
|
||||
this._isMovingNode=false;
|
||||
|
||||
// Register mouse move listener ...
|
||||
this._mouseMoveListenerInstance = this._mouseMoveListener.bindWithEvent(this,[topic]);
|
||||
screen.addEventListener('mousemove', this._mouseMoveListenerInstance);
|
||||
@ -66,22 +74,70 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
}
|
||||
},
|
||||
_mouseMoveListener:function(event, node){
|
||||
var screen = this._designer.getWorkSpace().getScreenManager();
|
||||
var nodePos = node.getPosition();
|
||||
var pos = screen.getWorkspaceMousePosition(event);
|
||||
var x = nodePos.x - pos.x;
|
||||
var y = nodePos.y - pos.y;
|
||||
var delta = new core.Point(x, y);
|
||||
var board = this.getTopicBoardForTopic(node.getParent());
|
||||
board.setNodeMarginTop(node, delta);
|
||||
//update children position
|
||||
this._updateNodePos(node, delta);
|
||||
if(!this._isMovingNode){
|
||||
this._isMovingNode=true;
|
||||
var screen = this._designer.getWorkSpace().getScreenManager();
|
||||
var nodePos = node.getPosition().clone();
|
||||
var pos = screen.getWorkspaceMousePosition(event);
|
||||
pos.x = Math.round(pos.x);
|
||||
pos.y = Math.round(pos.y);
|
||||
//If still in same side
|
||||
if(Math.sign(nodePos.x)==Math.sign(pos.x) || (Math.sign(nodePos.x)!=Math.sign(pos.x) && !this._isCentralTopic(node.getParent()))){
|
||||
var x = nodePos.x - pos.x;
|
||||
var y = nodePos.y - pos.y;
|
||||
var delta = new core.Point(Math.round(x), Math.round(y));
|
||||
var board = this.getTopicBoardForTopic(node.getParent());
|
||||
board.updateEntry(node, delta, this._modifiedTopics);
|
||||
} else {
|
||||
var parentBoard = this.getTopicBoardForTopic(node.getParent());
|
||||
var entryObj = parentBoard.findNodeEntryIndex(node);
|
||||
var entry = entryObj.table[entryObj.index];
|
||||
//.removeTopicFromBoard(node,this._modifiedTopics);
|
||||
parentBoard._removeEntry(node, entryObj.table, entryObj.index, this._modifiedTopics);
|
||||
this._changeChildrenSide(node, pos, this._modifiedTopics);
|
||||
node.setPosition(pos.clone(), false);
|
||||
if(this._modifiedTopics.set){
|
||||
var key = node.getId();
|
||||
if(this._modifiedTopics.hasKey(key)){
|
||||
nodePos = this._modifiedTopics.get(key).originalPos;
|
||||
}
|
||||
this._modifiedTopics.set(key,{originalPos:nodePos, newPos:pos});
|
||||
}
|
||||
entryObj = parentBoard.findNewNodeEntryIndex(entry);
|
||||
parentBoard._addEntry(entry, entryObj.table, entryObj.index);
|
||||
parentBoard._updateTable(entryObj.index, entryObj.table, this._modifiedTopics, true);
|
||||
//this.getTopicBoardForTopic(node.getParent()).addBranch(node,this._modifiedTopics);
|
||||
|
||||
}
|
||||
this._isMovingNode=false;
|
||||
}
|
||||
event.preventDefault();
|
||||
},
|
||||
_changeChildrenSide:function(node, newPos, modifiedTopics){
|
||||
var children = node._getChildren();
|
||||
if(children.length>0){
|
||||
var refPos = node.getPosition();
|
||||
for( var i = 0 ; i< children.length ; i++){
|
||||
var child = children[i];
|
||||
this._changeChildrenSide(child);
|
||||
var childPos = child.getPosition();
|
||||
var oldPos=childPos.clone();
|
||||
childPos.x = newPos.x +(childPos.x - refPos.x)*-1;
|
||||
childPos.y = newPos.y +(childPos.y - refPos.y);
|
||||
child.setPosition(childPos, false);
|
||||
if(modifiedTopics.set){
|
||||
var key = node.getId();
|
||||
if(modifiedTopics.hasKey(key)){
|
||||
childPos = this._modifiedTopics.get(key).originalPos;
|
||||
}
|
||||
this._modifiedTopics.set(key,{originalPos:oldPos, newPos:childPos});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_mouseUpListener:function(event, node){
|
||||
var id = node.getId();
|
||||
console.log("up on node: "+id);
|
||||
|
||||
|
||||
var screen = this._designer.getWorkSpace().getScreenManager();
|
||||
// Remove all the events.
|
||||
screen.removeEventListener('mousemove', this._mouseMoveListenerInstance);
|
||||
@ -101,19 +157,16 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
|
||||
this._designer.getWorkSpace().enableWorkspaceEvents(true);
|
||||
|
||||
this._command.setModifiedTopics(this._modifiedTopics);
|
||||
var actionRunner = mindplot.DesignerActionRunner.getInstance();
|
||||
actionRunner.execute(this._command);
|
||||
this._command=null;
|
||||
this._modifiedTopics=null;
|
||||
|
||||
// var topicId = draggedTopic.getId();
|
||||
// var command = new mindplot.commands.DragTopicCommand(topicId);
|
||||
|
||||
},
|
||||
_updateNodePos:function(node, delta){
|
||||
var pos = node.getPosition();
|
||||
node.setPosition(new core.Point(pos.x-delta.x, pos.y-delta.y));
|
||||
/*var children = node._getChildren();
|
||||
for (var i = 0; i < children.length; i++)
|
||||
{
|
||||
this._updateNodePos(children[i],delta);
|
||||
}*/
|
||||
},
|
||||
getClassName:function(){
|
||||
return mindplot.layoutManagers.FreeMindLayoutManager.NAME;
|
||||
},
|
||||
@ -122,6 +175,33 @@ mindplot.layoutManagers.FreeMindLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
},
|
||||
_createCentralTopicBoard:function(node){
|
||||
return new mindplot.layoutManagers.boards.freeMindBoards.CentralTopicBoard(node, this);
|
||||
},
|
||||
_updateParentBoard:function(node, modifiedTopics){
|
||||
var parent = node.getParent();
|
||||
if(!this._isCentralTopic(parent)){
|
||||
var parentBoard = this.getTopicBoardForTopic(parent.getParent());
|
||||
var result = parentBoard.findNodeEntryIndex(parent);
|
||||
var parentEntry = result.table[result.index];
|
||||
var board = this.getTopicBoardForTopic(parent);
|
||||
var table = board._getTableForNode(null);
|
||||
if(table.length>0){
|
||||
var firstChild = table[0];
|
||||
var marginTop = parentEntry.getPosition()-(firstChild.getPosition()-firstChild.getTotalMarginTop());
|
||||
parentBoard.setNodeChildrenMarginTop(parentEntry,marginTop);
|
||||
var lastChild = table[table.length-1];
|
||||
var marginBottom = (lastChild.getPosition()+lastChild.getTotalMarginBottom())-parentEntry.getPosition();
|
||||
parentBoard.setNodeChildrenMarginBottom(parentEntry,marginBottom);
|
||||
parentBoard._updateTable(result.index, result.table, modifiedTopics, false);
|
||||
}
|
||||
this._updateParentBoard(parent, modifiedTopics);
|
||||
}
|
||||
},
|
||||
_updateChildrenBoards:function(node, delta, modifiedTopics){
|
||||
var board = this.getTopicBoardForTopic(node);
|
||||
var topics = board._getTableForNode(null);
|
||||
for(var i=0; i<topics.length; i++){
|
||||
board._updateEntryPos(topics[i],delta, modifiedTopics, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,7 @@ mindplot.layoutManagers.OriginalLayoutManager = mindplot.layoutManagers.BaseLayo
|
||||
if(this._isCentralTopic(node)){
|
||||
var size = node.getSize();
|
||||
if(!this._isCentralTopic(node))
|
||||
this.getTopicBoardForTopic(node).updateChildrenPosition(node,size.height/2);
|
||||
this.getTopicBoardForTopic(node).updateChildrenPosition(node,size.height/2, []);
|
||||
}
|
||||
},
|
||||
_NodeRepositionateEvent:function(node){
|
||||
|
@ -13,17 +13,17 @@ mindplot.layoutManagers.boards.Board = new Class({
|
||||
getClassName:function(){
|
||||
return mindplot.layoutManagers.boards.Board.NAME;
|
||||
},
|
||||
removeTopicFromBoard:function(node){
|
||||
core.Utils.assert(false, "no Board implementation found!");
|
||||
removeTopicFromBoard:function(node, modifiedTopics){
|
||||
core.assert(false, "no Board implementation found!");
|
||||
},
|
||||
addBranch:function(node){
|
||||
core.Utils.assert(false, "no Board implementation found!");
|
||||
addBranch:function(node, modifiedTopics){
|
||||
core.assert(false, "no Board implementation found!");
|
||||
},
|
||||
updateChildrenPosition:function(node){
|
||||
core.Utils.assert(false, "no Board implementation found!");
|
||||
updateChildrenPosition:function(node, modifiedTopics){
|
||||
core.assert(false, "no Board implementation found!");
|
||||
},
|
||||
setNodeMarginTop:function(node, delta){
|
||||
core.Utils.assert(false, "no Board implementation found!");
|
||||
core.assert(false, "no Board implementation found!");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -9,57 +9,109 @@ mindplot.layoutManagers.boards.freeMindBoards.Board = mindplot.layoutManagers.bo
|
||||
this._positionTables = this._createTables();
|
||||
},
|
||||
_createTables:function(){
|
||||
core.Utils.assert(false, "no Board implementation found!")
|
||||
core.assert(false, "no Board implementation found!")
|
||||
},
|
||||
_getTableForNode:function(node){
|
||||
core.Utils.assert(false, "no Board implementation found!")
|
||||
core.assert(false, "no Board implementation found!")
|
||||
},
|
||||
removeTopicFromBoard:function(node){
|
||||
removeTopicFromBoard:function(node, modifiedTopics){
|
||||
var table = this._getTableForNode(node);
|
||||
var position = node.getPosition();
|
||||
var y = position.y;
|
||||
var id = node.getId();
|
||||
|
||||
//search for position
|
||||
for(var i = 0; i< table.length ; i++){
|
||||
var i;
|
||||
for(i = 0; i< table.length ; i++){
|
||||
var entry = table[i];
|
||||
if (entry.position == y){
|
||||
this._removeEntry(node, table, i);
|
||||
if (entry.getId() == id){
|
||||
break;
|
||||
}
|
||||
}
|
||||
core.assert(i<table.length,"node not found. Could not remove");
|
||||
this._removeEntry(node, table, i, modifiedTopics);
|
||||
this._updateTable(0,table, modifiedTopics, true);
|
||||
},
|
||||
addBranch:function(node){
|
||||
var result = this.findNodeEntryIndex(node);
|
||||
this._insertNewEntry(node, result.table, result.index);
|
||||
addBranch:function(node,modifiedTopics){
|
||||
var pos = (this._layoutManager._isMovingNode?node.getPosition():node.getModel().getFinalPosition() || node.getPosition());
|
||||
var entry = new mindplot.layoutManagers.boards.freeMindBoards.Entry(node, !this._layoutManager._isMovingNode);
|
||||
var result = this.findNewNodeEntryIndex(entry);
|
||||
|
||||
// if creating a sibling or child
|
||||
if(!this._layoutManager._isMovingNode && this._layoutManager.getDesigner().getSelectedNodes().length>0){
|
||||
var selectedNode = this._layoutManager.getDesigner().getSelectedNodes()[0];
|
||||
if(selectedNode.getParent()!= null && node.getParent().getId() == selectedNode.getParent().getId() && !this._layoutManager._isCentralTopic(node.getParent())){
|
||||
//creating a sibling - Lets put the new node below the selected node.
|
||||
var parentBoard = this._layoutManager.getTopicBoardForTopic(selectedNode.getParent());
|
||||
var selectedNodeResult = parentBoard.findNodeEntryIndex(selectedNode);
|
||||
var selectedNodeEntry = selectedNodeResult.table[selectedNodeResult.index];
|
||||
entry.setPosition(null, selectedNodeEntry.getPosition()+selectedNodeEntry.getTotalMarginBottom() + entry.getMarginTop());
|
||||
result.index = selectedNodeResult.index+1;
|
||||
} else if(node.getParent().getId() == selectedNode.getId()){
|
||||
//creating a child node - Lest put the new node as the last child.
|
||||
var selectedNodeBoard = this._layoutManager.getTopicBoardForTopic(selectedNode);
|
||||
var table = selectedNodeBoard._getTableForNode(node);
|
||||
if(table.length>0){
|
||||
//if no children use the position set by Entry initializer. Otherwise place as last child
|
||||
var lastChild = table[table.length-1];
|
||||
entry.setPosition(null, lastChild.getPosition()+lastChild.getTotalMarginBottom() + entry.getMarginTop());
|
||||
}
|
||||
result.index = table.length;
|
||||
}
|
||||
}
|
||||
this._addEntry(entry, result.table, result.index);
|
||||
if(pos){
|
||||
if(result.index>0){
|
||||
var prevEntry =result.table[result.index-1];
|
||||
entry.setMarginTop(pos.y-(prevEntry.getPosition() + prevEntry.getTotalMarginBottom()));
|
||||
}
|
||||
else if(result.table.length>1){
|
||||
var nextEntry = result.table[1];
|
||||
nextEntry.setMarginTop((nextEntry.getPosition() - nextEntry.getTotalMarginTop())-pos.y);
|
||||
}
|
||||
var parent = node.getParent();
|
||||
if(!this._layoutManager._isCentralTopic(parent) && (result.index == 0 || result.index==result.table.length-1)){
|
||||
var board = this._layoutManager.getTopicBoardForTopic(parent.getParent());
|
||||
var res2 = board.findNodeEntryIndex(parent);
|
||||
var parentEntry = res2.table[res2.index];
|
||||
var totalMarginTop = parentEntry.getTotalMarginTop();
|
||||
var totalMarginBottom = parentEntry.getTotalMarginBottom();
|
||||
var parentPosition = parentEntry.getPosition();
|
||||
if(result.index==0 && pos.y < parentPosition){
|
||||
var childrenMarginTop = parentEntry.getPosition()-(pos.y-entry.getTotalMarginTop());
|
||||
parentEntry.setMarginTop(totalMarginTop-childrenMarginTop);
|
||||
}else if(result.index==result.table.length-1 && pos.y>parentPosition){
|
||||
var childrenMarginBottom = (pos.y+entry.getTotalMarginBottom())-parentEntry.getPosition();
|
||||
parentEntry.setMarginBottom(totalMarginBottom - childrenMarginBottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._updateTable(result.index, result.table,modifiedTopics, false);
|
||||
this._layoutManager._updateParentBoard(node, modifiedTopics);
|
||||
},
|
||||
_insertNewEntry:function(node, table, index){
|
||||
var entry = new mindplot.layoutManagers.boards.freeMindBoards.Entry(node);
|
||||
table.splice(index, 0, entry);
|
||||
this._updateTable(index, table);
|
||||
},
|
||||
_removeEntry:function(node, table, index){
|
||||
_removeEntry:function(node, table, index, modifiedTopics){
|
||||
table.splice(index, 1);
|
||||
this._updateTable(index, table);
|
||||
this._updateTable(index, table, modifiedTopics, false);
|
||||
},
|
||||
_updateTable:function(index, table){
|
||||
_addEntry:function(entry, table, index){
|
||||
table.splice(index, 0, entry);
|
||||
},
|
||||
_updateTable:function(index, table, modifiedTopics, updateParents){
|
||||
var i = index;
|
||||
if(index >= table.length){
|
||||
i = table.length -1;
|
||||
}
|
||||
|
||||
var modifiedTopics = [];
|
||||
var delta = null;
|
||||
//check from index to 0;
|
||||
if(i>0){
|
||||
var entry = table[i];
|
||||
var prevEntry = table[i-1];
|
||||
var marginTop = entry.getPosition() + entry.getMarginTop();
|
||||
var marginBottom = prevEntry.getPosition() - prevEntry.getMarginBottom();
|
||||
if(marginTop>marginBottom){
|
||||
delta = marginBottom - marginTop;
|
||||
|
||||
var margin = entry.getTotalMarginTop() + prevEntry.getTotalMarginBottom();
|
||||
var distance = Math.abs(prevEntry.getPosition() - entry.getPosition());
|
||||
if(distance!=margin){
|
||||
delta = (distance - margin)*Math.sign(prevEntry.getPosition() - entry.getPosition());
|
||||
i--;
|
||||
while(i >= 0){
|
||||
this._moveTopic(table[i], delta, modifiedTopics);
|
||||
this._updateEntryPos(table[i], new core.Point(null, delta), modifiedTopics, updateParents);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
@ -72,27 +124,25 @@ mindplot.layoutManagers.boards.freeMindBoards.Board = mindplot.layoutManagers.bo
|
||||
if( i<table.length-1){
|
||||
entry = table[i];
|
||||
var nextEntry = table[i+1];
|
||||
marginBottom = entry.getPosition() - entry.getMarginBottom();
|
||||
marginTop = nextEntry.getPosition() + nextEntry.getMarginTop();
|
||||
if(marginTop>marginBottom){
|
||||
delta = marginTop-marginBottom;
|
||||
var margin = entry.getTotalMarginBottom() + nextEntry.getTotalMarginTop();
|
||||
var distance = Math.abs(entry.getPosition() - nextEntry.getPosition());
|
||||
if(distance!=margin){
|
||||
delta = (distance - margin)*Math.sign(nextEntry.getPosition() - entry.getPosition());
|
||||
i++;
|
||||
while(i<table.length){
|
||||
this._moveTopic(table[i], delta, modifiedTopics);
|
||||
this._updateEntryPos(table[i], new core.Point(null, delta), modifiedTopics, updateParents);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(updateParents && (i==0 || i==table.length-1)){
|
||||
// this._layoutManager._updateParentBoard(table[i].getNode(), modifiedTopics);
|
||||
// }
|
||||
},
|
||||
_moveTopic:function(entry, delta, modifiedTopics){
|
||||
var pos = entry.getPosition();
|
||||
pos -= delta;
|
||||
entry.setPosition(pos);
|
||||
modifiedTopics.push(entry);
|
||||
},
|
||||
updateChildrenPosition:function(node){
|
||||
updateChildrenPosition:function(node, modifiedTopics){
|
||||
var result = this.findNodeEntryIndex(node);
|
||||
this._updateTable(result.index, result.table);
|
||||
this._updateTable(result.index, result.table, modifiedTopics, false);
|
||||
},
|
||||
findNodeEntryIndex:function(node){
|
||||
var table = this._getTableForNode(node);
|
||||
@ -103,16 +153,65 @@ mindplot.layoutManagers.boards.freeMindBoards.Board = mindplot.layoutManagers.bo
|
||||
var i;
|
||||
for(i = 0; i< table.length ; i++){
|
||||
var entry = table[i];
|
||||
if (entry.getPosition() < y){
|
||||
if (entry.getNode().getId() == node.getId()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {index:i, table:table};
|
||||
},
|
||||
setNodeMarginTop:function(node, delta){
|
||||
var result = this.findNodeEntryIndex(node);
|
||||
var entry = result.table[result.index];
|
||||
findNewNodeEntryIndex:function(entry){
|
||||
var table = this._getTableForNode(entry.getNode());
|
||||
var position = entry.getPosition();
|
||||
//search for position
|
||||
var i;
|
||||
for(i = 0; i< table.length ; i++){
|
||||
var tableEntry = table[i];
|
||||
if (tableEntry.getPosition() > position){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {index:i, table:table};
|
||||
},
|
||||
setNodeMarginTop:function(entry, delta){
|
||||
var marginTop = entry.getMarginTop()-delta.y;
|
||||
entry.setMarginTop(marginTop);
|
||||
},
|
||||
setNodeMarginBottom:function(entry, delta){
|
||||
var marginBottom = entry.getMarginBottom()-delta.y;
|
||||
entry.setMarginBottom(marginBottom);
|
||||
},
|
||||
setNodeChildrenMarginTop:function(entry, delta){
|
||||
var marginTop = entry.getChildrenMarginTop()-delta.y;
|
||||
entry.setChildrenMarginTop(delta);
|
||||
},
|
||||
setNodeChildrenMarginBottom:function(entry, delta){
|
||||
var marginBottom = entry.getChildrenMarginBottom()-delta.y;
|
||||
entry.setChildrenMarginBottom(delta);
|
||||
},
|
||||
updateEntry:function(node, delta, modifiedTopics){
|
||||
var result = this.findNodeEntryIndex(node);
|
||||
if(result.index < result.table.length){
|
||||
var entry = result.table[result.index];
|
||||
if(result.index!=0)
|
||||
this.setNodeMarginTop(entry, delta);
|
||||
this._updateEntryPos(entry, delta, modifiedTopics, false);
|
||||
this._updateTable(result.index, result.table, modifiedTopics, false);
|
||||
this._layoutManager._updateParentBoard(entry.getNode(), modifiedTopics);
|
||||
}
|
||||
},
|
||||
_updateEntryPos:function(entry, delta, modifiedTopics, updateParents){
|
||||
var pos = entry.getNode().getPosition().clone();
|
||||
var newPos = new core.Point(pos.x-(delta.x==null?0:delta.x), pos.y-delta.y);
|
||||
entry.setPosition(newPos.x, newPos.y);
|
||||
this._layoutManager._updateChildrenBoards(entry.getNode(), delta, modifiedTopics);
|
||||
// if(updateParents)
|
||||
// this._layoutManager._updateParentBoard(entry.getNode(), modifiedTopics);
|
||||
if(modifiedTopics.set){
|
||||
var key = entry.getId();
|
||||
if(modifiedTopics.hasKey(key)){
|
||||
pos = modifiedTopics.get(key).originalPos;
|
||||
}
|
||||
modifiedTopics.set(key,{originalPos:pos, newPos:newPos});
|
||||
}
|
||||
}
|
||||
});
|
@ -1,43 +1,91 @@
|
||||
mindplot.layoutManagers.boards.freeMindBoards.Entry = new Class({
|
||||
initialize:function(node){
|
||||
initialize:function(node, useFinalPosition){
|
||||
this._node = node;
|
||||
this._DEFAULT_X_GAP = 30;
|
||||
var pos = node.getPosition();
|
||||
if(!pos){
|
||||
var parent = node.getParent();
|
||||
pos = parent.getPosition().clone();
|
||||
var pwidth = parent.getSize().width;
|
||||
var width = node.getSize().width;
|
||||
pos.x = pos.x + Math.sign(pos.x) * (this._DEFAULT_X_GAP + pwidth/2 + width/2);
|
||||
node.setPosition(pos, false);
|
||||
var pos = node.getModel().getFinalPosition();
|
||||
if(useFinalPosition && pos){
|
||||
this.setPosition(pos.x, pos.y);
|
||||
}
|
||||
else{
|
||||
pos = node.getPosition();
|
||||
if(!pos){
|
||||
var parent = node.getParent();
|
||||
pos = parent.getPosition().clone();
|
||||
var pwidth = parent.getSize().width;
|
||||
var width = node.getSize().width;
|
||||
pos.x = pos.x + Math.sign(pos.x) * (this._DEFAULT_X_GAP + pwidth/2 + width/2);
|
||||
node.setPosition(pos, false);
|
||||
|
||||
}
|
||||
}
|
||||
this._position = pos.y;
|
||||
var height = node.getSize().height;
|
||||
this._DEFAULT_GAP = 10;
|
||||
this._marginTop = this._DEFAULT_GAP + height/2;
|
||||
this._marginBottom = this._DEFAULT_GAP + height/2;
|
||||
var height = this.getNode().getSize().height;
|
||||
this._minimalMargin = this._DEFAULT_GAP + height/2;
|
||||
this._marginTop = this._minimalMargin;
|
||||
this._marginBottom = this._minimalMargin;
|
||||
this._marginTopChildren=0;
|
||||
this._marginBottomChildren=0;
|
||||
},
|
||||
getNode:function(){
|
||||
return this._node;
|
||||
},
|
||||
getId:function(){
|
||||
return this.getNode().getId();
|
||||
},
|
||||
getPosition:function(){
|
||||
return this._position;
|
||||
},
|
||||
setPosition:function(pos){
|
||||
var position = this._node.getPosition();
|
||||
position.y = pos;
|
||||
this._node.setPosition(position);
|
||||
this._position = pos;
|
||||
setPosition:function(x,y){
|
||||
var position = this._node.getPosition().clone();
|
||||
position.y = y;
|
||||
if(null != x){
|
||||
position.x = x;
|
||||
}
|
||||
|
||||
this._node.setPosition(position, false);
|
||||
this._position = y;
|
||||
},
|
||||
getMarginTop:function(){
|
||||
return this._marginTop;
|
||||
},
|
||||
setMarginTop:function(value){
|
||||
if(value >= this._DEFAULT_GAP){
|
||||
if(value >= this._minimalMargin){
|
||||
this._marginTop = value;
|
||||
}
|
||||
},
|
||||
setMarginBottom:function(value){
|
||||
if(value >= this._minimalMargin){
|
||||
this._marginBottom = value;
|
||||
}
|
||||
},
|
||||
getMarginBottom:function(){
|
||||
return this._marginTop;
|
||||
return this._marginBottom;
|
||||
},
|
||||
getChildrenMarginTop:function(){
|
||||
return this._marginTopChildren;
|
||||
},
|
||||
setChildrenMarginTop:function(value){
|
||||
if(value >= this._minimalMargin){
|
||||
this._marginTopChildren = value - this._minimalMargin;
|
||||
}else{
|
||||
this._marginTopChildren=0;
|
||||
}
|
||||
},
|
||||
setChildrenMarginBottom:function(value){
|
||||
if(value >= this._minimalMargin){
|
||||
this._marginBottomChildren = value - this._minimalMargin;
|
||||
}else{
|
||||
this._marginBottomChildren=0;
|
||||
}
|
||||
},
|
||||
getChildrenMarginBottom:function(){
|
||||
return this._marginBottomChildren;
|
||||
},
|
||||
getTotalMarginTop:function(){
|
||||
return this._marginTopChildren+this._marginTop;
|
||||
},
|
||||
getTotalMarginBottom:function(){
|
||||
return this._marginBottomChildren + this._marginBottom;
|
||||
}
|
||||
});
|
@ -64,11 +64,11 @@ public class ExportController extends BaseMultiActionController {
|
||||
|
||||
final String mapIdStr = request.getParameter(MAP_ID_PARAMETER);
|
||||
if (mapIdStr != null) {
|
||||
final String mapSvg = request.getParameter(MAP_SVG_PARAMETER);
|
||||
try {
|
||||
|
||||
int mindmapId = Integer.parseInt(mapIdStr);
|
||||
|
||||
final String mapSvg = request.getParameter(MAP_SVG_PARAMETER);
|
||||
logger.debug("SVG Map to export:"+mapSvg);
|
||||
if(mapSvg==null || mapSvg.isEmpty())
|
||||
{
|
||||
@ -116,6 +116,7 @@ public class ExportController extends BaseMultiActionController {
|
||||
} catch (Throwable e) {
|
||||
logger.error("Unexpexted error during export process", e);
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
logger.error("map: "+mapSvg);
|
||||
}
|
||||
} else {
|
||||
logger.warn("mapIdStr is null.Image could not be imported. UserAgent:" + request.getHeaders(UserAgent.USER_AGENT_HEADER));
|
||||
|
Loading…
Reference in New Issue
Block a user