commands.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. import $ from 'jquery';
  2. import { Types } from './types';
  3. import * as Models from './ivprog_elements';
  4. import { LocalizedStrings } from './../services/localizedStringsService';
  5. import * as GlobalsManagement from './globals';
  6. import * as VariablesManagement from './variables';
  7. import * as CommentsManagement from './commands/comment';
  8. import * as ReadersManagement from './commands/reader';
  9. import * as WritersManagement from './commands/writer';
  10. import * as AttributionsManagement from './commands/attribution';
  11. import * as IftruesManagement from './commands/iftrue';
  12. import * as RepeatNtimesManagement from './commands/repeatNtimes';
  13. import * as WhiletruesManagement from './commands/whiletrue';
  14. import * as DowhiletruesManagement from './commands/dowhiletrue';
  15. import * as SwitchesManagement from './commands/switch';
  16. import * as FunctioncallsManagement from './commands/functioncall';
  17. var has_element_created_draged = false;
  18. var which_element_is_draged = null;
  19. export function createFloatingCommand (function_obj, function_container, command_type, mouse_event) {
  20. var floatingObject;
  21. switch (command_type) {
  22. case Models.COMMAND_TYPES.comment:
  23. floatingObject = CommentsManagement.createFloatingCommand();
  24. break;
  25. case Models.COMMAND_TYPES.reader:
  26. floatingObject = ReadersManagement.createFloatingCommand();
  27. break;
  28. case Models.COMMAND_TYPES.writer:
  29. floatingObject = WritersManagement.createFloatingCommand();
  30. break;
  31. case Models.COMMAND_TYPES.attribution:
  32. floatingObject = AttributionsManagement.createFloatingCommand();
  33. break;
  34. case Models.COMMAND_TYPES.iftrue:
  35. floatingObject = IftruesManagement.createFloatingCommand();
  36. break;
  37. case Models.COMMAND_TYPES.repeatNtimes:
  38. floatingObject = RepeatNtimesManagement.createFloatingCommand();
  39. break;
  40. case Models.COMMAND_TYPES.whiletrue:
  41. floatingObject = WhiletruesManagement.createFloatingCommand();
  42. break;
  43. case Models.COMMAND_TYPES.dowhiletrue:
  44. floatingObject = DowhiletruesManagement.createFloatingCommand();
  45. break;
  46. case Models.COMMAND_TYPES.switch:
  47. floatingObject = SwitchesManagement.createFloatingCommand();
  48. break;
  49. case Models.COMMAND_TYPES.functioncall:
  50. floatingObject = FunctioncallsManagement.createFloatingCommand();
  51. break;
  52. }
  53. $(floatingObject).draggable().appendTo("body");
  54. $( floatingObject ).mouseup(function(evt) {
  55. manageCommand(function_obj, function_container, evt, command_type);
  56. });
  57. floatingObject.css("position", "absolute");
  58. mouse_event.type = "mousedown.draggable";
  59. mouse_event.target = floatingObject[0];
  60. floatingObject.css("left", mouse_event.pageX - 15);
  61. floatingObject.css("top", mouse_event.pageY - 15);
  62. floatingObject.trigger(mouse_event);
  63. }
  64. // before_after_inside: 1 -> before, 2 -> after, 3 -> inside
  65. function renderCommand (command, element_reference, before_after_inside) {
  66. var createdElement;
  67. switch (command.type) {
  68. case Models.COMMAND_TYPES.comment:
  69. createdElement = CommentsManagement.renderCommand(command);
  70. break;
  71. case Models.COMMAND_TYPES.reader:
  72. createdElement = ReadersManagement.renderCommand(command);
  73. break;
  74. case Models.COMMAND_TYPES.writer:
  75. createdElement = WritersManagement.renderCommand(command);
  76. break;
  77. case Models.COMMAND_TYPES.attribution:
  78. createdElement = AttributionsManagement.renderCommand(command);
  79. break;
  80. case Models.COMMAND_TYPES.iftrue:
  81. createdElement = IftruesManagement.renderCommand(command);
  82. break;
  83. case Models.COMMAND_TYPES.repeatNtimes:
  84. createdElement = RepeatNtimesManagement.renderCommand(command);
  85. break;
  86. case Models.COMMAND_TYPES.whiletrue:
  87. createdElement = WhiletruesManagement.renderCommand(command);
  88. break;
  89. case Models.COMMAND_TYPES.dowhiletrue:
  90. createdElement = DowhiletruesManagement.renderCommand(command);
  91. break;
  92. case Models.COMMAND_TYPES.switch:
  93. createdElement = SwitchesManagement.renderCommand(command);
  94. break;
  95. case Models.COMMAND_TYPES.functioncall:
  96. createdElement = FunctioncallsManagement.renderCommand(command);
  97. break;
  98. }
  99. switch (before_after_inside) {
  100. case 1:
  101. $( createdElement ).insertBefore(element_reference);
  102. break;
  103. case 2:
  104. $( createdElement ).insertAfter(element_reference);
  105. break;
  106. case 3:
  107. $( element_reference ).append(createdElement);
  108. break;
  109. }
  110. }
  111. function genericCreateCommand (command_type) {
  112. switch (command_type) {
  113. case Models.COMMAND_TYPES.comment:
  114. return new Models.Comment(null);
  115. case Models.COMMAND_TYPES.reader:
  116. return new Models.Reader(null, null, null);
  117. case Models.COMMAND_TYPES.writer:
  118. return new Models.Writer(null);
  119. case Models.COMMAND_TYPES.attribution:
  120. return new Models.Attribution(null, null);
  121. case Models.COMMAND_TYPES.iftrue:
  122. return new Models.IfTrue(null, null, null);
  123. case Models.COMMAND_TYPES.repeatNtimes:
  124. return new Models.RepeatNTimes(null, null, null, null);
  125. case Models.COMMAND_TYPES.whiletrue:
  126. return new Models.WhileTrue(null, null);
  127. case Models.COMMAND_TYPES.dowhiletrue:
  128. return new Models.DoWhileTrue(null, null);
  129. case Models.COMMAND_TYPES.switch:
  130. return new Models.Switch(null, null, null);
  131. case Models.COMMAND_TYPES.functioncall:
  132. return new Models.FunctionCall(null, null);
  133. }
  134. }
  135. function manageCommand (function_obj, function_container, event, command_type) {
  136. $( ".created_element" ).each(function( index ) {
  137. $(this).remove();
  138. });
  139. var el = document.elementFromPoint(event.clientX, event.clientY);
  140. console.log('soltou no: ');
  141. console.log(el);
  142. console.log($(el).data('fun'));
  143. // Primeiro verificar se ele soltou no espaço da função correta:
  144. var hier = $(el).parentsUntil(".all_functions");
  145. var esta_correto = false;
  146. var esta_na_div_correta = false;
  147. if ($(el).hasClass("commands_list_div")) {
  148. esta_na_div_correta = true;
  149. }
  150. for (var i = 0; i < hier.length; i++) {
  151. if ($(hier[i]).hasClass("commands_list_div")) {
  152. esta_na_div_correta = true;
  153. }
  154. if ($(hier[i]).data('fun') == function_obj) {
  155. esta_correto = true;
  156. break;
  157. }
  158. }
  159. if (!esta_correto) {
  160. has_element_created_draged = false;
  161. which_element_is_draged = null;
  162. return;
  163. } else {
  164. if (!esta_na_div_correta) {
  165. has_element_created_draged = false;
  166. which_element_is_draged = null;
  167. return;
  168. }
  169. }
  170. // Agora é descobrir qual o escopo para adicionar o comando:
  171. // Se o elemento clicado possuir o atributo "fun", então, é direto na div dos comandos:
  172. if (typeof $(el).data('fun') !== 'undefined') {
  173. // Se a lista de comandos estiver vazia, então é o primeiro.
  174. // Portanto, ele deve soltar o elemento obrigatoriamente no objeto vazio
  175. if (($(el).data('fun').commands == null) || ($(el).data('fun').commands.length == 0)) {
  176. // pode adicionar
  177. $(el).data('fun').commands = [];
  178. var new_cmd = genericCreateCommand(command_type);
  179. $(el).data('fun').commands.push(new_cmd);
  180. renderCommand(new_cmd, $(function_container).find('.commands_list_div'), 3);
  181. } else { // Entra nesse else, caso já existam outros comandos no bloco:
  182. findNearbyCommandToAddInFunctionScope(el, event, $(function_container).find('.commands_list_div'), function_obj, command_type);
  183. }
  184. return;
  185. } else { // Se entrar nesse bloco 'else', quer dizer que o usuário não soltou o elemento necessariamente na div específica da função
  186. // portanto, devemos procurar nos elementos DOM, em que lugar da função, ele soltou o comando
  187. /*var hier = $(el).parentsUntil(".all_functions");
  188. for (i = 0; i < hier.length; i++) {
  189. if ($(hier[i]).data('fun') == function_to_add) {
  190. programa.funcoes[function_to_add].comandos.push(createElementGenericFunction());
  191. break;
  192. }
  193. }*/
  194. //findPositionAndInsertCommand(el, event);
  195. var caminho = findPositionAndPathToElementTarget(el, event);
  196. console.log("soltou sobre o seguinte elemento: ");
  197. console.log(caminho);
  198. console.log("soltou sobre o seguinte DOM: ");
  199. console.log(el);
  200. // se for 1, então está no nível do corpo da função:
  201. if (caminho.length == 1) {
  202. console.log("o caminho é de tamanho 1 e o objeto é o seguinte: " + caminho[0]);
  203. console.log(programa.funcoes[function_to_add].comandos[caminho[0]]);
  204. // se for do tipo true ou false, temos que determinar se soltou no if ou no else:
  205. if (programa.funcoes[function_to_add].comandos[caminho[0]].tipo == tiposComandos.iftrue) {
  206. if ($(el).data('if')) {
  207. if ((programa.funcoes[function_to_add].comandos[caminho[0]].commands_block == null)
  208. || (programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.length == 0)) {
  209. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block = [];
  210. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.push(createElementGenericFunction());
  211. } else {
  212. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.push(createElementGenericFunction());
  213. }
  214. } else if ($(el).data('else')) {
  215. if ((programa.funcoes[function_to_add].comandos[caminho[0]].commands_else == null)
  216. || (programa.funcoes[function_to_add].comandos[caminho[0]].commands_else.length == 0)) {
  217. programa.funcoes[function_to_add].comandos[caminho[0]].commands_else = [];
  218. programa.funcoes[function_to_add].comandos[caminho[0]].commands_else.push(createElementGenericFunction());
  219. } else {
  220. programa.funcoes[function_to_add].comandos[caminho[0]].commands_else.push(createElementGenericFunction());
  221. }
  222. } else {
  223. console.log("soltou dentro do if, fora dos divs corretos... VERIFICAR QUAL ESTÁ MAIS PRÓXIMO... O IF OU O ELSE --- NNN11");
  224. discoveryIfOrElse(el, event);
  225. }
  226. } else {
  227. if ((programa.funcoes[function_to_add].comandos[caminho[0]].tipo == tiposComandos.repeatNtimes)
  228. || (programa.funcoes[function_to_add].comandos[caminho[0]].tipo == tiposComandos.whiletrue)
  229. || (programa.funcoes[function_to_add].comandos[caminho[0]].tipo == tiposComandos.dowhiletrue)
  230. || (programa.funcoes[function_to_add].comandos[caminho[0]].tipo == tiposComandos.switch) ) {
  231. if ((programa.funcoes[function_to_add].comandos[caminho[0]].commands_block == null)
  232. || (programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.length == 0)) {
  233. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block = [];
  234. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.push(createElementGenericFunction());
  235. } else {
  236. programa.funcoes[function_to_add].comandos[caminho[0]].commands_block.push(createElementGenericFunction());
  237. }
  238. } else {
  239. var result = getBeforeOrAfterOrEndAllocate(el, event);
  240. if (result == true) {
  241. console.log("adicionando ANTES");
  242. programa.funcoes[function_to_add].comandos.splice(caminho[0], 0, createElementGenericFunction());
  243. } else {
  244. console.log("adicionando DEPOIS");
  245. programa.funcoes[function_to_add].comandos.splice(caminho[0] + 1, 0, createElementGenericFunction());
  246. }
  247. }
  248. }
  249. } else { // caso seja mais de um, o caminho, então, precisamos percorrer até achar:
  250. // CONTINUAR DAQUI:
  251. console.log("ACHO QUE É A SITUAÇÃO DE BLOCO INTERNO");
  252. console.log("SOLTOU NO ELEMENTO A SEGUIR: ");
  253. console.log(el.relatedObj);
  254. console.log("PAI DO ELEMENTO QUE ELA SOLTOU: ");
  255. console.log(el.parentNode.relatedObj);
  256. //
  257. if ((el.parentNode.relatedObj.tipo == tiposComandos.iftrue)) {
  258. if ($(el.parentNode).data('if') || $(el).data('if')) {
  259. if ((el.parentNode.relatedObj.commands_block == null)
  260. || (el.parentNode.relatedObj.commands_block.length == 0)) {
  261. el.parentNode.relatedObj.commands_block = [];
  262. el.parentNode.relatedObj.commands_block.push(createElementGenericFunction());
  263. } else {
  264. if ($(el).data('if')) {
  265. // Descobrir qual o elemento mais próximo de onde ele soltou o comando recém criado:
  266. console.log("SITUAÇÃO TRATADA NO K1!");
  267. getNearbyIndexOfElementOnClick(el, event);
  268. } else {
  269. if (getBeforeOrAfterOrEndAllocate(el, event)) {
  270. console.log("K1 ANTECAO! SOLTOU ANTES DO ELEMENTO ALVO");
  271. el.parentNode.relatedObj.commands_block.splice($(el).data('index'), 0, createElementGenericFunction());
  272. } else {
  273. console.log("K1 ANTECAO! SOLTOU DEPOIS DO ELEMENTO ALVO");
  274. el.parentNode.relatedObj.commands_block.splice($(el).data('index') + 1, 0, createElementGenericFunction());
  275. }
  276. }
  277. //el.parentNode.relatedObj.commands_block.push(createElementGenericFunction());
  278. }
  279. } else if ($(el.parentNode).data('else') || $(el).data('else')) {
  280. if ((el.parentNode.relatedObj.commands_else == null)
  281. || (el.parentNode.relatedObj.commands_else.length == 0)) {
  282. el.parentNode.relatedObj.commands_else = [];
  283. el.parentNode.relatedObj.commands_else.push(createElementGenericFunction());
  284. } else {
  285. if ($(el).data('else')) {
  286. // Descobrir qual o elemento mais próximo de onde ele soltou o comando recém criado:
  287. console.log("SITUAÇÃO TRATADA NO K2!");
  288. getNearbyIndexOfElementOnClick(el, event);
  289. } else {
  290. if (getBeforeOrAfterOrEndAllocate(el, event)) {
  291. console.log("K2 ANTECAO! SOLTOU ANTES DO ELEMENTO ALVO");
  292. el.parentNode.relatedObj.commands_else.splice($(el).data('index'), 0, createElementGenericFunction());
  293. } else {
  294. console.log("K2 ANTECAO! SOLTOU DEPOIS DO ELEMENTO ALVO");
  295. el.parentNode.relatedObj.commands_else.splice($(el).data('index') + 1, 0, createElementGenericFunction());
  296. }
  297. }
  298. //el.parentNode.relatedObj.commands_else.push(createElementGenericFunction());
  299. }
  300. } else {
  301. console.log("soltou dentro do if, fora dos divs corretos... VERIFICAR QUAL ESTÁ MAIS PRÓXIMO... O IF OU O ELSE --- NNN22");
  302. discoveryIfOrElse(el, event);
  303. }
  304. } else {
  305. console.log("COMEÇAR A TRATAR!...");
  306. if ((el.parentNode.relatedObj.tipo == tiposComandos.repeatNtimes)
  307. || (el.parentNode.relatedObj.tipo == tiposComandos.whiletrue)
  308. || (el.parentNode.relatedObj.tipo == tiposComandos.dowhiletrue)
  309. || (el.parentNode.relatedObj.tipo == tiposComandos.switch)
  310. || (el.parentNode.relatedObj.tipo == tiposComandos.iftrue)) {
  311. if ((el.parentNode.relatedObj.commands_block == null)
  312. || (el.parentNode.relatedObj.commands_block.length == 0)) {
  313. el.parentNode.relatedObj.commands_block = [];
  314. el.parentNode.relatedObj.commands_block.push(createElementGenericFunction());
  315. } else {
  316. if (typeof $(el).data('subblock') !== 'undefined') {
  317. console.log("SITUAÇÃO TRATADA NO K3!");
  318. getNearbyIndexOfElementOnClick(el, event);
  319. } else {
  320. if (getBeforeOrAfterOrEndAllocate(el, event)) {
  321. console.log("K3 ANTECAO! SOLTOU ANTES DO ELEMENTO ALVO");
  322. el.parentNode.relatedObj.commands_block.splice($(el).data('index'), 0, createElementGenericFunction());
  323. } else {
  324. console.log("K3 ANTECAO! SOLTOU DEPOIS DO ELEMENTO ALVO");
  325. el.parentNode.relatedObj.commands_block.splice($(el).data('index') + 1, 0, createElementGenericFunction());
  326. }
  327. }
  328. //el.parentNode.relatedObj.commands_block.push(createElementGenericFunction());
  329. }
  330. } else {
  331. console.log("AGORA SIM! SITUAÇÃO K4!");
  332. console.log("VOU ADICIONAR NO SEGINTE ELEMENTO: ");
  333. console.log(el.parentNode.parentNode.relatedObj);
  334. if (getBeforeOrAfterOrEndAllocate(el.parentNode, event)) {
  335. el.parentNode.parentNode.relatedObj.commands_block.splice($(el.parentNode).data('index'), 0, createElementGenericFunction());
  336. } else {
  337. el.parentNode.parentNode.relatedObj.commands_block.splice($(el.parentNode).data('index') + 1, 0, createElementGenericFunction());
  338. }
  339. }
  340. }
  341. /*console.log("elemento superior: ");
  342. console.log(programa.funcoes[function_to_add].comandos[caminho[0]]);
  343. console.log("elemento específico:
  344. console.log(findElementByPath(caminho));*/
  345. }
  346. }
  347. //console.log("onde soltou:");
  348. //console.log(el);
  349. has_element_created_draged = false;
  350. which_element_is_draged = null;
  351. function_to_add = -1;
  352. renderAlgorithm();
  353. }
  354. function findNearbyCommandToAddInFunctionScope(el, event, node_list_commands, function_obj, command_type) {
  355. var all_sub = $(node_list_commands).find('div');
  356. var menor_distancia = 999999999;
  357. var elemento_menor_distancia = null;
  358. var antes = true;
  359. var t_bot;
  360. var t_top;
  361. // Descobrindo o elemento mais próximo:
  362. for (var i = 0; i < all_sub.length; i++) {
  363. t_top = all_sub[i].getBoundingClientRect().top;
  364. t_bot = all_sub[i].getBoundingClientRect().top + all_sub[i].getBoundingClientRect().height;
  365. if ((t_top - event.clientY) < menor_distancia) {
  366. menor_distancia = event.clientY - t_top;
  367. elemento_menor_distancia = all_sub[i];
  368. }
  369. }
  370. borda_inferior = elemento_menor_distancia.parentNode.getBoundingClientRect().top + elemento_menor_distancia.parentNode.getBoundingClientRect().height;
  371. // Está mais próximo da borda de baixo, ou seja.. inserir por último:
  372. if ((borda_inferior - event.clientY) < menor_distancia) {
  373. function_obj.commands.push(genericCreateCommand(command_type));
  374. } else {
  375. function_obj.commands.splice($(elemento_menor_distancia).data('index'), 0, genericCreateCommand(command_type));
  376. }
  377. }
  378. function findPositionAndPathToElementTarget(el, event) {
  379. var full_path = [];
  380. var m;
  381. if (typeof $(el).data('fullpath') !== 'undefined') {
  382. m = $(el).data('fullpath');
  383. } else {
  384. var hier = $(el).parentsUntil(".all_functions");
  385. for (var i = 0; i < hier.length; i++) {
  386. if (typeof $(hier[i]).data('fullpath') !== 'undefined') {
  387. m = $(hier[i]).data('fullpath');
  388. break;
  389. }
  390. }
  391. }
  392. if (isNaN(m)) {
  393. full_path = m.split(',');
  394. /*for (i = 0; i < full_path.length; i++) {
  395. full_path[i] = parseInt(full_path[i]);
  396. }*/
  397. return full_path;
  398. } else {
  399. return [m];
  400. }
  401. }