$Statement.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. MWF.xApplication.ScriptEditor.statement = MWF.xApplication.ScriptEditor.statement || {};
  2. MWF.xApplication.ScriptEditor.statement.$Statement = new Class({
  3. Extends: MWF.widget.Common,
  4. Implements: [Options, Events],
  5. options: {
  6. "style": "default"
  7. },
  8. _loadPath: function(){
  9. this.path = "/x_component_ScriptEditor/statement/$Statement/";
  10. this.cssPath = "/x_component_ScriptEditor/statement/$Statement/"+this.options.style+"/css.wcss";
  11. },
  12. initialize: function(node, block, area, options){
  13. this.setOptions(options);
  14. this._loadPath();
  15. this._loadCss();
  16. this.node = node;
  17. this.area = area;
  18. this.block = block;
  19. this.editor = this.area.editor;
  20. this.areaNode = this.area.blockArea;
  21. this.subStatements = [];
  22. this.links = [];
  23. this.mortises = [];
  24. this.inputs = [];
  25. this.selectors = [];
  26. this.mortises = [];
  27. this.init();
  28. },
  29. init: function(){
  30. this.statementType = "operation";
  31. this.parseNodes();
  32. },
  33. reBuild: function(){
  34. if (this.area.currentLink){
  35. this.linkTo(this.area.currentLink);
  36. this.setPosition(this.area.currentLink);
  37. }else{
  38. if (this.topLink){
  39. this.setPosition({
  40. "link": this.topLink,
  41. "toLink": this.topLink.toLink
  42. });
  43. }
  44. }
  45. },
  46. buildStatement: function(){},
  47. load :function(){
  48. this.buildStatement();
  49. if (!this.checkAvailable()) return false;
  50. this.node.setStyles(this.css.node);
  51. if (this.area.currentLink) this.linkTo(this.area.currentLink);
  52. if (this.area.currentLink) this.setPosition(this.area.currentLink);
  53. this.reportLinks();
  54. var drag = new Drag(this.node, {
  55. "snap": "1",
  56. "stopPropagation": true,
  57. "onStart": function(dragging, e){
  58. this.readyDrag();
  59. this.setDrag(e);
  60. }.bind(this)
  61. });
  62. // this.node.addEvent("mousedown", function(e){
  63. // this.readyDrag();
  64. // this.setDrag(e);
  65. // e.stopPropagation();
  66. // }.bind(this));
  67. this.area.currentLink = null;
  68. this.area.setAreaSize();
  69. },
  70. checkAvailable: function(){
  71. if (this.topLink){
  72. if (!this.area.currentLink){
  73. this.destroy();
  74. return false;
  75. }
  76. }else{
  77. this.area.beginStatements.push(this);
  78. }
  79. return true;
  80. },
  81. setDrag: function(e){
  82. this.drag = new Drag.Move(this.node, {
  83. "stopPropagation": true,
  84. "droppables": [this.areaNode],
  85. "onStart": function(dragging){
  86. this.dragStart(dragging);
  87. }.bind(this),
  88. "onEnter": function(dragging, inObj){
  89. }.bind(this),
  90. "onLeave": function(dragging, inObj){
  91. }.bind(this),
  92. "onDrag": function(e){
  93. var links = this.getConnectedLinks();
  94. this.area.checkBlockDrag(this.node, this, links);
  95. }.bind(this),
  96. "onDrop": function(dragging, inObj){
  97. }.bind(this),
  98. "onComplete": function(e, event){
  99. this.dragComplete(event, this.node, this.drag);
  100. if (this.area) this.area.setAreaSize();
  101. }.bind(this),
  102. "onCancel": function(dragging){
  103. this.area.currentLink = null;
  104. this.area.currentMortise = null;
  105. this.reBuild();
  106. }.bind(this)
  107. });
  108. this.drag.start(e);
  109. e.stopPropagation();
  110. },
  111. readyDrag: function(){
  112. //var p = this.node.getPosition(this.node.getOffsetParent());
  113. var p = this.node.getPosition(this.areaNode);
  114. this.node.inject(this.areaNode);
  115. this.node.setStyles({
  116. "z-index": MWF.SES.zIndexPool.apply(),
  117. "position": "absolute",
  118. "left": ""+p.x+"px",
  119. "top": ""+p.y+"px"
  120. });
  121. },
  122. getConnectedLinks: function(){
  123. var links = this.links;
  124. if (this.centerLink){
  125. if (this.centerLink.toLink){
  126. links = links.concat(this.centerLink.toLink.statement.getConnectedLinks());
  127. }
  128. }
  129. if (this.bottomLink){
  130. if (this.bottomLink.toLink){
  131. links = links.concat(this.bottomLink.toLink.statement.getConnectedLinks());
  132. }
  133. }
  134. return links;
  135. },
  136. dragStart: function(dragNode){
  137. //this.readyDrag();
  138. //dragNode.setStyle("z-index", MWF.SES.zIndexPool.apply());
  139. //this.node.setStyles({"position": "absolute"});
  140. },
  141. dragComplete: function(event, dragNode, nodeDrag){
  142. var statement = dragNode.retrieve("statement");
  143. if (!this.editor.moduleAreaNode.isOutside(event)){
  144. this.destroy();
  145. }else{
  146. var p0 = dragNode.getPosition(dragNode.getOffsetParent());
  147. var p1 = this.areaNode.getPosition(this.node.getOffsetParent());
  148. if (p0.x-p1.x<10){
  149. var x = 0+p1.x+10;
  150. dragNode.setStyle("left", ""+x+"px");
  151. }
  152. if (p0.y-p1.y<10){
  153. var y = 0+p1.y+10;
  154. dragNode.setStyle("top", ""+y+"px");
  155. }
  156. this.reBuild();
  157. }
  158. },
  159. linkTo: function(link){
  160. if (link.linkType==="up-down"){
  161. link.toLink.linkDown(link.link);
  162. }
  163. if (link.linkType==="down-up"){
  164. link.toLink.linkUp(link.link);
  165. }
  166. if (link.linkType==="up-middle"){
  167. link.toLink.linkMiddle(link.link);
  168. }
  169. if (link.linkType==="middle-up"){
  170. link.toLink.linkUpAround(link.link);
  171. }
  172. },
  173. setPosition: function(link){
  174. this.node.inject(link.toLink.node, "top");
  175. if (link.link.statement.centerLink){
  176. if (link.link.statement.centerLink.toLink){
  177. link.link.statement.centerLink.toLink.statement.node.inject(link.link.statement.centerLink.node, "top");
  178. }
  179. }
  180. var bottomLink = link.link.statement.bottomLink;
  181. while (bottomLink && bottomLink.toLink){
  182. bottomLink.toLink.statement.node.inject(bottomLink.node, "top");
  183. bottomLink = bottomLink.toLink.statement.bottomLink;
  184. }
  185. if (link.link.statement.bottomLink){
  186. if (link.link.statement.bottomLink.toLink){
  187. link.link.statement.bottomLink.toLink.statement.node.inject(link.link.statement.bottomLink.node, "top");
  188. }
  189. }
  190. this.node.setStyles({"position": "static", "top": "auto", "left": "auto"});
  191. link.toLink.statement.notReadyLink();
  192. link.link.statement.notReadyLinkTo();
  193. },
  194. readyLink: function(link){
  195. if (link.toLink.type==="up") this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(link.toLink.node, "bottom");
  196. if (link.toLink.type==="middle") this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(link.toLink.node, "top");
  197. if (link.toLink.type==="down") this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(link.toLink.node, "top");
  198. },
  199. notReadyLink: function(link){
  200. if (this.readyLinkNode) this.readyLinkNode.destroy();
  201. },
  202. readyLinkTo: function(link){
  203. if (link.link.type==="up") this.readyLinkToNode = new Element("div", {"styles": this.css.readyLinkToNode}).inject(link.link.node, "bottom");
  204. if (link.link.type==="middle") this.readyLinkToNode = new Element("div", {"styles": this.css.readyLinkToNode}).inject(link.link.node, "top");
  205. if (link.link.type==="down") this.readyLinkToNode = new Element("div", {"styles": this.css.readyLinkToNode}).inject(link.link.node, "top");
  206. },
  207. notReadyLinkTo: function(link){
  208. if (this.readyLinkToNode) this.readyLinkToNode.destroy();
  209. },
  210. normal: function(){
  211. if (this.tableNode){
  212. this.tableNode.setStyle("height", "auto");
  213. }
  214. },
  215. destroy: function(){
  216. if (this.topLink){
  217. if (this.topLink.toLink){
  218. this.topLink.toLink.toLink = null;
  219. }
  220. }
  221. if (this.centerLink){
  222. if (this.centerLink.toLink){
  223. this.centerLink.toLink.statement.destroy();
  224. }
  225. }
  226. if (this.bottomLink){
  227. if (this.bottomLink.toLink){
  228. this.bottomLink.toLink.statement.destroy();
  229. }
  230. }
  231. this.links.each(function(link){
  232. this.area.links.erase(link);
  233. }.bind(this));
  234. this.mortises.each(function(mortise){
  235. this.area.mortises.erase(mortise);
  236. }.bind(this));
  237. this.area.statementNodes.erase(this.node);
  238. this.area.statements.erase(this);
  239. this.area.clearCurrentLink();
  240. this.node.destroy();
  241. if (this.area) this.area.setAreaSize();
  242. MWF.release(this);
  243. },
  244. setLinkStyle: function(){}
  245. });
  246. MWF.xApplication.ScriptEditor.statement.$Statement.$Operation = new Class({
  247. Extends: MWF.xApplication.ScriptEditor.statement.$Statement,
  248. parseNodes: function(){
  249. this.contentNode = this.node.getFirst();
  250. this.table = this.contentNode.getElement("table");
  251. this.createLinks();
  252. this.loadContents();
  253. },
  254. createLinks: function(){
  255. this.downLinkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_down}).inject(this.node);
  256. this.upLinkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_up}).inject(this.node, "top");
  257. this.downLink = new MWF.xApplication.ScriptEditor.statement.Link(this, "down", this.downLinkStatementNode);
  258. this.upLink = new MWF.xApplication.ScriptEditor.statement.Link(this, "up", this.upLinkStatementNode);
  259. this.links.push(this.upLink);
  260. this.links.push(this.downLink);
  261. this.topLink = this.upLink;
  262. this.bottomLink = this.downLink;
  263. },
  264. loadContents: function(){
  265. this.loadInputs();
  266. this.loadSelectors();
  267. this.loadMortises();
  268. this.loadInputMortises();
  269. },
  270. loadInputs: function(){
  271. var inputs = this.node.getElements(".MWFBlockContent_input");
  272. inputs.each(function(input){
  273. var inputNode = input.getElement("input");
  274. inputNode.set("readonly", false);
  275. inputNode.setStyle("max-width", "none");
  276. inputNode.addEvents({
  277. "mousedown": function(e){e.stopPropagation();},
  278. "keyup": function(e){
  279. var width = MWF.getTextSize(this.get("value")).x;
  280. this.setStyle("width", ""+width+"px");
  281. e.stopPropagation();
  282. }
  283. });
  284. this.inputs.push(input.getFirst());
  285. }.bind(this));
  286. },
  287. loadSelectors: function(){
  288. var selectors = this.node.getElements(".MWFBlockContent_select");
  289. selectors.each(function(selector){
  290. selector.getFirst().addEvents({"mousedown": function(e){e.stopPropagation();}.bind(this)});
  291. this.selectors.push(selector.getFirst());
  292. }.bind(this));
  293. },
  294. loadMortises: function(){
  295. var mortises = this.node.getElements(".MWFBlockContent_mortise");
  296. mortises.each(function(mortiseNode){
  297. var content = this.block.data.contents[mortiseNode.cellIndex];
  298. var mortise = new MWF.xApplication.ScriptEditor.statement.Mortise(this, mortiseNode, content.tenonTypes, mortiseNode.getFirst());
  299. this.mortises.push(mortise);
  300. this.area.mortises.push(mortise);
  301. }.bind(this));
  302. },
  303. loadInputMortises: function(){
  304. var inputMortises = this.node.getElements(".MWFBlockContent_inputMortise");
  305. inputMortises.each(function(inputMortiseNode){
  306. var inputNode = inputMortiseNode.getElement("input");
  307. inputNode.set("readonly", false);
  308. inputNode.setStyle("max-width", "none");
  309. inputNode.addEvents({
  310. "mousedown": function(e){e.stopPropagation();},
  311. "keyup": function(e){
  312. var width = MWF.getTextSize(this.get("value")).x;
  313. this.setStyle("width", ""+width+"px");
  314. e.stopPropagation();
  315. }
  316. });
  317. var content = this.block.data.contents[inputMortiseNode.cellIndex];
  318. var inputMortise = new MWF.xApplication.ScriptEditor.statement.Mortise(this, inputMortiseNode, content.tenonTypes, inputMortiseNode.getFirst());
  319. this.mortises.push(inputMortise);
  320. this.area.mortises.push(inputMortise);
  321. }.bind(this));
  322. },
  323. buildStatement: function(){},
  324. reportLinks: function(){
  325. this.area.links.include(this.downLink.rePosition());
  326. this.area.links.include(this.upLink.rePosition());
  327. }
  328. });
  329. MWF.xApplication.ScriptEditor.statement.$Statement.$Expression = new Class({
  330. Extends: MWF.xApplication.ScriptEditor.statement.$Statement.$Operation,
  331. createLinks: function(){
  332. this.tenon = this.node;
  333. },
  334. reBuild: function(){
  335. if (this.area.currentMortise){
  336. this.tenonTo(this.area.currentMortise);
  337. this.setPosition(this.area.currentMortise);
  338. }else{
  339. if (this.toMortise){
  340. this.tenonTo(this.toMortise);
  341. this.setPosition(this.toMortise);
  342. }else{
  343. this.destroy();
  344. }
  345. }
  346. },
  347. load :function(){
  348. this.buildStatement();
  349. if (!this.checkAvailable()) return false;
  350. this.node.setStyles(this.css.node);
  351. if (this.area.currentMortise){
  352. this.tenonTo(this.area.currentMortise);
  353. this.setPosition(this.area.currentMortise);
  354. }
  355. this.node.addEvent("mousedown", function(e){
  356. this.readyDrag();
  357. this.setDrag(e);
  358. e.stopPropagation();
  359. }.bind(this));
  360. this.area.currentMortise = null;
  361. },
  362. checkAvailable: function(){
  363. if (!this.area.currentMortise){
  364. this.destroy();
  365. return false;
  366. }
  367. return true;
  368. },
  369. tenonTo: function(mortise){
  370. if (this.toMortise){
  371. this.toMortise.tenonStatement = null;
  372. }
  373. mortise.tenonStatement = this;
  374. this.toMortise = mortise;
  375. },
  376. setPosition: function(mortise){
  377. mortise.unshine();
  378. mortise.tenon();
  379. },
  380. readyDrag: function(){
  381. this.toMortise.split();
  382. },
  383. });
  384. MWF.xApplication.ScriptEditor.statement.$Statement.$Enumerate = new Class({
  385. Extends: MWF.xApplication.ScriptEditor.statement.$Statement.$Operation
  386. });
  387. MWF.xApplication.ScriptEditor.statement.$Statement.$Top = new Class({
  388. Extends: MWF.xApplication.ScriptEditor.statement.$Statement.$Operation,
  389. parseNodes: function(){
  390. var divs = this.node.getElements("div");
  391. this.topNode = divs[0];
  392. this.contentNode = divs[1];
  393. this.table = this.contentNode.getElement("table");
  394. this.createLinks();
  395. this.loadContents();
  396. },
  397. createLinks: function(){
  398. this.linkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_down}).inject(this.node);
  399. this.link = new MWF.xApplication.ScriptEditor.statement.Link(this, "down", this.linkStatementNode);
  400. this.links.push(this.link);
  401. this.topLink = null;
  402. this.bottomLink = this.link;
  403. },
  404. reportLinks: function(){
  405. this.area.links.include(this.link.rePosition());
  406. },
  407. readyLink: function(link){
  408. this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(this.linkStatementNode, "top");
  409. },
  410. readyLinkTo: function(link){
  411. this.readyLinkToNode = new Element("div", {"styles": this.css.readyLinkToNode}).inject(this.linkStatementNode, "top");
  412. }
  413. });
  414. MWF.xApplication.ScriptEditor.statement.$Statement.$Around = new Class({
  415. Extends: MWF.xApplication.ScriptEditor.statement.$Statement.$Operation,
  416. parseNodes: function(){
  417. this.beginNode = this.node.getFirst();
  418. this.beginContentNode = this.beginNode.getFirst();
  419. this.table = this.beginContentNode.getElement("table");
  420. this.contentNode = this.beginContentNode;
  421. this.middleNode = this.beginNode.getNext();
  422. this.tableNode = this.middleNode.getElement("table");
  423. var tds = this.tableNode.getElements("td");
  424. this.middleLeftNode = tds[0];
  425. this.middleRightNode = tds[1];
  426. this.subContentNode = this.middleRightNode.getFirst();
  427. this.endNode = this.middleNode.getNext();
  428. this.endContentNode = this.endNode.getFirst();
  429. this.conditionNode = this.beginContentNode.getFirst().getNext();
  430. this.createLinks();
  431. this.loadContents();
  432. },
  433. createLinks: function(){
  434. this.beginUplinkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_up}).inject(this.beginNode, "before");
  435. this.middlelinkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_down}).inject(this.subContentNode);
  436. this.endDownlinkStatementNode = new Element("div", {"styles": this.css.linkStatementNode_down}).inject(this.endNode, "after");
  437. this.upLink = new MWF.xApplication.ScriptEditor.statement.Link(this, "up", this.beginUplinkStatementNode);
  438. this.middleLink = new MWF.xApplication.ScriptEditor.statement.Link(this, "middle", this.middlelinkStatementNode);
  439. this.downLink = new MWF.xApplication.ScriptEditor.statement.Link(this, "down", this.endDownlinkStatementNode);
  440. this.links.push(this.upLink);
  441. this.links.push(this.middleLink);
  442. this.links.push(this.downLink);
  443. this.topLink = this.upLink;
  444. this.centerLink = this.middleLink;
  445. this.bottomLink = this.downLink;
  446. },
  447. reportLinks: function(){
  448. this.area.links.include(this.upLink.rePosition());
  449. this.area.links.include(this.middleLink.rePosition());
  450. this.area.links.include(this.downLink.rePosition());
  451. },
  452. readyLink: function(link){
  453. if (link.linkType==="up-down" || link.linkType==="up-middle"){
  454. this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(link.toLink.node, "top");
  455. }
  456. if (link.linkType==="down-up" || link.linkType==="middle-up"){
  457. this.readyLinkNode = new Element("div", {"styles": this.css.readyLinkNode}).inject(link.toLink.node, "bottom");
  458. }
  459. },
  460. readyLinkTo: function(link){
  461. if (link.linkType==="up-down" || link.linkType==="up-middle"){
  462. this.readyLinkToNode = new Element("div", {"styles": this.css.readyLinkToNode}).inject(link.link.node, "bottom");
  463. if (link.link.statement.centerLink && !link.link.statement.centerLink.toLink){
  464. if (link.toLink.toLink){
  465. if (link.toLink.toLink.statement!==this){
  466. var height = link.toLink.toLink.statement.node.getSize().y;
  467. this.tableNode.setStyle("height", ""+height+"px");
  468. }
  469. }
  470. }
  471. }
  472. },
  473. notReadyLinkTo: function(link){
  474. if (this.readyLinkToNode) this.readyLinkToNode.destroy();
  475. if (link){
  476. if (link.link.type==="middle"){
  477. this.tableNode.setStyle("height", "auto");
  478. }
  479. }else{
  480. this.tableNode.setStyle("height", "auto");
  481. }
  482. },
  483. getStatementGroupHeight: function(group){
  484. var first = group[0];
  485. var last = group[group.length-1];
  486. var topP = first.node.getPosition(this.areaNode);
  487. var bottomP = last.node.getPosition(this.areaNode);
  488. var bottomSize = last.node.getSize();
  489. return bottomP.y+bottomSize.y-topP.y
  490. }
  491. });
  492. MWF.xApplication.ScriptEditor.statement.$Statement.$EnumerateAround = new Class({
  493. Extends: MWF.xApplication.ScriptEditor.statement.$Statement.$Around
  494. });