电子档案
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.

317 lines
11 KiB

  1. /* Licensed under the Apache License, Version 2.0 (the "License");
  2. * you may not use this file except in compliance with the License.
  3. * You may obtain a copy of the License at
  4. *
  5. * http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Unless required by applicable law or agreed to in writing, software
  8. * distributed under the License is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. * See the License for the specific language governing permissions and
  11. * limitations under the License.
  12. */
  13. /*
  14. * Controller for morph shape selection
  15. */
  16. angular.module('flowableModeler').controller('FlowableBpmShapeSelectionCtrl',
  17. [ '$rootScope', '$scope', '$timeout', '$translate', 'editorManager', function($rootScope, $scope, $timeout, $translate, editorManager) {
  18. $scope.currentSelectedMorph = undefined;
  19. $scope.availableMorphShapes = [];
  20. for (var i = 0; i < $scope.morphShapes.length; i++) {
  21. if ($scope.morphShapes[i].id != $scope.currentSelectedShape.getStencil().idWithoutNs()) {
  22. $scope.availableMorphShapes.push($scope.morphShapes[i]);
  23. }
  24. }
  25. // Config for grid
  26. $scope.gridOptions = {
  27. data: $scope.availableMorphShapes,
  28. headerRowHeight: 28,
  29. enableRowSelection: true,
  30. enableRowHeaderSelection: false,
  31. multiSelect: false,
  32. modifierKeysToMultiSelect: false,
  33. enableHorizontalScrollbar: 0,
  34. enableColumnMenus: false,
  35. enableSorting: false,
  36. columnDefs: [{ field: 'objectId', displayName: 'Icon', width: 50, cellTemplate: 'editor-app/popups/icon-template.html?version=' + Date.now() },
  37. { field: 'name', displayName: 'Name', cellTemplate: '<div class="ui-grid-cell-contents">{{"" + row.entity[col.field] | translate}}</div>'}]
  38. };
  39. $scope.gridOptions.onRegisterApi = function(gridApi) {
  40. //set gridApi on scope
  41. $scope.gridApi = gridApi;
  42. gridApi.selection.on.rowSelectionChanged($scope, function(row) {
  43. if (row.isSelected) {
  44. $scope.currentSelectedMorph = row.entity;
  45. } else {
  46. $scope.currentSelectedMorph = undefined;
  47. }
  48. });
  49. };
  50. // Click handler for save button
  51. $scope.select = function() {
  52. if ($scope.currentSelectedMorph) {
  53. var MorphTo = ORYX.Core.Command.extend({
  54. construct: function(shape, stencil, facade){
  55. this.shape = shape;
  56. this.stencil = stencil;
  57. this.facade = facade;
  58. },
  59. execute: function(){
  60. var shape = this.shape;
  61. var stencil = this.stencil;
  62. var resourceId = shape.resourceId;
  63. // Serialize all attributes
  64. var serialized = shape.serialize();
  65. stencil.properties().each((function(prop) {
  66. if(prop.readonly()) {
  67. serialized = serialized.reject(function(serProp) {
  68. return serProp.name==prop.id();
  69. });
  70. }
  71. }).bind(this));
  72. // Get shape if already created, otherwise create a new shape
  73. if (this.newShape){
  74. newShape = this.newShape;
  75. this.facade.getCanvas().add(newShape);
  76. } else {
  77. newShape = this.facade.createShape({
  78. type: stencil.id(),
  79. namespace: stencil.namespace(),
  80. resourceId: resourceId
  81. });
  82. }
  83. // calculate new bounds using old shape's upperLeft and new shape's width/height
  84. var boundsObj = serialized.find(function(serProp){
  85. return (serProp.prefix === "oryx" && serProp.name === "bounds");
  86. });
  87. var changedBounds = null;
  88. if (!this.facade.getRules().preserveBounds(shape.getStencil())) {
  89. var bounds = boundsObj.value.split(",");
  90. if (parseInt(bounds[0], 10) > parseInt(bounds[2], 10)) { // if lowerRight comes first, swap array items
  91. var tmp = bounds[0];
  92. bounds[0] = bounds[2];
  93. bounds[2] = tmp;
  94. tmp = bounds[1];
  95. bounds[1] = bounds[3];
  96. bounds[3] = tmp;
  97. }
  98. bounds[2] = parseInt(bounds[0], 10) + newShape.bounds.width();
  99. bounds[3] = parseInt(bounds[1], 10) + newShape.bounds.height();
  100. boundsObj.value = bounds.join(",");
  101. } else {
  102. var height = shape.bounds.height();
  103. var width = shape.bounds.width();
  104. // consider the minimum and maximum size of
  105. // the new shape
  106. if (newShape.minimumSize) {
  107. if (shape.bounds.height() < newShape.minimumSize.height) {
  108. height = newShape.minimumSize.height;
  109. }
  110. if (shape.bounds.width() < newShape.minimumSize.width) {
  111. width = newShape.minimumSize.width;
  112. }
  113. }
  114. if (newShape.maximumSize) {
  115. if (shape.bounds.height() > newShape.maximumSize.height) {
  116. height = newShape.maximumSize.height;
  117. }
  118. if (shape.bounds.width() > newShape.maximumSize.width) {
  119. width = newShape.maximumSize.width;
  120. }
  121. }
  122. changedBounds = {
  123. a : {
  124. x: shape.bounds.a.x,
  125. y: shape.bounds.a.y
  126. },
  127. b : {
  128. x: shape.bounds.a.x + width,
  129. y: shape.bounds.a.y + height
  130. }
  131. };
  132. }
  133. var oPos = shape.bounds.center();
  134. if (changedBounds !== null) {
  135. newShape.bounds.set(changedBounds);
  136. }
  137. // Set all related dockers
  138. this.setRelatedDockers(shape, newShape);
  139. // store DOM position of old shape
  140. var parentNode = shape.node.parentNode;
  141. var nextSibling = shape.node.nextSibling;
  142. // Delete the old shape
  143. this.facade.deleteShape(shape);
  144. // Deserialize the new shape - Set all attributes
  145. newShape.deserialize(serialized);
  146. /*
  147. * Change color to default if unchanged
  148. * 23.04.2010
  149. */
  150. if (shape.getStencil().property("oryx-bgcolor")
  151. && shape.properties["oryx-bgcolor"]
  152. && shape.getStencil().property("oryx-bgcolor").value().toUpperCase()== shape.properties["oryx-bgcolor"].toUpperCase()){
  153. if (newShape.getStencil().property("oryx-bgcolor")){
  154. newShape.setProperty("oryx-bgcolor", newShape.getStencil().property("oryx-bgcolor").value());
  155. }
  156. }
  157. if (changedBounds !== null) {
  158. newShape.bounds.set(changedBounds);
  159. }
  160. if (newShape.getStencil().type()==="edge" || (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
  161. newShape.bounds.centerMoveTo(oPos);
  162. }
  163. if (newShape.getStencil().type()==="node" && (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
  164. this.setRelatedDockers(newShape, newShape);
  165. }
  166. // place at the DOM position of the old shape
  167. if(nextSibling) parentNode.insertBefore(newShape.node, nextSibling);
  168. else parentNode.appendChild(newShape.node);
  169. // Set selection
  170. this.facade.setSelection([newShape]);
  171. this.facade.getCanvas().update();
  172. this.facade.updateSelection();
  173. this.newShape = newShape;
  174. },
  175. rollback: function(){
  176. if (!this.shape || !this.newShape || !this.newShape.parent) {return;}
  177. // Append shape to the parent
  178. this.newShape.parent.add(this.shape);
  179. // Set dockers
  180. this.setRelatedDockers(this.newShape, this.shape);
  181. // Delete new shape
  182. this.facade.deleteShape(this.newShape);
  183. // Set selection
  184. this.facade.setSelection([this.shape]);
  185. // Update
  186. this.facade.getCanvas().update();
  187. this.facade.updateSelection();
  188. },
  189. /**
  190. * Set all incoming and outgoing edges from the shape to the new shape
  191. * @param {Shape} shape
  192. * @param {Shape} newShape
  193. */
  194. setRelatedDockers: function(shape, newShape){
  195. if(shape.getStencil().type()==="node") {
  196. (shape.incoming||[]).concat(shape.outgoing||[])
  197. .each(function(i) {
  198. i.dockers.each(function(docker) {
  199. if (docker.getDockedShape() == shape) {
  200. var rPoint = Object.clone(docker.referencePoint);
  201. // Move reference point per percent
  202. var rPointNew = {
  203. x: rPoint.x*newShape.bounds.width()/shape.bounds.width(),
  204. y: rPoint.y*newShape.bounds.height()/shape.bounds.height()
  205. };
  206. docker.setDockedShape(newShape);
  207. // Set reference point and center to new position
  208. docker.setReferencePoint(rPointNew);
  209. if(i instanceof ORYX.Core.Edge) {
  210. docker.bounds.centerMoveTo(rPointNew);
  211. } else {
  212. var absXY = shape.absoluteXY();
  213. docker.bounds.centerMoveTo({x:rPointNew.x+absXY.x, y:rPointNew.y+absXY.y});
  214. //docker.bounds.moveBy({x:rPointNew.x-rPoint.x, y:rPointNew.y-rPoint.y});
  215. }
  216. }
  217. });
  218. });
  219. // for attached events
  220. if(shape.dockers.length>0&&shape.dockers.first().getDockedShape()) {
  221. newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
  222. newShape.dockers.first().setReferencePoint(Object.clone(shape.dockers.first().referencePoint));
  223. }
  224. } else { // is edge
  225. newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
  226. newShape.dockers.first().setReferencePoint(shape.dockers.first().referencePoint);
  227. newShape.dockers.last().setDockedShape(shape.dockers.last().getDockedShape());
  228. newShape.dockers.last().setReferencePoint(shape.dockers.last().referencePoint);
  229. }
  230. }
  231. });
  232. var stencil = undefined;
  233. var stencilSets = editorManager.getStencilSets().values();
  234. var stencilId = $scope.currentSelectedMorph.id;
  235. if ($scope.currentSelectedMorph.genericTaskId) {
  236. stencilId = $scope.currentSelectedMorph.genericTaskId;
  237. }
  238. for (var i = 0; i < stencilSets.length; i++) {
  239. var stencilSet = stencilSets[i];
  240. var nodes = stencilSet.nodes();
  241. for (var j = 0; j < nodes.length; j++) {
  242. if (nodes[j].idWithoutNs() === stencilId) {
  243. stencil = nodes[j];
  244. break;
  245. }
  246. }
  247. }
  248. if (!stencil) return;
  249. // Create and execute command (for undo/redo)
  250. var command = new MorphTo($scope.currentSelectedShape, stencil, editorManager.getEditor());
  251. editorManager.executeCommands([command]);
  252. }
  253. $scope.close();
  254. };
  255. $scope.cancel = function() {
  256. $scope.$hide();
  257. };
  258. // Close button handler
  259. $scope.close = function() {
  260. $scope.$hide();
  261. };
  262. }]);