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

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

ファイルヘッダーコメントを追加

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