select-shape-controller.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Activiti Modeler component part of the Activiti project
  3. * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /*
  19. * Controller for morph shape selection
  20. */
  21. var KisBpmShapeSelectionCtrl = [ '$rootScope', '$scope', '$timeout', '$translate', function($rootScope, $scope, $timeout, $translate) {
  22. $scope.selectedMorphShapes = [];
  23. $scope.availableMorphShapes = [];
  24. for (var i = 0; i < $scope.morphShapes.length; i++)
  25. {
  26. if ($scope.morphShapes[i].id != $scope.currentSelectedShape.getStencil().idWithoutNs())
  27. {
  28. $scope.availableMorphShapes.push($scope.morphShapes[i]);
  29. }
  30. }
  31. // Config for grid
  32. $scope.gridOptions = {
  33. data: 'availableMorphShapes',
  34. enableRowReordering: true,
  35. headerRowHeight: 28,
  36. multiSelect: false,
  37. keepLastSelected : false,
  38. selectedItems: $scope.selectedMorphShapes,
  39. columnDefs: [{ field: 'objectId', displayName: 'Icon', width: 50, cellTemplate: 'editor-app/popups/icon-template.html?version=' + Date.now() },
  40. { field: 'name', displayName: 'Name'}]
  41. };
  42. // Click handler for save button
  43. $scope.select = function() {
  44. if ($scope.selectedMorphShapes.length > 0)
  45. {
  46. var MorphTo = ORYX.Core.Command.extend({
  47. construct: function(shape, stencil, facade){
  48. this.shape = shape;
  49. this.stencil = stencil;
  50. this.facade = facade;
  51. },
  52. execute: function(){
  53. var shape = this.shape;
  54. var stencil = this.stencil;
  55. var resourceId = shape.resourceId;
  56. // Serialize all attributes
  57. var serialized = shape.serialize();
  58. stencil.properties().each((function(prop) {
  59. if(prop.readonly()) {
  60. serialized = serialized.reject(function(serProp) {
  61. return serProp.name==prop.id();
  62. });
  63. }
  64. }).bind(this));
  65. // Get shape if already created, otherwise create a new shape
  66. if (this.newShape){
  67. newShape = this.newShape;
  68. this.facade.getCanvas().add(newShape);
  69. } else {
  70. newShape = this.facade.createShape({
  71. type: stencil.id(),
  72. namespace: stencil.namespace(),
  73. resourceId: resourceId
  74. });
  75. }
  76. // calculate new bounds using old shape's upperLeft and new shape's width/height
  77. var boundsObj = serialized.find(function(serProp){
  78. return (serProp.prefix === "oryx" && serProp.name === "bounds");
  79. });
  80. var changedBounds = null;
  81. if (!this.facade.getRules().preserveBounds(shape.getStencil())) {
  82. var bounds = boundsObj.value.split(",");
  83. if (parseInt(bounds[0], 10) > parseInt(bounds[2], 10)) { // if lowerRight comes first, swap array items
  84. var tmp = bounds[0];
  85. bounds[0] = bounds[2];
  86. bounds[2] = tmp;
  87. tmp = bounds[1];
  88. bounds[1] = bounds[3];
  89. bounds[3] = tmp;
  90. }
  91. bounds[2] = parseInt(bounds[0], 10) + newShape.bounds.width();
  92. bounds[3] = parseInt(bounds[1], 10) + newShape.bounds.height();
  93. boundsObj.value = bounds.join(",");
  94. } else {
  95. var height = shape.bounds.height();
  96. var width = shape.bounds.width();
  97. // consider the minimum and maximum size of
  98. // the new shape
  99. if (newShape.minimumSize) {
  100. if (shape.bounds.height() < newShape.minimumSize.height) {
  101. height = newShape.minimumSize.height;
  102. }
  103. if (shape.bounds.width() < newShape.minimumSize.width) {
  104. width = newShape.minimumSize.width;
  105. }
  106. }
  107. if(newShape.maximumSize) {
  108. if(shape.bounds.height() > newShape.maximumSize.height) {
  109. height = newShape.maximumSize.height;
  110. }
  111. if(shape.bounds.width() > newShape.maximumSize.width) {
  112. width = newShape.maximumSize.width;
  113. }
  114. }
  115. changedBounds = {
  116. a : {
  117. x: shape.bounds.a.x,
  118. y: shape.bounds.a.y
  119. },
  120. b : {
  121. x: shape.bounds.a.x + width,
  122. y: shape.bounds.a.y + height
  123. }
  124. };
  125. }
  126. var oPos = shape.bounds.center();
  127. if(changedBounds !== null) {
  128. newShape.bounds.set(changedBounds);
  129. }
  130. // Set all related dockers
  131. this.setRelatedDockers(shape, newShape);
  132. // store DOM position of old shape
  133. var parentNode = shape.node.parentNode;
  134. var nextSibling = shape.node.nextSibling;
  135. // Delete the old shape
  136. this.facade.deleteShape(shape);
  137. // Deserialize the new shape - Set all attributes
  138. newShape.deserialize(serialized);
  139. /*
  140. * Change color to default if unchanged
  141. * 23.04.2010
  142. */
  143. if(shape.getStencil().property("oryx-bgcolor")
  144. && shape.properties["oryx-bgcolor"]
  145. && shape.getStencil().property("oryx-bgcolor").value().toUpperCase()== shape.properties["oryx-bgcolor"].toUpperCase()){
  146. if(newShape.getStencil().property("oryx-bgcolor")){
  147. newShape.setProperty("oryx-bgcolor", newShape.getStencil().property("oryx-bgcolor").value());
  148. }
  149. }
  150. if(changedBounds !== null) {
  151. newShape.bounds.set(changedBounds);
  152. }
  153. if(newShape.getStencil().type()==="edge" || (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
  154. newShape.bounds.centerMoveTo(oPos);
  155. }
  156. if(newShape.getStencil().type()==="node" && (newShape.dockers.length==0 || !newShape.dockers[0].getDockedShape())) {
  157. this.setRelatedDockers(newShape, newShape);
  158. }
  159. // place at the DOM position of the old shape
  160. if(nextSibling) parentNode.insertBefore(newShape.node, nextSibling);
  161. else parentNode.appendChild(newShape.node);
  162. // Set selection
  163. this.facade.setSelection([newShape]);
  164. this.facade.getCanvas().update();
  165. this.facade.updateSelection();
  166. this.newShape = newShape;
  167. },
  168. rollback: function(){
  169. if (!this.shape || !this.newShape || !this.newShape.parent) {return;}
  170. // Append shape to the parent
  171. this.newShape.parent.add(this.shape);
  172. // Set dockers
  173. this.setRelatedDockers(this.newShape, this.shape);
  174. // Delete new shape
  175. this.facade.deleteShape(this.newShape);
  176. // Set selection
  177. this.facade.setSelection([this.shape]);
  178. // Update
  179. this.facade.getCanvas().update();
  180. this.facade.updateSelection();
  181. },
  182. /**
  183. * Set all incoming and outgoing edges from the shape to the new shape
  184. * @param {Shape} shape
  185. * @param {Shape} newShape
  186. */
  187. setRelatedDockers: function(shape, newShape){
  188. if(shape.getStencil().type()==="node") {
  189. (shape.incoming||[]).concat(shape.outgoing||[])
  190. .each(function(i) {
  191. i.dockers.each(function(docker) {
  192. if (docker.getDockedShape() == shape) {
  193. var rPoint = Object.clone(docker.referencePoint);
  194. // Move reference point per percent
  195. var rPointNew = {
  196. x: rPoint.x*newShape.bounds.width()/shape.bounds.width(),
  197. y: rPoint.y*newShape.bounds.height()/shape.bounds.height()
  198. };
  199. docker.setDockedShape(newShape);
  200. // Set reference point and center to new position
  201. docker.setReferencePoint(rPointNew);
  202. if(i instanceof ORYX.Core.Edge) {
  203. docker.bounds.centerMoveTo(rPointNew);
  204. } else {
  205. var absXY = shape.absoluteXY();
  206. docker.bounds.centerMoveTo({x:rPointNew.x+absXY.x, y:rPointNew.y+absXY.y});
  207. //docker.bounds.moveBy({x:rPointNew.x-rPoint.x, y:rPointNew.y-rPoint.y});
  208. }
  209. }
  210. });
  211. });
  212. // for attached events
  213. if(shape.dockers.length>0&&shape.dockers.first().getDockedShape()) {
  214. newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
  215. newShape.dockers.first().setReferencePoint(Object.clone(shape.dockers.first().referencePoint));
  216. }
  217. } else { // is edge
  218. newShape.dockers.first().setDockedShape(shape.dockers.first().getDockedShape());
  219. newShape.dockers.first().setReferencePoint(shape.dockers.first().referencePoint);
  220. newShape.dockers.last().setDockedShape(shape.dockers.last().getDockedShape());
  221. newShape.dockers.last().setReferencePoint(shape.dockers.last().referencePoint);
  222. }
  223. }
  224. });
  225. var stencil = undefined;
  226. var stencilSets = $scope.editor.getStencilSets().values();
  227. var stencilId = $scope.selectedMorphShapes[0].id;
  228. if ($scope.selectedMorphShapes[0].genericTaskId)
  229. {
  230. stencilId = $scope.selectedMorphShapes[0].genericTaskId;
  231. }
  232. for (var i = 0; i < stencilSets.length; i++)
  233. {
  234. var stencilSet = stencilSets[i];
  235. var nodes = stencilSet.nodes();
  236. for (var j = 0; j < nodes.length; j++)
  237. {
  238. if (nodes[j].idWithoutNs() === stencilId)
  239. {
  240. stencil = nodes[j];
  241. break;
  242. }
  243. }
  244. }
  245. if (!stencil) return;
  246. // Create and execute command (for undo/redo)
  247. var command = new MorphTo($scope.currentSelectedShape, stencil, $scope.editor);
  248. $scope.editor.executeCommands([command]);
  249. }
  250. $scope.close();
  251. };
  252. $scope.cancel = function() {
  253. $scope.$hide();
  254. };
  255. // Close button handler
  256. $scope.close = function() {
  257. $scope.$hide();
  258. };
  259. }];