compile_utils.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. * Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. * See COPYING.lesser and README.md in the root of this project for full details
  4. */
  5. ///////////////////////////////////////////////////////////////////////////////
  6. // DEPRECATED FUNCTIONS
  7. ///////////////////////////////////////////////////////////////////////////////
  8. function _compileToASMM(fname){
  9. AtomPMClient.alertDeprecatedFunctionCall("_compileToASMM");
  10. CompileUtils.compileToASMM(fname);
  11. }
  12. function _compileToCSMM(fname){
  13. AtomPMClient.alertDeprecatedFunctionCall("_compileToCSMM");
  14. CompileUtils.compileToCSMM(fname);
  15. }
  16. function _compileToPatternMM(fname){
  17. AtomPMClient.alertDeprecatedFunctionCall("_compileToPatternMM");
  18. CompileUtils.compileToPatternMM(fname);
  19. }
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // DEPRECATED FUNCTIONS
  22. ///////////////////////////////////////////////////////////////////////////////
  23. /* draw the icon specified by the given icon model on the provided canvas
  24. 0. initialize a group that will contain the 'compiled' icon
  25. 1. for every ConcreteSyntax primitive (e.g., Rectangle, Text) contained
  26. within the given icon model
  27. a. create appropriate Raphael-SVG objects
  28. b. style these and position/orient/scale them
  29. c. initialize various attributes and remember various values that are used
  30. to manipulate and reason about vobjects later on
  31. d. apply layout constraint solver and/or link decorator positioner
  32. transformations... to remain backward-compatible with existing
  33. pre-lcs/ldp models, default values are provided if needed
  34. e. add objects to group from step 0.
  35. 2. apply options:
  36. size: force the icon to have a certain size
  37. wrap: wrap the canvas around the icon
  38. id: this icon is a canvas icon (not a toolbar icon)... save it
  39. and its vobjects in __icons and give it some default
  40. parameters
  41. attrs: add extra attributes to icon
  42. behaviour: indicates that the icon should have event listeners
  43. NOTE:: because text's origin defaults to (0,height/2), we move text elements
  44. by (0,height/2) (via __valignText()) to ensure their top-left corner
  45. lands on the specified (x,y)... for the computed height to be correct,
  46. we must style the text element beforehand
  47. NOTE:: because (x,y) are not parameters of Raphael.Paths, we translate paths
  48. according to vobj['position'] manually
  49. NOTE:: when im.nodes is empty (this may occur when a Link defines no
  50. decorators), a Raphael.point is used to ensure the icon is not empty
  51. NOTE:: text is made non-selectable to avoid default browser mouse dragging
  52. behaviour (select any encoutered text) and subsequent default browser
  53. selected text dragging behaviour
  54. NOTE:: throught this function, we use *.initial and *.latest values... the
  55. former are attributes of vobjects as they were drawn by the user...
  56. the latter are added translations/rotations/scalings applied by the
  57. layout constraint solver and link decorator positioner */
  58. CompileUtils = function(){
  59. /* draw the edge specified by the given segments
  60. 1. draw the edge given the specified segments and style
  61. 2. encapsulate it within a group, remember the uris of the start and end
  62. icons, and save the edge and segments in __edges
  63. 3. give the edge appropriate event handlers and return it
  64. NOTE:: we use insertBefore() to ensure that edges get drawn beneath link
  65. decorators, if any */
  66. /**
  67. * Draws the edge specified by the given segments
  68. *
  69. * 1. Draws the edge given the specified segments and style
  70. * 2. Encapsulates it within a group and remembers the URIs of the start and
  71. * end icons, then saves the edge and segments in the AtomPMClient edges
  72. * variable
  73. * 3. Assigns the appropriate event handles to the edge and then returns
  74. */
  75. this.compileAndDrawEdge = function(segments, linkStyle, start, end, linkuri){
  76. var path = __canvas.path(segments),
  77. edge = __canvas.group(),
  78. edgeId = start+'--'+end;
  79. edge.insertBefore(__getIcon(linkuri).node);
  80. path.attr(linkStyle);
  81. edge.push(path);
  82. edge.setAttr('__edgeId',edgeId);
  83. edge.setAttr('__linkuri',linkuri);
  84. edge.setAttr('class','clickable');
  85. __edges[edgeId] =
  86. {'icon':edge,
  87. 'start':start,
  88. 'end':end,
  89. 'segments':segments};
  90. edge.node.onmousedown =
  91. function(event)
  92. {
  93. if( event.button == 0 )
  94. BehaviorManager.handleUserEvent(__EVENT_LEFT_PRESS_ICON,event);
  95. else if( event.button == 2 )
  96. BehaviorManager.handleUserEvent(__EVENT_RIGHT_PRESS_ICON,event);
  97. };
  98. edge.node.onmouseup =
  99. function(event)
  100. {
  101. if( event.button == 0 )
  102. BehaviorManager.handleUserEvent(__EVENT_LEFT_RELEASE_ICON,event);
  103. else if( event.button == 2 )
  104. BehaviorManager.handleUserEvent(__EVENT_RIGHT_RELEASE_ICON,event);
  105. else if( event.button == 1 )
  106. BehaviorManager.handleUserEvent(__EVENT_MIDDLE_RELEASE_ICON,event);
  107. };
  108. /*edge.node.onmouseover =
  109. function(event)
  110. {
  111. BehaviorManager.handleUserEvent(__EVENT_MOUSE_OVER_ICON,event);
  112. }*/
  113. return edge;
  114. };
  115. // TODO: split this function up
  116. /**
  117. * Compiles the icon and returns it in order to be placed
  118. * on the canvas
  119. */
  120. this.compileAndDrawIconModel = function( im, canvas, options ){
  121. var icon = canvas.group(),
  122. vobjects = {};
  123. for( var vid in im.nodes )
  124. {
  125. var vobj = im.nodes[vid],
  126. x = __getVobjGeomAttrVal(vobj['position']['value'][0]),
  127. y = __getVobjGeomAttrVal(vobj['position']['value'][1]);
  128. if( vobj['$type'].match(/\/Text$/) )
  129. {
  130. var tc = vobj['textContent']['value'];
  131. vobjects[vid] = canvas.text(x.initial,y.initial,tc);
  132. vobjects[vid].attr('text-anchor','start');
  133. vobjects[vid].attr(vobj['style']['value']);
  134. __valignText(vobjects[vid]);
  135. vobjects[vid].node.setAttribute('class','unselectable');
  136. }
  137. else if( vobj['$type'].match(/\/Rectangle$/) )
  138. {
  139. var w = parseFloat(vobj['width']['value']),
  140. h = parseFloat(vobj['height']['value']),
  141. cr = parseFloat(vobj['cornerRadius']['value']);
  142. vobjects[vid] = canvas.rect(x.initial,y.initial,w,h,cr);
  143. }
  144. else if( vobj['$type'].match(/\/Circle$/) )
  145. {
  146. var r = parseFloat(vobj['r']['value']);
  147. vobjects[vid] = canvas.circle(x.initial+r,y.initial+r,r);
  148. }
  149. else if( vobj['$type'].match(/\/Ellipse$/) )
  150. {
  151. var rx = parseFloat(vobj['rx']['value']),
  152. ry = parseFloat(vobj['ry']['value']);
  153. vobjects[vid] = canvas.ellipse(x.initial+rx,y.initial+ry,rx,ry);
  154. }
  155. else if( vobj['$type'].match(/\/Polygon$/) )
  156. {
  157. var r = parseFloat(vobj['r']['value']),
  158. sides = parseInt(vobj['sides']['value']);
  159. vobjects[vid] = __drawPolygon(canvas,x.initial,y.initial,r,sides);
  160. }
  161. else if( vobj['$type'].match(/\/Star$/) )
  162. {
  163. var r = parseFloat(vobj['r']['value']),
  164. rays = parseInt(vobj['rays']['value']);
  165. vobjects[vid] = __drawStar(canvas,x.initial,y.initial,r,rays);
  166. }
  167. else if( vobj['$type'].match(/\/Path$/) )
  168. {
  169. var segments = vobj['segments']['value'];
  170. vobjects[vid] = canvas.path(segments);
  171. __translatePath(vobjects[vid],x.initial,y.initial);
  172. }
  173. else if( vobj['$type'].match(/\/Image$/) )
  174. {
  175. var w = parseFloat(vobj['width']['value']),
  176. h = parseFloat(vobj['height']['value']),
  177. src = __relativizeURL(vobj['src']['value']);
  178. vobjects[vid] = canvas.image(src,x.initial,y.initial,w,h);
  179. }
  180. else
  181. /* ignore layout constraints */
  182. continue;
  183. var r = __getVobjGeomAttrVal(vobj['orientation']['value']),
  184. sx = __getVobjGeomAttrVal(vobj['scale']['value'][0]);
  185. sy = __getVobjGeomAttrVal(vobj['scale']['value'][1]);
  186. vobjects[vid].attr(vobj['style']['value']);
  187. vobjects[vid].transform(
  188. 'r'+r.initial+','+x.initial+','+y.initial+
  189. 's'+sx.initial+','+sy.initial+','+x.initial+','+y.initial);
  190. vobjects[vid].node.setAttribute('__vobjuri',vid);
  191. vobjects[vid].node.setAttribute('__x',
  192. utils.buildVobjGeomAttrVal(x.initial, x.latest || 0));
  193. vobjects[vid].node.setAttribute('__y',
  194. utils.buildVobjGeomAttrVal(y.initial, y.latest || 0));
  195. vobjects[vid].node.setAttribute('__r',
  196. utils.buildVobjGeomAttrVal(r.initial, r.latest || 0));
  197. vobjects[vid].node.setAttribute('__sx',
  198. utils.buildVobjGeomAttrVal(sx.initial, sx.latest || 1));
  199. vobjects[vid].node.setAttribute('__sy',
  200. utils.buildVobjGeomAttrVal(sy.initial, sy.latest || 1));
  201. __setVobjectTransform(vobjects[vid]);
  202. icon.push(vobjects[vid]);
  203. }
  204. if( utils.keys(im.nodes).length == 0 )
  205. {
  206. icon.push( __canvas.point(0,0) );
  207. icon.setAttr('class','empty_icon');
  208. }
  209. if( options != undefined )
  210. {
  211. if( 'size' in options )
  212. {
  213. var size = options['size'],
  214. bbox = icon.getBBox();
  215. scaleBy = Math.min(size/bbox.width,size/bbox.height);
  216. icon.scale( scaleBy, scaleBy );
  217. }
  218. if( 'wrap' in options )
  219. {
  220. var bbox = icon.getBBox(),
  221. size = Math.max(bbox.width, bbox.height);
  222. icon.translate( -bbox.x, -bbox.y );
  223. bbox = icon.getBBox();
  224. if( bbox.width > bbox.height )
  225. icon.translate( 0, (size/2 - bbox.height/2) );
  226. else
  227. icon.translate( (size/2 - bbox.width/2), 0 );
  228. icon.translate( 1, 1 );
  229. canvas.setSize( size+2, size+2);
  230. }
  231. if( 'id' in options )
  232. {
  233. var id = options['id'];
  234. __icons[id] =
  235. {'icon':icon,
  236. 'vobjects':vobjects,
  237. 'edgesIn':[],
  238. 'edgesOut':[]};
  239. icon.setAttr('__csuri',id);
  240. icon.setAttr('__x',0);
  241. icon.setAttr('__y',0);
  242. icon.setAttr('__r',0);
  243. icon.setAttr('__sx',1);
  244. icon.setAttr('__sy',1);
  245. icon.setAttr('id', id);
  246. }
  247. if( 'attrs' in options )
  248. {
  249. var attrs = options['attrs'];
  250. for( var attr in attrs )
  251. icon.setAttr(attr,attrs[attr]);
  252. }
  253. if( 'behaviours' in options )
  254. {
  255. icon.setAttr('class','clickable');
  256. icon.node.onmousedown =
  257. function(event)
  258. {
  259. if( event.button == 0 )
  260. BehaviorManager.handleUserEvent(__EVENT_LEFT_PRESS_ICON,event);
  261. else if( event.button == 2 )
  262. BehaviorManager.handleUserEvent(__EVENT_RIGHT_PRESS_ICON,event);
  263. };
  264. icon.node.onmouseup =
  265. function(event)
  266. {
  267. if( event.button == 0 )
  268. {
  269. if( event.shiftKey )
  270. BehaviorManager.handleUserEvent(__EVENT_SHIFT_LEFT_RELEASE_ICON,event);
  271. else
  272. BehaviorManager.handleUserEvent(__EVENT_LEFT_RELEASE_ICON,event);
  273. }
  274. else if( event.button == 2 )
  275. BehaviorManager.handleUserEvent(__EVENT_RIGHT_RELEASE_ICON,event);
  276. else if( event.button == 1 )
  277. {
  278. if( event.shiftKey )
  279. BehaviorManager.handleUserEvent(__EVENT_SHIFT_MIDDLE_RELEASE_ICON,event);
  280. else
  281. BehaviorManager.handleUserEvent(__EVENT_MIDDLE_RELEASE_ICON,event);
  282. }
  283. };
  284. let shiftWheelFunction =
  285. function(event)
  286. {
  287. if( event.shiftKey )
  288. {
  289. BehaviorManager.handleUserEvent(__EVENT_SHIFT_WHEEL_ICON,event);
  290. return false;
  291. }
  292. };
  293. icon.node.onmousewheel = shiftWheelFunction;
  294. icon.node.onwheel = shiftWheelFunction;
  295. /*icon.node.onmouseover =
  296. function(event)
  297. {
  298. BehaviorManager.handleUserEvent(__EVENT_MOUSE_OVER_ICON,event);
  299. };
  300. icon.node.onmouseout =
  301. function(event)
  302. {
  303. BehaviorManager.handleUserEvent(__EVENT_MOUSE_OUT_ICON,event);
  304. };*/
  305. }
  306. }
  307. return icon;
  308. };
  309. /**
  310. * Compile the current model to an Abstract Syntax Metamodel
  311. */
  312. this.compileToASMM = function (fname) {
  313. if (!__isAbstractSyntaxMetamodel(fname))
  314. WindowManagement.openDialog(
  315. _ERROR,
  316. 'invalid extension... abstract syntax metamodels are "*.metamodel" files');
  317. else
  318. HttpUtils.httpReq('PUT', HttpUtils.url(fname, __FORCE_GET), null,
  319. function (status, text) {
  320. //there was a problem
  321. if (!utils.isHttpSuccessCode(status)) {
  322. //let resp = JSON.parse(text);
  323. WindowManagement.openDialog(_ERROR, JSON.stringify(text));
  324. }
  325. });
  326. };
  327. /**
  328. * Compile the current model to a Concrete Syntax Metamodel
  329. */
  330. this.compileToCSMM = function (fname) {
  331. if (!__isIconMetamodel(fname))
  332. WindowManagement.openDialog(
  333. _ERROR,
  334. 'invalid extension... icon definition metamodels are "*Icons.metamodel" files');
  335. else
  336. HttpUtils.httpReq('PUT', HttpUtils.url(fname, __FORCE_GET), null,
  337. function (status, text) {
  338. //there was a problem
  339. if (!utils.isHttpSuccessCode(status)) {
  340. let resp = text;
  341. if (!(resp.startsWith("500"))) {
  342. resp = JSON.parse(text);
  343. }
  344. if (resp["code"] && resp["code"].includes("ENOENT")) {
  345. let msg = "ERROR: Corresponding metamodel could not be found in same directory!";
  346. WindowManagement.openDialog(_ERROR, msg);
  347. } else {
  348. WindowManagement.openDialog(_ERROR, JSON.stringify(text));
  349. }
  350. }
  351. });
  352. };
  353. /**
  354. * Compiles the current model to an Icon Pattern Metamodel
  355. */
  356. this.compileToPatternMM = function(fname){
  357. if( ! __isAbstractSyntaxMetamodel(fname) )
  358. WindowManagement.openDialog(
  359. _ERROR,
  360. 'invalid extension... abstract syntax metamodels are "*.metamodel" files');
  361. else
  362. {
  363. var patternmm = fname.substring(0,fname.length-'metamodel'.length)+'pattern.metamodel';
  364. HttpUtils.httpReq('PUT', HttpUtils.url(patternmm,__FORCE_GET));
  365. }
  366. };
  367. return this;
  368. }();