Browse Source

Implement new terminal with clear, hide and show button and distinction between user input and program output

Lucas de Souza 5 years ago
parent
commit
6cc9f3a376
5 changed files with 254 additions and 29 deletions
  1. 108 6
      css/ivprog-term.css
  2. 3 0
      i18n/pt/ui.json
  3. 94 10
      js/io/domConsole.js
  4. 38 10
      js/visualUI/functions.js
  5. 11 3
      templates/index.html

+ 108 - 6
css/ivprog-term.css

@@ -1,11 +1,11 @@
 .ivprog-term-div {
-  background-color: black;
+  /* background-color: black; */
   width: 100%;
   height: 12rem;
   overflow-y: scroll;
 }
 
-.ivprog-term-userText {
+.ivprog-term-userText, .ivprog-term-userInput {
   color: white;
 }
 
@@ -31,17 +31,17 @@
 }
 
 #ivprog-term {
-  border: 1px solid gray;
+  /* border: 1px solid gray;
   background: black;
   margin-top: -30px;
   position: relative;
   padding: 5px;
-  z-index: 999;
+  z-index: 999; */
 }
-#ivprog-term i {
+/* #ivprog-term i {
   margin-left: 5px;
   cursor: pointer;
-}
+} */
 .div_toggle_console {
   cursor: pointer;
 }
@@ -70,3 +70,105 @@
     background: green;
     -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
 }
+
+/**novas regras bash*/
+#ivprog-terminal-inputdiv {
+  padding-left: 12px;
+}
+#ivprog-console-clearbtn, #ivprog-console-showbtn, #ivprog-console-hidebtn {
+  cursor: pointer;
+}
+
+.bash {
+  box-shadow: 0 0 30px rgba(0,0,0,0.4);
+  border-radius: 3px;
+}
+
+.bash-title {
+  text-align: center;
+  color: #525252;
+  padding: 5px 0;
+  margin: 0;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
+  font-size: 0.85em;
+  border: 1px solid #CCCCCC;
+  border-bottom: none;
+
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+
+  background: #f7f7f7; /* Old browsers */
+  background: linear-gradient(to bottom,  #f7f7f7 0%,#B8B8B8 100%); /* W3C */
+}
+
+.bash-body {
+  /* margin: 0;
+  padding: 5px; */
+  background: #141414;
+  /* list-style: none; */
+  color: #F8F8FF;
+  
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+  border: 1px solid #CCCCCC;
+  border-bottom-right-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+
+.bash-text {
+  font: 14px 'Andale Mono', Consolas, 'Courier New';
+  line-height: 1.6em;
+}
+
+.bash-highlight {
+  color: #45D40C;
+}
+
+.bash-highlight a {
+  color: #45D40C;
+  text-decoration: underline;
+}
+
+.bash-body li:before {
+  content: '$';
+  color: #F8F8FF;
+  position: absolute;
+  left: 0;
+  top: 0;
+}
+
+.bash-body i {
+  cursor: text;
+}
+
+.bash-body li {
+  word-wrap: break-word;
+  position: relative;
+  padding: 0 0 0 15px;
+}
+
+#cmd {
+  font-family: courier;
+  font-size: 14px;
+  line-height: normal;
+  background:inherit;
+  color: #21f838;
+  padding: 5px;
+  overflow: hidden;
+}
+#cmd span {
+  float: left;
+  padding-left: 3px;
+  white-space: pre;
+}
+#cursor {
+  float: left;
+  width: 5px;
+  height: 14px;
+  background: #21f838;
+}
+#cmd ~ input {
+  width: 0;
+  height: 0;
+  opacity: 0;
+}

+ 3 - 0
i18n/pt/ui.json

@@ -111,6 +111,9 @@
   "inform_valid_variable_duplicated" : "Já existe uma variável local com o nome informado.",
   "arrangement": "Arranjo",
   "conversion": "Conversao",
+  "terminal_clear":"Limpa o terminal removendo todos os textos",
+  "terminal_show":"Exibe o terminal caso esteja escondido",
+  "terminal_hide":"Esconde o terminal caso não esteja escondido",
   "$sin": "seno",
   "$cos": "cosseno",
   "$tan": "tangente",

+ 94 - 10
js/io/domConsole.js

@@ -12,14 +12,24 @@ export class DOMConsole {
     return 2;
   }
 
+  static get INPUT () {
+    return 3;
+  }
+
   constructor (elementID) {
     this.input = null;
+    this.cursorInterval = null;
+    this.inputDiv = null;
+    this.inputCMD = null;
+    this.inputSpan = null;
+    this.cursorRef = null;
     this.needInput = false;
     this.termDiv = null;
     this.anyKey = false;
     this.parent = $(elementID);
     this.setup();
     this.inputListeners = [];
+    this.hideInput();
   }
 
   setup () {
@@ -30,7 +40,6 @@ export class DOMConsole {
   _setupEvents () {
     this.input.on("keydown", (event) => {
       if (!this.needInput) {
-        event.preventDefault();
         return;
       }
       const keyCode = event.which;
@@ -38,8 +47,9 @@ export class DOMConsole {
         let text = this.input.val();
         text = text.replace('[\n\r]+', '');
         this.notifyListeners(text);
-        this.write(text);
+        this._appendUserInput(text);
         this.input.val("");
+        this.inputSpan.text("");
       }
     });
   }
@@ -47,10 +57,52 @@ export class DOMConsole {
   _setupDom () {
     this.termDiv = $("<div></div>");
     this.termDiv.addClass("ivprog-term-div");
-    this.input = $('<input text="type">')
-    this.input.addClass("ivprog-term-input");
-    this.termDiv.append(this.input);
+    this.inputDiv = $(`
+      <div id="ivprog-terminal-inputdiv">
+        <div id="cmd">
+          <span></span>
+          <div id="cursor"></div>
+        </div>
+      </div>
+    `);
+    this.input = $('<input type="text" name="command" value=""/>');
+    this.inputDiv.append(this.input);
+    this.cursorRef = $(this.inputDiv.find("#cursor")[0]);
+    this.inputSpan = $(this.inputDiv.find("#cmd").children('span')[0]);
+    this.inputCMD = $(this.inputDiv.find("#cmd")[0]);
+    //this.input.addClass("ivprog-term-input");
+    this.termDiv.append(this.inputDiv);
     this.parent.append(this.termDiv);
+    this._setupCursor();
+  }
+
+  _setupCursor () {
+    const outerRef = this
+    this.inputCMD.click(function() {
+      if(outerRef.cursorInterval != null) {
+        return;
+      }
+      outerRef.input.focus();
+      outerRef.cursorInterval = window.setInterval(function() {
+        if (outerRef.cursorRef.css('visibility') === 'visible') {
+          outerRef.cursorRef.css({visibility: 'hidden'});
+        } else {
+          outerRef.cursorRef.css({visibility: 'visible'});
+        }
+      }, 550);
+    });
+
+    this.inputCMD.click();
+    
+    this.input.keyup(function() {
+      outerRef.inputSpan.text(outerRef.input.val());
+    });
+
+    this.input.blur(function() {
+      clearInterval(outerRef.cursorInterval);
+      outerRef.cursorInterval = null;
+      outerRef.cursorRef.css({visibility: 'visible'});
+    });
   }
 
   notifyListeners (text) {
@@ -77,7 +129,18 @@ export class DOMConsole {
     const textDiv = $("<div></div>");
     textDiv.addClass(divClass);
     textDiv.append(text);
-    textDiv.insertBefore(this.input);
+    textDiv.insertBefore(this.inputDiv);
+    this.scrollTerm();
+  }
+
+  _appendUserInput (text) {
+    const divClass = this.getClassForType(DOMConsole.INPUT);
+    const textDiv = $(`<div>
+      <i class="icon keyboard outline" style="float:left"></i>
+      <span>${text}</span>
+    </div>`);
+    textDiv.addClass(divClass);
+    textDiv.insertBefore(this.inputDiv);
     this.scrollTerm();
   }
 
@@ -87,8 +150,21 @@ export class DOMConsole {
     }, 0);
   }
 
+  focus () {
+    this.parent.show();
+    const prev = this.inputDiv.prev();
+    if(prev.length > 0)
+      prev[0].scrollIntoView();
+  }
+
+  hide () {
+    this.parent.hide();
+  }
+
   getClassForType (type) {
     switch (type) {
+      case DOMConsole.INPUT:
+        return "ivprog-term-userInput";
       case DOMConsole.USER:
         return "ivprog-term-userText";
       case DOMConsole.INFO:
@@ -103,17 +179,24 @@ export class DOMConsole {
     this.input.off();
     this.input = null;
     this.parent.empty();
+    if(this.cursorInterval != null) {
+      clearInterval(this.cursorInterval);
+    }
+    this.inputCMD.off();
   }
 
   showInput () {
     this.needInput = true;
-    this.input.show();
-    this.input.focus();
+    this.inputDiv.show();
+    this.inputCMD.click();
+    this.inputCMD[0].scrollIntoView();
   }
 
   hideInput () {
     this.needInput = false;
-    this.input.hide();
+    this.inputDiv.hide();
+    clearInterval(this.cursorInterval);
+    this.cursorInterval = null;
   }
 
   requestInput (callback, anyKey = false) {
@@ -131,7 +214,8 @@ export class DOMConsole {
   }
 
   clear () {
-    this.input.parent().children().not(this.input).remove();
+    this.inputDiv.parent().children().not(this.inputDiv).remove();
     this.input.val("");
+    this.inputSpan.text("");
   }
 }

+ 38 - 10
js/visualUI/functions.js

@@ -712,6 +712,8 @@ export function initVisualUI () {
   // const mainDiv = $('#visual-main-div');
   // fill mainDiv with functions and globals...
   // renderAlgorithm()...
+  domConsole = new DOMConsole("#ivprog-term");
+  domConsole.hide();
   $('.add_function_button').on('click', () => {
     addFunctionHandler();
   });
@@ -747,6 +749,26 @@ export function initVisualUI () {
     window.open('https://www.usp.br/line/ivprog/', '_blank');
   });
   $('.main_title h2').prop('title', LocalizedStrings.getUI('text_ivprog_description'));
+  $('#ivprog-console-clearbtn').on('click', () => {
+    if (domConsole != null) {
+      domConsole.clear();
+    }
+  });
+  $('#ivprog-console-clearbtn').popup({content:LocalizedStrings.getUI("terminal_clear")});
+
+  $('#ivprog-console-showbtn').on('click', () => {
+    if (domConsole != null) {
+      domConsole.focus();
+    }
+  });
+  $('#ivprog-console-showbtn').popup({content:LocalizedStrings.getUI("terminal_show")});
+
+  $('#ivprog-console-hidebtn').on('click', () => {
+    if (domConsole != null) {
+      domConsole.hide();
+    }
+  });
+  $('#ivprog-console-hidebtn').popup({content:LocalizedStrings.getUI("terminal_hide")});
 
   var time_show = 750;
   $('.visual_coding_button').popup({
@@ -847,6 +869,7 @@ export function initVisualUI () {
        updateSequenceGlobals(evt.oldIndex, evt.newIndex);
     }
   });
+  
 }
 
 export function setTestCases (testCases) {
@@ -890,9 +913,9 @@ function runCodeAssessment () {
 
   toggleConsole(true);
 
-  if(domConsole == null)
-    domConsole = new DOMConsole("#ivprog-term");
-  $("#ivprog-term").slideDown(500);
+  // if(domConsole == null)
+  //   domConsole = new DOMConsole("#ivprog-term");
+  // $("#ivprog-term").slideDown(500);
   const runner = new IVProgAssessment(strCode, _testCases, domConsole);
   isRunning = true;
   runner.runTest().then(grade => {
@@ -920,9 +943,9 @@ function runCode () {
   
   toggleConsole(true);
 
-  if(domConsole == null)
-    domConsole = new DOMConsole("#ivprog-term");
-  $("#ivprog-term").slideDown(500);
+  // if(domConsole == null)
+  //   domConsole = new DOMConsole("#ivprog-term");
+  //$("#ivprog-term").slideDown(500);
   try {
     const data = SemanticAnalyser.analyseFromSource(strCode);
     const proc = new IVProgProcessor(data);
@@ -952,7 +975,12 @@ function toggleConsole (is_running) {
   if (is_running) {
     $('.ivprog-term-div').css('display', 'block');
     $('#ivprog-term').css('min-height', '160px');
-    $('#ivprog-term').css('margin-top', '-170px');
+    if(domConsole != null)
+      domConsole.focus();
+    //$('#ivprog-term').css('margin-top', '-170px');
+    return;
+  } else {
+    domConsole.hide();
     return;
   }
 
@@ -960,13 +988,13 @@ function toggleConsole (is_running) {
     // esconder
     $('.ivprog-term-div').css('display', 'none');
     $('#ivprog-term').css('min-height', '0');
-    $('#ivprog-term').css('margin-top', '-30px');
-    $('#ivprog-term').css('padding', '5px');
+    //$('#ivprog-term').css('margin-top', '-30px');
+    //$('#ivprog-term').css('padding', '5px');
   } else {
     // mostrar
     $('.ivprog-term-div').css('display', 'block');
     $('#ivprog-term').css('min-height', '160px');
-    $('#ivprog-term').css('margin-top', '-170px');
+    //$('#ivprog-term').css('margin-top', '-170px');
   }
 }
 

+ 11 - 3
templates/index.html

@@ -93,9 +93,17 @@
         <div class="ui one column container segment ivprog_textual_panel loading" style="display: none;">
           <textarea class="ivprog_textual_code" readonly></textarea>
         </div>
-
-        <div id='ivprog-term' class="six column wide">
-          <div class="div_toggle_console"><i class="inverted terminal icon green button_toggle_console"></i></div>
+        <div id='ivprog-term-div' class="six column wide">
+          <div class="bash">
+            <div class="bash-title">
+              <i id="ivprog-console-clearbtn" class="icon eraser" style="float:left;padding-left: 5px"></i>
+              <span>Terminal</span>
+              <i id="ivprog-console-showbtn" class="icon window maximize outline" style="float:right"></i>
+              <i id="ivprog-console-hidebtn" class="icon window minimize outline" style="float:right"></i>
+            </div>
+            <div id='ivprog-term' class="bash-body">
+            </div>
+          </div>
         </div>
       </div>