functions_sidebar.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  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_sidebar';
  6. import * as VariablesManagement from './variables';
  7. import * as CommandsManagement from './commands_sidebar';
  8. import * as CodeManagement from './code_generator';
  9. import * as VariableValueMenu from './commands/variable_value_menu';
  10. import { DOMConsole } from './../io/domConsole';
  11. import { IVProgParser } from './../ast/ivprogParser';
  12. import { IVProgProcessor } from './../processor/ivprogProcessor';
  13. import WatchJS from 'melanke-watchjs';
  14. import { SemanticAnalyser } from '../processor/semantic/semanticAnalyser';
  15. import { IVProgAssessment } from '../assessment/ivprogAssessment';
  16. import * as AlgorithmManagement from './algorithm_sidebar';
  17. var counter_new_functions = 0;
  18. var counter_new_parameters = 0;
  19. let studentTemp = null;
  20. let domConsole = null;
  21. window.studentGrade = null;
  22. const program = new Models.Program();
  23. /*const variable1 = new Models.Variable(Types.INTEGER, "a", 1);*/
  24. const mainFunction = new Models.Function(LocalizedStrings.getUI("start"), Types.VOID, 0, [], true, false);
  25. mainFunction.function_comment = new Models.Comment(LocalizedStrings.getUI('text_comment_main'));
  26. /*const parameter1 = new Models.Variable(Types.INTEGER, "par_1", 1);
  27. const command1 = new Models.Comment(new Models.VariableValueMenu(VariableValueMenu.VAR_OR_VALUE_TYPES.only_value, "Testing rendering commands"));
  28. const sumFunction = new Models.Function("soma", Types.INTEGER, 0, [parameter1], false, false, [], null, [command1]);*/
  29. program.addFunction(mainFunction);
  30. //program.addFunction(sumFunction);
  31. window.program_obj = program;
  32. window.generator = CodeManagement.generate;
  33. window.runCodeAssessment = runCodeAssessment;
  34. window.renderAlgorithm = AlgorithmManagement.renderAlgorithm;
  35. WatchJS.watch(program.globals, function(){
  36. AlgorithmManagement.renderAlgorithm();
  37. }, 1);
  38. function addFunctionHandler () {
  39. var new_function = new Models.Function(LocalizedStrings.getUI("new_function") + "_" + counter_new_functions, Types.VOID, 0, [], false, false, [], new Models.Comment(LocalizedStrings.getUI('text_comment_start')));
  40. program.addFunction(new_function);
  41. counter_new_functions ++;
  42. renderFunction(new_function);
  43. }
  44. function addParameter (function_obj, function_container) {
  45. if (function_obj.parameters_list == null) {
  46. function_obj.parameters_list = [];
  47. }
  48. var new_parameter = new Models.Variable(Types.INTEGER, LocalizedStrings.getUI("new_parameter") + "_" + counter_new_parameters);
  49. function_obj.parameters_list.push(new_parameter);
  50. counter_new_parameters ++;
  51. renderParameter(function_obj, new_parameter, function_container);
  52. }
  53. function updateReturnType (function_obj, new_type, new_dimensions = 0) {
  54. function_obj.return_type = new_type;
  55. function_obj.return_dimensions = new_dimensions;
  56. }
  57. function removeFunction (function_obj) {
  58. var index = program.functions.indexOf(function_obj);
  59. if (index > -1) {
  60. program.functions.splice(index, 1);
  61. }
  62. }
  63. function minimizeFunction (function_obj) {
  64. function_obj.is_hidden = !function_obj.is_hidden;
  65. }
  66. function addHandlers (function_obj, function_container) {
  67. // function_container.on('dragenter',function(e) {
  68. // e.preventDefault();
  69. // $(e.target).addClass('div-over')
  70. // console.log(e.target)
  71. // })
  72. function_container.find('.ui.dropdown.function_return').dropdown({
  73. onChange: function(value, text, $selectedItem) {
  74. $selectedItem = $($selectedItem);
  75. if ($selectedItem.data('dimensions')) {
  76. updateReturnType(function_obj, Types[$selectedItem.data('type')], $selectedItem.data('dimensions'));
  77. } else {
  78. updateReturnType(function_obj, Types[$selectedItem.data('type')]);
  79. }
  80. }
  81. });
  82. function_container.find( ".name_function_updated" ).on('click', function(e){
  83. enableNameFunctionUpdate(function_obj, function_container);
  84. });
  85. function_container.find( ".add_parameter_button" ).on('click', function(e){
  86. addParameter(function_obj, function_container);
  87. });
  88. function_container.find('.menu_commands').dropdown({
  89. on: 'hover'
  90. });
  91. function_container.find('.menu_commands a').on('click', function(evt){
  92. if (function_obj.commands == null || function_obj.commands.length == 0) {
  93. function_obj.commands = [];
  94. var new_cmd = CommandsManagement.genericCreateCommand($(this).data('command'));
  95. function_obj.commands.push(new_cmd);
  96. CommandsManagement.renderCommand(new_cmd, function_container.find('.commands_list_div'), 3, function_obj);
  97. } else {
  98. CommandsManagement.createFloatingCommand(function_obj, function_container, $(this).data('command'), evt);
  99. }
  100. });
  101. function_container.find('.add_var_button_function').on('click', function(e){
  102. VariablesManagement.addVariable(function_obj, function_container);
  103. });
  104. function_container.find('.remove_function_button').on('click', function(e){
  105. removeFunction(function_obj);
  106. function_container.slideUp(400);
  107. });
  108. function_container.find('.minimize_function_button').on('click', function(e){
  109. minimizeFunction(function_obj);
  110. function_container.find(".function_area").toggle();
  111. function_container.find(".add_var_top_button").toggle();
  112. });
  113. }
  114. // Essa função imprime o tipo de retorno da função e cria o menu do tipo 'select' para alteração
  115. function renderFunctionReturn (function_obj, function_element) {
  116. var ret = '<div class="ui dropdown function_return">';
  117. if (function_obj.return_dimensions > 0) {
  118. ret += '<div class="text">'+ LocalizedStrings.getUI("vector") +':'+ LocalizedStrings.getUI(function_obj.return_type);
  119. ret += '</div>';
  120. } else {
  121. ret += '<div class="text">'+LocalizedStrings.getUI(function_obj.return_type)+'</div>';
  122. }
  123. ret += '<i class="dropdown icon"></i>'
  124. + '<div class="menu">';
  125. for (var tm in Types) {
  126. ret += '<div class="item ' + (function_obj.return_type == tm.toLowerCase() && function_obj.return_dimensions < 1 ? ' selected ' : '') + '" data-type="'+tm+'" >'+LocalizedStrings.getUI(tm.toLowerCase())+'</div>';
  127. }
  128. for (var tm in Types) {
  129. if (tm == Types.VOID.toUpperCase()) {
  130. continue;
  131. }
  132. ret += '<div class="item">'
  133. + '<i class="dropdown icon"></i>'
  134. + LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())
  135. + '<div class="menu">'
  136. + '<div class="item '+(function_obj.return_type == tm.toLowerCase() && function_obj.return_dimensions > 0 ? ' selected ' : '')+'" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] " data-type="'+tm+'" data-dimensions="1">[ ]</div>'
  137. + '<div class="item '+(function_obj.return_type == tm.toLowerCase() && function_obj.return_dimensions > 0 ? ' selected ' : '')+'" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] [ ] " data-type="'+tm+'" data-dimensions="2">[ ] [ ] </div>'
  138. + '</div>'
  139. + '</div>';
  140. }
  141. ret += '</div></div>';
  142. ret = $(ret);
  143. function_element.find('.function_return').append(ret);
  144. }
  145. export function renderFunction (function_obj) {
  146. var appender = '<div class="ui secondary segment function_div list-group-item">';
  147. if (function_obj.function_comment) {
  148. //appender += renderComment(function_obj.function_comment, sequence, true, -1);
  149. }
  150. appender += '<span class="glyphicon glyphicon-move move_function" aria-hidden="true"><i class="icon sort alternate vertical"></i></span>';
  151. appender += (function_obj.is_main ? '<div class="div_start_minimize_v"> </div>' : '<button class="ui icon button large remove_function_button"><i class="red icon times"></i></button>')
  152. + '<button class="ui icon button tiny minimize_function_button"><i class="icon window minimize"></i></button>';
  153. appender += '<div class="ui small icon buttons add_var_top_button"><div class="ui icon button add_var_button_function"><i class="icon superscript"></i></div>';
  154. appender += '<div class="ui icon button dropdown menu_commands" ><i class="icon code"></i> <div class="menu"> ';
  155. appender += '<a class="item" data-command="'+Models.COMMAND_TYPES.reader+'"><i class="download icon"></i> ' +LocalizedStrings.getUI('text_read_var')+ '</a>'
  156. + '<a class="item" data-command="'+Models.COMMAND_TYPES.writer+'"><i class="upload icon"></i> '+LocalizedStrings.getUI('text_write_var')+'</a>'
  157. + '<a class="item" data-command="'+Models.COMMAND_TYPES.comment+'"><i class="quote left icon"></i> '+LocalizedStrings.getUI('text_comment')+'</a>'
  158. + '<a class="item" data-command="'+Models.COMMAND_TYPES.attribution+'"><i class="arrow left icon"></i> '+LocalizedStrings.getUI('text_attribution')+'</a>'
  159. + '<a class="item" data-command="'+Models.COMMAND_TYPES.functioncall+'"><i class="hand point right icon"></i> '+LocalizedStrings.getUI('text_functioncall')+'</a>'
  160. + '<a class="item" data-command="'+Models.COMMAND_TYPES.iftrue+'" ><i class="random icon"></i> '+LocalizedStrings.getUI('text_iftrue')+'</a>'
  161. + '<a class="item" data-command="'+Models.COMMAND_TYPES.repeatNtimes+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_repeatNtimes')+'</a>'
  162. + '<a class="item" data-command="'+Models.COMMAND_TYPES.whiletrue+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_whiletrue')+'</a>'
  163. + '<a class="item" data-command="'+Models.COMMAND_TYPES.dowhiletrue+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_dowhiletrue')+'</a>'
  164. + '<a class="item" data-command="'+Models.COMMAND_TYPES.switch+'"><i class="list icon"></i> '+LocalizedStrings.getUI('text_switch')+'</a>'
  165. + '<a class="item" data-command="'+Models.COMMAND_TYPES.return+'"><i class="reply icon"></i> '+LocalizedStrings.getUI('text_btn_return')+'</a>'
  166. + '</div></div></div>';
  167. appender += '<div class="function_signature_div">'+LocalizedStrings.getUI("function")+' ';
  168. if (function_obj.is_main) {
  169. appender += '<div class="function_name_div"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ' + LocalizedStrings.getUI('void') + ' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="span_name_function" >'+function_obj.name+'</span> </div> '
  170. + '( <div class="ui large labels parameters_list">';
  171. } else {
  172. appender += '<div class="ui function_return"></div>';
  173. appender += '<div class="function_name_div"><span class="span_name_function name_function_updated">'+function_obj.name+'</span> <i class="icon small pencil alternate enable_edit_name_function name_function_updated"></i></div> '
  174. + '( <i class="ui icon plus square outline add_parameter_button"></i> <div class="ui large labels parameters_list container_parameters_list">';
  175. }
  176. appender += '</div> ) </div>'
  177. + (function_obj.is_hidden ? ' <div class="function_area" style="display: none;"> ' : ' <div class="function_area"> ')
  178. + '<div class="ui top attached segment variables_list_div">'
  179. /*+ renderVariables(function_obj, sequence)*/
  180. + '</div>'
  181. + '<div class="ui bottom attached segment commands_list_div" id="function_drag_cmd_">';
  182. appender += '</div>';
  183. appender += '<div class="function_close_div"></div>'
  184. + '</div>'
  185. + '</div>';
  186. appender = $(appender);
  187. $('.all_functions').append(appender);
  188. appender.data('fun', function_obj);
  189. appender.find('.commands_list_div').data('fun', function_obj);
  190. renderFunctionReturn(function_obj, appender);
  191. addHandlers(function_obj, appender);
  192. // Rendering parameters:
  193. for (var j = 0; j < function_obj.parameters_list.length; j++) {
  194. renderParameter(function_obj, function_obj.parameters_list[j], appender);
  195. }
  196. // Rendering variables:
  197. for (var j = 0; j < function_obj.variables_list.length; j++) {
  198. VariablesManagement.renderVariable(appender, function_obj.variables_list[j], function_obj);
  199. }
  200. // Rendering commands:
  201. for (var j = 0; j < function_obj.commands.length; j++) {
  202. CommandsManagement.renderCommand(function_obj.commands[j], $(appender.find('.commands_list_div')[0]), 3, function_obj);
  203. }
  204. }
  205. export function initVisualUI () {
  206. // MUST USE CONST, LET, OR VAR !!!!!!
  207. const mainDiv = $('#visual-main-div');
  208. // fill mainDiv with functions and globals...
  209. // renderAlgorithm()...
  210. $('.add_function_button').on('click', () => {
  211. addFunctionHandler();
  212. });
  213. $('.add_global_button').on('click', () => {
  214. GlobalsManagement.addGlobal(program);
  215. });
  216. $('.run_button').on('click', () => {
  217. runCode();
  218. });
  219. $('.visual_coding_button').on('click', () => {
  220. toggleVisualCoding();
  221. });
  222. $('.textual_coding_button').on('click', () => {
  223. toggleTextualCoding();
  224. });
  225. $('.assessment').on('click', () => {
  226. runCodeAssessment();
  227. is_iassign = true;
  228. });
  229. }
  230. var is_iassign = false;
  231. $( document ).ready(function() {
  232. for (var i = 0; i < program.functions.length; i++) {
  233. renderFunction(program.functions[i]);
  234. }
  235. $('.div_to_body div a').popup({
  236. delay: {
  237. show: 750,
  238. hide: 0
  239. }
  240. });
  241. });
  242. function runCodeAssessment () {
  243. window.studentGrade = null;
  244. studentTemp = null;
  245. const strCode = CodeManagement.generate();
  246. if (strCode == null) {
  247. return;
  248. }
  249. if(domConsole == null)
  250. domConsole = new DOMConsole("#ivprog-term");
  251. $("#ivprog-term").slideDown(500);
  252. const runner = new IVProgAssessment(strCode, testCases, domConsole);
  253. runner.runTest().then(grade => {
  254. if (!is_iassign) {
  255. parent.getEvaluationCallback(grade);
  256. } else {
  257. is_iassign = false;
  258. }
  259. }).catch( err => domConsole.err(err.message));
  260. }
  261. function runCode () {
  262. const strCode = CodeManagement.generate();
  263. if (strCode == null) {
  264. return;
  265. }
  266. if(domConsole == null)
  267. domConsole = new DOMConsole("#ivprog-term");
  268. $("#ivprog-term").slideDown(500);
  269. try {
  270. const parser = IVProgParser.createParser(strCode);
  271. const analyser = new SemanticAnalyser(parser.parseTree());
  272. const data = analyser.analyseTree();
  273. const proc = new IVProgProcessor(data);
  274. proc.registerInput(domConsole);
  275. proc.registerOutput(domConsole);
  276. proc.interpretAST().then( _ => {
  277. domConsole.info("Programa executado com sucesso!");
  278. }).catch(err => {
  279. domConsole.err(err.message);
  280. })
  281. } catch (error) {
  282. domConsole.err(error.message);
  283. console.log(error);
  284. }
  285. }
  286. function waitToCloseConsole () {
  287. domConsole.info("Aperte qualquer tecla para fechar...");
  288. const p = new Promise((resolve, _) => {
  289. domConsole.requestInput(resolve, true);
  290. });
  291. p.then( _ => {
  292. domConsole.dispose();
  293. domConsole = null;
  294. $("#ivprog-term").hide();
  295. })
  296. }
  297. function toggleTextualCoding () {
  298. var code = CodeManagement.generate();
  299. $('.ivprog_visual_panel').css('display', 'none');
  300. $('.ivprog_textual_panel').css('display', 'block');
  301. $('.ivprog_textual_panel').removeClass('loading');
  302. $('.ivprog_textual_code').text(code);
  303. }
  304. function toggleVisualCoding () {
  305. $('.ivprog_textual_panel').addClass('loading');
  306. $('.ivprog_textual_panel').css('display', 'none');
  307. $('.ivprog_visual_panel').css('display', 'block');
  308. }
  309. function removeParameter (function_obj, parameter_obj, parameter_container) {
  310. var index = function_obj.parameters_list.indexOf(parameter_obj);
  311. if (index > -1) {
  312. function_obj.parameters_list.splice(index, 1);
  313. }
  314. $(parameter_container).remove();
  315. }
  316. function updateParameterType(parameter_obj, new_type, new_dimensions = 0) {
  317. parameter_obj.type = new_type;
  318. parameter_obj.dimensions = new_dimensions;
  319. if (new_dimensions > 0) {
  320. parameter_obj.rows = new_dimensions;
  321. parameter_obj.columns = 2;
  322. }
  323. }
  324. function renderParameter (function_obj, parameter_obj, function_container) {
  325. var ret = "";
  326. ret += '<div class="ui label function_name_parameter">';
  327. ret += '<div class="ui dropdown parameter_type">';
  328. if (parameter_obj.dimensions > 0) {
  329. ret += '<div class="text">'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(parameter_obj.type);
  330. ret += '</div>';
  331. } else {
  332. ret += '<div class="text">'+LocalizedStrings.getUI(parameter_obj.type)+'</div>';
  333. }
  334. ret += '<i class="dropdown icon"></i>'
  335. + '<div class="menu">';
  336. for (var tm in Types) {
  337. if (tm == Types.VOID.toUpperCase()) {
  338. continue;
  339. }
  340. ret += '<div class="item ' + (parameter_obj.type == tm.toLowerCase() ? ' selected ' : '') + '" data-type="'+tm+'" >'+LocalizedStrings.getUI(tm.toLowerCase())+'</div>';
  341. }
  342. for (var tm in Types) {
  343. if (tm == Types.VOID.toUpperCase()) {
  344. continue;
  345. }
  346. ret += '<div class="item">'
  347. + '<i class="dropdown icon"></i>'
  348. + LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())
  349. + '<div class="menu">'
  350. + '<div class="item" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] " data-type="'+tm+'" data-dimensions="1">[ ]</div>'
  351. + '<div class="item" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] [ ] " data-type="'+tm+'" data-dimensions="2">[ ] [ ] </div>'
  352. + '</div>'
  353. + '</div>';
  354. }
  355. ret += '</div></div>';
  356. ret += '<span class="span_name_parameter label_enable_name_parameter">'+parameter_obj.name+'</span> <i class="icon small pencil alternate enable_edit_name_parameter label_enable_name_parameter"></i>';
  357. ret += ' <i class="red icon times remove_parameter"></i></div>';
  358. ret = $(ret);
  359. function_container.find('.container_parameters_list').append(ret);
  360. ret.find('.remove_parameter').on('click', function(e){
  361. removeParameter(function_obj, parameter_obj, ret);
  362. });
  363. ret.find('.ui.dropdown.parameter_type').dropdown({
  364. onChange: function(value, text, $selectedItem) {
  365. if ($($selectedItem).data('dimensions')) {
  366. updateParameterType(parameter_obj, Types[$($selectedItem).data('type')], $($selectedItem).data('dimensions'));
  367. } else {
  368. updateParameterType(parameter_obj, Types[$($selectedItem).data('type')]);
  369. }
  370. }
  371. });
  372. ret.find('.label_enable_name_parameter').on('click', function(e){
  373. enableNameParameterUpdate(parameter_obj, ret);
  374. });
  375. }
  376. var opened_name_parameter = false;
  377. var opened_input_parameter = null;
  378. function enableNameParameterUpdate (parameter_obj, parent_node) {
  379. if (opened_name_parameter) {
  380. $(opened_input_parameter).focus();
  381. return;
  382. }
  383. opened_name_parameter = true;
  384. $(parent_node).find('.span_name_parameter').text('');
  385. $( "<input type='text' class='width-dynamic input_name_function' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' value='"+parameter_obj.name+"' />" ).insertBefore($(parent_node).find('.span_name_parameter'));
  386. $('.width-dynamic').on('input', function() {
  387. var inputWidth = $(this).textWidth()+10;
  388. opened_input_parameter = this;
  389. $(this).focus();
  390. var tmpStr = $(this).val();
  391. $(this).val('');
  392. $(this).val(tmpStr);
  393. $(this).css({
  394. width: inputWidth
  395. })
  396. }).trigger('input');
  397. $('.width-dynamic').focusout(function() {
  398. /// update array:
  399. if ($(this).val().trim()) {
  400. parameter_obj.name = $(this).val().trim();
  401. $(parent_node).find('.span_name_parameter').text(parameter_obj.name);
  402. }
  403. $(this).remove();
  404. /// update elements:
  405. opened_name_parameter = false;
  406. opened_input_parameter = false;
  407. });
  408. $('.width-dynamic').on('keydown', function(e) {
  409. var code = e.keyCode || e.which;
  410. if(code == 13) {
  411. if ($(this).val().trim()) {
  412. parameter_obj.name = $(this).val().trim();
  413. $(parent_node).find('.span_name_parameter').text(parameter_obj.name);
  414. }
  415. $(this).remove();
  416. /// update elements:
  417. opened_name_parameter = false;
  418. opened_input_parameter = false;
  419. }
  420. if(code == 27) {
  421. $(parent_node).find('.span_name_parameter').text(parameter_obj.name);
  422. $(this).remove();
  423. /// update elements:
  424. opened_name_parameter = false;
  425. opened_input_parameter = false;
  426. }
  427. });
  428. }
  429. var opened_name_function = false;
  430. var opened_input = null;
  431. function enableNameFunctionUpdate(function_obj, parent_node) {
  432. if (opened_name_function) {
  433. $(opened_input).focus();
  434. return;
  435. }
  436. $(parent_node).find('.span_name_function').text('');
  437. $( "<input type='text' class='width-dynamic input_name_function' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' value='"+function_obj.name+"' />" ).insertBefore($(parent_node).find('.span_name_function'));
  438. $('.width-dynamic').on('input', function() {
  439. var inputWidth = $(this).textWidth()+10;
  440. opened_input = this;
  441. $(this).focus();
  442. var tmpStr = $(this).val();
  443. $(this).val('');
  444. $(this).val(tmpStr);
  445. $(this).css({
  446. width: inputWidth
  447. })
  448. }).trigger('input');
  449. $('.width-dynamic').focusout(function() {
  450. /// update array:
  451. if ($(this).val().trim()) {
  452. function_obj.name = $(this).val().trim();
  453. }
  454. $(this).remove();
  455. $(parent_node).find('.span_name_function').text(function_obj.name);
  456. /// update elements:
  457. opened_name_function = false;
  458. opened_input = false;
  459. });
  460. $('.width-dynamic').on('keydown', function(e) {
  461. var code = e.keyCode || e.which;
  462. if(code == 13) {
  463. if ($(this).val().trim()) {
  464. function_obj.name = $(this).val().trim();
  465. }
  466. $(this).remove();
  467. $(parent_node).find('.span_name_function').text(function_obj.name);
  468. /// update elements:
  469. opened_name_function = false;
  470. opened_input = false;
  471. }
  472. if(code == 27) {
  473. $(this).remove();
  474. $(parent_node).find('.span_name_function').text(function_obj.name);
  475. /// update elements:
  476. opened_name_function = false;
  477. opened_input = false;
  478. }
  479. });
  480. }
  481. /****************************************************
  482. //DOUGLAS
  483. *******************************************************/
  484. removeFunction = function(function_obj) {
  485. var index = program.functions.indexOf(function_obj);
  486. if (index > -1) {
  487. program.functions.splice(index, 1);
  488. }
  489. $('.functions_labels > [data-function=' + function_obj.name + ']').remove();
  490. }
  491. renderFunction = function(function_obj) {
  492. var appender = '<div class="ui secondary segment function_div list-group-item">';
  493. if (function_obj.function_comment) {
  494. //appender += renderComment(function_obj.function_comment, sequence, true, -1);
  495. }
  496. appender += '<span class="glyphicon glyphicon-move move_function" aria-hidden="true"><i class="icon sort alternate vertical"></i></span>';
  497. appender += (function_obj.is_main ? '<div class="div_start_minimize_v"> </div>' : '<button class="ui icon button large remove_function_button"><i class="red icon times"></i></button>')
  498. + '<button class="ui icon button tiny minimize_function_button"><i class="icon window minimize"></i></button>';
  499. appender += '<div class="ui small icon buttons add_var_top_button"><div class="ui icon button add_var_button_function"><i class="icon superscript"></i></div>';
  500. appender += '<div class="ui icon button dropdown menu_commands" ><i class="icon code"></i> <div class="menu"> ';
  501. appender += '<a class="item" data-command="'+Models.COMMAND_TYPES.reader+'"><i class="download icon"></i> ' +LocalizedStrings.getUI('text_read_var')+ '</a>'
  502. + '<a class="item" data-command="'+Models.COMMAND_TYPES.writer+'"><i class="upload icon"></i> '+LocalizedStrings.getUI('text_write_var')+'</a>'
  503. + '<a class="item" data-command="'+Models.COMMAND_TYPES.comment+'"><i class="quote left icon"></i> '+LocalizedStrings.getUI('text_comment')+'</a>'
  504. + '<a class="item" data-command="'+Models.COMMAND_TYPES.attribution+'"><i class="arrow left icon"></i> '+LocalizedStrings.getUI('text_attribution')+'</a>'
  505. + '<a class="item" data-command="'+Models.COMMAND_TYPES.functioncall+'"><i class="hand point right icon"></i> '+LocalizedStrings.getUI('text_functioncall')+'</a>'
  506. + '<a class="item" data-command="'+Models.COMMAND_TYPES.iftrue+'" ><i class="random icon"></i> '+LocalizedStrings.getUI('text_iftrue')+'</a>'
  507. + '<a class="item" data-command="'+Models.COMMAND_TYPES.repeatNtimes+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_repeatNtimes')+'</a>'
  508. + '<a class="item" data-command="'+Models.COMMAND_TYPES.whiletrue+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_whiletrue')+'</a>'
  509. + '<a class="item" data-command="'+Models.COMMAND_TYPES.dowhiletrue+'"><i class="sync icon"></i> '+LocalizedStrings.getUI('text_dowhiletrue')+'</a>'
  510. + '<a class="item" data-command="'+Models.COMMAND_TYPES.switch+'"><i class="list icon"></i> '+LocalizedStrings.getUI('text_switch')+'</a>'
  511. + '<a class="item" data-command="'+Models.COMMAND_TYPES.return+'"><i class="reply icon"></i> '+LocalizedStrings.getUI('text_btn_return')+'</a>'
  512. + '</div></div></div>';
  513. appender += '<div class="function_signature_div">'+LocalizedStrings.getUI("function")+' ';
  514. if (function_obj.is_main) {
  515. appender += '<div class="function_name_div"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ' + LocalizedStrings.getUI('void') + ' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="span_name_function" >'+function_obj.name+'</span> </div> '
  516. + '( <div class="ui large labels parameters_list">';
  517. } else {
  518. appender += '<div class="ui function_return"></div>';
  519. appender += '<div class="function_name_div"><span class="span_name_function name_function_updated">'+function_obj.name+'</span> <i class="icon small pencil alternate enable_edit_name_function name_function_updated"></i></div> '
  520. + '( <i class="ui icon plus square outline add_parameter_button"></i> <div class="ui large labels parameters_list container_parameters_list">';
  521. var menu_button = '<button class="fluid ui container segment labeled icon button list-group-item menu-item" draggable="true" data-function="' + function_obj.name + '"><i class="list icon"></i> <span class="function_name">' + function_obj.name + '</span> (<span class="function_params"></span>) : <span class="function_return_type"></span></button>';
  522. var params = "";
  523. menu_button = $(menu_button);
  524. for (var j = 0; j < function_obj.parameters_list.length; j++) {
  525. if (j > 0)
  526. params += ',';
  527. params += function_obj.parameters_list[j].type;
  528. }
  529. menu_button
  530. .data('fun',function_obj)
  531. .on('dragstart', function(e) {
  532. e.originalEvent.dataTransfer.setData("text",JSON.stringify({type:"function",content:function_obj}));
  533. //evt.originalEvent.dataTransfer.setData("text",$(this).data('command'));
  534. })
  535. .find('.function_params').text(params)
  536. .find('.function_return_type').text(function_obj.type);
  537. $('.functions_labels').append(menu_button);
  538. console.log("aqui");
  539. //var menu_button = $('.functions_labels > [data-function=' + function_obj.name + ']');
  540. //var params = "";
  541. //menu_button
  542. }
  543. appender += '</div> ) </div>'
  544. + (function_obj.is_hidden ? ' <div class="function_area" style="display: none;"> ' : ' <div class="function_area"> ')
  545. + '<div class="ui top attached segment variables_list_div">'
  546. /*+ renderVariables(function_obj, sequence)*/
  547. + '</div>'
  548. + '<div class="ui bottom attached segment commands_list_div" id="function_drag_cmd_">';
  549. appender += '</div>';
  550. appender += '<div class="function_close_div"></div>'
  551. + '</div>'
  552. + '</div>';
  553. appender = $(appender);
  554. $('.all_functions').append(appender);
  555. appender.data('fun', function_obj);
  556. console.log("----====----->");
  557. appender.find('.commands_list_div')
  558. .data('fun', function_obj)
  559. .attr('droppable',true)
  560. .on('dragenter',function(e) {
  561. e.preventDefault();
  562. console.log('dragenter');
  563. console.log(e.target)
  564. $(e.target).addClass('div-over')
  565. //e.stopPropagation();
  566. }).on('dragover',function(e){
  567. e.preventDefault();
  568. })
  569. .on('dragleave',function(e) {
  570. e.preventDefault();
  571. //e.stopPropagation();
  572. console.log("dragleave")
  573. $(e.target).removeClass('div-over')
  574. console.log(e.target)
  575. })
  576. .on('drop',function(e){
  577. e.preventDefault();
  578. console.log('ondrop ' + e.originalEvent.dataTransfer.getData("text"));
  579. console.log(e)
  580. $(e.target).removeClass('div-over')
  581. var data = JSON.parse(e.originalEvent.dataTransfer.getData("text"));
  582. if (data.type == 'command')
  583. CommandsManagement.prepareManageCommand(function_obj, $(e.target).closest('.function_div'), e, data.content);
  584. else {
  585. CommandsManagement.prepareManageCommand(function_obj, $(e.target).closest('.function_div'), e, "functioncall", data.content);
  586. }
  587. });
  588. renderFunctionReturn(function_obj, appender);
  589. addHandlers(function_obj, appender);
  590. // Rendering parameters:
  591. for (var j = 0; j < function_obj.parameters_list.length; j++) {
  592. renderParameter(function_obj, function_obj.parameters_list[j], appender);
  593. }
  594. // Rendering variables:
  595. for (var j = 0; j < function_obj.variables_list.length; j++) {
  596. VariablesManagement.renderVariable(appender, function_obj.variables_list[j], function_obj);
  597. }
  598. // Rendering commands:
  599. for (var j = 0; j < function_obj.commands.length; j++) {
  600. CommandsManagement.renderCommand(function_obj.commands[j], $(appender.find('.commands_list_div')[0]), 3, function_obj);
  601. }
  602. console.log('kk')
  603. console.log($($('.function_div')[0]).data('fun'))
  604. console.log(appender.data('fun'))
  605. }
  606. initVisualUI = function() {
  607. // MUST USE CONST, LET, OR VAR !!!!!!
  608. const mainDiv = $('#visual-main-div');
  609. // fill mainDiv with functions and globals...
  610. // renderAlgorithm()...
  611. $('.add_function_button').on('click', () => {
  612. addFunctionHandler();
  613. });
  614. $('.add_global_button').on('click', () => {
  615. GlobalsManagement.addGlobal(program);
  616. });
  617. $('.run_button').on('click', () => {
  618. runCode();
  619. });
  620. $('.visual_coding_button').on('click', () => {
  621. toggleVisualCoding();
  622. });
  623. $('.textual_coding_button').on('click', () => {
  624. toggleTextualCoding();
  625. });
  626. var commands = [
  627. {type: Models.COMMAND_TYPES.break, icon: "stop", text: LocalizedStrings.getUI('text_break')},
  628. {type: Models.COMMAND_TYPES.reader, icon: "download", text: LocalizedStrings.getUI('text_read_var')},
  629. {type: Models.COMMAND_TYPES.writer, icon: "upload", text: LocalizedStrings.getUI('text_write_var')},
  630. {type: Models.COMMAND_TYPES.comment, icon: "quote left", text: LocalizedStrings.getUI('text_comment')},
  631. {type: Models.COMMAND_TYPES.attribution, icon: "arrow left", text: LocalizedStrings.getUI('text_attribution')},
  632. //{type: Models.COMMAND_TYPES.functioncall, icon: "hand point right", text: LocalizedStrings.getUI('text_functioncall')},
  633. {type: Models.COMMAND_TYPES.iftrue, icon: "random", text: LocalizedStrings.getUI('text_iftrue')},
  634. {type: Models.COMMAND_TYPES.repeatNtimes, icon: "sync", text: LocalizedStrings.getUI('text_repeatNtimes')},
  635. {type: Models.COMMAND_TYPES.whiletrue, icon: "sync", text: LocalizedStrings.getUI('text_whiletrue')},
  636. {type: Models.COMMAND_TYPES.dowhiletrue, icon: "sync", text: LocalizedStrings.getUI('text_dowhiletrue')},
  637. {type: Models.COMMAND_TYPES.switch, icon: "list", text: LocalizedStrings.getUI('text_switch')}
  638. ];
  639. for (var i = 0; i < commands.length; i++) {
  640. var command = '<button class="fluid ui container segment labeled icon button list-group-item menu-item" draggable="true" data-command="' + commands[i].type + '"><i class="' + commands[i].icon + ' icon"></i> ' + commands[i].text + '</button>';
  641. command = $(command);
  642. command.on('dragstart', function(evt){
  643. //evt.originalEvent.dataTransfer.setData("text",$(this).data('command'));
  644. evt.originalEvent.dataTransfer.setData("text",JSON.stringify({type:"command",content:$(this).data('command')}));
  645. console.log('dragstart')
  646. // $('.commands_list_div').attr('droppable',true)
  647. // .on('dragenter',function(e) {
  648. // e.preventDefault();
  649. // //e.stopPropagation();
  650. // console.log("dragenter")
  651. // e.originalEvent.dataTransfer.setData("text",$(this).data('command'));
  652. // console.log($(this).data('command'))
  653. // $(e.target).addClass('div-over')
  654. // console.log(e.target)
  655. // }).on('dragover',function(e){
  656. // e.preventDefault();
  657. // })
  658. // .on('dragleave',function(e) {
  659. // e.preventDefault();
  660. // //e.stopPropagation();
  661. // console.log("dragleave")
  662. // $(e.target).removeClass('div-over')
  663. // console.log(e.target)
  664. // })
  665. // .on('drop',function(e){
  666. // e.preventDefault();
  667. // console.log('ondrop ' + e.originalEvent.dataTransfer.getData("text"))
  668. // CommandsManagement.prepareManageCommand(null, null, e, e.originalEvent.dataTransfer.getData("text"));
  669. // })
  670. /*$(".commands_list_div, .commands_list_div, .block_commands, .command_container").hover(
  671. function(e) {
  672. console.log("enter =>")
  673. $(e.currentTarget).addClass('div-over');
  674. console.log({target: e.target, currentTarget: e.currentTarget, relatedTarget: e.relatedTarget, delegateTarget: e.delegateTarget})
  675. },
  676. function(e) {
  677. console.log("leave =>")
  678. $(e.currentTarget).removeClass('div-over');
  679. console.log({target: e.target, currentTarget: e.currentTarget, relatedTarget: e.relatedTarget, delegateTarget: e.delegateTarget})
  680. }
  681. )
  682. CommandsManagement.createFloatingCommand(null, null, $(this).data('command'), evt);*/
  683. });
  684. $('.list-commands').prepend(command);
  685. }
  686. }
  687. renderParameter = function(function_obj, parameter_obj, function_container) {
  688. var ret = "";
  689. ret += '<div class="ui label function_name_parameter"><span class="span_name_parameter label_enable_name_parameter">'+parameter_obj.name+'</span> <i class="icon small pencil alternate enable_edit_name_parameter label_enable_name_parameter"></i>';
  690. ret += '<div class="ui dropdown parameter_type">';
  691. if (parameter_obj.dimensions > 0) {
  692. ret += '<div class="text">'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(parameter_obj.type);
  693. ret += '</div>';
  694. } else {
  695. ret += '<div class="text">'+LocalizedStrings.getUI(parameter_obj.type)+'</div>';
  696. }
  697. ret += '<i class="dropdown icon"></i>'
  698. + '<div class="menu">';
  699. for (var tm in Types) {
  700. if (tm == Types.VOID.toUpperCase()) {
  701. continue;
  702. }
  703. ret += '<div class="item ' + (parameter_obj.type == tm.toLowerCase() ? ' selected ' : '') + '" data-type="'+tm+'" >'+LocalizedStrings.getUI(tm.toLowerCase())+'</div>';
  704. }
  705. for (var tm in Types) {
  706. if (tm == Types.VOID.toUpperCase()) {
  707. continue;
  708. }
  709. ret += '<div class="item">'
  710. + '<i class="dropdown icon"></i>'
  711. + LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())
  712. + '<div class="menu">'
  713. + '<div class="item" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] " data-type="'+tm+'" data-dimensions="1">[ ]</div>'
  714. + '<div class="item" data-text="'+ LocalizedStrings.getUI('vector')+':'+LocalizedStrings.getUI(tm.toLowerCase())+' [ ] [ ] " data-type="'+tm+'" data-dimensions="2">[ ] [ ] </div>'
  715. + '</div>'
  716. + '</div>';
  717. }
  718. ret += '</div></div>';
  719. ret += ' <i class="red icon times remove_parameter"></i></div>';
  720. ret = $(ret);
  721. function_container.find('.container_parameters_list').append(ret);
  722. ret.find('.remove_parameter').on('click', function(e){
  723. removeParameter(function_obj, parameter_obj, ret);
  724. });
  725. ret.find('.ui.dropdown.parameter_type').dropdown({
  726. onChange: function(value, text, $selectedItem) {
  727. if ($($selectedItem).data('dimensions')) {
  728. updateParameterType(parameter_obj, Types[$($selectedItem).data('type')], $($selectedItem).data('dimensions'));
  729. } else {
  730. updateParameterType(parameter_obj, Types[$($selectedItem).data('type')]);
  731. }
  732. }
  733. });
  734. ret.find('.label_enable_name_parameter').on('click', function(e){
  735. enableNameParameterUpdate(parameter_obj, ret);
  736. });
  737. }
  738. enableNameFunctionUpdate = function(function_obj, parent_node) {
  739. if (opened_name_function) {
  740. $(opened_input).focus();
  741. return;
  742. }
  743. $(parent_node).find('.span_name_function').text('');
  744. $( "<input type='text' class='width-dynamic input_name_function' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' value='"+function_obj.name+"' />" ).insertBefore($(parent_node).find('.span_name_function'));
  745. $('.width-dynamic').on('input', function() {
  746. var inputWidth = $(this).textWidth()+10;
  747. opened_input = this;
  748. $(this).focus();
  749. var tmpStr = $(this).val();
  750. $(this).val('');
  751. $(this).val(tmpStr);
  752. $(this).css({
  753. width: inputWidth
  754. })
  755. }).trigger('input');
  756. $('.width-dynamic').focusout(function() {
  757. /// update array:
  758. if ($(this).val().trim()) {
  759. function_obj.name = $(this).val().trim();
  760. }
  761. $(this).remove();
  762. $(parent_node).find('.span_name_function').text(function_obj.name);
  763. /// update elements:
  764. opened_name_function = false;
  765. opened_input = false;
  766. });
  767. $('.width-dynamic').on('keydown', function(e) {
  768. var code = e.keyCode || e.which;
  769. if(code == 13) {
  770. $('.functions_labels > [data-function=' + function_obj.name + ']')
  771. .attr('data-function', $(this).val().trim())
  772. .html('<i class="list icon"></i> ' + $(this).val().trim());
  773. if ($(this).val().trim()) {
  774. function_obj.name = $(this).val().trim();
  775. }
  776. $(this).remove();
  777. $(parent_node).find('.span_name_function').text(function_obj.name);
  778. /// update elements:
  779. opened_name_function = false;
  780. opened_input = false;
  781. }
  782. if(code == 27) {
  783. $(this).remove();
  784. $(parent_node).find('.span_name_function').text(function_obj.name);
  785. /// update elements:
  786. opened_name_function = false;
  787. opened_input = false;
  788. }
  789. });
  790. }
  791. addParameter = function (function_obj, function_container) {
  792. if (function_obj.parameters_list == null) {
  793. function_obj.parameters_list = [];
  794. }
  795. var new_parameter = new Models.Variable(Types.INTEGER, LocalizedStrings.getUI("new_parameter") + "_" + counter_new_parameters);
  796. function_obj.parameters_list.push(new_parameter);
  797. counter_new_parameters ++;
  798. renderParameter(function_obj, new_parameter, function_container);
  799. var menu_button = $('.functions_labels > [data-function=' + function_obj.name + ']');
  800. var params = "";
  801. for (var j = 0; j < function_obj.parameters_list.length; j++) {
  802. if (j > 0)
  803. params += ',';
  804. params += function_obj.parameters_list[j].type;
  805. }
  806. menu_button.find('.function_params').text(params);
  807. }
  808. updateReturnType = function (function_obj, new_type, new_dimensions = 0) {
  809. function_obj.return_type = new_type;
  810. function_obj.return_dimensions = new_dimensions;
  811. var menu_button = $('.functions_labels > [data-function=' + function_obj.name + ']');
  812. menu_button.find('.function_return_type').text(new_type);
  813. }
  814. updateParameterType = function (parameter_obj, new_type, new_dimensions = 0) {
  815. parameter_obj.type = new_type;
  816. parameter_obj.dimensions = new_dimensions;
  817. if (new_dimensions > 0) {
  818. parameter_obj.rows = new_dimensions;
  819. parameter_obj.columns = 2;
  820. }
  821. var menu_button = $('.functions_labels > [data-function=' + function_obj.name + ']');
  822. var params = "";
  823. for (var j = 0; j < function_obj.parameters_list.length; j++) {
  824. if (j > 0)
  825. params += ',';
  826. params += function_obj.parameters_list[j].type;
  827. }
  828. menu_button.find('.function_params').text(params);
  829. }