source: EcnlProtoTool/trunk/webapp/webmrbc/App.cs@ 273

Last change on this file since 273 was 273, 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: 11.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using Bridge;
5using Bridge.Html5;
6using Bridge.jQuery2;
7
8namespace WebMrbc
9{
10 delegate bool jQueryKeyboardHandler(jQueryKeyboardEvent e);
11
12 public static class App
13 {
14 public static Mruby Module;
15 public static Terminal Term;
16 public static AceEditor CodeEditor;
17 public static TargetBoard TargetBoard;
18 public static bool changedAfterTranslating;
19 public static bool translating;
20 public static JsonClassInfo NodeProfileClass;
21 public static JsonClassGroupInfo[] ClassGroups;
22 public static JsonPropertyInfo[] BaseObjectPropertyList;
23 public static string ArduinoToolbox;
24 public static string EcnlToolbox;
25
26 [Ready]
27 public static void Main()
28 {
29 Script.Write("Number.isFinite = Number.isFinite || function(any) { return typeof any === 'number' && isFinite(any); }");
30 Script.Write("Number.isNaN = Number.isNaN || function(any) { return typeof any === 'number' && isNaN(any); }");
31
32 App.TargetBoard = new GrPeach();
33 Collections.ClassWorkspaces = new Collection<IClassWorkspace>();
34 Views.ClassSelectorView = new ClassSelectorView();
35 Views.ClassSelectorView.SetCollection(Collections.ClassWorkspaces);
36 Views.EObjectModalView = new EObjectModalView();
37 Views.MainMenuView = new MainMenuView();
38
39 var termElement = Document.GetElementById("term");
40 Term = new Terminal(new TerminalOption() {
41 cols = 80,
42 rows = 24,
43 useStyle = true,
44 screenKeys = true,
45 cursorBlink = false
46 });
47 Term.on("data", new Action<object>((data) => {
48 if (Module != null && Module["stdin"] != null)
49 Module.stdin(data);
50 }));
51 Term.on("title", new Action<string>((title) => {
52 Document.Title = title;
53 }));
54
55 Term.open(termElement);
56
57 CodeEditor = ace.edit("text-editor");
58 Window.Set("textEditor", CodeEditor);
59 CodeEditor.setTheme("ace/theme/twilight");
60 CodeEditor.setShowInvisibles(true);
61 CodeEditor.gotoLine(0, 0);
62 CodeEditor.On("change", new Action(() => {
63 if (!translating) {
64 changedAfterTranslating = true;
65 }
66 }));
67 var session = CodeEditor.getSession();
68 session.setMode("ace/mode/ruby");
69 session.setTabSize(2);
70 session.setUseSoftTabs(false);
71
72 var statusElement = Document.GetElementById("status");
73 var progressElement = Document.GetElementById("progress");
74 var spinnerElement = Document.GetElementById("spinner");
75
76 statusElement.InnerHTML = "Downloading...";
77
78 jQuery.Ready(() => {
79 InitClassGroups((result) => {
80 if (result) {
81 Views.EObjectModalView.InitClassGroups();
82 }
83 InitArduinoToolbox((result1) => {
84 InitEcnlToolbox((result2) => {
85 if (result1 && result2) {
86 AddMainLoop();
87 AddEcnlTask();
88 AddENode();
89 }
90 statusElement.InnerHTML = "";
91 spinnerElement.Style.Display = Display.None;
92 });
93 });
94 });
95 });
96 }
97
98 public static void InitClassGroups(Action<bool> action)
99 {
100 jQuery.Ajax(new AjaxOptions() {
101 Url = "echonet_objects.json",
102 Success = (data, textStatus, request) => {
103 ClassGroupsSuccess(data, textStatus, request);
104 action?.Invoke(true);
105 },
106 Error = (request, textStatus, error) => {
107 AjaxError(request, textStatus, error);
108 action?.Invoke(false);
109 }
110 });
111 }
112
113 private static void ClassGroupsSuccess(object data, string textStatus, jqXHR request)
114 {
115 var _deviceInfo = (dynamic)((data.GetType() == typeof(string)) ? jQuery.ParseJSON((string)data) : data);
116 var profProps = new JsonPropertyInfo[0];
117 foreach (var property in _deviceInfo.baseProfilePropertyList) {
118 profProps.Push(new JsonPropertyInfo(property));
119 }
120 var objProps = new JsonPropertyInfo[0];
121 foreach (var property in _deviceInfo.baseObjectPropertyList) {
122 objProps.Push(new JsonPropertyInfo(property));
123 }
124 BaseObjectPropertyList = objProps;
125
126 var classGroups = new JsonClassGroupInfo[0];
127 foreach (var _item in _deviceInfo.classGroupList) {
128 var item = new JsonClassGroupInfo(_item);
129 classGroups.Push(item);
130 var classes = new JsonClassInfo[0];
131 foreach (var _cls in _item.classList) {
132 var cls = new JsonClassInfo(_cls);
133 cls.classGroup = item;
134 classes.Push(cls);
135 var properties = new JsonPropertyInfo[0];
136 foreach (var property in _cls.propertyList) {
137 properties.Push(new JsonPropertyInfo(property));
138 }
139 if ((item.classGroupCode == 0xE) && (cls.classCode == 0xF0)) {
140 cls.properties = (JsonPropertyInfo[])profProps.Concat(properties);
141 NodeProfileClass = cls;
142 }
143 else {
144 cls.properties = properties;
145 }
146 }
147 item.classes = classes;
148 }
149 ClassGroups = classGroups;
150 }
151
152 public static void InitArduinoToolbox(Action<bool> action)
153 {
154 jQuery.Ajax(new AjaxOptions() {
155 Url = "arduino_toolbox.xml",
156 DataType = "text",
157 Success = (data, textStatus, request) => {
158 ArduinoToolbox = (string)data;
159 action?.Invoke(true);
160 },
161 Error = (request, textStatus, error) => {
162 AjaxError(request, textStatus, error);
163 action?.Invoke(false);
164 }
165 });
166 }
167
168 public static void InitEcnlToolbox(Action<bool> action)
169 {
170 jQuery.Ajax(new AjaxOptions() {
171 Url = "ecnl_toolbox.xml",
172 DataType = "text",
173 Success = (data, textStatus, request) => {
174 EcnlToolbox = (string)data;
175 action?.Invoke(true);
176 },
177 Error = (request, textStatus, error) => {
178 AjaxError(request, textStatus, error);
179 action?.Invoke(false);
180 }
181 });
182 }
183
184 private static void AjaxError(jqXHR request, string textStatus, string error)
185 {
186 }
187
188 /// <summary>
189 /// テキスト入力欄のEnter(Return)キーを無視する
190 /// </summary>
191 /// <param name="el"></param>
192 /// <returns></returns>
193 static jQuery ignoreEnterKey(jQuery el)
194 {
195 return el.Find("input[type=text]").KeyPress(new jQueryKeyboardHandler((e) => {
196 if (e == null)
197 e = (jQueryKeyboardEvent)Window.Get("Event");
198 if (e.KeyCode == 13)
199 return false;
200 else
201 return true;
202 }));
203 }
204
205 private static void AddMainLoop()
206 {
207 var view = Views.MainMenuView.NewBlocklyView("MainLoop");
208 var workspace = new MainLoopWorkspace(view);
209 Collections.MainLoopWorkspace = workspace;
210 Collections.ClassWorkspaces.Add(workspace);
211 Views.ClassSelectorView.SelectClassWorkspace(workspace);
212 view.ReloadToolbox(workspace);
213 }
214
215 private static void AddEcnlTask()
216 {
217 var identifier = Collections.ClassWorkspaces.UniqueName("EcnlTask");
218 var view = Views.MainMenuView.NewBlocklyView(identifier);
219 var workspace = new EcnlTaskWorkspace(view);
220 Collections.EcnlTaskWorkspace = workspace;
221 Collections.ClassWorkspaces.Add(workspace);
222 Views.ClassSelectorView.SelectClassWorkspace(workspace);
223 view.ReloadToolbox(workspace);
224 }
225
226 private static void AddENode()
227 {
228 var identifier = Collections.ClassWorkspaces.UniqueName("LocalNode");
229 var localNode = new JsonNodeInfo(NodeProfileClass, identifier, "local");
230 var properties = new JsonPropertyInfo[0];
231 foreach (var item in localNode.type.properties) {
232 if ((item.required.Length > 0) && (item.required[0] != "NONE")) {
233 properties.Push(new JsonPropertyInfo(item));
234 }
235 }
236 localNode.properties = properties;
237 var view = Views.MainMenuView.NewBlocklyView(localNode.identifier);
238 var workspace = new ENodeWorkspace(view, localNode);
239 Collections.LocalNode = workspace;
240 Collections.ClassWorkspaces.Add(workspace);
241 Views.ClassSelectorView.SelectClassWorkspace(workspace);
242 view.BlockCreated += workspace.OnBlockCreated;
243 view.BlockDeleted += workspace.OnBlockDeleted;
244 view.BlockChanged += workspace.OnBlockChanged;
245 view.BlockMoveed += workspace.OnBlockMoveed;
246 view.ReloadToolbox(workspace);
247 }
248
249 internal static void NewItem(Action<IClassWorkspace> callback)
250 {
251 var identifier = Collections.ClassWorkspaces.UniqueName("Kaden");
252 var eobject = new JsonObjectInfo(App.NodeProfileClass, identifier);
253 var properties = new JsonPropertyInfo[0];
254 if ((eobject.type.classGroup.classGroupCode != 0x0E)
255 && (eobject.type.classCode != 0xF0)) {
256 foreach (var item in App.BaseObjectPropertyList) {
257 if ((item.required.Length > 0) && (item.required[0] != "NONE")) {
258 properties.Push(new JsonPropertyInfo(item));
259 }
260 }
261 }
262 foreach (var item in eobject.type.properties) {
263 if ((item.required.Length > 0) && (item.required[0] != "NONE")) {
264 properties.Push(new JsonPropertyInfo(item));
265 }
266 }
267 eobject.properties = properties;
268 var view = Views.MainMenuView.NewBlocklyView(eobject.identifier);
269 var workspace = new EObjectWorkspace(view, eobject);
270 view.BlockCreated += workspace.OnBlockCreated;
271 view.BlockDeleted += workspace.OnBlockDeleted;
272 view.BlockChanged += workspace.OnBlockChanged;
273 view.BlockMoveed += workspace.OnBlockMoveed;
274 callback(workspace);
275 }
276
277 internal static void RemoveItem(IClassWorkspace item)
278 {
279 Views.MainMenuView.RemoveEObjectWorkspace(item);
280 }
281
282 internal static void Write(string text)
283 {
284 Term?.write(text.Replace("\n", "\r\n"));
285 }
286
287 internal static void WriteLine(string text)
288 {
289 Term?.write(text.Replace("\n", "\r\n") + "\r\n");
290 }
291 }
292
293 public interface IClassWorkspace : IModel
294 {
295 Workspace Workspace { get; }
296 BlocklyView View { get; }
297 Ruby RubyCode { get; }
298 string GetImageUrl();
299 bool IsPreset();
300 string ToCode(string filename);
301 void Activate();
302 void Inactivate();
303 void ReloadToolbox(HTMLElement toolbox);
304 void OpenModifyView(Action<bool> callback);
305 string Template(string template);
306 }
307
308 public class Collections
309 {
310 [Name(false)]
311 internal static ENodeWorkspace LocalNode;
312 [Name(false)]
313 internal static Collection<IClassWorkspace> ClassWorkspaces;
314 [Name(false)]
315 internal static EcnlTaskWorkspace EcnlTaskWorkspace;
316 [Name(false)]
317 internal static MainLoopWorkspace MainLoopWorkspace;
318 }
319
320 public class Views
321 {
322 [Name(false)]
323 internal static MainMenuView MainMenuView;
324 [Name(false)]
325 internal static ClassSelectorView ClassSelectorView;
326 [Name(false)]
327 internal static EObjectModalView EObjectModalView;
328 }
329
330 public class HexDump
331 {
332 string text;
333
334 public HexDump(Uint8Array bytes, int width)
335 {
336 var sb = new string[0];
337
338 for (int index = 0; index < bytes.Length; index += width) {
339 sb.Push(String.Format("{0:X4} : ", index)
340 + BinBump(bytes, index, width)
341 + AsciiDump(bytes, index, width));
342 }
343
344 text = sb.Join("\n");
345 }
346
347 private string BinBump(Uint8Array bytes, int offset, int width)
348 {
349 var sb = new System.Text.StringBuilder();
350
351 for (int index = 0; index < width; index++) {
352 if (index + offset < bytes.Length) {
353 sb.AppendFormat("{0:X2} ", bytes[index + offset]);
354 }
355 else {
356 sb.Append(" ");
357 }
358 }
359
360 return sb.ToString();
361 }
362
363 private string AsciiDump(Uint8Array bytes, int index, int width)
364 {
365 var sb = "";
366
367 if (index < bytes.Length) {
368 width = System.Math.Min(width, bytes.Length - index);
369
370 sb += ": ";
371 for (int i = 0; i < width; i++) {
372 byte b = bytes[i + index];
373 if (b < 0x20)
374 sb += "\x1B[1;3;31m" + String.FromCharCode(b + 0x40) + "\x1B[0m";
375 else
376 sb += String.FromCharCode(b);
377 }
378 }
379 else {
380 sb += ": ";
381 }
382
383 return sb;
384 }
385
386 public override string ToString()
387 {
388 return text;
389 }
390 }
391}
Note: See TracBrowser for help on using the repository browser.