using System; using System.Collections.Generic; using System.Linq; using System.Text; using Bridge; using Bridge.Bootstrap3; using Bridge.Html5; using Bridge.jQuery2; using Bridge.Text.RegularExpressions; namespace WebMrbc { public class MainMenuView { private Tuple[] _BlockIds; private Dictionary _Files = new Dictionary(); private Uint8Array _CFile; private Uint8Array _MrbFile; private string filename; jQuery el; IClassWorkspace current; public MainMenuView() { el = new jQuery("#main-menu"); var filedialog = (HTMLInputElement)Document.GetElementById("load-file"); filedialog.OnChange += (ele) => { if (filedialog.Value == null) return; onUpload(filedialog); }; // HACK: if don't do below, can't open submenu on Chromium on Raspberry Pi jQuery.Select(".dropdown-toggle").Dropdown(); Views.ClassSelectorView.Selected += ClassSelectorView1_Selected; Views.ClassSelectorView.Removed += ClassSelectorView1_Removed; Views.ClassSelectorView.MarkClicked += ClassSelectorView1_MarkClicked; current = Views.ClassSelectorView.Current; } private void ToRubyAll() { foreach (var item in Collections.ClassWorkspaces) { var view = item.View; if (view.Changed || item.RubyCode == null) { var rubyfile = item.Identifier + ".rb"; var workspace = item.Workspace; var code = item.ToCode(rubyfile); _Files[rubyfile] = code; } } } private void GetCompileArgs(string[] rubyfiles, string path, string ext, ref string outfile) { var i = rubyfiles.Length; rubyfiles.Push("placeholder.out"); if (!path.EndsWith("/")) path = path + "/"; ToRubyAll(); var list = new IClassWorkspace[0]; list.Push(Collections.LocalNode); foreach (var item in Collections.ClassWorkspaces) { if ((item == Collections.LocalNode) || (item == Collections.EcnlTaskWorkspace) || (item == Collections.MainLoopWorkspace)) continue; list.Push(item); } list.Push(Collections.EcnlTaskWorkspace); list.Push(Collections.MainLoopWorkspace); foreach (var file in list) { rubyfiles.Push(path + file.Identifier + ".rb"); } if (String.IsNullOrEmpty(outfile) && (i + 1 < rubyfiles.Length)) outfile = rubyfiles[i + 1].Replace(new Regex(".rb$", "g"), ext.StartsWith(".") ? ext : ("." + ext)); rubyfiles[i] = outfile; } public void onHelp() { App.Module = new Mruby(); var args = new[] { "mrbc", "--help" }; App.Module.run(args); onOutputMode(); } public void onVersion() { App.Module = new Mruby(); var args = new[] { "mrbc", "--version" }; App.Module.run(args); onOutputMode(); } void Mruby_PreRun() { var FS = App.Module.GetFileSystem(); FS.createFolder("/", "src", true, false); FS.createFolder("/", "build", true, true); foreach (var f in _Files) { FS.writeFile("/src/" + f.Key, f.Value); } } void Mruby_ToCPostRun() { var FS = App.Module.GetFileSystem(); var filename = "/build/main_rb.c"; var stt = FS.stat(filename); var stream = FS.open(filename, "r"); var buf = new Uint8Array(stt.size); FS.read(stream, buf, 0, stt.size, 0); FS.close(stream); _CFile = buf; } void Mruby_ToMrbPostRun() { var FS = App.Module.GetFileSystem(); var filename = "/build/main_rb.mrb"; var stt = FS.stat(filename); var stream = FS.open(filename, "r"); var buf = new Uint8Array(stt.size); FS.read(stream, buf, 0, stt.size, 0); FS.close(stream); _MrbFile = buf; } public void onCompileToC() { var args = new[] { "mrbc", "-Bmain_rb_code", "-e", "-o" }; string mrbfile = "/build/main_rb.c"; GetCompileArgs(args, "/src/", "c", ref mrbfile); _CFile = null; App.Module = new Mruby(); App.Module.preRun.Push(new Action(Mruby_PreRun)); App.Module.postRun.Push(new Action(() => { Mruby_ToCPostRun(); if (_CFile != null) { App.WriteLine(App.Module.UTF8ArrayToString(_CFile, 0)); var blob = new Blob(new BlobDataObject[] { _CFile.Buffer }, new BlobPropertyBag() { Type = "text/plain;charset=utf-8" }); Script.Call("saveAs", blob, "main_rb.c"); } })); App.Module.run(args); onOutputMode(); } public void onCompileToMrb() { var args = new[] { "mrbc", "-e", "-o" }; string mrbfile = "/build/main_rb.mrb"; GetCompileArgs(args, "/src/", "mrb", ref mrbfile); _MrbFile = null; App.Module = new Mruby(); App.Module.preRun.Push(new Action(Mruby_PreRun)); App.Module.postRun.Push(new Action(() => { Mruby_ToMrbPostRun(); if (_MrbFile != null) { App.WriteLine((new HexDump(_MrbFile, 16)).ToString()); var blob = new Blob(new BlobDataObject[] { _MrbFile.Buffer }, new BlobPropertyBag() { Type = "application/octet-stream" }); Script.Call("saveAs", blob, "main_rb.mrb"); } })); App.Module.run(args); onOutputMode(); } public void onBlockMode() { SelectBlockTab(); } public void onRubyMode() { UpdateCode(); SelectRubyTab(); } public void onOutputMode() { SelectOutputTab(); App.Term.fit(); } public void onLoad() { var filedialog = (HTMLInputElement)Document.GetElementById("load-file"); filedialog.Value = null; filedialog.Click(); } private void onUpload(HTMLInputElement filedialog) { var view = Views.ClassSelectorView.Current; if (view == null) return; var file = filedialog.Files[0]; try { var reader = Script.Write("new FileReader()"); reader.onload = new Action((e) => { var xml = Blockly.Xml.textToDom(reader.result); Blockly.Xml.domToWorkspace(xml, view.Workspace); }); reader.readAsText(file); } catch (Exception e) { App.WriteLine(e.ToString()); } } public void onSaveWorkspace() { var zip = Script.Write("new JSZip()"); foreach (var e in Collections.ClassWorkspaces) { var xml = Blockly.Xml.workspaceToDom(e.Workspace); zip.file(e.Identifier + ".xml", xml.OuterHTML); } var blob = Script.Write("zip.generate({ type: \"blob\" })"); Script.Call("saveAs", blob, "Workspace.zip"); } public void onSaveRuby() { ToRubyAll(); var zip = Script.Write("new JSZip()"); foreach (var f in _Files) { zip.file(f.Key, f.Value); } var blob = Script.Write("zip.generate({ type: \"blob\" })"); Script.Call("saveAs", blob, "Workspace.zip"); } public void onReset() { } public void onRun() { var args = new[] { "mrbc", "-e", "-o" }; string mrbfile = "/build/main_rb.mrb"; GetCompileArgs(args, "/src/", "mrb", ref mrbfile); _MrbFile = null; App.Module = new Mruby(); App.Module.preRun.Push(new Action(Mruby_PreRun)); App.Module.postRun.Push(new Action(() => { Mruby_ToMrbPostRun(); if (_MrbFile == null) return; App.WriteLine((new HexDump(_MrbFile, 16)).ToString()); var btn = jQuery.Select("#message-button"); btn.Hide(); var el = jQuery.Select("#message-modal"); el.Modal(new ModalOptions() { Backdrop = "static", Show = true }); var textel = jQuery.Select("#message-text"); textel.Text("実行ファイルを転送しています。"); jQuery.Ajax(new AjaxOptions() { Url = "/upload/main.mrb", Type = "POST", DataType = "*", Data = _MrbFile.Buffer, ProcessData = false, ContentType = false, Success = (data, textStatus, request) => { btn.Show(); App.WriteLine(textStatus); textel.Text("実行を開始しました。"); }, Error = (request, textStatus, error) => { btn.Show(); App.WriteLine(textStatus); textel.Text("実行に失敗しました。"); } }); })); App.Module.run(args); } public void onMessageClose() { var el = jQuery.Select("#message-modal"); el.Modal(ModalOperation.Hide); } private static void SelectBlockTab() { jQuery.Select("#tabs a[href='#block-tab']").Tab(TabOperation.Show); //jQuery.Select(".blocklyToolboxDiv").Show(); } private static void SelectRubyTab() { jQuery.Select("#tabs a[href='#ruby-tab']").Tab(TabOperation.Show); //jQuery.Select(".blocklyToolboxDiv").Hide(); } private static void SelectOutputTab() { jQuery.Select("#tabs a[href='#output-tab']").Tab(TabOperation.Show); //jQuery.Select(".blocklyToolboxDiv").Hide(); } private void ClassSelectorView1_Selected(object sender, EventArgs e) { var item = Views.ClassSelectorView.Current; if (item == null) { UpdateCode(); SelectRubyTab(); } else { var view = item.View; view.Show(); SelectBlockTab(); foreach (var i in Collections.ClassWorkspaces) { if (i != item) { i.View.Hide(); } } } if (current != item) { current?.View.Hide(); } current = item; } private void ClassSelectorView1_Removed(object sender, ItemRemovedEventArgs e) { var view = e.Item.View; view.Dispose(); } private void ClassSelectorView1_MarkClicked(object sender, EventArgs e) { } private void UpdateCode() { string code = ""; var item = Views.ClassSelectorView.Current; if (item != null) { var view = item.View; if (view.Changed || item.RubyCode == null) { var rubyfile = item.Identifier + ".rb"; var workspace = item.Workspace; code = item.ToCode(rubyfile); _Files[rubyfile] = code; this.filename = rubyfile; } else { code = _Files[item.RubyCode.filename]; this.filename = item.RubyCode.filename; } } App.CodeEditor.setValue(code); App.CodeEditor.gotoLine(0, 0); } internal BlocklyView NewBlocklyView(string identifier) { return new BlocklyView(identifier); } internal void RemoveEObjectWorkspace(IClassWorkspace item) { var view = item.View; view.Dispose(); } } }