You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
13 KiB
323 lines
13 KiB
/* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/**
|
|
* Created by Pardo David on 3/01/2017.
|
|
* For this service to work the user must call bootEditor method
|
|
*/
|
|
angular.module("flowableModeler").factory("editorManager", ["$http", function ($http) {
|
|
var editorManager = Class.create({
|
|
initialize: function () {
|
|
this.treeFilteredElements = ["SubProcess", "CollapsedSubProcess"];
|
|
this.canvasTracker = new Hash();
|
|
this.structualIcons = {
|
|
"SubProcess": "expanded.subprocess.png",
|
|
"CollapsedSubProcess": "subprocess.png",
|
|
"EventSubProcess": "event.subprocess.png"
|
|
};
|
|
|
|
this.current = this.modelId;
|
|
this.loading = true;
|
|
},
|
|
getModelId: function () {
|
|
return this.modelId;
|
|
},
|
|
setModelId: function (modelId){
|
|
this.modelId = modelId;
|
|
},
|
|
getCurrentModelId: function () {
|
|
return this.current;
|
|
},
|
|
setStencilData: function(stencilData){
|
|
//we don't want a references!
|
|
this.stencilData = jQuery.extend(true, {},stencilData);
|
|
},
|
|
getStencilData: function () {
|
|
return this.stencilData;
|
|
},
|
|
getSelection: function () {
|
|
return this.editor.selection;
|
|
},
|
|
getSubSelection: function () {
|
|
return this.editor._subSelection;
|
|
},
|
|
handleEvents: function (events) {
|
|
this.editor.handleEvents(events);
|
|
},
|
|
setSelection: function (selection) {
|
|
this.editor.setSelection(selection);
|
|
},
|
|
registerOnEvent: function (event, callback) {
|
|
this.editor.registerOnEvent(event, callback);
|
|
},
|
|
getChildShapeByResourceId: function (resourceId) {
|
|
return this.editor.getCanvas().getChildShapeByResourceId(resourceId);
|
|
},
|
|
getJSON: function () {
|
|
return this.editor.getJSON();
|
|
},
|
|
getStencilSets: function () {
|
|
return this.editor.getStencilSets();
|
|
},
|
|
getEditor: function () {
|
|
return this.editor; //TODO: find out if we can avoid exposing the editor object to angular.
|
|
},
|
|
executeCommands: function (commands) {
|
|
this.editor.executeCommands(commands);
|
|
},
|
|
getCanvas: function () {
|
|
return this.editor.getCanvas();
|
|
},
|
|
getRules: function () {
|
|
return this.editor.getRules();
|
|
},
|
|
eventCoordinates: function (coordinates) {
|
|
return this.editor.eventCoordinates(coordinates);
|
|
},
|
|
eventCoordinatesXY: function (x, y) {
|
|
return this.editor.eventCoordinatesXY(x, y);
|
|
},
|
|
updateSelection: function () {
|
|
this.editor.updateSelection();
|
|
},
|
|
/**
|
|
* @returns the modeldata as received from the server. This does not represent the current editor data.
|
|
*/
|
|
getBaseModelData: function () {
|
|
return this.modelData;
|
|
},
|
|
edit: function (resourceId) {
|
|
//Save the current canvas in the canvastracker if it is the root process.
|
|
this.syncCanvasTracker();
|
|
|
|
this.loading = true;
|
|
|
|
var shapes = this.getCanvas().getChildren();
|
|
shapes.each(function (shape) {
|
|
this.editor.deleteShape(shape);
|
|
}.bind(this));
|
|
|
|
shapes = this.canvasTracker.get(resourceId);
|
|
if(!shapes){
|
|
shapes = JSON.stringify([]);
|
|
}
|
|
|
|
this.editor.loadSerialized({
|
|
childShapes: shapes
|
|
});
|
|
|
|
this.getCanvas().update();
|
|
|
|
this.current = resourceId;
|
|
|
|
this.loading = false;
|
|
FLOWABLE.eventBus.dispatch("EDITORMANAGER-EDIT-ACTION", {});
|
|
FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_UNDO_REDO_RESET, {});
|
|
},
|
|
getTree: function () {
|
|
//build a tree of all subprocesses and there children.
|
|
var result = new Hash();
|
|
var parent = this.getModel();
|
|
result.set("name", parent.properties["name"] || "No name provided");
|
|
result.set("id", this.modelId);
|
|
result.set("type", "root");
|
|
result.set("current", this.current === this.modelId)
|
|
var childShapes = parent.childShapes;
|
|
var children = this._buildTreeChildren(childShapes);
|
|
result.set("children", children);
|
|
return result.toObject();
|
|
},
|
|
_buildTreeChildren: function (childShapes) {
|
|
var children = [];
|
|
for (var i = 0; i < childShapes.length; i++) {
|
|
var childShape = childShapes[i];
|
|
var stencilId = childShape.stencil.id;
|
|
//we are currently only interested in the expanded subprocess and collapsed processes
|
|
if (stencilId && this.treeFilteredElements.indexOf(stencilId) > -1) {
|
|
var child = new Hash();
|
|
child.set("name", childShape.properties.name || "No name provided");
|
|
child.set("id", childShape.resourceId);
|
|
child.set("type", stencilId);
|
|
child.set("current", childShape.resourceId === this.current);
|
|
|
|
//check if childshapes
|
|
|
|
if (stencilId === "CollapsedSubProcess") {
|
|
//the save function stores the real object as a childshape
|
|
//it is possible that there is no child element because the user did not open the collapsed subprocess.
|
|
if (childShape.childShapes.length === 0) {
|
|
child.set("children", []);
|
|
} else {
|
|
child.set("children", this._buildTreeChildren(childShape.childShapes));
|
|
}
|
|
child.set("editable", true);
|
|
} else {
|
|
child.set("children", this._buildTreeChildren(childShape.childShapes));
|
|
child.set("editable", false);
|
|
}
|
|
child.set("icon", this.structualIcons[stencilId]);
|
|
children.push(child.toObject());
|
|
}
|
|
}
|
|
return children;
|
|
},
|
|
syncCanvasTracker: function () {
|
|
var shapes = this.getCanvas().getChildren();
|
|
var jsonShapes = [];
|
|
shapes.each(function (shape) {
|
|
//toJson is an summary object but its not a json string.!!!!!
|
|
jsonShapes.push(shape.toJSON());
|
|
});
|
|
this.canvasTracker.set(this.current, JSON.stringify(jsonShapes));
|
|
},
|
|
getModel: function () {
|
|
this.syncCanvasTracker();
|
|
|
|
var modelMetaData = this.getBaseModelData();
|
|
|
|
var stencilId = undefined;
|
|
var stencilSetNamespace = undefined;
|
|
var stencilSetUrl = undefined;
|
|
if (modelMetaData.model.stencilset.namespace == 'http://b3mn.org/stencilset/cmmn1.1#') {
|
|
stencilId = 'CMMNDiagram';
|
|
stencilSetNamespace = 'http://b3mn.org/stencilset/cmmn1.1#';
|
|
stencilSetUrl = '../editor/stencilsets/cmmn1.1/cmmn1.1.json';
|
|
} else {
|
|
stencilId = 'BPMNDiagram';
|
|
stencilSetNamespace = 'http://b3mn.org/stencilset/bpmn2.0#';
|
|
stencilSetUrl = '../editor/stencilsets/bpmn2.0/bpmn2.0.json';
|
|
}
|
|
|
|
//this is an object.
|
|
var editorConfig = this.editor.getJSON();
|
|
var model = {
|
|
modelId: this.modelId,
|
|
bounds: editorConfig.bounds,
|
|
properties: editorConfig.properties,
|
|
childShapes: JSON.parse(this.canvasTracker.get(this.modelId)),
|
|
stencil: {
|
|
id: stencilId,
|
|
},
|
|
stencilset: {
|
|
namespace: stencilSetNamespace,
|
|
url: stencilSetUrl
|
|
}
|
|
};
|
|
|
|
this._mergeCanvasToChild(model);
|
|
|
|
return model;
|
|
},
|
|
setModelData: function(response){
|
|
this.modelData = response.data;
|
|
},
|
|
bootEditor: function () {
|
|
//TODO: populate the canvas with correct json sections.
|
|
//resetting the state
|
|
this.canvasTracker = new Hash();
|
|
var config = jQuery.extend(true, {}, this.modelData); //avoid a reference to the original object.
|
|
if(!config.model.childShapes){
|
|
config.model.childShapes = [];
|
|
}
|
|
|
|
this.findAndRegisterCanvas(config.model.childShapes); //this will remove any childshapes of a collapseable subprocess.
|
|
this.canvasTracker.set(config.modelId, JSON.stringify(config.model.childShapes)); //this will be overwritten almost instantly.
|
|
|
|
this.editor = new ORYX.Editor(config);
|
|
this.current = this.editor.id;
|
|
this.loading = false;
|
|
|
|
FLOWABLE.eventBus.editor = this.editor;
|
|
FLOWABLE.eventBus.dispatch("ORYX-EDITOR-LOADED", {});
|
|
FLOWABLE.eventBus.dispatch(FLOWABLE.eventBus.EVENT_TYPE_EDITOR_BOOTED, {});
|
|
},
|
|
findAndRegisterCanvas: function (childShapes) {
|
|
for (var i = 0; i < childShapes.length; i++) {
|
|
var childShape = childShapes[i];
|
|
if (childShape.stencil.id === "CollapsedSubProcess") {
|
|
if (childShape.childShapes.length > 0) {
|
|
//the canvastracker will auto correct itself with a new canvasmodel see this.edit()...
|
|
this.findAndRegisterCanvas(childShape.childShapes);
|
|
//a canvas can't be nested as a child because the editor would crash on redundant information.
|
|
this.canvasTracker.set(childShape.resourceId, JSON.stringify(childShape.childShapes));
|
|
//reference to config will clear the value.
|
|
childShape.childShapes = [];
|
|
} else {
|
|
this.canvasTracker.set(childShape.resourceId, '[]');
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_mergeCanvasToChild: function (parent) {
|
|
for (var i = 0; i < parent.childShapes.length; i++) {
|
|
var childShape = parent.childShapes[i]
|
|
if(childShape.stencil.id === "CollapsedSubProcess"){
|
|
|
|
var elements = this.canvasTracker.get(childShape.resourceId);
|
|
if(elements){
|
|
elements = JSON.parse(elements);
|
|
}else{
|
|
elements = [];
|
|
}
|
|
childShape.childShapes = elements;
|
|
this._mergeCanvasToChild(childShape);
|
|
}else if(childShape.stencil.id === "SubProcess"){
|
|
this._mergeCanvasToChild(childShape);
|
|
}else{
|
|
//do nothing?
|
|
}
|
|
}
|
|
},
|
|
dispatchOryxEvent: function (event) {
|
|
FLOWABLE.eventBus.dispatchOryxEvent(event);
|
|
},
|
|
isLoading: function(){
|
|
return this.loading;
|
|
},
|
|
navigateTo: function(resourceId){
|
|
//TODO: this could be improved by check if the resourceId is not equal to the current tracker...
|
|
this.syncCanvasTracker();
|
|
var found = false;
|
|
this.canvasTracker.each(function(pair){
|
|
var key = pair.key;
|
|
var children = JSON.parse(pair.value);
|
|
var targetable = this._findTarget(children, resourceId);
|
|
if (!found && targetable){
|
|
this.edit(key);
|
|
var flowableShape = this.getCanvas().getChildShapeByResourceId(targetable);
|
|
this.setSelection([flowableShape],[],true);
|
|
found = true;
|
|
}
|
|
},this);
|
|
},
|
|
_findTarget: function(children,resourceId){
|
|
for(var i =0; i < children.length; i++){
|
|
var child = children[i];
|
|
if(child.resourceId === resourceId){
|
|
return child.resourceId;
|
|
}else if(child.properties && child.properties["overrideid"] === resourceId){
|
|
return child.resourceId;
|
|
}else{
|
|
var result = this._findTarget(child.childShapes,resourceId);
|
|
if(result){
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
|
|
return new editorManager();
|
|
}]);
|