Browse Source

Merge branch 'expression_keyboard_input' of LInE/iVProg into master

GitAdmin 3 năm trước cách đây
mục cha
commit
aef2b36f09

+ 21 - 0
css/ivprog-visual-1.0.css

@@ -1140,4 +1140,25 @@ i.button_alternate_expression {
 	padding-left: .25rem;
 	cursor: pointer;
 	margin-top: .15rem;
+}
+
+.button_write_expression {
+	cursor: pointer;
+	margin-left: 1rem !important;
+}
+
+.input-expression-field {
+	width: 50%;
+}
+
+.expression-edit-confirm {
+	color: #32a852;
+	font-size: 1.2rem !important;
+	cursor: pointer;
+	margin-left: 1rem !important;
+  margin-right: 1rem !important;
+}
+
+.expression-edit-cancel {
+	cursor: pointer;
 }

+ 11 - 0
i18n/ui.csv

@@ -9,6 +9,9 @@ btn_arithmetic_division,Divisão,Division,División
 btn_arithmetic_module,Módulo,Remainder,Resto
 btn_break,Pare,break,break
 btn_case,Caso,Case,Caso
+expression_invalid,Expressão inválida. Verifique a sintáxe antes de continuar.,Invalid expression. Check the syntax before proceeding.,Expresión no válida. Verifique la sintaxis antes de continuar.
+expression_undelcared_variable,Variáveis não declaradas:,Undeclared variables:,Variables no declaradas:
+expression_undeclared_function,Funções não definidas:,Undefined functions:,Funcíon no declaradas:
 start,inicio,main,main
 type_void,vazio,void,void
 type_integer,inteiro,int,int
@@ -30,6 +33,14 @@ new_global,global,global,global
 new_function,nova_funcao,new_function,nueva_función
 matrix,matriz,matrix,matriz
 vector,vetor,vector,vector
+text_lock_expression,Bloquear expressão,Block expression,Expresión de bloque 
+text_unlock_expression,Desbloquear expressão,Unlock expression,Desbloquear expresión 
+text_edit_expression,Editar expressão manualmente,Edit expression manually,Editar expresión manualmente 
+text_edit_expression_confirm,Confirmar edição,Confirm edition,Confirmar edición
+text_edit_expression_cancel,Cancelar edição,Cancel edition,Cancelar edición
+text_add_function,Adicionar uma nova função ao programa,Add a new function to the program,Agregar una nueva función al programa
+text_move_command,Mover comando,Move command,Mover comando
+text_add_parameters,Adicionar um novo parâmetro,Add a new parameter,Agregar un nuevo parámetro
 text_comment_start,Comentário inicial da função...,Function initial comment,Comentario inicial de la función
 text_comment_main,Esta é a função principal...,This is the main funcion,Esta es la función principal
 text_read_var,Entrada/Leitura de dados,Input/Read data,Entrada/Lectura de dados

+ 1 - 0
js/io/domConsole.js

@@ -110,6 +110,7 @@ export class DOMConsole {
     this.input.setAttribute("name", "command");
     this.input.setAttribute("value", "");
     this.input.setAttribute("type", "text");
+    this.input.setAttribute("autocomplete", "off");
     this.inputDiv.append(this.input);
     this.termDiv.append(this.inputDiv);
     bashNode.append(this.termDiv);

+ 10 - 1
js/visualUI/algorithm.js

@@ -30,5 +30,14 @@ export function renderAlgorithm () {
 
 	if (settingsFilter && settingsFilter[0]) {
       blockAllEditingOptions();
-    } 
+		} 
+	
+	$('.command_drag').popup({
+    content : LocalizedStrings.getUI("text_move_command"),
+    delay: {
+      show: 1000,
+      hide: 0
+    }
+  });
+		
 }

+ 1 - 1
js/visualUI/code_generator.js

@@ -688,7 +688,7 @@ function readersCode (command_obj, indentation) {
   return ret;
 }
 
-function variableValueMenuCode (variable_obj, is_return = false) {
+export function variableValueMenuCode (variable_obj, is_return = false) {
   let ret = "";
   try {
     if (variable_obj.function_called) {

+ 137 - 1
js/visualUI/commands/attribution.js

@@ -5,6 +5,7 @@ import * as VariableValueMenuManagement from './variable_value_menu';
 import * as CommandsManagement from '../commands';
 import * as ExpressionManagement from './generic_expression';
 import * as CodeGenerator from '../code_generator';
+import { renderAlgorithm } from '../algorithm';
 
 export function createFloatingCommand () {
 	return $('<div class="ui attribution created_element"> <i class="ui icon small arrow left"></i> <span> x <&#8212; 1 + 1 </span></div>');
@@ -12,7 +13,7 @@ export function createFloatingCommand () {
 
 export function renderCommand (command, function_obj) {
 	var el = $('<div class="ui attribution command_container"><i class="ui icon small arrow left command_drag"></i> <i class="ui icon times red button_remove_command"></i> <div class="var_attributed"></div> <span class="text_attr_receives span_command_spec">'+LocalizedStrings.getUI('text_receives')+'</span> '
-		 + '<div class="expression_elements"></div>  <span class="textual_expression"></span> <i class="ui icon unlock button_alternate_expression"></i> </div>');
+		 + '<div class="expression_elements"></div>  <span class="textual_expression"></span> <i class="ui icon i cursor button_write_expression"></i> <i class="ui icon unlock button_alternate_expression"></i> </div>');
 	el.data('command', command);
 
 	VariableValueMenu.renderMenu(command, command.variable, el.find('.var_attributed'), function_obj);
@@ -42,6 +43,29 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.button_write_expression').popup({
+		content : LocalizedStrings.getUI("text_edit_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
+
 	return el;
 
 }
@@ -428,6 +452,101 @@ function addMenuItens (command, function_obj, expression_div) {
 
 function addHandlers (command, function_obj, attribution_dom) {
 
+	attribution_dom.find('.button_write_expression').on('click', function() {
+
+		window.expressionEdition = true;
+		window.inputExpression = null;
+		
+		var afterWhichElement;
+		var lockButton = $(attribution_dom.find('.button_alternate_expression')[0]);
+		var editButton = $(this);
+
+		afterWhichElement = attribution_dom.find('.expression_elements');
+
+		if (command.lockexpression) {
+			afterWhichElement = attribution_dom.find('.textual_expression');
+		}
+
+		var text = "";
+		if (command.expression) {
+			if (command.expression.length == 1 && command.expression[0].content == null && !command.expression[0].function_called) {
+				text = "";
+			} else {
+				try {
+					text = CodeGenerator.elementExpressionCode(command.expression);
+				} catch(ex) {
+					text = "";
+				}
+			}
+		}
+
+		var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
+		var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
+		var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
+		input.val(text);
+
+		input.focusout(function(evt) {
+			console.log('focosout event!');
+			ok_button.click();
+			evt.preventDefault();
+			return true;
+		});
+		
+		input.keyup(function(evt) {
+			if (evt.keyCode == 27) { // esc
+				cancel_button.click();
+			} 
+			if (evt.keyCode == 13) { // enter
+				ok_button.click();
+			}
+		});
+
+		ok_button.click(function() {
+			var parsed = null;
+			parsed = ExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		cancel_button.mousedown(function(evt) {
+			var parsed = ExpressionManagement.expressionParserToVisual(text, function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		input.insertAfter(afterWhichElement);
+		input.focus();
+		cancel_button.insertAfter(input);
+		ok_button.insertAfter(input);
+		var len = text.length; 
+		input[0].setSelectionRange(len, len); 
+
+		afterWhichElement.css('display', 'none');
+		lockButton.css('display', 'none');
+		editButton.css('display', 'none');
+
+		ok_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_confirm"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+		cancel_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_cancel"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+	});
+
 	$(attribution_dom.find('.textual_expression')[0]).toggle();
 	
 	attribution_dom.find('.button_alternate_expression').on('click', function() {
@@ -440,6 +559,23 @@ function addHandlers (command, function_obj, attribution_dom) {
 				$(this).toggleClass('unlock').toggleClass('lock');
 				command.lockexpression = !command.lockexpression;
 			}
+			if (command.lockexpression) {
+				attribution_dom.find('.lock').popup({
+					content : LocalizedStrings.getUI("text_unlock_expression"),
+					delay: {
+						show: 750,
+						hide: 0
+					}
+				});
+			} else {
+				attribution_dom.find('.unlock').popup({
+					content : LocalizedStrings.getUI("text_lock_expression"),
+					delay: {
+						show: 750,
+						hide: 0
+					}
+				});
+			}
 		}
 	});
 

+ 135 - 1
js/visualUI/commands/dowhiletrue.js

@@ -15,7 +15,7 @@ export function renderCommand (command, function_obj) {
 	ret += '<div class="ui block_commands" data-subblock="" data-idcommand="">';
 	ret += '</div>';
 	ret += ' <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_do_until') + ' </span> <span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="textual_expression"></span> <span class="span_command_spec"> ) </span>';
-	ret += ' <i class="ui icon unlock button_alternate_expression"></i> <div class="ui context_menu"></div> ';
+	ret += '  <i class="ui icon i cursor button_write_expression" style="display: inline !important;"></i> <i class="ui icon unlock button_alternate_expression" style="margin-left: 1rem !important;"></i> <div class="ui context_menu"></div> ';
 	ret += '</div>';
 
 	var el = $(ret);
@@ -54,12 +54,128 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.button_write_expression').popup({
+		content : LocalizedStrings.getUI("text_edit_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
 	return el;
 }
 
 
 function addHandlers (command, function_obj, dowhiletrue_dom) {
 
+	dowhiletrue_dom.find('.button_write_expression').on('click', function() {
+
+		window.expressionEdition = true;
+		window.inputExpression = null;
+		
+		var afterWhichElement;
+		var lockButton = $(dowhiletrue_dom.find('.button_write_expression')[dowhiletrue_dom.find('.button_write_expression').length - 1]);
+		var editButton = $(this);
+
+		afterWhichElement = $(dowhiletrue_dom.find('.conditional_expression')[dowhiletrue_dom.find('.conditional_expression').length - 1]);
+
+		if (command.lockexpression) {
+			afterWhichElement = $(dowhiletrue_dom.find('.textual_expression')[dowhiletrue_dom.find('.textual_expression').length - 1]);
+		}
+
+		var text = "";
+		if (command.expression) {
+			if (command.expression.length == 1 && command.expression[0].content == null && !command.expression[0].function_called) {
+				text = "";
+			} else {
+				try {
+					text = CodeGenerator.elementExpressionCode(command.expression);
+				} catch(ex) {
+					text = "";
+				}
+			}
+		}
+
+		var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
+		var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
+		var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
+		input.val(text);
+
+		input.focusout(function(evt) {
+			ok_button.click();
+			evt.preventDefault();
+			return true;
+		});
+		
+		input.keyup(function(evt) {
+			if (evt.keyCode == 27) { // esc
+				cancel_button.click();
+			} 
+			if (evt.keyCode == 13) { // enter
+				ok_button.click();
+			}
+		});
+
+		ok_button.click(function() {
+			var parsed = null;
+			parsed = GenericExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		cancel_button.mousedown(function(evt) {
+			var parsed = GenericExpressionManagement.expressionParserToVisual(text, function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		input.insertAfter(afterWhichElement);
+		input.focus();
+		cancel_button.insertAfter(input);
+		ok_button.insertAfter(input);
+		var len = text.length; 
+		input[0].setSelectionRange(len, len); 
+
+		afterWhichElement.css('display', 'none');
+		lockButton.css('display', 'none');
+		editButton.css('display', 'none');
+
+		ok_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_confirm"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+		cancel_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_cancel"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+	});
+
 	dowhiletrue_dom.find('.minimize_block_button').on('click', function(evt){
 		dowhiletrue_dom.children('.ui.block_commands').toggle();
 		command.collapsed = !command.collapsed;
@@ -79,6 +195,24 @@ function addHandlers (command, function_obj, dowhiletrue_dom) {
 				command.lockexpression = !command.lockexpression;
 			}
 		}
+
+		if (command.lockexpression) {
+			dowhiletrue_dom.find('.lock').popup({
+				content : LocalizedStrings.getUI("text_unlock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		} else {
+			dowhiletrue_dom.find('.unlock').popup({
+				content : LocalizedStrings.getUI("text_lock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		}
 	});
 
 	dowhiletrue_dom.find('.button_remove_command').on('click', function() {

+ 330 - 0
js/visualUI/commands/generic_expression.js

@@ -4,6 +4,7 @@ import { LocalizedStrings } from "../../services/localizedStringsService";
 import * as VariableValueMenuManagement from "./variable_value_menu";
 import { registerUserEvent, ActionTypes } from "../../services/userLog";
 import WatchJS from "melanke-watchjs";
+import * as Utils from '../utils';
 
 window.timer = false;
 
@@ -1302,3 +1303,332 @@ function getSeparator () {
     "write_seprator_menu_text"
   )}</div>`;
 }
+
+function getVariable (function_obj, search) {
+  if (search == ")" || search == "(") {
+    return search;
+  }
+
+  if (search.instance == "operator") {
+    var obj;
+    switch (search.value) {
+      case '+':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_arithmetic, 
+                  Models.ARITHMETIC_TYPES.plus); 
+        break;
+      case '-':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_arithmetic, 
+                  Models.ARITHMETIC_TYPES.minus); 
+        break;
+      case '*':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_arithmetic, 
+                  Models.ARITHMETIC_TYPES.multiplication); 
+        break;
+      case '/':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_arithmetic, 
+                  Models.ARITHMETIC_TYPES.division); 
+        break;
+      case '%':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_arithmetic, 
+                  Models.ARITHMETIC_TYPES.module); 
+        break;
+      case '>':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_conditional, 
+                    Models.ARITHMETIC_COMPARISON.greater_than); 
+          break;
+      case '<':
+        obj = new Models.ExpressionOperator(
+                  Models.EXPRESSION_TYPES.exp_conditional, 
+                  Models.ARITHMETIC_COMPARISON.less_than); 
+        break;
+      case '>=':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_conditional, 
+                    Models.ARITHMETIC_COMPARISON.greater_than_or_equals_to); 
+          break;
+      case '<=':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_conditional, 
+                    Models.ARITHMETIC_COMPARISON.less_than_or_equals_to); 
+          break;
+      case '==':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_conditional, 
+                    Models.ARITHMETIC_COMPARISON.equals_to); 
+          break;
+      case '!=':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_conditional, 
+                    Models.ARITHMETIC_COMPARISON.not_equals_to); 
+          break;
+      case 'and':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_logic, 
+                    Models.LOGIC_COMPARISON.and); 
+          break;
+      case 'or':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_logic, 
+                    Models.LOGIC_COMPARISON.or); 
+          break;
+      case 'not':
+          obj = new Models.ExpressionOperator(
+                    Models.EXPRESSION_TYPES.exp_logic, 
+                    Models.LOGIC_COMPARISON.not); 
+          break;
+    }
+    return obj;
+  }
+
+  if (search.instance == "expression" 
+          && search.type == "const") {
+      if (search.value === true) {
+        var obj = new Models.VariableValueMenu(
+          VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+          LocalizedStrings.getUI('logic_value_true'),
+          null,
+          null,
+          true
+        );
+        return obj;
+      }
+      if (search.value === false) {
+        var obj = new Models.VariableValueMenu(
+          VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+          LocalizedStrings.getUI('logic_value_false'),
+          null,
+          null,
+          true
+        );
+        return obj;
+      }
+      var obj = new Models.VariableValueMenu(
+        VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+        search.value,
+        null,
+        null,
+        true
+      );
+      return obj;
+    }
+
+  var variavel = null;
+  if (search.instance == "expression"
+    && search.type == "var") {
+    // 1. Procurar a variável na função:
+    for (var j = 0; j < function_obj.variables_list.length; j++) {
+      if (function_obj.variables_list[j].name == search.value) {
+        variavel = function_obj.variables_list[j];
+        break;
+      }
+    }
+
+    // 2. Procurar a variável nas gloais: 
+    if (!variavel)
+      for (var j = 0; j < program_obj.globals.length; j++) {
+        if (program_obj.globals[j].name == search.value) {
+          variavel = program_obj.globals[j];
+          break;
+        }
+      }
+    
+    // 3. Procurar na lista de parâmetros: 
+    if (!variavel)
+      for (var j = 0; j < function_obj.parameters_list.length; j++) {
+        if (function_obj.parameters_list[j].name == search.value) {
+          variavel = function_obj.parameters_list[j];
+          break;
+        }
+      }
+  }
+
+  if (search.instance == "expression"
+    && search.type == "var"
+    && !search.line) {
+
+    var obj = new Models.VariableValueMenu(
+      VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+      variavel,
+      null,
+      null,
+      true
+    );
+    return obj;
+  }
+
+  if (search.instance == "expression"
+    && search.type == "var"
+    && search.class == "vector") {
+      
+    var obj = new Models.VariableValueMenu(
+      VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+      variavel,
+      null,
+      getVariable(function_obj, search.line[0]),
+      true
+    );
+    return obj;
+  }
+
+  if (search.instance == "expression"
+    && search.type == "var"
+    && search.class == "matrix") {
+    var obj = new Models.VariableValueMenu(
+      VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+      variavel,
+      getVariable(function_obj, search.line[0]),
+      getVariable(function_obj, search.column[0]),
+      true
+    );
+    return obj;
+  }
+
+  if (search.instance == "expression"
+    && search.type == "function") {
+    var obj = new Models.VariableValueMenu(
+      VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+      variavel,
+      null,
+      null,
+      true
+    );
+    // Procurar a função para referência:
+    for (var i = 0; i < program_obj.functions.length; i++) {
+      if (program_obj.functions[i].name == search.value) {
+        obj.function_called = program_obj.functions[i];
+      }
+    }
+
+    // Se ainda não foi encontrada, procurar na biblioteca do iVProg:
+    if (!obj.function_called) {
+      for (var i = 0; i < window.system_functions.length; i++) {
+        if (search.value.split(".")[1] && search.value.split(".")[1] 
+            == window.system_functions[i].identifier) {
+          obj.function_called = window.system_functions[i];
+        } else if (search.value == window.system_functions[i].identifier) {
+          obj.function_called = window.system_functions[i];
+        }
+      }
+    }
+
+    obj.parameters_list = [];
+
+    for (var i = 0; i < search.params.length; i++) {
+      obj.parameters_list.push(getVariable(function_obj,search.params[i][0]));
+    }
+    return obj;
+  }
+}
+
+export function expressionParserToVisual (text, function_obj, input_field) {
+
+  if (text.trim().length == 0) {
+    return [new Models.VariableValueMenu(
+      VariableValueMenuManagement.VAR_OR_VALUE_TYPES.all,
+      null,
+      null,
+      null,
+      true
+    )];
+  }
+
+  var var_not_found = [];
+  var fun_not_found = [];
+  var parsed;
+  try {
+    parsed = ivprogCore.parseExpression(text);
+  } catch (ex) {
+    Utils.renderErrorMessage(input_field, LocalizedStrings.getUI('expression_invalid'));
+  }
+  if (!parsed) return null;
+
+  for (var i = 0; i < parsed.length; i++) {
+    var variavel = null;
+    if (parsed[i].instance == "expression"
+          && parsed[i].type == "var") {
+      // 1. Procurar a variável na função:
+      for (var j = 0; j < function_obj.variables_list.length; j++) {
+        if (function_obj.variables_list[j].name == parsed[i].value) {
+          variavel = function_obj.variables_list[j];
+          break;
+        }
+      }
+
+      // 2. Procurar a variável nas globais: 
+      if (!variavel)
+        for (var j = 0; j < program_obj.globals.length; j++) {
+          if (program_obj.globals[j].name == parsed[i].value) {
+            variavel = program_obj.globals[j];
+            break;
+          }
+        }
+
+      // 3. Procurar a variável nos parâmetros:
+      if (!variavel)
+        for (var j = 0; j < function_obj.parameters_list.length; j++) {
+          if (function_obj.parameters_list[j].name == parsed[i].value) {
+            variavel = function_obj.parameters_list[j];
+            break;
+          }
+        }
+      
+      if (!variavel)
+        var_not_found.push(parsed[i].value);
+    }
+
+    var funcao;
+    if (parsed[i].instance == "expression"
+      && parsed[i].type == "function") {
+    
+      // Procurar a função para referência:
+      for (var j = 0; j < program_obj.functions.length; j++) {
+        if (program_obj.functions[j].name == parsed[i].value) {
+          funcao = program_obj.functions[j];
+        }
+      }
+
+      // Se ainda não encontrou, procurar na biblioteca do iVProg:
+      if (!funcao) {
+        for (var j = 0; j < window.system_functions.length; j++) {
+          if (parsed[i].value.split(".")[1] && parsed[i].value.split(".")[1] 
+              == window.system_functions[j].identifier) {
+            funcao = window.system_functions[j];
+          } else if (parsed[i].value == window.system_functions[j].identifier) {
+            funcao = window.system_functions[j];
+          }
+        }
+      }
+
+    if (!funcao) {
+      fun_not_found.push(parsed[i].value);
+    }
+  }
+}
+
+  if (fun_not_found.length > 0) {
+    let uniqueWords = [...new Set(fun_not_found)];
+    Utils.renderErrorMessage(input_field,  LocalizedStrings.getUI('expression_undeclared_function') + " " + uniqueWords.join(", "));
+    return null;
+  }
+
+  if (var_not_found.length > 0) {
+    let uniqueWords = [...new Set(var_not_found)];
+    Utils.renderErrorMessage(input_field,  LocalizedStrings.getUI('expression_undelcared_variable') + " " + uniqueWords.join(", "));
+    return null;
+  }
+
+  var exp_obj = [];
+  for (var i = 0; i < parsed.length; i++) {
+    exp_obj.push(getVariable(function_obj, parsed[i]));
+  }
+
+  
+
+  return exp_obj;
+}

+ 135 - 1
js/visualUI/commands/iftrue.js

@@ -12,6 +12,7 @@ export function renderCommand (command, function_obj) {
 	ret += '<div class="ui iftrue command_container"><div class="ui data_block_if" data-if="true">  <i class="ui icon small random command_drag"></i> <i class="ui icon times red button_remove_command"></i> <button class="ui icon button minimize_block_button tiny"><i class="icon window minimize"></i></button>';
 	ret += '<span class="span_command_spec"> ' + LocalizedStrings.getUI('text_if') + '</span>';
 	ret += ' <span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="textual_expression"></span> <span class="span_command_spec"> ) </span> ';
+	ret += '  <i class="ui icon i cursor button_write_expression" style="margin-right: 1rem !important;"></i>  ';
 	ret += '<i class="ui icon unlock button_alternate_expression"></i>';
 	ret += '<span> </span> ';
 	ret += '<div class="ui block_commands commands_if conditional_comands_block" data-if="true">';
@@ -32,7 +33,6 @@ export function renderCommand (command, function_obj) {
 	addHandlers(command, function_obj, el);
 
 	//ConditionalExpressionManagement.renderExpression(command, command.expression, function_obj, el.find('.conditional_expression'));
-
 	GenericExpressionManagement.renderExpression(command, function_obj, el.find('.conditional_expression'), command.expression);
 
 	if (command.commands_block) {
@@ -67,12 +67,128 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.button_write_expression').popup({
+		content : LocalizedStrings.getUI("text_edit_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
 	return el;
 }
 
 
 function addHandlers (command, function_obj, iftrue_dom) {
 
+	iftrue_dom.find('.button_write_expression').on('click', function() {
+
+		window.expressionEdition = true;
+		window.inputExpression = null;
+		
+		var afterWhichElement;
+		var lockButton = $(iftrue_dom.find('.button_alternate_expression')[0]);
+		var editButton = $(this);
+
+		afterWhichElement = $(iftrue_dom.find('.conditional_expression')[0]);
+
+		if (command.lockexpression) {
+			afterWhichElement = $(iftrue_dom.find('.textual_expression')[0]);
+		}
+
+		var text = "";
+		if (command.expression) {
+			if (command.expression.length == 1 && command.expression[0].content == null && !command.expression[0].function_called) {
+				text = "";
+			} else {
+				try {
+					text = CodeGenerator.elementExpressionCode(command.expression);
+				} catch(ex) {
+					text = "";
+				}
+			}
+		}
+
+		var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
+		var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
+		var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
+		input.val(text);
+
+		input.focusout(function(evt) {
+			ok_button.click();
+			evt.preventDefault();
+			return true;
+		});
+		
+		input.keyup(function(evt) {
+			if (evt.keyCode == 27) { // esc
+				cancel_button.click();
+			} 
+			if (evt.keyCode == 13) { // enter
+				ok_button.click();
+			}
+		});
+
+		ok_button.click(function() {
+			var parsed = null;
+			parsed = GenericExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		cancel_button.mousedown(function(evt) {
+			var parsed = GenericExpressionManagement.expressionParserToVisual(text, function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		input.insertAfter(afterWhichElement);
+		input.focus();
+		cancel_button.insertAfter(input);
+		ok_button.insertAfter(input);
+		var len = text.length; 
+		input[0].setSelectionRange(len, len); 
+
+		afterWhichElement.css('display', 'none');
+		lockButton.css('display', 'none');
+		editButton.css('display', 'none');
+
+		ok_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_confirm"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+		cancel_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_cancel"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+	});
+
 	$(iftrue_dom.find('.textual_expression')[0]).toggle();
 	
 	iftrue_dom.find('.button_alternate_expression').on('click', function() {
@@ -86,6 +202,24 @@ function addHandlers (command, function_obj, iftrue_dom) {
 				command.lockexpression = !command.lockexpression;
 			}
 		}
+
+		if (command.lockexpression) {
+			iftrue_dom.find('.lock').popup({
+				content : LocalizedStrings.getUI("text_unlock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		} else {
+			iftrue_dom.find('.unlock').popup({
+				content : LocalizedStrings.getUI("text_lock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		}
 	});
 
 	iftrue_dom.find('.button_remove_command').on('click', function() {

+ 33 - 0
js/visualUI/commands/repeatNtimes.js

@@ -107,6 +107,21 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
 	return el;
 }
 
@@ -218,6 +233,24 @@ function addHandlers (command, function_obj, repeatNtimes_dom) {
 
 			command.lockexpression = !command.lockexpression;
 		}
+
+		if (command.lockexpression) {
+			repeatNtimes_dom.find('.lock').popup({
+				content : LocalizedStrings.getUI("text_unlock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		} else {
+			repeatNtimes_dom.find('.unlock').popup({
+				content : LocalizedStrings.getUI("text_lock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		}
 	});
 
 	repeatNtimes_dom.find('.button_remove_command').on('click', function() {

+ 136 - 1
js/visualUI/commands/whiletrue.js

@@ -14,7 +14,7 @@ export function renderCommand (command, function_obj) {
 	ret += '<div class="ui whiletrue command_container"> <i class="ui icon small sync command_drag"></i> <i class="ui icon times red button_remove_command"></i><button class="ui icon button minimize_block_button tiny"><i class="icon window minimize"></i></button> <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_while') + ' </span>';
 	ret += '<span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="textual_expression"></span> <span class="span_command_spec"> ) </span>';
 	ret += ' </span>';
-	ret += '<i class="ui icon unlock button_alternate_expression"></i> <div class="ui context_menu"></div>';
+	ret += ' <i class="ui icon i cursor button_write_expression" style="margin-right: 1rem !important;"></i>  <i class="ui icon unlock button_alternate_expression"></i> <div class="ui context_menu"></div>';
 	ret += '<div class="ui block_commands">';
 	ret += '</div>';
 	ret += '<span> </span>';
@@ -54,11 +54,128 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 	
+	el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.button_write_expression').popup({
+		content : LocalizedStrings.getUI("text_edit_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
 	return el;
 }
 
 function addHandlers (command, function_obj, whiletrue_dom) {
 
+	whiletrue_dom.find('.button_write_expression').on('click', function() {
+
+		window.expressionEdition = true;
+		window.inputExpression = null;
+		
+		var afterWhichElement;
+		var lockButton = $(whiletrue_dom.find('.button_alternate_expression')[0]);
+		var editButton = $(this);
+
+		afterWhichElement = $(whiletrue_dom.find('.conditional_expression')[0]);
+
+		if (command.lockexpression) {
+			afterWhichElement = $(whiletrue_dom.find('.textual_expression')[0]);
+		}
+
+		var text = "";
+		if (command.expression) {
+			if (command.expression.length == 1 && command.expression[0].content == null && !command.expression[0].function_called) {
+				text = "";
+			} else {
+				try {
+					text = CodeGenerator.elementExpressionCode(command.expression);
+				} catch(ex) {
+					text = "";
+				}
+			}
+		}
+
+		var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
+		var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
+		var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
+		input.val(text);
+
+		input.focusout(function(evt) {
+			console.log('focosout event!');
+			ok_button.click();
+			evt.preventDefault();
+			return true;
+		});
+		
+		input.keyup(function(evt) {
+			if (evt.keyCode == 27) { // esc
+				cancel_button.click();
+			} 
+			if (evt.keyCode == 13) { // enter
+				ok_button.click();
+			}
+		});
+
+		ok_button.click(function() {
+			var parsed = null;
+			parsed = GenericExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		cancel_button.mousedown(function(evt) {
+			var parsed = GenericExpressionManagement.expressionParserToVisual(text, function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.expression = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		input.insertAfter(afterWhichElement);
+		input.focus();
+		cancel_button.insertAfter(input);
+		ok_button.insertAfter(input);
+		var len = text.length; 
+		input[0].setSelectionRange(len, len); 
+
+		afterWhichElement.css('display', 'none');
+		lockButton.css('display', 'none');
+		editButton.css('display', 'none');
+
+		ok_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_confirm"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+		cancel_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_cancel"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+	});
+
 	whiletrue_dom.find('.minimize_block_button').on('click', function(evt){
 		whiletrue_dom.children('.ui.block_commands').toggle();
 		command.collapsed = !command.collapsed;
@@ -77,6 +194,24 @@ function addHandlers (command, function_obj, whiletrue_dom) {
 				command.lockexpression = !command.lockexpression;
 			}
 		}
+
+		if (command.lockexpression) {
+			whiletrue_dom.find('.lock').popup({
+				content : LocalizedStrings.getUI("text_unlock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		} else {
+			whiletrue_dom.find('.unlock').popup({
+				content : LocalizedStrings.getUI("text_lock_expression"),
+				delay: {
+					show: 750,
+					hide: 0
+				}
+			});
+		}
 	});
 
 	whiletrue_dom.find('.button_remove_command').on('click', function() {

+ 136 - 0
js/visualUI/commands/writer.js

@@ -26,6 +26,7 @@ export function renderCommand (command, function_obj) {
     <img data-state="${command.newline ? "on" : "false"}" src="${
     command.newline ? "img/new_line.svg" : "img/no_new_line.svg"
   }" class="ivprog_newline_btn"/> 
+    <i class="ui icon i cursor button_write_expression" style="margin-left: 3rem !important; margin-right: -1.1rem !important;"></i> 
     <i class="ui icon unlock button_alternate_expression"></i>
     </div>`;
   const el = $(ret);
@@ -57,6 +58,28 @@ export function renderCommand (command, function_obj) {
     }
   }
 
+  el.find('.unlock').popup({
+		content : LocalizedStrings.getUI("text_lock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+	el.find('.lock').popup({
+		content : LocalizedStrings.getUI("text_unlock_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+  });
+  el.find('.button_write_expression').popup({
+		content : LocalizedStrings.getUI("text_edit_expression"),
+		delay: {
+			show: 750,
+			hide: 0
+		}
+	});
+
   return el;
 }
 
@@ -89,6 +112,101 @@ function addHandlersManager (
 function addHandlers (command, function_obj, writer_dom) {
 
   $(writer_dom.find('.textual_expression')[0]).toggle();
+
+  writer_dom.find('.button_write_expression').on('click', function() {
+
+		window.expressionEdition = true;
+		window.inputExpression = null;
+		
+		var afterWhichElement;
+		var lockButton = $(writer_dom.find('.button_alternate_expression')[0]);
+		var editButton = $(this);
+
+		afterWhichElement = writer_dom.find('.all_elements_write');
+
+		if (command.lockexpression) {
+			afterWhichElement = writer_dom.find('.textual_expression');
+		}
+
+		var text = "";
+		if (command.content) {
+			if (command.content.length == 1 && command.content[0].content == null && !command.content[0].function_called) {
+				text = "";
+			} else {
+				try {
+					text = CodeGenerator.elementExpressionCode(command.content);
+				} catch(ex) {
+					text = "";
+				}
+			}
+		}
+
+		var ok_button = $('<i class="ui icon check circle expression-edit-confirm"></i>');
+		var cancel_button = $('<i class="ui icon undo expression-edit-cancel"></i>');
+		var input = $('<input type="text" spellcheck="false" autocomplete="off" class="input-expression-field" >');
+		input.val(text);
+
+		input.focusout(function(evt) {
+			ok_button.click();
+			evt.preventDefault();
+			return true;
+		});
+		
+		input.keyup(function(evt) {
+			if (evt.keyCode == 27) { // esc
+				cancel_button.click();
+			} 
+			if (evt.keyCode == 13) { // enter
+				ok_button.click();
+			}
+		});
+
+		ok_button.click(function() {
+			var parsed = null;
+			parsed = GenericExpressionManagement.expressionParserToVisual(input.val(), function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.content = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		cancel_button.mousedown(function(evt) {
+			var parsed = GenericExpressionManagement.expressionParserToVisual(text, function_obj, input);
+			if (parsed) {
+				window.expressionEdition = false;
+				command.content = parsed;
+				renderAlgorithm();
+			}
+		});
+
+		input.insertAfter(afterWhichElement);
+		input.focus();
+		cancel_button.insertAfter(input);
+		ok_button.insertAfter(input);
+		var len = text.length; 
+		input[0].setSelectionRange(len, len); 
+
+		afterWhichElement.css('display', 'none');
+		lockButton.css('display', 'none');
+		editButton.css('display', 'none');
+
+		ok_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_confirm"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+		cancel_button.popup({
+			content : LocalizedStrings.getUI("text_edit_expression_cancel"),
+			delay: {
+				show: 750,
+				hide: 0
+			}
+		});
+	});
+
 	
 	writer_dom.find('.button_alternate_expression').on('click', function() {
 		if (command.content) {
@@ -99,6 +217,24 @@ function addHandlers (command, function_obj, writer_dom) {
 				$(writer_dom.find('.textual_expression')[0]).toggle();
 				$(this).toggleClass('unlock').toggleClass('lock');
 				command.lockexpression = !command.lockexpression;
+      }
+      
+      if (command.lockexpression) {
+				writer_dom.find('.lock').popup({
+					content : LocalizedStrings.getUI("text_unlock_expression"),
+					delay: {
+						show: 750,
+						hide: 0
+					}
+				});
+			} else {
+				writer_dom.find('.unlock').popup({
+					content : LocalizedStrings.getUI("text_lock_expression"),
+					delay: {
+						show: 750,
+						hide: 0
+					}
+				});
 			}
 		}
 	});

+ 14 - 0
js/visualUI/functions.js

@@ -462,6 +462,14 @@ export function renderFunction (function_obj) {
   
   cont ++;
 
+  appender.find('.add_parameter_button').popup({
+    content : LocalizedStrings.getUI("text_add_parameters"),
+    delay: {
+      show: 750,
+      hide: 0
+    }
+  });
+
   return appender;
 }
 
@@ -715,6 +723,12 @@ export function initVisualUI () {
   $(document.getElementById("ivprog-term-div")).draggable()
   $('.add_function_button').on('click', () => {
     addFunctionHandler();
+  }).popup({
+    content : LocalizedStrings.getUI("text_add_function"),
+    delay: {
+      show: 750,
+      hide: 0
+    }
   });
   $('.add_global_button').on('click', () => {
     window.insertContext = true;