diff --git a/index.html b/index.html index 76666dc..db22337 100755 --- a/index.html +++ b/index.html @@ -6,13 +6,15 @@ - - - - - - - + + + + + + + + +
Disconnected
@@ -59,7 +61,7 @@
- +
diff --git a/styles.css b/styles.css index c05cc6e..2e0b38b 100755 --- a/styles.css +++ b/styles.css @@ -15,10 +15,6 @@ table.blockly-table { height: 95%; width: 100%; } -/* non clickable input forms */ -.non-clickable { - pointer-events: none; -} /* spans */ span.has-error { color: #a94442 !important; @@ -126,7 +122,7 @@ div#stream { td#blocklyCodeArea { display: none; } - textarea#blocklyCode { + div#blocklyCode { display: none; } } @@ -140,8 +136,7 @@ div#stream { width: 40%; height: 100%; } - textarea#blocklyCode { - border: none; + div#blocklyCode { width: 100%; height: 100%; font-size: 1.8em; diff --git a/sumorobot.js b/sumorobot.js index 8856bb0..5e8928a 100755 --- a/sumorobot.js +++ b/sumorobot.js @@ -6,6 +6,9 @@ var remoteControl = false; //var robotServer = "10.42.0.1"; var robotServer = "iot.koodur.com"; +/* ace editor object */ +var pythonEditor = null; + /* the sumorobot code */ var sumocode = ""; /* the sumorobot object */ @@ -129,6 +132,44 @@ window.onload = function() { /* load the control panel */ updateControlPanel(); + /* load ace editor */ + pythonEditor = ace.edit("blocklyCode"); + /* set the style */ + pythonEditor.setTheme("ace/theme/textmate"); + pythonEditor.session.setMode("ace/mode/python"); + pythonEditor.session.setTabSize(2); + pythonEditor.setReadOnly(true); + /* disable scrolling warning */ + pythonEditor.$blockScrolling = Infinity; + /* enable autocomplete */ + ace.require("ace/ext/language_tools"); + pythonEditor.setOptions({ + enableSnippets: true, + enableLiveAutocompletion: true, + enableBasicAutocompletion: true + }); + /* add autocomplete keywords */ + pythonEditor.completers.push({ + getCompletions: function(editor, session, pos, prefix, callback) { + callback(null, [ + {value: "STOP", score: 1000, meta: "sumorobot"}, + {value: "LEFT", score: 1000, meta: "sumorobot"}, + {value: "RIGHT", score: 1000, meta: "sumorobot"}, + {value: "FORWARD", score: 1000, meta: "sumorobot"}, + {value: "BACKWARD", score: 1000, meta: "sumorobot"}, + {value: "STATUS", score: 1000, meta: "sumorobot"}, + {value: "LEFT_LINE", score: 1000, meta: "sumorobot"}, + {value: "RIGHT_LINE", score: 1000, meta: "sumorobot"}, + {value: "sumorobot", score: 1000, meta: "sumorobot"}, + {value: "move", score: 1000, meta: "sumorobot"}, + {value: "set_led", score: 1000, meta: "sumorobot"}, + {value: "is_line", score: 1000, meta: "sumorobot"}, + {value: "set_servo", score: 1000, meta: "sumorobot"}, + {value: "is_opponent", score: 1000, meta: "sumorobot"} + ]); + } + }); + /* change the if block to be more cheerful */ Blockly.Msg.LOGIC_HUE = '#44CC00'; Blockly.Constants.Logic.HUE = '#44CC00'; @@ -327,7 +368,7 @@ window.onload = function() { } /* retrieve the blocks */ - var xml = Blockly.Xml.textToDom(getLocalStorageItem("sumorobot.currentProgram")); + var xml = Blockly.Xml.textToDom(getLocalStorageItem("sumorobot.blockly")); /* resume the blocks */ Blockly.Xml.domToWorkspace(xml, workspace); @@ -358,12 +399,13 @@ window.onload = function() { /* generate code from the used blocks */ sumocode = Blockly.Python.workspaceToCode(workspace); - /* show the code to the user, filter out block IDs */ - document.getElementById("blocklyCode").value = sumocode.replace(/[,]?[ ]?"(.*?)"/g, ""); + /* show the code in the ace editor, filter out block IDs */ + pythonEditor.setValue("\n" + sumocode.replace(/[,]?[ ]?"(.*?)"/g, "")); + pythonEditor.clearSelection(); /* save the code to the local storage */ var xml = Blockly.Xml.workspaceToDom(workspace); - localStorage.setItem("sumorobot.currentProgram", Blockly.Xml.domToText(xml)); + localStorage.setItem("sumorobot.blockly", Blockly.Xml.domToText(xml)); /* if control_if block is used */ if (controlBlockId != "") { @@ -431,14 +473,29 @@ window.onload = function() { $("#blocklyCode").toggle(); break; case 80: // p - $("#blocklyCode").blur(); $("#blocklyDiv").toggle(); $("#blocklyArea").toggle(); - $("#blocklyCode").toggleClass("non-clickable"); - var event = {type: Blockly.Events.CHANGE}; - workspace.fireChangeListener(event); + /* disable / enable ace editor */ + pythonEditor.setReadOnly(pythonEnabled); /* toggle python enabled */ pythonEnabled = !pythonEnabled; + if (pythonEnabled) { + /* get the saved Python code from local storage or set empty */ + pythonEditor.setValue(getLocalStorageItem("sumorobot.python") || ""); + /* add an input listener for the code editor */ + pythonEditor.on("change", function() { + setLocalStorageItem("sumorobot.python", pythonEditor.getValue()) + }); + pythonEditor.clearSelection(); + pythonEditor.focus(); + } else { + /* remove input listener from the code editor */ + pythonEditor.session.removeAllListeners("change"); + /* fire CHANGE event in Blockly workspace to change the Python code */ + var event = {type: Blockly.Events.CHANGE}; + workspace.fireChangeListener(event); + pythonEditor.blur(); + } break; case 82: // r if (remoteControl) @@ -483,7 +540,7 @@ window.onload = function() { /* if we are in Python mode */ if (pythonEnabled) { /* send the code from the textarea to the SumoRobot */ - sumorobot.send("start:" + $("#blocklyCode").val()); + sumorobot.send("start:" + pythonEditor.getValue()); /* otherwise when we are in Blockly mode */ } else { /* send the code from the blocks to the SumoRobot */