source: EcnlProtoTool/trunk/webapp/webmrbc/MainMenuView.cs@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csharp
File size: 9.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Bridge;
6using Bridge.Bootstrap3;
7using Bridge.Html5;
8using Bridge.jQuery2;
9using Bridge.Text.RegularExpressions;
10
11namespace WebMrbc
12{
13 public class MainMenuView
14 {
15 private Tuple<string, string>[] _BlockIds;
16 private Dictionary<string, string> _Files = new Dictionary<string, string>();
17 private Uint8Array _CFile;
18 private Uint8Array _MrbFile;
19 private string filename;
20 jQuery el;
21 IClassWorkspace current;
22
23 public MainMenuView()
24 {
25 el = new jQuery("#main-menu");
26
27 var filedialog = (HTMLInputElement)Document.GetElementById("load-file");
28 filedialog.OnChange += (ele) => {
29 if (filedialog.Value == null)
30 return;
31
32 onUpload(filedialog);
33 };
34
35 // HACK: if don't do below, can't open submenu on Chromium on Raspberry Pi
36 jQuery.Select(".dropdown-toggle").Dropdown();
37
38 Views.ClassSelectorView.Selected += ClassSelectorView1_Selected;
39 Views.ClassSelectorView.Removed += ClassSelectorView1_Removed;
40 Views.ClassSelectorView.MarkClicked += ClassSelectorView1_MarkClicked;
41
42 current = Views.ClassSelectorView.Current;
43 }
44
45 private void ToRubyAll()
46 {
47 foreach (var item in Collections.ClassWorkspaces) {
48 var view = item.View;
49 if (view.Changed || item.RubyCode == null) {
50 var rubyfile = item.Identifier + ".rb";
51 var workspace = item.Workspace;
52 var code = item.ToCode(rubyfile);
53
54 _Files[rubyfile] = code;
55 }
56 }
57 }
58
59 private void GetCompileArgs(string[] rubyfiles, string path, string ext, ref string outfile)
60 {
61 var i = rubyfiles.Length;
62 rubyfiles.Push("placeholder.out");
63
64 if (!path.EndsWith("/"))
65 path = path + "/";
66
67 ToRubyAll();
68
69 var list = new IClassWorkspace[0];
70 list.Push(Collections.LocalNode);
71 foreach (var item in Collections.ClassWorkspaces) {
72 if ((item == Collections.LocalNode)
73 || (item == Collections.EcnlTaskWorkspace)
74 || (item == Collections.MainLoopWorkspace))
75 continue;
76 list.Push(item);
77 }
78 list.Push(Collections.EcnlTaskWorkspace);
79 list.Push(Collections.MainLoopWorkspace);
80
81 foreach (var file in list) {
82 rubyfiles.Push(path + file.Identifier + ".rb");
83 }
84
85 if (String.IsNullOrEmpty(outfile) && (i + 1 < rubyfiles.Length))
86 outfile = rubyfiles[i + 1].Replace(new Regex(".rb$", "g"), ext.StartsWith(".") ? ext : ("." + ext));
87 rubyfiles[i] = outfile;
88 }
89
90 public void onHelp()
91 {
92 App.Module = new Mruby();
93
94 var args = new[] { "mrbc", "--help" };
95 App.Module.run(args);
96 onOutputMode();
97 }
98
99 public void onVersion()
100 {
101 App.Module = new Mruby();
102
103 var args = new[] { "mrbc", "--version" };
104 App.Module.run(args);
105 onOutputMode();
106 }
107
108 void Mruby_PreRun()
109 {
110 var FS = App.Module.GetFileSystem();
111
112 FS.createFolder("/", "src", true, false);
113 FS.createFolder("/", "build", true, true);
114
115 foreach (var f in _Files) {
116 FS.writeFile("/src/" + f.Key, f.Value);
117 }
118 }
119
120 void Mruby_ToCPostRun()
121 {
122 var FS = App.Module.GetFileSystem();
123
124 var filename = "/build/main_rb.c";
125 var stt = FS.stat(filename);
126 var stream = FS.open(filename, "r");
127 var buf = new Uint8Array(stt.size);
128 FS.read(stream, buf, 0, stt.size, 0);
129 FS.close(stream);
130
131 _CFile = buf;
132 }
133
134 void Mruby_ToMrbPostRun()
135 {
136 var FS = App.Module.GetFileSystem();
137
138 var filename = "/build/main_rb.mrb";
139 var stt = FS.stat(filename);
140 var stream = FS.open(filename, "r");
141 var buf = new Uint8Array(stt.size);
142 FS.read(stream, buf, 0, stt.size, 0);
143 FS.close(stream);
144
145 _MrbFile = buf;
146 }
147
148 public void onCompileToC()
149 {
150 var args = new[] { "mrbc", "-Bmain_rb_code", "-e", "-o" };
151 string mrbfile = "/build/main_rb.c";
152 GetCompileArgs(args, "/src/", "c", ref mrbfile);
153
154 _CFile = null;
155 App.Module = new Mruby();
156 App.Module.preRun.Push(new Action(Mruby_PreRun));
157 App.Module.postRun.Push(new Action(() => {
158 Mruby_ToCPostRun();
159
160 if (_CFile != null) {
161 App.WriteLine(App.Module.UTF8ArrayToString(_CFile, 0));
162
163 var blob = new Blob(new BlobDataObject[] { _CFile.Buffer },
164 new BlobPropertyBag() { Type = "text/plain;charset=utf-8" });
165 Script.Call("saveAs", blob, "main_rb.c");
166 }
167 }));
168 App.Module.run(args);
169 onOutputMode();
170 }
171
172 public void onCompileToMrb()
173 {
174 var args = new[] { "mrbc", "-e", "-o" };
175 string mrbfile = "/build/main_rb.mrb";
176 GetCompileArgs(args, "/src/", "mrb", ref mrbfile);
177
178 _MrbFile = null;
179 App.Module = new Mruby();
180 App.Module.preRun.Push(new Action(Mruby_PreRun));
181 App.Module.postRun.Push(new Action(() => {
182 Mruby_ToMrbPostRun();
183
184 if (_MrbFile != null) {
185 App.WriteLine((new HexDump(_MrbFile, 16)).ToString());
186
187 var blob = new Blob(new BlobDataObject[] { _MrbFile.Buffer },
188 new BlobPropertyBag() { Type = "application/octet-stream" });
189 Script.Call("saveAs", blob, "main_rb.mrb");
190 }
191 }));
192 App.Module.run(args);
193 onOutputMode();
194 }
195
196 public void onBlockMode()
197 {
198 SelectBlockTab();
199 }
200
201 public void onRubyMode()
202 {
203 UpdateCode();
204
205 SelectRubyTab();
206 }
207
208 public void onOutputMode()
209 {
210 SelectOutputTab();
211 App.Term.fit();
212 }
213
214 public void onLoad()
215 {
216 var filedialog = (HTMLInputElement)Document.GetElementById("load-file");
217 filedialog.Value = null;
218 filedialog.Click();
219 }
220
221 private void onUpload(HTMLInputElement filedialog)
222 {
223 var view = Views.ClassSelectorView.Current;
224 if (view == null)
225 return;
226
227 var file = filedialog.Files[0];
228 try {
229 var reader = Script.Write<dynamic>("new FileReader()");
230 reader.onload = new Action<object>((e) => {
231 var xml = Blockly.Xml.textToDom(reader.result);
232 Blockly.Xml.domToWorkspace(xml, view.Workspace);
233 });
234 reader.readAsText(file);
235 }
236 catch (Exception e) {
237 App.WriteLine(e.ToString());
238 }
239 }
240
241 public void onSaveWorkspace()
242 {
243 var zip = Script.Write<dynamic>("new JSZip()");
244 foreach (var e in Collections.ClassWorkspaces) {
245 var xml = Blockly.Xml.workspaceToDom(e.Workspace);
246 zip.file(e.Identifier + ".xml", xml.OuterHTML);
247 }
248 var blob = Script.Write<object>("zip.generate({ type: \"blob\" })");
249 Script.Call("saveAs", blob, "Workspace.zip");
250 }
251
252 public void onSaveRuby()
253 {
254 ToRubyAll();
255
256 var zip = Script.Write<dynamic>("new JSZip()");
257 foreach (var f in _Files) {
258 zip.file(f.Key, f.Value);
259 }
260 var blob = Script.Write<object>("zip.generate({ type: \"blob\" })");
261 Script.Call("saveAs", blob, "Workspace.zip");
262 }
263
264 public void onReset()
265 {
266 }
267
268 public void onRun()
269 {
270 var args = new[] { "mrbc", "-e", "-o" };
271 string mrbfile = "/build/main_rb.mrb";
272 GetCompileArgs(args, "/src/", "mrb", ref mrbfile);
273
274 _MrbFile = null;
275 App.Module = new Mruby();
276 App.Module.preRun.Push(new Action(Mruby_PreRun));
277 App.Module.postRun.Push(new Action(() => {
278 Mruby_ToMrbPostRun();
279
280 if (_MrbFile == null)
281 return;
282
283 App.WriteLine((new HexDump(_MrbFile, 16)).ToString());
284
285 var btn = jQuery.Select("#message-button");
286 btn.Hide();
287 var el = jQuery.Select("#message-modal");
288 el.Modal(new ModalOptions() {
289 Backdrop = "static",
290 Show = true
291 });
292 var textel = jQuery.Select("#message-text");
293 textel.Text("実行ファイルを転送しています。");
294
295 jQuery.Ajax(new AjaxOptions() {
296 Url = "/upload/main.mrb",
297 Type = "POST",
298 DataType = "*",
299 Data = _MrbFile.Buffer,
300 ProcessData = false,
301 ContentType = false,
302 Success = (data, textStatus, request) => {
303 btn.Show();
304 App.WriteLine(textStatus);
305 textel.Text("実行を開始しました。");
306 },
307 Error = (request, textStatus, error) => {
308 btn.Show();
309 App.WriteLine(textStatus);
310 textel.Text("実行に失敗しました。");
311 }
312 });
313 }));
314 App.Module.run(args);
315 }
316
317 public void onMessageClose()
318 {
319 var el = jQuery.Select("#message-modal");
320 el.Modal(ModalOperation.Hide);
321 }
322
323 private static void SelectBlockTab()
324 {
325 jQuery.Select("#tabs a[href='#block-tab']").Tab(TabOperation.Show);
326 //jQuery.Select(".blocklyToolboxDiv").Show();
327 }
328
329 private static void SelectRubyTab()
330 {
331 jQuery.Select("#tabs a[href='#ruby-tab']").Tab(TabOperation.Show);
332 //jQuery.Select(".blocklyToolboxDiv").Hide();
333 }
334
335 private static void SelectOutputTab()
336 {
337 jQuery.Select("#tabs a[href='#output-tab']").Tab(TabOperation.Show);
338 //jQuery.Select(".blocklyToolboxDiv").Hide();
339 }
340
341 private void ClassSelectorView1_Selected(object sender, EventArgs e)
342 {
343 var item = Views.ClassSelectorView.Current;
344 if (item == null) {
345 UpdateCode();
346
347 SelectRubyTab();
348 }
349 else {
350 var view = item.View;
351 view.Show();
352
353 SelectBlockTab();
354
355 foreach (var i in Collections.ClassWorkspaces) {
356 if (i != item) {
357 i.View.Hide();
358 }
359 }
360 }
361
362 if (current != item) {
363 current?.View.Hide();
364 }
365 current = item;
366 }
367
368 private void ClassSelectorView1_Removed(object sender, ItemRemovedEventArgs e)
369 {
370 var view = e.Item.View;
371 view.Dispose();
372 }
373
374 private void ClassSelectorView1_MarkClicked(object sender, EventArgs e)
375 {
376 }
377
378 private void UpdateCode()
379 {
380 string code = "";
381 var item = Views.ClassSelectorView.Current;
382 if (item != null) {
383 var view = item.View;
384 if (view.Changed || item.RubyCode == null) {
385 var rubyfile = item.Identifier + ".rb";
386 var workspace = item.Workspace;
387 code = item.ToCode(rubyfile);
388
389 _Files[rubyfile] = code;
390 this.filename = rubyfile;
391 }
392 else {
393 code = _Files[item.RubyCode.filename];
394 this.filename = item.RubyCode.filename;
395 }
396 }
397 App.CodeEditor.setValue(code);
398 App.CodeEditor.gotoLine(0, 0);
399 }
400
401 internal BlocklyView NewBlocklyView(string identifier)
402 {
403 return new BlocklyView(identifier);
404 }
405
406 internal void RemoveEObjectWorkspace(IClassWorkspace item)
407 {
408 var view = item.View;
409 view.Dispose();
410 }
411 }
412}
Note: See TracBrowser for help on using the repository browser.