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

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

Visual Studio 2019 と Bridge.NET でビルドできるよう更新。

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csharp;charset=UTF-8
File size: 13.3 KB
Line 
1/*
2 * TOPPERS/ECNL Prototyping tool
3 *
4 * Copyright (C) 2017 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37using System;
38using System.Collections.Generic;
39using System.Linq;
40using System.Text;
41using Bridge;
42using Bridge.Bootstrap3;
43using Bridge.Html5;
44using Bridge.jQuery2;
45
46namespace WebMrbc
47{
48 public class MainMenuView
49 {
50 private Tuple<string, string>[] _BlockIds;
51 private Dictionary<string, string> _Files = new Dictionary<string, string>();
52 private Uint8Array _CFile;
53 private Uint8Array _MrbFile;
54 private string filename;
55 jQuery el;
56 IClassWorkspace current;
57
58 public MainMenuView()
59 {
60 el = new jQuery("#main-menu");
61
62 var filedialog = (HTMLInputElement)Document.GetElementById("load-file");
63 filedialog.OnChange += (ele) => {
64 if (filedialog.Value == null)
65 return;
66
67 onUpload(filedialog);
68 };
69
70 // HACK: if don't do below, can't open submenu on Chromium on Raspberry Pi
71 jQuery.Select(".dropdown-toggle").Dropdown();
72
73 Views.ClassSelectorView.Selected += ClassSelectorView1_Selected;
74 Views.ClassSelectorView.Removed += ClassSelectorView1_Removed;
75 Views.ClassSelectorView.MarkClicked += ClassSelectorView1_MarkClicked;
76
77 current = Views.ClassSelectorView.Current;
78 }
79
80 private void ToRubyAll()
81 {
82 foreach (var item in Collections.ClassWorkspaces) {
83 var view = item.View;
84 if (view.Changed || item.RubyCode == null) {
85 var rubyfile = item.Identifier + ".rb";
86 var workspace = item.Workspace;
87 var code = item.ToCode(rubyfile);
88
89 _Files[rubyfile] = code;
90 }
91 }
92 }
93
94 private void GetCompileArgs(string[] rubyfiles, string path, string ext, ref string outfile)
95 {
96 var i = rubyfiles.Length;
97 rubyfiles.Push("placeholder.out");
98
99 if (!path.EndsWith("/"))
100 path = path + "/";
101
102 ToRubyAll();
103
104 var list = new IClassWorkspace[0];
105 list.Push(Collections.LocalNode);
106 foreach (var item in Collections.ClassWorkspaces) {
107 if ((item == Collections.LocalNode)
108 || (item == Collections.EcnlTaskWorkspace)
109 || (item == Collections.MainLoopWorkspace))
110 continue;
111 list.Push(item);
112 }
113 list.Push(Collections.EcnlTaskWorkspace);
114 list.Push(Collections.MainLoopWorkspace);
115
116 foreach (var file in list) {
117 rubyfiles.Push(path + file.Identifier + ".rb");
118 }
119
120 if (String.IsNullOrEmpty(outfile) && (i + 1 < rubyfiles.Length))
121 outfile = rubyfiles[i + 1].Replace(new RegExp(".rb$", "g"), ext.StartsWith(".") ? ext : ("." + ext));
122 rubyfiles[i] = outfile;
123 }
124
125 public void onHelp()
126 {
127 App.Module = new Mruby();
128
129 var args = new[] { "mrbc", "--help" };
130 App.Module.run(args);
131 onOutputMode();
132 }
133
134 public void onVersion()
135 {
136 App.Module = new Mruby();
137
138 var args = new[] { "mrbc", "--version" };
139 App.Module.run(args);
140 onOutputMode();
141 }
142
143 void Mruby_PreRun()
144 {
145 var FS = App.Module.GetFileSystem();
146
147 FS.createFolder("/", "src", true, false);
148 FS.createFolder("/", "build", true, true);
149
150 foreach (var f in _Files) {
151 FS.writeFile("/src/" + f.Key, f.Value);
152 }
153 }
154
155 void Mruby_ToCPostRun()
156 {
157 var FS = App.Module.GetFileSystem();
158
159 var filename = "/build/main_rb.c";
160 var stt = FS.stat(filename);
161 var stream = FS.open(filename, "r");
162 var buf = new Uint8Array(stt.size);
163 FS.read(stream, buf, 0, stt.size, 0);
164 FS.close(stream);
165
166 _CFile = buf;
167 }
168
169 void Mruby_ToMrbPostRun()
170 {
171 var FS = App.Module.GetFileSystem();
172
173 var filename = "/build/main_rb.mrb";
174 var stt = FS.stat(filename);
175 var stream = FS.open(filename, "r");
176 var buf = new Uint8Array(stt.size);
177 FS.read(stream, buf, 0, stt.size, 0);
178 FS.close(stream);
179
180 _MrbFile = buf;
181 }
182
183 public void onCompileToC()
184 {
185 var args = new[] { "mrbc", "-Bmain_rb_code", "-e", "-o" };
186 string mrbfile = "/build/main_rb.c";
187 GetCompileArgs(args, "/src/", "c", ref mrbfile);
188
189 _CFile = null;
190 App.Module = new Mruby();
191 App.Module.preRun.Push(new Action(Mruby_PreRun));
192 App.Module.postRun.Push(new Action(() => {
193 Mruby_ToCPostRun();
194
195 if (_CFile != null) {
196 App.WriteLine(App.Module.UTF8ArrayToString(_CFile, 0));
197
198 var blob = new Blob(new BlobDataObject[] { _CFile.Buffer },
199 new BlobPropertyBag() { Type = "text/plain;charset=utf-8" });
200 Script.Call("saveAs", blob, "main_rb.c");
201 }
202 }));
203 App.Module.run(args);
204 onOutputMode();
205 }
206
207 public void onCompileToMrb()
208 {
209 var args = new[] { "mrbc", "-e", "-o" };
210 string mrbfile = "/build/main_rb.mrb";
211 GetCompileArgs(args, "/src/", "mrb", ref mrbfile);
212
213 _MrbFile = null;
214 App.Module = new Mruby();
215 App.Module.preRun.Push(new Action(Mruby_PreRun));
216 App.Module.postRun.Push(new Action(() => {
217 Mruby_ToMrbPostRun();
218
219 if (_MrbFile != null) {
220 App.WriteLine((new HexDump(_MrbFile, 16)).ToString());
221
222 var blob = new Blob(new BlobDataObject[] { _MrbFile.Buffer },
223 new BlobPropertyBag() { Type = "application/octet-stream" });
224 Script.Call("saveAs", blob, "main_rb.mrb");
225 }
226 }));
227 App.Module.run(args);
228 onOutputMode();
229 }
230
231 public void onBlockMode()
232 {
233 SelectBlockTab();
234 }
235
236 public void onRubyMode()
237 {
238 UpdateCode();
239
240 SelectRubyTab();
241 }
242
243 public void onOutputMode()
244 {
245 SelectOutputTab();
246 App.Term.fit();
247 }
248
249 public void onLoad()
250 {
251 var filedialog = (HTMLInputElement)Document.GetElementById("load-file");
252 filedialog.Value = null;
253 filedialog.Click();
254 }
255
256 private void onUpload(HTMLInputElement filedialog)
257 {
258 var view = Views.ClassSelectorView.Current;
259 if (view == null)
260 return;
261
262 var file = filedialog.Files[0];
263 try {
264 var reader = Script.Write<dynamic>("new FileReader()");
265 reader.onload = new Action<object>((e) => {
266 var xml = Blockly.Xml.textToDom(reader.result);
267 Blockly.Xml.domToWorkspace(xml, view.Workspace);
268 });
269 reader.readAsText(file);
270 }
271 catch (Exception e) {
272 App.WriteLine(e.ToString());
273 }
274 }
275
276 public void onSaveWorkspace()
277 {
278 var zip = Script.Write<dynamic>("new JSZip()");
279 foreach (var e in Collections.ClassWorkspaces) {
280 var xml = Blockly.Xml.workspaceToDom(e.Workspace);
281 zip.file(e.Identifier + ".xml", xml.OuterHTML);
282 }
283 var blob = Script.Write<object>("zip.generate({ type: \"blob\" })");
284 Script.Call("saveAs", blob, "Workspace.zip");
285 }
286
287 public void onSaveRuby()
288 {
289 ToRubyAll();
290
291 var zip = Script.Write<dynamic>("new JSZip()");
292 foreach (var f in _Files) {
293 zip.file(f.Key, f.Value);
294 }
295 var blob = Script.Write<object>("zip.generate({ type: \"blob\" })");
296 Script.Call("saveAs", blob, "Workspace.zip");
297 }
298
299 public void onReset()
300 {
301 }
302
303 public void onRun()
304 {
305 var args = new[] { "mrbc", "-e", "-o" };
306 string mrbfile = "/build/main_rb.mrb";
307 GetCompileArgs(args, "/src/", "mrb", ref mrbfile);
308
309 _MrbFile = null;
310 App.Module = new Mruby();
311 App.Module.preRun.Push(new Action(Mruby_PreRun));
312 App.Module.postRun.Push(new Action(() => {
313 Mruby_ToMrbPostRun();
314
315 if (_MrbFile == null)
316 return;
317
318 App.WriteLine((new HexDump(_MrbFile, 16)).ToString());
319
320 var btn = jQuery.Select("#message-button");
321 btn.Hide();
322 var el = jQuery.Select("#message-modal");
323 el.Modal(new ModalOptions() {
324 Backdrop = "static",
325 Show = true
326 });
327 var textel = jQuery.Select("#message-text");
328 textel.Text("実行ファイルを転送しています。");
329
330 jQuery.Ajax(new AjaxOptions() {
331 Url = "/upload/main.mrb",
332 Type = "POST",
333 DataType = "*",
334 Data = _MrbFile.Buffer,
335 ProcessData = false,
336 ContentType = false,
337 Success = (data, textStatus, request) => {
338 btn.Show();
339 App.WriteLine(textStatus);
340 textel.Text("実行を開始しました。");
341 },
342 Error = (request, textStatus, error) => {
343 btn.Show();
344 App.WriteLine(textStatus);
345 textel.Text("実行に失敗しました。");
346 }
347 });
348 }));
349 App.Module.run(args);
350 }
351
352 public void onMessageClose()
353 {
354 var el = jQuery.Select("#message-modal");
355 el.Modal(ModalOperation.Hide);
356 }
357
358 public void onInformationOpen()
359 {
360 jQuery.Ajax(new AjaxOptions() {
361 Url = "/information.json",
362 DataType = "json",
363 Success = (data, textStatus, request) => {
364 var items = (dynamic[])data;
365
366 var listview = jQuery.Select("#software-list");
367 listview.Html("");
368
369 foreach (var item in items) {
370 string title = item.title;
371 string version = item.version;
372 string link = item.link;
373 string note = item.note;
374
375 var a = new jQuery("<a>").Attr("class", "list-group-item");
376 a.Append(new jQuery("<h4>").Attr("class", "list-group-item-heading").Text(title));
377 if (String.IsNullOrEmpty(link)) {
378 a.Attr("href", "#");
379 }
380 else {
381 a.Attr("href", link);
382 a.Attr("target", "_blank");
383 }
384 a.Append(new jQuery("<p>").Attr("class", "list-group-item-text").Text("Version " + version));
385 if (!String.IsNullOrEmpty(note))
386 a.Append(new jQuery("<p>").Attr("class", "list-group-item-text").Text(note));
387 listview.Append(a);
388 }
389
390 var el = jQuery.Select("#information-modal");
391 el.Modal(ModalOperation.Show);
392 },
393 Error = (request, textStatus, error) => {
394 },
395 });
396 }
397
398 public void onInformationClose()
399 {
400 var el = jQuery.Select("#information-modal");
401 el.Modal(ModalOperation.Hide);
402 }
403
404 private static void SelectBlockTab()
405 {
406 jQuery.Select("#tabs a[href='#block-tab']").Tab(TabOperation.Show);
407 //jQuery.Select(".blocklyToolboxDiv").Show();
408 }
409
410 private static void SelectRubyTab()
411 {
412 jQuery.Select("#tabs a[href='#ruby-tab']").Tab(TabOperation.Show);
413 //jQuery.Select(".blocklyToolboxDiv").Hide();
414 }
415
416 private static void SelectOutputTab()
417 {
418 jQuery.Select("#tabs a[href='#output-tab']").Tab(TabOperation.Show);
419 //jQuery.Select(".blocklyToolboxDiv").Hide();
420 }
421
422 private void ClassSelectorView1_Selected(object sender, EventArgs e)
423 {
424 var item = Views.ClassSelectorView.Current;
425 if (item == null) {
426 UpdateCode();
427
428 SelectRubyTab();
429 }
430 else {
431 var view = item.View;
432 view.Show();
433
434 SelectBlockTab();
435
436 foreach (var i in Collections.ClassWorkspaces) {
437 if (i != item) {
438 i.View.Hide();
439 }
440 }
441 }
442
443 if (current != item) {
444 current?.View.Hide();
445 }
446 current = item;
447 }
448
449 private void ClassSelectorView1_Removed(object sender, ItemRemovedEventArgs e)
450 {
451 var view = e.Item.View;
452 view.Dispose();
453 }
454
455 private void ClassSelectorView1_MarkClicked(object sender, EventArgs e)
456 {
457 }
458
459 private void UpdateCode()
460 {
461 string code = "";
462 var item = Views.ClassSelectorView.Current;
463 if (item != null) {
464 var view = item.View;
465 if (view.Changed || item.RubyCode == null) {
466 var rubyfile = item.Identifier + ".rb";
467 var workspace = item.Workspace;
468 code = item.ToCode(rubyfile);
469
470 _Files[rubyfile] = code;
471 this.filename = rubyfile;
472 }
473 else {
474 code = _Files[item.RubyCode.filename];
475 this.filename = item.RubyCode.filename;
476 }
477 }
478 App.CodeEditor.setValue(code);
479 App.CodeEditor.gotoLine(0, 0);
480 }
481
482 internal BlocklyView NewBlocklyView(string identifier)
483 {
484 return new BlocklyView(identifier);
485 }
486
487 internal void RemoveEObjectWorkspace(IClassWorkspace item)
488 {
489 var view = item.View;
490 view.Dispose();
491 }
492 }
493}
Note: See TracBrowser for help on using the repository browser.