query_response.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. var __nextASWSequenceNumber = '/asworker#1',
  2. __nextCSWSequenceNumber = '/csworker#1',
  3. __pendingASWChangelogs = [],
  4. __pendingCSWChangelogs = [];
  5. /* delete pending changelogs older than the specified sequence number */
  6. function __clearObsoleteChangelogs(pendingChangelogs,sn)
  7. {
  8. pendingChangelogs =
  9. pendingChangelogs.filter(
  10. function(c)
  11. {
  12. return utils.sn2int(pc['sequence#']) > utils.sn2int(sn);
  13. });
  14. }
  15. /* set the value of __nextASWSequenceNumber to the given sequence number */
  16. function __forceNextASWSequenceNumber(sn)
  17. {
  18. __nextASWSequenceNumber = sn;
  19. __clearObsoleteChangelogs(__pendingASWChangelogs,sn)
  20. }
  21. /* set the value of __nextCSWSequenceNumber to the given sequence number */
  22. function __forceNextCSWSequenceNumber(sn)
  23. {
  24. __nextCSWSequenceNumber = sn;
  25. __clearObsoleteChangelogs(__pendingCSWChangelogs,sn)
  26. }
  27. //Todo: Shred this into smaller functions
  28. /* apply a changelog (or postpone its application)
  29. 0. check the changelog's sequence number to know if we should handle it
  30. now or later... note that we will be receiving changelogs with both
  31. asworker and csworker sequence numbers
  32. 1. iterate through and handle the changelog's steps
  33. 2. apply next pending changelog, if any and if applicable */
  34. function __handleChangelog(changelog,seqNum,hitchhiker)
  35. {
  36. console.debug(' ++ ('+seqNum+') ',changelog);
  37. var isCSWChangelog = seqNum.match(/csworker/)
  38. nextSeqNum =
  39. (isCSWChangelog ? __nextCSWSequenceNumber : __nextASWSequenceNumber),
  40. pendingChangelogs =
  41. (isCSWChangelog ? __pendingCSWChangelogs : __pendingASWChangelogs);
  42. if( utils.sn2int(seqNum) > utils.sn2int(nextSeqNum) )
  43. {
  44. pendingChangelogs.push(
  45. {'changelog':changelog,
  46. 'sequence#':seqNum,
  47. 'hitchhiker':hitchhiker});
  48. pendingChangelogs.sort(
  49. function(a,b)
  50. {
  51. return utils.sn2int(a['sequence#']) - utils.sn2int(b['sequence#']);
  52. });
  53. return;
  54. }
  55. else if( utils.sn2int(seqNum) < utils.sn2int(nextSeqNum) )
  56. {
  57. WindowManagement.openDialog(
  58. __FATAL_ERROR,
  59. 'invalid changelog sequence# :: '+utils.sn2int(seqNum));
  60. return;
  61. }
  62. WindowManagement.setWindowTitle(true);
  63. changelog.forEach(
  64. function(step)
  65. {
  66. if( (step['op'] == 'RMNODE' ||
  67. step['op'] == 'RMEDGE' ||
  68. step['op'] == 'CHATTR') &&
  69. __watching(step['id']) )
  70. {
  71. console.warn(
  72. 'someone has altered the node you are currently editing...'+
  73. 'to keep your changes, click OK... to discard them and see'+
  74. ' what has changed, click CANCEL');
  75. __changed(step['id'],true);
  76. }
  77. if( step['op'] == 'MKEDGE' )
  78. ;
  79. /* react to the removal of an edge */
  80. else if( step['op'] == 'RMEDGE' )
  81. {
  82. __removeEdge(
  83. step['id1']+'--'+step['id2'],
  84. [step['id1'],step['id2']]);
  85. if( __selection != undefined )
  86. __select( utils.filter(__selection['items'],[edgeId]) );
  87. }
  88. /* react to the creation of a node */
  89. else if( step['op'] == 'MKNODE' )
  90. {
  91. var node = utils.jsonp(step['node']),
  92. icon = __createIcon(node,step['id']);
  93. if( '$segments' in node )
  94. {
  95. var linkStyle = node['link-style']['value'],
  96. segments = node['$segments']['value'];
  97. icon.setAttr('__segments',utils.jsons(segments));
  98. for( var edgeId in segments )
  99. __createEdge(segments[edgeId], linkStyle, edgeId, step['id']);
  100. }
  101. }
  102. /* react to the removal of a node */
  103. else if( step['op'] == 'RMNODE' )
  104. {
  105. __icons[step['id']]['icon'].remove();
  106. __icons[step['id']]['edgesOut'].forEach(__removeEdge);
  107. __icons[step['id']]['edgesIn'].forEach(__removeEdge);
  108. delete __icons[step['id']];
  109. if( __selection != undefined )
  110. __select( utils.filter(__selection['items'],[step['id']]) );
  111. }
  112. /* react to attribute update
  113. CASE 1 : Icon/Link layout attribute (position, etc.)
  114. update the corresponding attribute of the corresponding icon
  115. in __icons + actually effect the layout transformation (via
  116. __setIconTransform())
  117. CASE 2 : Link attribute ($segments / link-style)
  118. redraw existing edges and create any new ones
  119. CASE 3 : VisualObject attribute update
  120. update the corresponding attribute of the corresponding icon's
  121. corresponding vobject */
  122. else if( step['op'] == 'CHATTR' )
  123. {
  124. /* CASE 1 */
  125. if(utils.contains(['position','orientation','scale'],step['attr']))
  126. {
  127. var newVal = step['new_val'],
  128. icon = __icons[step['id']]['icon'];
  129. /* bugfix where newVal would get a string instead of the array of values
  130. should search for reason why it has string in the first place - Vasco - 02-02-2017*/
  131. if( typeof newVal == 'string'){
  132. newVal = newVal.replace('[','');
  133. newVal = newVal.replace(']','');
  134. newVal = newVal.split(',');
  135. }
  136. /* endbugfix*/
  137. if( step['attr'] == 'position' )
  138. {
  139. var bbox = icon.getBBox();
  140. icon.setAttr('__x', __getAbsoluteCoordinate(newVal[0],bbox.width) );
  141. icon.setAttr('__y', __getAbsoluteCoordinate(newVal[1],bbox.height) );
  142. }
  143. else if( step['attr'] == 'orientation' )
  144. icon.setAttr('__r',newVal);
  145. else if( step['attr'] == 'scale' )
  146. {
  147. icon.setAttr('__sx',newVal[0]);
  148. icon.setAttr('__sy',newVal[1]);
  149. }
  150. __setIconTransform(step['id']);
  151. }
  152. /* CASE 2 */
  153. else if(utils.contains(['$segments','link-style','arrowTail','arrowHead'],step['attr']))
  154. {
  155. var icon = __icons[step['id']]['icon'],
  156. segments,
  157. linkStyle;
  158. if( step['attr'] == '$segments' )
  159. {
  160. segments = step['new_val'];
  161. linkStyle = utils.jsonp(icon.getAttr('__linkStyle'));
  162. icon.setAttr('__segments',utils.jsons(segments));
  163. }
  164. else if (step['attr'] == 'link-style')
  165. {
  166. segments = utils.jsonp(icon.getAttr('__segments'));
  167. linkStyle = step['new_val'];
  168. icon.setAttr('__linkStyle',utils.jsons(linkStyle));
  169. }
  170. else
  171. {
  172. segments = utils.jsonp(icon.getAttr('__segments'));
  173. linkStyle = utils.jsonp(icon.getAttr('__linkStyle'));
  174. }
  175. for( var edgeId in segments )
  176. if( edgeId in __edges )
  177. __redrawEdge(edgeId,segments[edgeId],linkStyle);
  178. else
  179. /* react to the creation of an edge */
  180. __createEdge(
  181. segments[edgeId], linkStyle, edgeId, step['id']);
  182. }
  183. /* CASE 3
  184. NOTE:: certain VisualObject parameters need some special care...
  185. a) position, orientation, scale: these can only be changed by
  186. the csworker layout constraint solver and link decorator
  187. positioner... after each change, the transformation applied
  188. to the vobject is overwritten
  189. b) r/rx/ry: changing these causes relevant shapes to grow
  190. around their center thereby changing their top-left corner
  191. ... we translate the said shapes to compensate
  192. c) Polygons/Stars: see __editPolygon/Star(..)
  193. d) style: pass {...,attr:val,...} hash directly to attr(..)
  194. e) src: make sure URL is valid / make it valid
  195. f) Text VisualObject: see __valignText(..) */
  196. else
  197. {
  198. var matches = step['attr'].match(/.*\/(.*)\/(.*)/),
  199. vid = matches[1],
  200. vobj = __icons[step['id']]['vobjects'][vid],
  201. attr = matches[2];
  202. if(utils.contains(['position','scale','orientation'],attr))
  203. {
  204. var newVal = (utils.isArray(step['new_val']) ?
  205. [__getVobjGeomAttrVal(step['new_val'][0]).latest,
  206. __getVobjGeomAttrVal(step['new_val'][1]).latest] :
  207. parseFloat(
  208. __getVobjGeomAttrVal(step['new_val']).latest) );
  209. if( attr == 'position' )
  210. {
  211. vobj.node.setAttribute('__x',
  212. utils.buildVobjGeomAttrVal(
  213. vobj.node.getAttribute('__x'), newVal[0]) );
  214. vobj.node.setAttribute('__y',
  215. utils.buildVobjGeomAttrVal(
  216. vobj.node.getAttribute('__y'), newVal[1]) );
  217. }
  218. else if( attr == 'scale' )
  219. {
  220. var sx = vobj.node.getAttribute('__sx'),
  221. sy = vobj.node.getAttribute('__sy');
  222. vobj.node.setAttribute('__sx',
  223. utils.buildVobjGeomAttrVal(
  224. sx, newVal[0]*__getVobjGeomAttrVal(sx).initial) );
  225. vobj.node.setAttribute('__sy',
  226. utils.buildVobjGeomAttrVal(
  227. sy, newVal[1]*__getVobjGeomAttrVal(sy).initial) );
  228. }
  229. else
  230. {
  231. var r = vobj.node.getAttribute('__r');
  232. vobj.node.setAttribute('__r',
  233. utils.buildVobjGeomAttrVal(
  234. r, newVal+__getVobjGeomAttrVal(r).initial) );
  235. }
  236. __setVobjectTransform(vobj);
  237. }
  238. if(utils.contains(['r','rx','ry'],attr))
  239. {
  240. var oldVal = vobj.attr(attr) || vobj.node.getAttribute('__'+attr);
  241. offset = step['new_val'] - oldVal;
  242. vobj.translate(
  243. utils.contains(['r','rx'],attr) ? offset : 0,
  244. utils.contains(['r','ry'],attr) ? offset : 0);
  245. }
  246. if( step['id'].match(/\/PolygonIcon\//) &&
  247. utils.contains(['r','sides'],attr) )
  248. __editPolygon(vobj,attr,step['new_val']);
  249. else if( step['id'].match(/\/StarIcon\//) &&
  250. utils.contains(['r','rays'],attr) )
  251. __editStar(vobj,attr,step['new_val']);
  252. try {var newVal = utils.jsonp(step['new_val']);}
  253. catch(err) {var newVal = step['new_val'];}
  254. if( attr == 'style' )
  255. vobj.attr( newVal );
  256. else if( attr == 'src' )
  257. vobj.attr( 'src', __relativizeURL(newVal) );
  258. else
  259. vobj.attr( __ATTR_MAP[attr] || attr, newVal );
  260. if( vobj.type == 'text' )
  261. __valignText(vobj);
  262. }
  263. if( __isSelected(step['id']) )
  264. utils.doAfterUnlessRepeated(
  265. function(selection) {
  266. __select(selection);
  267. }, [__selection['items']], 5
  268. )
  269. }
  270. /* react to loading of an IconDefinition (CS metamodel)
  271. 1. setup and show appropriate toolbar
  272. 2. replace default toolbar button icons by icons described in
  273. the loaded metamodel */
  274. else if( step['op'] == 'LOADMM' )
  275. {
  276. var data = eval('('+step['mm']+')');
  277. GUIUtils.setupAndShowToolbar(
  278. step['name']+'.metamodel',
  279. data,
  280. __METAMODEL_TOOLBAR);
  281. for( var t in data.types )
  282. {
  283. if( t.match(/(.*)Link$/) )
  284. continue;
  285. else if( ! GUIUtils.$$(step['name']+'.metamodel/'+t) )
  286. {
  287. if( !t.match(/(.*)Icon$/) )
  288. console.error('Icon typenames must be "<AbstractType>Icon", the following does not conform :: '+t);
  289. else
  290. console.error('found icon definition for unknwon abstract type :: '+t);
  291. continue;
  292. }
  293. var im =
  294. data.types[t].filter(
  295. function(attr)
  296. {
  297. return attr['name'] == '$contents';
  298. })[0]['default'];
  299. CompileUtils.compileAndDrawIconModel(
  300. im,
  301. Raphael(GUIUtils.$$(step['name']+'.metamodel/'+t)),
  302. {'size':__ICON_SIZE,
  303. 'wrap':true});
  304. GUIUtils.$$(step['name']+'.metamodel/'+t).removeChild(
  305. GUIUtils.$$(step['name']+'.metamodel/'+t).lastChild );
  306. }
  307. }
  308. else if( step['op'] == 'LOADASMM' )
  309. __loadedToolbars[step['name']+'.metamodel'] =
  310. eval('('+step['mm']+')');
  311. else if( step['op'] == 'DUMPMM' )
  312. {
  313. var csmmPath = step['name']+'.metamodel';
  314. GUIUtils.removeToolbar(csmmPath);
  315. }
  316. else if( step['op'] == 'RESETM' )
  317. {
  318. var m = utils.jsonp(step['new_model']);
  319. GUIUtils.resetCanvas();
  320. for( var id in m.nodes )
  321. {
  322. var node = m.nodes[id],
  323. icon = __createIcon(node,id);
  324. if( '$segments' in node )
  325. {
  326. var linkStyle = node['link-style']['value'],
  327. segments = node['$segments']['value'];
  328. icon.setAttr('__segments',utils.jsons(segments));
  329. for( var edgeId in segments )
  330. __createEdge( segments[edgeId], linkStyle, edgeId, id);
  331. }
  332. }
  333. WindowManagement.setWindowTitle(false);
  334. }
  335. else if( step['op'] == 'SYSOUT' )
  336. {
  337. if( step['text'].match(/^ERROR :: /) )
  338. console.error(step['text']);
  339. else if( step['text'].match(/^WARNING :: /) )
  340. console.warn(step['text']);
  341. else if( step['text'].match(/^CLIENT_BDAPI :: /) )
  342. {
  343. var op = utils.jsonp(step['text'].match(/^CLIENT_BDAPI :: (.*)/)[1]);
  344. this[op['func']](op['args']);
  345. }
  346. else
  347. console.log('MESSAGE :: '+step['text']);
  348. }
  349. ///////
  350. else if (step['op'] == 'CHAT')
  351. {
  352. Collaboration.updateChat(step['text']);
  353. }
  354. });
  355. if( isCSWChangelog )
  356. nextSeqNum = __nextCSWSequenceNumber =
  357. utils.incrementSequenceNumber(nextSeqNum);
  358. else
  359. nextSeqNum = __nextASWSequenceNumber =
  360. utils.incrementSequenceNumber(nextSeqNum);
  361. if( pendingChangelogs.length > 0 &&
  362. nextSeqNum == pendingChangelogs[0]['sequence#'] )
  363. {
  364. var pc = pendingChangelogs.shift();
  365. __handleChangelog(
  366. pc['changelog'],
  367. pc['sequence#'],
  368. pc['hitchhiker']);
  369. }
  370. }