compile_utils.js 13 KB

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