Browse Source

Merge branch 'master' into features/accessible

Marcelo Vilas Boas Correa Filho 3 years ago
parent
commit
83c3e22a19

+ 88 - 11
css/ivprog-visual-1.0.css

@@ -138,17 +138,6 @@ body {
 	margin-right: 10px;
 }
 
-.case_commands_block {
-	/*border: 1px solid red;*/
-}
-
-.context_menu {
-	display: inline;
-	float: right; 
-	margin-right: 25px;
-	margin-top: -4px;
-}
-
 .case_div {
 	border: 1px solid gray;
 	margin-left: 30px;
@@ -1085,3 +1074,91 @@ div.ui.checkbox.transition.visible {
   height: 32px;
   cursor: pointer;
 }
+
+.ui.icon.button.minimize_block_button {
+	background: none;
+	float: right;
+	padding-top: .25rem;
+	margin-right: .3rem;
+}
+
+div.ui.dropdown.menu_commands.pause {
+
+}
+
+.context_menu {
+	display: inline;
+	margin-left: 1rem;
+}
+
+.data_block_if span.textual_expression,
+.ui.dowhiletrue span.textual_expression,
+.ui.whiletrue span.textual_expression,
+.attribution span.textual_expression,
+.writer span.textual_expression,
+.return span.textual_expression {
+	color: #2325a6;
+	font-weight: bold;
+	font-size: 1.2rem;
+}
+
+i.button_alternate_expression {
+	cursor: pointer;
+	font-size: 1.1rem;
+	margin-left: 0.3rem;
+	color: black;
+}
+
+.attribution i.button_alternate_expression {
+	margin-left: .8rem;
+}
+.repeatN_text_par_1, .repeatN_text_par_2, 
+.repeatN_text_par_3, .repeatN_text_par_4 {
+	margin-left: .2rem;
+	font-weight: bold;
+	font-size: 1.2rem;
+	margin-right: .3rem;
+	color: #2325a6;
+}
+
+.repeatN_text_par_1 {
+	margin-left: -1.2rem;
+}
+
+.writer .button_alternate_expression {
+	margin-left: 2.5rem;
+}
+
+.ui.dropdown.menu_commands.pause button {
+	border: none;
+	background: #f2711c;
+	color: white;
+	border-radius: .2rem;
+	padding: .1rem;
+	padding-left: 0.1rem;
+	font-size: .9rem;
+	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

File diff suppressed because it is too large
+ 381 - 250
js/ast/ivprogParser.js


+ 31 - 0
js/iassign-integration-functions.js

@@ -20,11 +20,42 @@ var iLMparameters = {
 // and no dependency to the global scope, avoind future 'strict mode' problems
 //localStorage.setItem('ivprog.lang', iLMparameters.lang);
 
+function removeCollapseValue (command) {
+  if (command.collapsed) {
+    delete command.collapsed;
+  }
+  if (command.type == 'iftrue') {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+    if (command.commands_else)
+      for (var i = 0; i < command.commands_else.length; i++) {
+        removeCollapseValue(command.commands_else[i]);
+      }
+  } else if (command.type == 'repeatNtimes' 
+            || command.type == 'whiletrue' 
+            || command.type == 'dowhiletrue' ) {
+    if (command.commands_block)
+      for (var i = 0; i < command.commands_block.length; i++) {
+        removeCollapseValue(command.commands_block[i]);
+      }
+  }
+}
+
 // Função chamada pelo iTarefa quando o professor finaliza a criação da atividade
 // ou quando o aluno finaliza a resolução do exercício
 // O retorno é um JSON com os dados do exercício ou da resolução
 // Esse retorno será armazenado no banco de dados do Moodle, pelo iTarefa
 function getAnswer () {
+  // Remover o colapsar usado localmente:
+  if (window.program_obj) {
+    for (var i = 0; i < window.program_obj.functions.length; i++) {
+      for (var j = 0; j < window.program_obj.functions[i].commands.length; j++) {
+        removeCollapseValue(window.program_obj.functions[i].commands[j]);
+      }
+    }
+  }
   // Se o parâmetro "iLM_PARAM_SendAnswer" for false,
   // então trata-se de resolução de atividade
   if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {

+ 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);

+ 4 - 3
js/main.js

@@ -22,8 +22,9 @@ import {
   prepareActivityToStudentHelper,
   autoEval,
 } from "./util/iassignHelpers";
-import {openAssessmentDetail} from "./util/utils";
-import {Config} from "./util/config";
+import { openAssessmentDetail } from "./util/utils";
+import { Config } from "./util/config";
+import { parseExpression } from "./util/parseFromVisual";
 import * as CodeEditorAll from "./visualUI/text_editor";
 import {autoGenerateTestCaseOutput} from "./util/auto_gen_output";
 
@@ -61,5 +62,5 @@ export {
   autoGenerateTestCaseOutput,
   Config,
   initAccessibleUI,
+  parseExpression,
 };
-

+ 1 - 1
js/processor/ivprogProcessor.js

@@ -146,7 +146,7 @@ export class IVProgProcessor {
       funcStore,
       func.variablesDeclarations
     );
-    const finalSto = this.executeCommands(stoWithVars, func.commands);
+    const finalSto = await this.executeCommands(stoWithVars, func.commands);
     this.stores.pop();
     this.context.pop();
     return finalSto;

+ 16 - 20
js/util/outputTest.js

@@ -1,7 +1,6 @@
-import { Output } from './../io/output';
+import { Output } from "./../io/output";
 
 export class OutputTest extends Output {
-
   constructor () {
     super();
     this.list = [];
@@ -10,7 +9,7 @@ export class OutputTest extends Output {
 
   write (text, newLine = false) {
     if (this.currentLine == null) {
-      this.currentLine = this.list.push('') - 1;
+      this.currentLine = this.list.push("") - 1;
     }
 
     this.list[this.currentLine] += text;
@@ -20,25 +19,22 @@ export class OutputTest extends Output {
   }
 
   sendOutput (text) {
-    let output = '' + text;
-    if (output.indexOf('\n') !== -1) {
-      const outputList = output.split('\n');
-      let last = outputList.pop();
-      outputList.forEach( t => {
-        t = t.replace(/\t/g, '&#x0020;&#x0020;');
-        t = t.replace(/\s/g, "&#x0020;");
-        if (t.length == 0)
-          this.currentLine = null;
-        else
-          this.write(t, true);
+    const output = "" + text;
+    if (output.indexOf("\n") !== -1) {
+      const outputList = output.split("\n");
+      const last = outputList.pop();
+      outputList.forEach((t) => {
+        //t = t.replace(/\t/g, '&#x0020;&#x0020;');
+        //t = t.replace(/\s/g, "&#x0020;");
+        if (t.length == 0) this.currentLine = null;
+        else this.write(t, true);
       });
-      last = last.replace(/\t/g, '&#x0020;&#x0020;');
-      last = last.replace(/\s/g, "&#x0020;");
-      if (last.length != 0)
-        this.write(last);
+      //last = last.replace(/\t/g, '&#x0020;&#x0020;');
+      //last = last.replace(/\s/g, "&#x0020;");
+      if (last.length != 0) this.write(last);
     } else {
-      output = output.replace(/\t/g, '&#x0020;&#x0020;');
-      output = output.replace(/\s/g, "&#x0020;");
+      //output = output.replace(/\t/g, '&#x0020;&#x0020;');
+      //output = output.replace(/\s/g, "&#x0020;");
       this.write(output);
     }
   }

+ 143 - 0
js/util/parseFromVisual.js

@@ -0,0 +1,143 @@
+import { IVProgParser } from "../ast/ivprogParser";
+import * as Expressions from "../ast/expressions";
+import { Types } from "../typeSystem/types";
+import { convertBoolToString } from "../typeSystem/parsers";
+
+const TYPES = {
+  VARIABLE: "var",
+  CONST: "const",
+  FUNCTION: "function",
+  RELATIONAL: "relational",
+  LOGIC: "logic",
+  ARITHMETIC: "arithmetic",
+};
+
+function translateOp (type, op) {
+  switch (type) {
+    case TYPES.ARITHMETIC:
+      return op.value;
+    case TYPES.RELATIONAL:
+      return op.value;
+    case TYPES.LOGIC: {
+      if (op.ord === 11) {
+        return "and";
+      } else if (op.ord === 12) {
+        return "or";
+      } else {
+        return "not";
+      }
+    }
+  }
+}
+
+function getOpType (op) {
+  switch (op.ord) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return TYPES.ARITHMETIC;
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+      return TYPES.RELATIONAL;
+    default:
+      return TYPES.LOGIC;
+  }
+}
+
+function expressionWalker (expression) {
+  let result;
+  if (expression instanceof Expressions.VariableLiteral) {
+    result = [
+      { instance: "expression", type: TYPES.VARIABLE, value: expression.id },
+    ];
+  } else if (expression instanceof Expressions.FunctionCall) {
+    const funcObj = {
+      instance: "expression",
+      type: TYPES.FUNCTION,
+      value: expression.id,
+    };
+    const paramsList = expression.actualParameters.map((e) =>
+      expressionWalker(e)
+    );
+    //const params = Array.prototype.concat.apply([], paramsList);
+    funcObj.params = paramsList;
+    result = [funcObj];
+  } else if (expression instanceof Expressions.UnaryApp) {
+    const left = expressionWalker(expression.left);
+    const opType = getOpType(expression.op);
+    const opValue = translateOp(opType, expression.op);
+    result = [{ instance: "operator", type: opType, value: opValue }, ...left];
+  } else if (expression instanceof Expressions.InfixApp) {
+    const left = expressionWalker(expression.left);
+    const right = expressionWalker(expression.right);
+    const opType = getOpType(expression.op);
+    const opValue = translateOp(opType, expression.op);
+    result = [
+      ...left,
+      { instance: "operator", type: opType, value: opValue },
+      ...right,
+    ];
+  } else if (expression instanceof Expressions.ArrayAccess) {
+    const line = expressionWalker(expression.line);
+    let arrayClass = "vector";
+    let column = null;
+    if (expression.column) {
+      arrayClass = "matrix";
+      column = expressionWalker(expression.column);
+    }
+    result = [
+      {
+        instance: "expression",
+        type: TYPES.VARIABLE,
+        class: arrayClass,
+        column: column,
+        line: line,
+        value: expression.id,
+      },
+    ];
+  } else if (expression instanceof Expressions.BoolLiteral) {
+    const value = expression.value;
+    result = [
+      {
+        instance: "expression",
+        class: "simple",
+        type: TYPES.CONST,
+        value: convertBoolToString(value),
+      },
+    ];
+  } else {
+    let value = expression.value;
+    if (expression.value.toNumber) {
+      if (
+        Types.REAL.isCompatible(expression.type) &&
+        expression.value.decimalPlaces() == 0
+      ) {
+        value = expression.value.toFixed(2);
+      } else {
+        value = expression.value.toNumber();
+      }
+    }
+    result = [
+      {
+        instance: "expression",
+        class: "simple",
+        type: TYPES.CONST,
+        value: value,
+      },
+    ];
+  }
+  if (expression.parenthesis) return ["(", ...result, ")"];
+  else return result;
+}
+
+export function parseExpression (text) {
+  const parser = IVProgParser.createParser(text);
+  const expressionAST = parser.parseExpressionOR();
+  return expressionWalker(expressionAST);
+}

+ 10 - 3
js/visualUI/algorithm.js

@@ -11,7 +11,6 @@ export function renderAlgorithm () {
 		return;
 	}
 	window.block_render = true;
-	console.log('rendering algorithm');
 
  	$('.all_functions').children().off();
 	$('.all_functions').empty();
@@ -28,9 +27,17 @@ export function renderAlgorithm () {
 	}	
 
 	setTimeout(function(){ window.block_render = false; }, 100);
-	console.log('fim do render');
 
 	if (settingsFilter && settingsFilter[0]) {
       blockAllEditingOptions();
-    } 
+		} 
+	
+	$('.command_drag').popup({
+    content : LocalizedStrings.getUI("text_move_command"),
+    delay: {
+      show: 1000,
+      hide: 0
+    }
+  });
+		
 }

+ 38 - 28
js/visualUI/code_generator.js

@@ -238,6 +238,42 @@ function switchcasesCode (switchcase, indentation) {
   return ret;
 }
 
+export function repeatNtimesHeader (command_obj) {
+  let ret = "";
+  if (command_obj.var_attribution) {
+    ret += '<span class="repeatN_text_par_1">';
+    ret += variableValueMenuCode(command_obj.var_attribution);
+    ret += '</span>';
+    ret += ` ${LocalizedStrings.getUI("text_code_for_from")} `;
+    ret += '<span class="repeatN_text_par_2">';
+    ret += variableValueMenuCode(command_obj.expression1);
+    ret += '</span>';
+  }
+
+  if (command_obj.expression2) {
+    ret += ` ${LocalizedStrings.getUI("text_code_for_to")} `;
+    ret += '<span class="repeatN_text_par_3">';
+    ret += variableValueMenuCode(command_obj.expression2);
+    ret += '</span>';
+  }
+
+  if (command_obj.expression3) {
+    ret += ` ${LocalizedStrings.getUI("text_code_for_pass")} `;
+    ret += '<span class="repeatN_text_par_4">';
+    switch (command_obj.expression3.itens[1]) {
+      case Models.ARITHMETIC_TYPES.plus:
+        ret += " +";
+        break;
+      case Models.ARITHMETIC_TYPES.minus:
+        ret += " -";
+        break;
+    }
+    ret += variableValueMenuCode(command_obj.expression3.itens[2]);
+    ret += '</span>';
+  }
+  return ret;
+}
+
 function repeatNtimesCode (command_obj, indentation) {
   let ret = "\n";
 
@@ -271,32 +307,6 @@ function repeatNtimesCode (command_obj, indentation) {
     ret += variableValueMenuCode(command_obj.expression3.itens[2]);
   }
 
-  /*if (command_obj.var_incrementation) {
-                ret += variableValueMenuCode(command_obj.var_incrementation);
-                ret += ' <- ';
-                ret += variableValueMenuCode(command_obj.expression3.itens[0]);
-
-                switch (command_obj.expression3.itens[1]) {
-                        case Models.ARITHMETIC_TYPES.plus:
-                                ret += ' + ';
-                                break;
-                        case Models.ARITHMETIC_TYPES.minus:
-                                ret += ' - ';
-                                break;
-                        case Models.ARITHMETIC_TYPES.multiplication:
-                                ret += ' * ';
-                                break;
-                        case Models.ARITHMETIC_TYPES.division:
-                                ret += ' / ';
-                                break;
-                        case Models.ARITHMETIC_TYPES.module:
-                                ret += ' % ';
-                                break;
-                }
-
-                ret += variableValueMenuCode(command_obj.expression3.itens[2]);
-        }*/
-
   ret += " { ";
 
   if (command_obj.commands_block) {
@@ -580,7 +590,7 @@ function attributionsCode (command_obj, indentation) {
   return ret;
 }
 
-function elementExpressionCode (expression_obj) {
+export function elementExpressionCode (expression_obj) {
   let ret = "";
 
   for (let i = 0; i < expression_obj.length; i++) {
@@ -678,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) {

+ 5 - 101
js/visualUI/commands.js

@@ -47,8 +47,6 @@ export function removeCommand (command, function_obj, dom_obj) {
 	} catch (err) {}
 
 	if (dom_obj.parent().data('switchcase')) {
-		console.log("o que encontrei: ");
-		console.log(dom_obj.parent().data('switchcase'));
 		dom_obj.parent().data('switchcase').commands_block.splice(dom_obj.parent().data('switchcase').commands_block.indexOf(command), 1);
 		return true;
 	}
@@ -125,8 +123,6 @@ export function createFloatingCommand (function_obj, function_container, command
 		function_container = $(mouse_event.originalEvent.srcElement.closest('.function_div'));
 	}
 
-	console.log('function_container', function_container);
-
 	function_container_active = function_container;
 
 	function_container.find('.commands_list_div').on('mousemove', function(evt) {
@@ -173,18 +169,18 @@ function addGhostToEmptyBlock (element, evt) {
 
 	if (window.active_container != null) {
 		if (window.active_container.is(container)) {
-			console.log('é o mesmo, não mudou!');
+			//console.log('é o mesmo, não mudou!');
 		} else {
 			if (container.length < 1) {
 				container = element.closest('.commands_list_div');
 				if (window.active_container.is(container)) {
-					console.log('é o mesmo command list');
+					//console.log('é o mesmo command list');
 				} else {
-					console.log('mudou para um command list');
+					//console.log('mudou para um command list');
 					window.active_container = container;
 				}
 			} else {
-				console.log('mudou para um outro container?');
+				//console.log('mudou para um outro container?');
 			}
 		}
 	}
@@ -236,7 +232,6 @@ function addGhostToNotEmptyBlock (element, evt) {
 
 	// quem está mais próximo? // Essa regra se aplica somente quando o over está sobre um comando
 	var allfilhos;
-	console.log('olha o container: ', container);
 	if (container.hasClass('iftrue')) {
 		
 		if ($(evt.target).closest('.data_block_if').length > 0) {
@@ -276,8 +271,6 @@ function addGhostToNotEmptyBlock (element, evt) {
 		bottomDistances.push(botD);
 	}
 
-	console.log('topDistances\n', topDistances, '\nbottomDistances\n', bottomDistances)
-
 	var menorTop = Math.min.apply(null, topDistances);
 	var indiceTop = topDistances.indexOf(menorTop);
 
@@ -289,8 +282,6 @@ function addGhostToNotEmptyBlock (element, evt) {
 	} else {
 		window.ghostDiv.insertAfter($(allfilhos.get(indiceBot)));
 	}
-
-	console.log('distancias: menorTop ', menorTop, ' menorBot ', menorBot);
 }
 
 function addGhostToFunctionArea (undermouse, evt) {
@@ -549,8 +540,6 @@ function findSingleElement (searching, query) {
 			searching.commands_else = [];
 		}
 
-		console.log('\n\nveja onde: ', searching.commands_block, ' \n\nquery: ', query);
-
 		if (searching.commands_block.indexOf(query) >= 0) {
 			return 'if[' + searching.commands_block.indexOf(query) + ']';
 		} else {
@@ -573,9 +562,6 @@ function findPathRecursive (starter_index, hierarquia_bottom_up, function_obj, i
 	var full_path = '';
 	
 	for (var i = 0; i <= hierarquia_bottom_up.length; i ++) {
-
-		console.log('\n\n:: ', i, ':\n', hierarquia_bottom_up[i]);
-
 		full_path += findSingleElement(hierarquia_bottom_up[i], hierarquia_bottom_up[i + 1]) + '-';
 	}
 
@@ -593,11 +579,6 @@ function manageCommand (function_obj, function_container, event, command_type) {
 	if (el.hasClass('ghost_div')) {
 		if (el.closest('.command_container').length < 1) {
 			
-
-			console.log('\n\nvou tentar!!!!');
-
-			console.log(el.closest('.commands_list_div'), '\n\n');
-
 			el.closest('.commands_list_div').css('height', el.closest('.commands_list_div').css('height') + 30);
 			
 			//$('.ghost_div').remove();
@@ -606,10 +587,6 @@ function manageCommand (function_obj, function_container, event, command_type) {
 		}
 	}
 
-	console.log('soltou no: ');
-	console.log(el);
-	console.log(el.data('fun'));
-
 	// Primeiro verificar se ele soltou no espaço da função correta:
 	var hier = el.parentsUntil(".all_functions");
 	var esta_correto = false;
@@ -642,7 +619,6 @@ function manageCommand (function_obj, function_container, event, command_type) {
 	}
 	var hierarquia_bottom_up = null;
 	// Agora é descobrir qual o escopo para adicionar o comando:
-	console.log('ev0');
 	// Se o elemento clicado possuir o atributo "fun", então, é direto na div dos comandos:
 	if (typeof el.data('fun') !== 'undefined') {
 
@@ -665,7 +641,6 @@ function manageCommand (function_obj, function_container, event, command_type) {
 		}
 
 	} else {
-		console.log("soltou em um comando");
 		// descobrir em qual comando ele soltou: 
 		var hier_find = el.parentsUntil(".commands_list_div");
 		hierarquia_bottom_up = [];
@@ -677,13 +652,7 @@ function manageCommand (function_obj, function_container, event, command_type) {
 				hierarquia_bottom_up.push($(hier_find[i]).data('command'));
 			}
 		}
-		console.log("comando em que soltou: ");
-		console.log(hierarquia_bottom_up[0]);
-		console.log("hierarquia de baixo para cima na árvore, de onde ele soltou: ");
-		for (var i = 0; i < hierarquia_bottom_up.length; i++) {
-			console.log(hierarquia_bottom_up[i]);
-		}
-
+		
 		// Se for do tipo break, verificar se está no contexto correto: 
 		// Caso não esteja no contexto, apenas retorna sem dar continuidade:
 		var is_correct_context = false;
@@ -707,33 +676,25 @@ function manageCommand (function_obj, function_container, event, command_type) {
 
 		// se a hierarquia possuir apenas um elemento, então está na raiz dos comandos: 
 		if (hierarquia_bottom_up.length == 1) {
-			console.log('QQ1');
 			var sub_elemento = false;
 			for (var i = 0; i < hier_find.length; i++) {
 				if (typeof $(hier_find[i]).data('command') !== 'undefined') {
-					console.log('QQ2');
 					findBeforeOrAfterCommandToAdd(hier_find[i], event, function_obj, command_type);
 					sub_elemento = true;
 					break;
 				}
 			}
 			if (!sub_elemento) {
-				console.log('QQ3');
 				findBeforeOrAfterCommandToAdd(el[0], event, function_obj, command_type);
 			}
 		} else {
-			console.log('QQ4');
 			// caso exista mais de um elemento na hierarquia:
 			if (typeof $(el).data('command') !== 'undefined') {
-				console.log('QQ5');
-				console.log("PPP1");
 				insertCommandInBlockHierar(el[0], event, function_obj, command_type, hier_find, hierarquia_bottom_up);
 			} else {
-				console.log('QQ6');
 				var sub_elemento = false;
 				for (var i = 0; i < hier_find.length; i++) {
 					if (typeof $(hier_find[i]).data('command') !== 'undefined') {
-						console.log('QQ7');
 						insertCommandInBlockHierar(hier_find[i], event, function_obj, command_type, hier_find, hierarquia_bottom_up);
 						sub_elemento = true;
 						break;
@@ -748,13 +709,10 @@ function manageCommand (function_obj, function_container, event, command_type) {
 	// which_element_is_draged = null;
 
 	if (hierarquia_bottom_up) {
-		console.log('\n\n:::índices::\n\n');
 		var i = hierarquia_bottom_up.length - 1;
 		var starter_index = window.program_obj.functions[window.program_obj.functions.indexOf(function_obj)].commands.indexOf(hierarquia_bottom_up[i]);
 		var all_str_path = starter_index + '-' + findPathRecursive(starter_index, hierarquia_bottom_up, function_obj);
 		registerUserEvent(function_obj.name, ActionTypes.INSERT_COMMAND, command_type, '/' , all_str_path);
-		console.log('\n\nfull path: \n\n', all_str_path);
-		console.log('fim dos índices');
 	}
 
 	renderAlgorithm();
@@ -769,14 +727,10 @@ function insertCommandInBlockHierar (el, event, function_obj, command_type, hier
 		(el_jq.data('command').type == Models.COMMAND_TYPES.dowhiletrue) ||
 		(el_jq.data('command').type == Models.COMMAND_TYPES.switch) ) {
 
-		console.log('QQ17');
-
 		if ((el_jq.data('command').type == Models.COMMAND_TYPES.repeatNtimes) ||
 			(el_jq.data('command').type == Models.COMMAND_TYPES.whiletrue)  ||
 			(el_jq.data('command').type == Models.COMMAND_TYPES.dowhiletrue) ) {
 
-			console.log('QQ18');
-
 			// Se não tiver outro comando ainda no bloco, só adiciona: 
 			if (command_parent.commands_block == null || command_parent.commands_block.length == 0) {
 				command_parent.commands_block = [];
@@ -796,7 +750,6 @@ function insertCommandInBlockHierar (el, event, function_obj, command_type, hier
 		}
 
 	} else {
-		console.log('QQ19');
 		// entra neste bloco, se soltou o comando sobre outro comando dentro de um subbloco:
 		findBeforeOrAfterCommandToAddInsertBlock(el, event, function_obj, command_type);
 	}
@@ -804,8 +757,6 @@ function insertCommandInBlockHierar (el, event, function_obj, command_type, hier
 
 function findNearbyCommandToAddInBlockScope (el, event, node_list_commands, function_obj, command_type, command_parent) {
 
-	console.log("\n\n\n::COMANDOS:\n\n", el, event, node_list_commands, function_obj, command_type, command_parent);
-
 	var all_sub = $(node_list_commands).find('div.command_container');
 
 	var menor_distancia = 999999999;
@@ -900,12 +851,9 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 
 	if ((command_parent.type != Models.COMMAND_TYPES.iftrue) && (command_parent.type != Models.COMMAND_TYPES.switch)) {
 		var hier = temp_parent.parentsUntil(".all_cases_div");
-		console.log("vou procurar!!");
 		for (var i = 0; i < hier.length; i++) {
-			console.log("estou vasculhando...");
 			var temp = $(hier[i]);
 			if (typeof temp.data('switchcase') !== 'undefined') {
-				console.log("encontrei");
 				command_parent = temp.data('switchcase');
 				is_in_else = false;
 				break;
@@ -913,14 +861,6 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 		}
 	}
 
-	console.log('debugging:');
-	console.log('el_jq');
-	console.log(el_jq);
-	console.log('command_parent');
-	console.log(command_parent);
-	console.log('command_target');
-	console.log(command_target);
-
 	var menor_distancia = 999999999;
 	var antes = true;
 
@@ -939,14 +879,9 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 		
 		var recentComand = genericCreateCommand(command_type);
 
-		console.log('MMM1');
-
 		if (is_in_else) {
 
-			console.log('MMM2');
-
 			if (command_parent == command_target) {
-				console.log('MMM3');
 				if (command_parent.commands_else == null || command_parent.commands_else.length == 0) {
 					command_parent.commands_else = [];
 
@@ -959,7 +894,6 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 				}
 				return;
 			}
-			console.log('MMM7');
 			var index = command_parent.commands_else.indexOf(command_target);
 
 			if (index > -1) {
@@ -968,25 +902,20 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 
 			renderCommand(recentComand, el, 1, function_obj);
 		} else {
-			console.log('MMM4');
 			if (command_parent == command_target) {
-				console.log('Nxxxx5');
 				if (command_parent.commands_block == null || command_parent.commands_block.length == 0) {
 					command_parent.commands_block = [];
-					console.log('SSS4');
 					var recentComand = genericCreateCommand(command_type);
 					command_parent.commands_block.push(recentComand);
 
 					renderCommand(recentComand, el_jq, 3, function_obj);
 				} else {
-					console.log('SSS5');
 					findInBlockCorrectPlace(el_jq, event, function_obj, command_type);
 				}
 				
 				
 				return;
 			}
-			console.log('MMM6');
 
 			var index = command_parent.commands_block.indexOf(command_target);
 
@@ -1000,28 +929,23 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 		
 
 	} else {
-		console.log('XXX1');
 		var recentComand = genericCreateCommand(command_type);
 
 		if (is_in_else) {
 
 			if (command_parent == command_target) {
-				console.log('MMM3');
 				if (command_parent.commands_else == null || command_parent.commands_else.length == 0) {
 					command_parent.commands_else = [];
-					console.log('SSS1');
 					var recentComand = genericCreateCommand(command_type);
 					command_parent.commands_else.push(recentComand);
 
 					renderCommand(recentComand, el_jq, 3, function_obj);
 				} else { // Se já tem algum comando no bloco:
-					console.log('SSS2');
 					findInBlockCorrectPlace(el_jq, event, function_obj, command_type, true);
 				}
 				return;
 			}
 
-			console.log('XXX2');
 			var index = command_parent.commands_else.indexOf(command_target);
 
 			if (index > -1) {
@@ -1033,16 +957,13 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 		} else {
 
 			if (command_parent == command_target) {
-				console.log('Nxxxx78');
 				if (command_parent.commands_block == null || command_parent.commands_block.length == 0) {
 					command_parent.commands_block = [];
 
 					var recentComand = genericCreateCommand(command_type);
 					command_parent.commands_block.push(recentComand);
-					console.log('SSS6');
 					renderCommand(recentComand, el_jq, 3, function_obj);
 				} else {
-					console.log('SSS7');
 					findInBlockCorrectPlace(el_jq, event, function_obj, command_type);
 				}
 				
@@ -1050,7 +971,6 @@ function findBeforeOrAfterCommandToAddInsertBlock (el, event, function_obj, comm
 				return;
 			}
 
-			console.log('XXX3');
 			var index = command_parent.commands_block.indexOf(command_target);
 
 			if (index > -1) {
@@ -1086,8 +1006,6 @@ function insertCommandInBlock (el, event, function_obj, command_type) {
 
 	} else if (el_jq.data('command').type == Models.COMMAND_TYPES.iftrue) {
 
-		console.log('QQ9');
-		
 		// no if ou no else?
 		var correct_div = $(document.elementFromPoint(event.pageX, event.pageY));
 		var is_in_if = true;
@@ -1137,7 +1055,6 @@ function insertCommandInBlock (el, event, function_obj, command_type) {
 		}
 
 	} else { // é do tipo switch
-		console.log("está tentando inserir em um switch que está na raiz!");
 		addCommandToSwitchCase(event, function_obj, command_type);
 	}
 }
@@ -1245,31 +1162,20 @@ function findInBlockCorrectPlace (el, event, function_obj, command_type, is_in_e
 	}
 
 	var borda_inferior = elemento_menor_distancia.parentNode.getBoundingClientRect().top + elemento_menor_distancia.parentNode.getBoundingClientRect().height;
-
-	console.log("menor_distancia: ");
-	console.log(elemento_menor_distancia);
 	
 	// Está mais próximo da borda de baixo, ou seja.. inserir por último:
 	if ((borda_inferior - event.clientY) < menor_distancia) {
 
-		console.log('QQ11');
-		
 		var recentComand = genericCreateCommand(command_type);
 
 		var command_parent = el_jq.data('command');
 
 		if (is_in_else) {
-			console.log('QQ15');
 			command_parent.commands_else.push(recentComand);
-			console.log('el_jq');
-			console.log(el_jq);
-			console.log("$(el_jq.find('.commands_else')[0]):: ");
-			console.log($(el_jq.find('.commands_else')[0]));
 
 			renderCommand(recentComand, el_jq, 3, function_obj);
 
 		} else {
-			console.log('QQ16');
 			command_parent.commands_block.push(recentComand);
 
 			renderCommand(recentComand, $(el_jq.find('.block_commands')[0]), 3, function_obj);
@@ -1277,8 +1183,6 @@ function findInBlockCorrectPlace (el, event, function_obj, command_type, is_in_e
 
 	} else {
 
-		console.log('QQ12');
-
 		var recentComand = genericCreateCommand(command_type);
 
 		var command_parent = el_jq.data('command');

+ 169 - 4
js/visualUI/commands/attribution.js

@@ -4,15 +4,16 @@ import * as VariableValueMenu from './variable_value_menu';
 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>');
 }
 
 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> </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);
@@ -26,7 +27,44 @@ export function renderCommand (command, function_obj) {
 
 	ExpressionManagement.renderExpression(command, function_obj, el.find('.expression_elements'), command.expression);
 
-	//renderExpressionElements(command, function_obj, el);
+	if (command.lockexpression) {
+		if (command.expression) {
+			try {
+				var text = CodeGenerator.elementExpressionCode(command.expression);
+				if (text) {
+					$(el.find('.expression_elements')[0]).toggle();
+					$(el.find('.textual_expression')[0]).text(text);
+					$(el.find('.textual_expression')[0]).toggle();
+					$(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+				}
+			} catch (e) {
+				command.lockexpression = false;
+			}
+		}
+	}
+
+	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;
 
@@ -150,7 +188,7 @@ function renderOperator (command, function_obj, temp_op, expression_element, ind
 
 	context_menu.dropdown({
 		onChange: function(value, text, $selectedItem) {
-	     expression_element.itens[index_op] = value;
+			 expression_element.itens[index_op] = value;
       }
 	});
 
@@ -414,6 +452,133 @@ 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() {
+		if (command.expression) {
+			var text = CodeGenerator.elementExpressionCode(command.expression);
+			if (text) {
+				$(attribution_dom.find('.expression_elements')[0]).toggle();
+				$(attribution_dom.find('.textual_expression')[0]).text(text);
+				$(attribution_dom.find('.textual_expression')[0]).toggle();
+				$(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
+					}
+				});
+			}
+		}
+	});
+
 	attribution_dom.find('.button_remove_command').on('click', function() {
 		if (CommandsManagement.removeCommand(command, function_obj, attribution_dom)) {
 			attribution_dom.fadeOut(400, function() {

+ 2 - 2
js/visualUI/commands/break.js

@@ -2,11 +2,11 @@ import { LocalizedStrings } from '../../services/localizedStringsService';
 import * as CommandsManagement from '../commands';
 
 export function createFloatingCommand () {
-	return $('<div class="ui comment created_element"> <i class="ui icon small quote left"></i> <span> '+LocalizedStrings.getUI('text_break')+' </span></div>');
+	return $('<div class="ui comment created_element"> <i class="ui icon small pause"></i> <span> '+LocalizedStrings.getUI('text_break')+' </span></div>');
 }
 
 export function renderCommand (command, function_obj) {
-	var el = $('<div class="ui comment command_container"> <i class="ui icon small quote left"></i> <i class="ui icon times red button_remove_command"></i> <span>'+LocalizedStrings.getUI('text_break')+'</span> </div>');
+	var el = $('<div class="ui comment command_container"> <i class="ui icon small pause"></i> <i class="ui icon times red button_remove_command"></i> <span>'+LocalizedStrings.getUI('text_break')+'</span> </div>');
 	el.data('command', command);
 
 	addHandlers(command, function_obj, el);

+ 8 - 4
js/visualUI/commands/contextualized_menu.js

@@ -6,18 +6,18 @@ import * as SwitchManagement from './switch';
 
 export function renderMenu (command, dom_where_render, function_obj, dom_command) {
 
-	var menu_div = '<div class="ui dropdown menu_commands" ><i class="icon code"></i> <div class="menu"> ';
+	var menu_div = '<div class="ui dropdown menu_commands pause" ><button><i class="icon code"></i></button> <div class="menu"> ';
 
 	if ((command.type == Models.COMMAND_TYPES.repeatNtimes) 
 		|| (command.type == Models.COMMAND_TYPES.whiletrue) 
 		|| (command.type == Models.COMMAND_TYPES.dowhiletrue)) {
 
-		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.break+'"><i class="download icon"></i> '+LocalizedStrings.getUI('btn_break')+' </a>';
+		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.break+'"><i class="pause icon"></i> '+LocalizedStrings.getUI('btn_break')+' </a>';
 
 	} else {
 
-		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.break+'"><i class="download icon"></i> '+LocalizedStrings.getUI('btn_break')+' </a>';
-		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.switchcase+'"><i class="download icon"></i> '+LocalizedStrings.getUI('btn_case')+' </a>';
+		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.break+'"><i class="pause icon"></i> '+LocalizedStrings.getUI('btn_break')+' </a>';
+		menu_div += '<a class="item" data-command="'+Models.COMMAND_TYPES.switchcase+'"><i class="plus icon"></i> '+LocalizedStrings.getUI('btn_case')+' </a>';
 
 	}
 
@@ -28,6 +28,10 @@ export function renderMenu (command, dom_where_render, function_obj, dom_command
 	dom_where_render.append(menu_div);
 
 	addHandlers(command, dom_where_render, function_obj, dom_command);
+
+	if (command.collapsed) {
+		dom_command.children('.ui.block_commands').toggle();
+	}
 }
 
 function addHandlers (command, dom_where_render, function_obj, dom_command) {

+ 175 - 2
js/visualUI/commands/dowhiletrue.js

@@ -3,6 +3,7 @@ import * as CommandsManagement from '../commands';
 import * as ConditionalExpressionManagement from './conditional_expression';
 import * as ContextualizedMenu from './contextualized_menu';
 import * as GenericExpressionManagement from './generic_expression';
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
 	return $('<div class="ui dowhiletrue created_element"> <i class="ui icon small sync"></i> <span> '+ LocalizedStrings.getUI('text_command_do') +' <br> ' + LocalizedStrings.getUI('text_command_do_until') +'(x < 10) </span></div>');
@@ -10,10 +11,11 @@ export function createFloatingCommand () {
 
 export function renderCommand (command, function_obj) {
 	var ret = '';
-	ret += '<div class="ui dowhiletrue command_container"> <i class="ui icon small sync command_drag"></i> <i class="ui icon times red button_remove_command"></i> <div class="ui context_menu"></div>  <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_do') + ' </span>';
+	ret += '<div class="ui dowhiletrue 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_do') + ' </span>';
 	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="span_command_spec"> ) </span>';
+	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 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);
@@ -36,12 +38,183 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	if (command.lockexpression) {
+		if (command.expression) {
+			try {
+				var text = CodeGenerator.elementExpressionCode(command.expression);
+				if (text) {
+					$(el.find('.conditional_expression')[el.find('.conditional_expression').length - 1]).toggle();
+					$(el.find('.textual_expression')[el.find('.textual_expression').length - 1]).text(text);
+					$(el.find('.textual_expression')[el.find('.textual_expression').length - 1]).toggle();
+					$(el.find('.button_alternate_expression')[el.find('.button_alternate_expression').length - 1]).toggleClass('unlock').toggleClass('lock');
+				}
+			} catch (e) {
+				command.lockexpression = false;
+			}
+		}
+	}
+
+	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;
+	});
+
+	$(dowhiletrue_dom.find('.textual_expression')[0]).toggle();
+	
+	dowhiletrue_dom.find('.button_alternate_expression').on('click', function() {
+		if (command.expression) {
+			var text = CodeGenerator.elementExpressionCode(command.expression);
+			if (text) {
+				$(dowhiletrue_dom.find('.conditional_expression')[dowhiletrue_dom.find('.conditional_expression').length - 1]).toggle();
+				$(dowhiletrue_dom.find('.textual_expression')[dowhiletrue_dom.find('.textual_expression').length - 1]).text(text);
+				$(dowhiletrue_dom.find('.textual_expression')[dowhiletrue_dom.find('.textual_expression').length - 1]).toggle();
+
+				$(this).toggleClass('unlock').toggleClass('lock');
+				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() {
 		if (CommandsManagement.removeCommand(command, function_obj, dowhiletrue_dom)) {
 			dowhiletrue_dom.fadeOut(400, function() {

+ 331 - 7
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;
 
@@ -101,7 +102,7 @@ export function renderExpression (
         types_included.push(Models.EXPRESSION_TYPES.exp_logic);
         types_included.push(Models.EXPRESSION_TYPES.exp_arithmetic);
       } else {
-        console.log("NÃO RECONHECI! VEJA: ", command.variable.content.type);
+        //console.log("NÃO RECONHECI! VEJA: ", command.variable.content.type);
       }
 
       renderElements(
@@ -200,7 +201,6 @@ export function renderExpression (
 function removeElement (event, expression_array) {
   const indice = $(event.item).data("index");
   const first = expression_array[0];
-  console.log("indice: ", indice);
   if (expression_array[indice].type) {
     // if is alone in expression:
     if (expression_array.length == 1) {
@@ -394,9 +394,7 @@ function renderElements (
       }
     } else {
       if (i == 0) {
-        console.log("NEGAÇÃO NO PRIMEIRO ELEMENTO");
       } else if (expression_array[i - 1] == "(") {
-        console.log("NEGAÇÃO APÓS O PARÊNTESES");
       }
       renderOperatorMenu(
         command,
@@ -906,7 +904,6 @@ function renderStartAddOperator (
       const sera = position;
 
       if (types_included.indexOf(Models.EXPRESSION_TYPES.exp_arithmetic) >= 0) {
-        console.log("p1");
         expression_array.splice(
           sera,
           0,
@@ -918,7 +915,6 @@ function renderStartAddOperator (
       } else if (
         types_included.indexOf(Models.EXPRESSION_TYPES.exp_logic) >= 0
       ) {
-        console.log("p2");
         expression_array.splice(
           sera,
           0,
@@ -930,7 +926,6 @@ function renderStartAddOperator (
       } else if (
         types_included.indexOf(Models.EXPRESSION_TYPES.exp_conditional) >= 0
       ) {
-        console.log("p3");
         expression_array.splice(
           sera,
           0,
@@ -1308,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;
+}

+ 182 - 4
js/visualUI/commands/iftrue.js

@@ -1,7 +1,7 @@
 import { LocalizedStrings } from '../../services/localizedStringsService';
 import * as CommandsManagement from '../commands';
-import * as ConditionalExpressionManagement from './conditional_expression';
 import * as GenericExpressionManagement from './generic_expression';
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
 	return $('<div class="ui iftrue created_element"> <i class="ui icon small random"></i> <span> if (x < 1) { } </span></div>');
@@ -9,9 +9,11 @@ export function createFloatingCommand () {
 
 export function renderCommand (command, function_obj) {
 	var ret = '';
-	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>';
+	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="span_command_spec"> ) </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">';
  	ret += '</div></div>';
@@ -31,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) {
@@ -45,12 +46,182 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	if (command.collapsed) {
+		el.children('.data_block_else').toggle();
+		$(el.find('.block_commands')[0]).toggle();
+	}
+
+	if (command.lockexpression) {
+		if (command.expression) {
+			try {
+				var text = CodeGenerator.elementExpressionCode(command.expression);
+				if (text) {
+					$(el.find('.conditional_expression')[0]).toggle();
+					$(el.find('.textual_expression')[0]).text(text);
+					$(el.find('.textual_expression')[0]).toggle();
+					$(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+				}
+			} catch (e) {
+				command.lockexpression = false;
+			}
+		}
+	}
+
+	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() {
+		if (command.expression) {
+			var text = CodeGenerator.elementExpressionCode(command.expression);
+			if (text) {
+				$(iftrue_dom.find('.conditional_expression')[0]).toggle();
+				$(iftrue_dom.find('.textual_expression')[0]).text(text);
+				$(iftrue_dom.find('.textual_expression')[0]).toggle();
+				$(this).toggleClass('unlock').toggleClass('lock');
+				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() {
 		if (CommandsManagement.removeCommand(command, function_obj, iftrue_dom)) {
 			iftrue_dom.fadeOut(400, function() {
@@ -58,4 +229,11 @@ function addHandlers (command, function_obj, iftrue_dom) {
 			});
 		}
 	});
+
+	iftrue_dom.find('.minimize_block_button').on('click', function() {
+		iftrue_dom.children('.data_block_else').toggle();
+		$(iftrue_dom.find('.block_commands')[0]).toggle();
+		command.collapsed = !command.collapsed;
+	});
+
 }

+ 84 - 2
js/visualUI/commands/repeatNtimes.js

@@ -5,6 +5,7 @@ import * as ConditionalExpressionManagement from './conditional_expression';
 import * as VariableValueMenu from './variable_value_menu';
 import * as ContextualizedMenu from './contextualized_menu';
 import * as GenericExpressionManagement from './generic_expression';
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
 	return $('<div class="ui repeatNtimes created_element"> <i class="ui icon small sync"></i> <span> repita_para i de 0 ate 10 passo 1 <br> </span></div>');
@@ -14,7 +15,8 @@ export function renderCommand (command, function_obj) {
 	let ret = `<div class="ui repeatNtimes command_container"> 
 		<i class="ui icon small sync command_drag"></i>
 		<i class="ui icon times red button_remove_command"></i>
-		<div class="ui context_menu"></div>  <span class="span_command_spec"> ${LocalizedStrings.getUI('text_for')}
+		<button class="ui icon button minimize_block_button tiny"><i class="icon window minimize"></i></button>
+		<span class="span_command_spec"> ${LocalizedStrings.getUI('text_for')}
 		</span>  <div class="ui attribution_expression">
 		<div class="ui variable_attribution"></div>
 		<span class="text_receives span_command_spec" style="margin-left: 10px;margin-right: 20px;"></span>
@@ -25,7 +27,9 @@ export function renderCommand (command, function_obj) {
 		<div class="conditional_expression"></div> <div class="pass_button"></div> 
 		<div class="ui incrementation_field"><span class="text_inc_receives span_command_spec"></span>
 		<div class="ui first_operand"></div><div class="ui operator"></div>
-		<div class="ui second_operand"></div></div>  <span class="span_command_spec"> </span>'`;
+		<div class="ui second_operand"></div></div>  <span class="span_command_spec"> </span>
+		<span class="textual_expression"></span> <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>';
@@ -83,6 +87,41 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	if (command.lockexpression) {
+		try {
+			var text = CodeGenerator.repeatNtimesHeader(command);
+			if (text) {
+				$(el.find('.textual_expression')[0]).html(text);
+				$(el.find('.textual_expression')[0]).toggle();
+
+				$(el.find('.attribution_expression')[0]).toggle();
+				$(el.find('.span_command_spec.separator_character')[0]).toggle();
+				$(el.find('.conditional_expression')[0]).toggle();
+				$(el.find('.pass_button')[0]).toggle();
+				$(el.find('.incrementation_field')[0]).toggle();
+
+				$(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+			}
+		} catch (e) {
+			command.lockexpression = false;
+		}
+	}
+
+	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;
 }
 
@@ -171,6 +210,49 @@ export function manageClearExpressionElements (command, ref_object, dom_object,
 
 function addHandlers (command, function_obj, repeatNtimes_dom) {
 
+	repeatNtimes_dom.find('.minimize_block_button').on('click', function(evt){
+		repeatNtimes_dom.children('.ui.block_commands').toggle();
+		command.collapsed = !command.collapsed;
+	});
+
+	$(repeatNtimes_dom.find('.textual_expression')[0]).toggle();
+	
+	repeatNtimes_dom.find('.button_alternate_expression').on('click', function() {
+		var text = CodeGenerator.repeatNtimesHeader(command);
+		if (text) {
+			$(repeatNtimes_dom.find('.textual_expression')[0]).html(text);
+			$(repeatNtimes_dom.find('.textual_expression')[0]).toggle();
+
+			$(repeatNtimes_dom.find('.attribution_expression')[0]).toggle();
+			$(repeatNtimes_dom.find('.span_command_spec.separator_character')[0]).toggle();
+			$(repeatNtimes_dom.find('.conditional_expression')[0]).toggle();
+			$(repeatNtimes_dom.find('.pass_button')[0]).toggle();
+			$(repeatNtimes_dom.find('.incrementation_field')[0]).toggle();
+
+			$(repeatNtimes_dom.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+
+			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() {
 		if (CommandsManagement.removeCommand(command, function_obj, repeatNtimes_dom)) {
 			repeatNtimes_dom.fadeOut(400, function() {

+ 34 - 3
js/visualUI/commands/return.js

@@ -4,32 +4,63 @@ import * as VariableValueMenu from './variable_value_menu';
 import * as CommandsManagement from '../commands';
 import * as GenericExpressionManagement from './generic_expression';
 import * as Models from '../ivprog_elements';
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
 	return $('<div class="ui return created_element"> <i class="ui icon small reply"></i> <span> '+LocalizedStrings.getUI('text_return')+' </span></div>');
 }
 
 export function renderCommand (command, function_obj) {
-	var el = $('<div class="ui return command_container"> <i class="ui icon small reply command_drag"></i> <i class="ui icon times red button_remove_command"></i> <span class="span_command_spec"> '+LocalizedStrings.getUI('text_return')+' </span>  <div class="expression_elements"></div></div>');
+	var el = $('<div class="ui return command_container"> <i class="ui icon small reply command_drag"></i> <i class="ui icon times red button_remove_command"></i> <span class="span_command_spec"> '+LocalizedStrings.getUI('text_return')+' </span>  <div class="expression_elements"></div><span class="textual_expression" style="display: none; margin-left: 1rem;"></span></div>');
 	el.data('command', command);
 
-	addHandlers(command, function_obj, el);
-
 	if (function_obj.return_type != Types.VOID) {
 		if (!command.variable_value_menu) {
 			command.variable_value_menu = [new Models.VariableValueMenu(VariableValueMenu.VAR_OR_VALUE_TYPES.all, null, null, null, true)];
 		}
 		GenericExpressionManagement.renderExpression(command, function_obj, el.find('.expression_elements'), command.variable_value_menu);
+		el.append($('<i class="ui icon unlock button_alternate_expression" style="margin-left: 1rem;"></i>'));
+
+		if (command.lockexpression) {
+			if (command.variable_value_menu) {
+				try {
+					var text = CodeGenerator.elementExpressionCode(command.variable_value_menu);
+					if (text) {
+						$(el.find('.expression_elements')[0]).toggle();
+						$(el.find('.textual_expression')[0]).text(text);
+						$(el.find('.textual_expression')[0]).toggle();
+						$(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+					}
+				} catch (e) {
+					command.lockexpression = false;
+				}
+			}
+		}
 	} else {
 		el.find('.expression_elements').remove();
 		command.variable_value_menu = null;
 	}
 	
+	addHandlers(command, function_obj, el);
+
 	return el;
 }
 
 function addHandlers (command, function_obj, return_dom) {
 
+	return_dom.find('.button_alternate_expression').on('click', function() {
+		if (command.variable_value_menu) {
+      var text = CodeGenerator.elementExpressionCode(command.variable_value_menu);
+			if (text) {
+				$(return_dom.find('.expression_elements')[0]).toggle();
+				$(return_dom.find('.textual_expression')[0]).text(text);
+				$(return_dom.find('.textual_expression')[0]).toggle();
+				$(this).toggleClass('unlock').toggleClass('lock');
+				command.lockexpression = !command.lockexpression;
+			}
+		}
+	});
+
 	return_dom.find('.button_remove_command').on('click', function() {
 		if (CommandsManagement.removeCommand(command, function_obj, return_dom)) {
 			return_dom.fadeOut(400, function() {

+ 1 - 1
js/visualUI/commands/switch.js

@@ -9,7 +9,7 @@ export function createFloatingCommand () {
 
 export function renderCommand (command, function_obj) {
 	var ret = '';
-	ret += '<div class="ui switch command_container"> <i class="ui icon small random command_drag" ></i> <i class="ui icon times red button_remove_command"></i> <div class="ui context_menu"></div> <span> '+LocalizedStrings.getUI('text_code_switch')+' ( <div class="ui variable_to_switch"></div> ) <div class="ui all_cases_div"></div></span>';
+	ret += '<div class="ui switch command_container"> <i class="ui icon small random command_drag" ></i> <i class="ui icon times red button_remove_command"></i> <span> '+LocalizedStrings.getUI('text_code_switch')+' ( <div class="ui variable_to_switch"></div> ) <div class="ui context_menu"></div> <div class="ui all_cases_div"></div></span>';
 	ret += '</div>';
 
 	var el = $(ret);

+ 4 - 24
js/visualUI/commands/variable_value_menu.js

@@ -467,9 +467,7 @@ function variableValueMenuCode (
 
       context_menu.dropdown({
         onChange: function (value, text, $selectedItem) {
-          console.log("S1");
           if ($selectedItem.data("clear")) {
-            console.log("PP1");
             dom_object.text("");
 
             variable_obj.content = null;
@@ -579,9 +577,7 @@ function variableValueMenuCode (
 
       context_menu.dropdown({
         onChange: function (value, text, $selectedItem) {
-          console.log("S2");
           if ($selectedItem.data("clear")) {
-            console.log("PP2");
             dom_object.text("");
 
             variable_obj.content = null;
@@ -657,9 +653,7 @@ function variableValueMenuCode (
 
       context_menu.dropdown({
         onChange: function (value, text, $selectedItem) {
-          console.log("S3");
           if ($selectedItem.data("clear")) {
-            console.log("PP3");
             dom_object.text("");
 
             variable_obj.content = null;
@@ -755,9 +749,7 @@ function variableValueMenuCode (
 
       context_menu.dropdown({
         onChange: function (value, text, $selectedItem) {
-          console.log("S4");
           if ($selectedItem.data("clear")) {
-            console.log("PP4");
             dom_object.text("");
 
             variable_obj.content = null;
@@ -864,9 +856,7 @@ function variableValueMenuCode (
 
       context_menu.dropdown({
         onChange: function (value, text, $selectedItem) {
-          console.log("S5");
           if ($selectedItem.data("clear")) {
-            console.log("PP5");
             dom_object.text("");
 
             variable_obj.content = null;
@@ -908,7 +898,7 @@ function variableValueMenuCode (
       '<div class="variable_rendered"> <span class="var_name">';
 
     if (isNaN(variable_obj.content)) {
-      variable_render += variable_obj.content.replaceAll(" ", "&nbsp;");
+      variable_render += variable_obj.content.split(" ").join("&nbsp;");
     } else {
       variable_render += variable_obj.content;
     }
@@ -946,9 +936,7 @@ function variableValueMenuCode (
 
     context_menu.dropdown({
       onChange: function (value, text, $selectedItem) {
-        console.log("S6");
         if ($selectedItem.data("clear")) {
-          console.log("PP6");
           dom_object.text("");
 
           variable_obj.content = null;
@@ -1189,7 +1177,6 @@ function addHandlers (
   if (ref_object.variable_and_value != VAR_OR_VALUE_TYPES.only_value) {
     menu_var_or_value.dropdown({
       onChange: function (value, text, $selectedItem) {
-        console.log("S7");
         dom_object.find(".var_name").remove();
         switch ($selectedItem.data("option")) {
           case VAR_OR_VALUE_TYPES.only_function:
@@ -1394,9 +1381,7 @@ function openInputToFunction (
 
     context_menu.dropdown({
       onChange: function (value, text, $selectedItem) {
-        console.log("S8");
         if ($selectedItem.data("clear")) {
-          console.log("PP7");
           dom_object.text("");
 
           ref_object.content = null;
@@ -1480,9 +1465,7 @@ function openInputToFunction (
 
     context_menu.dropdown({
       onChange: function (value, text, $selectedItem) {
-        console.log("S9");
         if ($selectedItem.data("clear")) {
-          console.log("PP8");
           dom_object.text("");
 
           ref_object.content = null;
@@ -1635,9 +1618,7 @@ function openInputToVariable (
 
   context_menu.dropdown({
     onChange: function (value, text, $selectedItem) {
-      console.log("S10");
       if ($selectedItem.data("clear")) {
-        console.log("PP9");
         dom_object.text("");
 
         ref_object.content = null;
@@ -1804,7 +1785,7 @@ function openInputToValue (
         .val();
 
     if (isNaN(ref_object.content)) {
-      rendered.html(ref_object.content.replaceAll(" ", "&nbsp;"));
+      rendered.html(ref_object.content.split(" ").join("&nbsp;"));
     } else {
       rendered.text(ref_object.content);
     }
@@ -1827,7 +1808,7 @@ function openInputToValue (
           .val();
 
       if (isNaN(ref_object.content)) {
-        rendered.html(ref_object.content.replaceAll(" ", "&nbsp;"));
+        rendered.html(ref_object.content.split(" ").join("&nbsp;"));
       } else {
         rendered.text(ref_object.content);
       }
@@ -1836,7 +1817,7 @@ function openInputToValue (
     }
     if (code == 27) {
       if (isNaN(ref_object.content)) {
-        rendered.html(ref_object.content.replaceAll(" ", "&nbsp;"));
+        rendered.html(ref_object.content.split(" ").join("&nbsp;"));
       } else {
         rendered.text(ref_object.content);
       }
@@ -1860,7 +1841,6 @@ function openInputToValue (
   }
 
   rendered.on("click", function (e) {
-    console.log("TTT2");
     rendered.empty();
     rendered.remove();
     dom_object.empty();

+ 175 - 2
js/visualUI/commands/whiletrue.js

@@ -3,6 +3,7 @@ import * as CommandsManagement from '../commands';
 import * as ConditionalExpressionManagement from './conditional_expression';
 import * as ContextualizedMenu from './contextualized_menu';
 import * as GenericExpressionManagement from './generic_expression';
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
 	return $('<div class="ui whiletrue created_element"> <i class="ui icon small sync"></i> <span> ' + LocalizedStrings.getUI('text_command_while') + ' ( x < 10 ) <br> </span></div>');
@@ -10,9 +11,10 @@ export function createFloatingCommand () {
 
 export function renderCommand (command, function_obj) {
 	var ret = '';
-	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> <div class="ui context_menu"></div>  <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="span_command_spec"> ) </span>';
+	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 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>';
@@ -36,11 +38,182 @@ export function renderCommand (command, function_obj) {
 		}
 	}
 
+	if (command.lockexpression) {
+		if (command.expression) {
+			try {
+				var text = CodeGenerator.elementExpressionCode(command.expression);
+				if (text) {
+					$(el.find('.conditional_expression')[0]).toggle();
+					$(el.find('.textual_expression')[0]).text(text);
+					$(el.find('.textual_expression')[0]).toggle();
+					$(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+				}
+			} catch (e) {
+				command.lockexpression = false;
+			}
+		}
+	}
+	
+	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;
+	});
+
+	$(whiletrue_dom.find('.textual_expression')[0]).toggle();
+	
+	whiletrue_dom.find('.button_alternate_expression').on('click', function() {
+		if (command.expression) {
+			var text = CodeGenerator.elementExpressionCode(command.expression);
+			if (text) {
+				$(whiletrue_dom.find('.conditional_expression')[0]).toggle();
+				$(whiletrue_dom.find('.textual_expression')[0]).text(text);
+				$(whiletrue_dom.find('.textual_expression')[0]).toggle();
+				$(this).toggleClass('unlock').toggleClass('lock');
+				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() {
 		if (CommandsManagement.removeCommand(command, function_obj, whiletrue_dom)) {
 			whiletrue_dom.fadeOut(400, function() {

+ 170 - 19
js/visualUI/commands/writer.js

@@ -4,6 +4,7 @@ import * as VariableValueMenu from "./variable_value_menu";
 import * as VariableValueMenuManagement from "./variable_value_menu";
 import * as CommandsManagement from "../commands";
 import * as GenericExpressionManagement from "./generic_expression";
+import * as CodeGenerator from '../code_generator';
 
 export function createFloatingCommand () {
   return $(
@@ -20,11 +21,13 @@ export function renderCommand (command, function_obj) {
       <span class="span_command_spec">${LocalizedStrings.getUI(
         "text_command_write"
       )}
-      ( </span><div class="all_elements_write"></div>
+      ( </span><div class="all_elements_write"></div> <span class="textual_expression"></span>
       <span class="close_parentheses span_command_spec">)</span>
     <img data-state="${command.newline ? "on" : "false"}" src="${
     command.newline ? "img/new_line.svg" : "img/no_new_line.svg"
-  }" class="ivprog_newline_btn"/>
+  }" 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);
   el.data("command", command);
@@ -38,26 +41,45 @@ export function renderCommand (command, function_obj) {
     command.content
   );
 
-  /*for (var i = 0; i < command.content.length; i ++) {
-		var new_div_item = $( '<div class="var_value_menu_div"></div>' );
-		var div_parent_with_handler = $( '<div class="div_parent_handler"></div>' );
-		div_parent_with_handler.append($('<i class="ui icon ellipsis vertical inverted handler"></i>'));
-		div_parent_with_handler.append(new_div_item);
-		div_parent_with_handler.append($('<i class="white inverted icon times handler"></i>'));
-
-		el.find('.all_elements_write').append(div_parent_with_handler);
-		VariableValueMenu.renderMenu(command, command.content[i], new_div_item, function_obj);
-
-		addHandlerIconAdd(el.find('.all_elements_write'), command, function_obj);
+ 
+  addHandlers(command, function_obj, el);
 
-		addHandlersManager(command, function_obj, el, div_parent_with_handler, command.content[i]);
-	}
+  if (command.content && command.lockexpression) {
+    try {
+      var text = CodeGenerator.elementExpressionCode(command.content);
+      if (text) {
+        $(el.find('.all_elements_write')[0]).toggle();
+        $(el.find('.textual_expression')[0]).text(text);
+        $(el.find('.textual_expression')[0]).toggle();
+        $(el.find('.button_alternate_expression')[0]).toggleClass('unlock').toggleClass('lock');
+      }
+    } catch (e) {
+      command.lockexpression = false;
+    }
+  }
 
-	if (command.content.length == 0) {
-		addHandlerIconAdd(el.find('.all_elements_write'), 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
+		}
+	});
 
-  addHandlers(command, function_obj, el);
   return el;
 }
 
@@ -88,6 +110,135 @@ 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) {
+      var text = CodeGenerator.elementExpressionCode(command.content);
+			if (text) {
+				$(writer_dom.find('.all_elements_write')[0]).toggle();
+				$(writer_dom.find('.textual_expression')[0]).text(text);
+				$(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
+					}
+				});
+			}
+		}
+	});
+
   writer_dom.find(".button_remove_command").on("click", function () {
     if (CommandsManagement.removeCommand(command, function_obj, writer_dom)) {
       writer_dom.fadeOut(400, function () {

+ 15 - 21
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;
 }
 
@@ -509,10 +517,8 @@ function updateProgramObjDrag () {
   var index_each = [];
   var path_relative = [];
   for (var i = path_target.length - 1; i >= 0; i --) {
-    console.log('da vez', $(path_target[i + 1]));
     if (i == (path_target.length - 1)) { // está na raiz
       var indice_na_raiz = function_obj.find('.command_container').index(path_target[i]);
-      console.log('índice na raiz: ', indice_na_raiz);
     } else {
       if ($(path_target[i + 1]).hasClass('iftrue')) {
         if ($(path_target[i]).parent().hasClass('commands_if')) {
@@ -543,24 +549,7 @@ function updateProgramObjDrag () {
   // index_in_block = $(evento_drag.item).parent().find('.command_container').index(evento_drag.item);
 
   const is_in_case_switch = $(evento_drag.item).parent().hasClass('case_commands_block');
-  // var index_case_of_switch = -1;
-  // if (is_in_case_switch) {
-  //   index_case_of_switch = $(evento_drag.item).parent().parent().parent().find('.case_div').index($(evento_drag.item).parent().parent());
-  // }
-
-  /*console.log('path_relative:');
-  console.log(path_relative);
-  console.log('index_each:');
-  console.log(index_each);
-  console.log('index_in_block:');
-  console.log(index_in_block);
-  console.log('ele está em algum bloco de senão? ');
-  console.log(is_in_else);
-  console.log('ele está dentro de um case de switch?');
-  console.log(is_in_case_switch);
-  console.log('qual é o índice do case: ');
-  console.log(index_case_of_switch);*/
-
+  
   // encontrar o elemento na árvore:
 
   var command_start_point = window.program_obj.functions[function_index].commands[indice_na_raiz];
@@ -595,7 +584,6 @@ function updateProgramObjDrag () {
   } else {
     // verificar se tem alguma coisa no bloco:
     if (block_to_insert.commands_block) {
-      console.log("existe alguma coisa dentro do bloco, index: ", evento_drag.newIndex);
       block_to_insert.commands_block.splice(evento_drag.newIndex, 0, command_in_drag);
     } else {
       block_to_insert.commands_block = [];
@@ -735,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;