implement simple panel generator.
@@ -0,0 +1,531 @@ | ||
1 | +# | |
2 | +# panel_generator.rb | |
3 | +# | |
4 | +# Copyright (c) 2012 project bchan | |
5 | +# | |
6 | +# This software is provided 'as-is', without any express or implied | |
7 | +# warranty. In no event will the authors be held liable for any damages | |
8 | +# arising from the use of this software. | |
9 | +# | |
10 | +# Permission is granted to anyone to use this software for any purpose, | |
11 | +# including commercial applications, and to alter it and redistribute it | |
12 | +# freely, subject to the following restrictions: | |
13 | +# | |
14 | +# 1. The origin of this software must not be misrepresented; you must not | |
15 | +# claim that you wrote the original software. If you use this software | |
16 | +# in a product, an acknowledgment in the product documentation would be | |
17 | +# appreciated but is not required. | |
18 | +# | |
19 | +# 2. Altered source versions must be plainly marked as such, and must not be | |
20 | +# misrepresented as being the original software. | |
21 | +# | |
22 | +# 3. This notice may not be removed or altered from any source | |
23 | +# distribution. | |
24 | +# | |
25 | + | |
26 | +require 'yaml' | |
27 | +require 'erb' | |
28 | +require 'jcode' | |
29 | + | |
30 | +def conv_euc_to_TCArray(str) | |
31 | + ret = Array.new(); | |
32 | + str.each_char do |x| | |
33 | + i = x.length - 1; | |
34 | + val = 0; | |
35 | + x.each_byte do |ch| | |
36 | + val += ch << (8 * i); | |
37 | + i -= 1; | |
38 | + end | |
39 | + ret.push(val & 0x7f7f); | |
40 | + end | |
41 | + ret; | |
42 | +end | |
43 | + | |
44 | +def conv_TCArray_to_hex_definition(a) | |
45 | + str = String.new(); | |
46 | + a.each do |x| | |
47 | + str += "0x" + x.to_s(16) + ", " | |
48 | + end | |
49 | + str += "TNULL"; | |
50 | +end | |
51 | + | |
52 | +def calc_euc_to_TCArray_length(str) | |
53 | + str = conv_euc_to_TCArray(str); | |
54 | + return str.length; | |
55 | +end | |
56 | + | |
57 | +class PanelItem | |
58 | + attr_accessor :yaml | |
59 | + def initialize(yaml) | |
60 | + @yaml = yaml; | |
61 | + end | |
62 | + def type | |
63 | + @yaml["type"] | |
64 | + end | |
65 | + def name | |
66 | + @yaml["name"] | |
67 | + end | |
68 | + def item_text() | |
69 | + @yaml["text"] | |
70 | + end | |
71 | + def width | |
72 | + if @yaml["size"] != nil and @yaml["size"]["h"] | |
73 | + return @yaml["size"]["h"] | |
74 | + end | |
75 | + end | |
76 | + def height | |
77 | + if @yaml["size"] != nil and @yaml["size"]["v"] | |
78 | + return @yaml["size"]["v"] | |
79 | + end | |
80 | + end | |
81 | + def item_text_to_hex_definition() | |
82 | + conv_TCArray_to_hex_definition(conv_euc_to_TCArray(@yaml["text"])); | |
83 | + end | |
84 | + def item_text_length_in_TC | |
85 | + return calc_euc_to_TCArray_length(@yaml["text"]); | |
86 | + end | |
87 | + | |
88 | + def generate_pnl_item_value(i, left, top) | |
89 | + return ""; | |
90 | + end | |
91 | +end | |
92 | + | |
93 | +class PanelFixedTextItem < PanelItem | |
94 | + def width | |
95 | + w = super; | |
96 | + if w != nil | |
97 | + return w; | |
98 | + end | |
99 | + return 16 * item_text_length_in_TC; | |
100 | + end | |
101 | + def height | |
102 | + h = super; | |
103 | + if h != nil | |
104 | + return h; | |
105 | + end | |
106 | + return 16; | |
107 | + end | |
108 | + | |
109 | + def generate_pnl_item_value(i, left, top) | |
110 | + script = <<-EOS | |
111 | + pnl_item[<%= i %>].itype = TEXT_ITEM|ATR_TEXT; | |
112 | + pnl_item[<%= i %>].info = 0; | |
113 | + pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height %>}}; | |
114 | + pnl_item[<%= i %>].desc = 0; | |
115 | + pnl_item[<%= i %>].dnum = 0; | |
116 | + pnl_item[<%= i %>].ptr = (H*)(TC[]){<%= self.item_text_to_hex_definition() %>}; | |
117 | + EOS | |
118 | + | |
119 | + erb = ERB.new(script, nil, '-'); | |
120 | + erb.result(binding) | |
121 | + end | |
122 | +end | |
123 | + | |
124 | +class PanelNullItem < PanelItem | |
125 | + def generate_pnl_item_value(i, left, top) | |
126 | + script = <<-EOS | |
127 | + pnl_item[<%= i %>].itype = NULL_ITEM; | |
128 | + pnl_item[<%= i %>].info = 0; | |
129 | + pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height %>}}; | |
130 | + pnl_item[<%= i %>].desc = 0; | |
131 | + pnl_item[<%= i %>].dnum = 0; | |
132 | + pnl_item[<%= i %>].ptr = NULL; | |
133 | + EOS | |
134 | + | |
135 | + erb = ERB.new(script, nil, '-'); | |
136 | + erb.result(binding) | |
137 | + end | |
138 | +end | |
139 | + | |
140 | +class PanelButtonItem < PanelItem | |
141 | + def width | |
142 | + w = super; | |
143 | + if w != nil | |
144 | + return w; | |
145 | + end | |
146 | + return 16 * item_text_length_in_TC + 16; | |
147 | + end | |
148 | + def height | |
149 | + h = super; | |
150 | + if h != nil | |
151 | + return h; | |
152 | + end | |
153 | + return 24; | |
154 | + end | |
155 | + | |
156 | + def generate_pnl_item_value(i, left, top) | |
157 | + script = <<-EOS | |
158 | + pnl_item[<%= i %>].itype = PARTS_ITEM; | |
159 | + pnl_item[<%= i %>].info = 0; | |
160 | + pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height%>}}; | |
161 | + pnl_item[<%= i %>].desc = 0; | |
162 | + pnl_item[<%= i %>].dnum = 0; | |
163 | + pnl_item[<%= i %>].ptr = (H*)&(SWSEL){MS_PARTS|P_DISP, (RECT){{0, 0, <%= self.width %>, <%= self.height %>}}, 0, (TC[]){MC_STR, <%= self.item_text_to_hex_definition() %>}, {0, 0, -1, 0}}; | |
164 | + EOS | |
165 | + | |
166 | + erb = ERB.new(script, nil, '-'); | |
167 | + erb.result(binding) | |
168 | + end | |
169 | +end | |
170 | + | |
171 | +def generate_parts(type, a) | |
172 | + case type | |
173 | + when "fixedtext" | |
174 | + return PanelFixedTextItem.new(a); | |
175 | + when "null_item" | |
176 | + return PanelNullItem.new(a); | |
177 | + when "button" | |
178 | + return PanelButtonItem.new(a); | |
179 | + end | |
180 | +end | |
181 | + | |
182 | +class PanelLine | |
183 | + attr_accessor :yaml, :items | |
184 | + def initialize(yaml) | |
185 | + @yaml = yaml; | |
186 | + @items = Array.new(); | |
187 | + if yaml["items"] != nil | |
188 | + yaml["items"].each { |a| | |
189 | + i = generate_parts(a["type"], a) | |
190 | + @items.push(i); | |
191 | + }; | |
192 | + end | |
193 | + end | |
194 | + | |
195 | + def height | |
196 | + h = 0; | |
197 | + @items.each { |item| | |
198 | + if h < item.height | |
199 | + h = item.height; | |
200 | + end | |
201 | + } | |
202 | + return h; | |
203 | + end | |
204 | + def width | |
205 | + w = 0; | |
206 | + @items.each { |item| | |
207 | + w += item.width; | |
208 | + } | |
209 | + return w; | |
210 | + end | |
211 | +end | |
212 | + | |
213 | +class Panel | |
214 | + attr_accessor :yaml, :lines, :margin_left, :margin_top, :margin_right, :margine_bottom, :panel_padding_left, :panel_padding_top, :panel_padding_right, :panel_padding_bottom | |
215 | + def initialize(yaml) | |
216 | + @yaml = yaml; | |
217 | + @lines = Array.new(); | |
218 | + if yaml["lines"] != nil | |
219 | + yaml["lines"].each { |a| | |
220 | + l = PanelLine.new(a); | |
221 | + @lines.push(l); | |
222 | + }; | |
223 | + end | |
224 | + @margin_left = 4; | |
225 | + @margin_top = 4; | |
226 | + @margin_right = 4; | |
227 | + @margin_bottom = 4; | |
228 | + @panel_padding_left = 20; | |
229 | + @panel_padding_top = 20; | |
230 | + @panel_padding_right = 20; | |
231 | + @panel_padding_bottom = 20; | |
232 | + end | |
233 | + def panel_name() | |
234 | + @yaml["panel_name"] | |
235 | + end | |
236 | + def panel_function_name() | |
237 | + self.panel_name(); | |
238 | + end | |
239 | + def panel_result_type_name() | |
240 | + self.panel_name().upcase + "_RESULT"; | |
241 | + end | |
242 | + def panel_arguments() | |
243 | + "" | |
244 | + end | |
245 | + | |
246 | + def each_item() | |
247 | + @lines.each { |l| | |
248 | + l.items.each { |i| | |
249 | + yield(i); | |
250 | + } | |
251 | + } | |
252 | + end | |
253 | + def number_items | |
254 | + n = 0; | |
255 | + each_item() { |i| | |
256 | + n += 1; | |
257 | + } | |
258 | + return n; | |
259 | + end | |
260 | + def each_item_type(type) | |
261 | + @lines.each { |l| | |
262 | + l.items.each { |i| | |
263 | + if i.type == type | |
264 | + yield(i); | |
265 | + end | |
266 | + } | |
267 | + } | |
268 | + end | |
269 | + | |
270 | + def content_width | |
271 | + w = @margin_left + @margin_right; | |
272 | + @lines.each { |line| | |
273 | + w2 = @margin_left + line.width + @margin_right; | |
274 | + if w2 > w | |
275 | + w = w2 | |
276 | + end | |
277 | + } | |
278 | + return w; | |
279 | + end | |
280 | + def content_height | |
281 | + h = 0; | |
282 | + @lines.each { |line| | |
283 | + h += @margin_top + line.height + @margin_bottom; | |
284 | + } | |
285 | + return h; | |
286 | + end | |
287 | + | |
288 | + def generate_header_retval_definition() | |
289 | + script = <<-EOS | |
290 | +enum <%= panel_result_type_name() %>_ { | |
291 | +<%- self.each_item_type("button") do |i| -%> | |
292 | + <%= panel_result_type_name().upcase %>_<%= i.name().upcase %>, | |
293 | +<%- end -%> | |
294 | +}; | |
295 | +typedef enum <%= panel_result_type_name() %>_ <%= panel_result_type_name() %>; | |
296 | + EOS | |
297 | + | |
298 | + erb = ERB.new(script, nil, '-'); | |
299 | + erb.result(binding) | |
300 | + end | |
301 | + def generate_header_function() | |
302 | + script = <<-EOS | |
303 | +IMPORT <%= panel_result_type_name() %> <%= panel_function_name() %>(<%= panel_arguments() %>); | |
304 | + EOS | |
305 | + | |
306 | + erb = ERB.new(script, nil, '-'); | |
307 | + erb.result(binding) | |
308 | + end | |
309 | + | |
310 | + def generate_source_function_pnl_item_value_each() | |
311 | + n = 0; | |
312 | + left = @panel_padding_left + @margin_left; | |
313 | + top = @panel_padding_top + @margin_top; | |
314 | + @lines.each { |l| | |
315 | + l.items.each { |i| | |
316 | + s = i.generate_pnl_item_value(n, left, top); | |
317 | + yield(s); | |
318 | + n += 1; | |
319 | + left += i.width + @margin_right + @margin_left; | |
320 | + } | |
321 | + left = @panel_padding_left + @margin_left; | |
322 | + top += l.height + @margin_bottom + @margin_top; | |
323 | + } | |
324 | + end | |
325 | + def generate_source_function_ret_handler() | |
326 | + n = 0; | |
327 | + script = <<-EOS | |
328 | +<%- self.each_item() do |i| -%><%- if i.type == "button" -%> | |
329 | + if (itemno == (<%= n %> + 1)) { | |
330 | + ret = <%= panel_result_type_name().upcase %>_<%= i.name().upcase %>; | |
331 | + break; | |
332 | + } | |
333 | +<%- end -%><%- n += 1 -%><%- end -%> | |
334 | + EOS | |
335 | + | |
336 | + erb = ERB.new(script, nil, '-'); | |
337 | + erb.result(binding) | |
338 | + end | |
339 | + | |
340 | + def generate_source_function_function_name() | |
341 | + script = <<-EOS | |
342 | +EXPORT <%= panel_result_type_name() %> <%= panel_function_name() %>(<%= panel_arguments() %>) | |
343 | + EOS | |
344 | + | |
345 | + erb = ERB.new(script, nil, '-'); | |
346 | + erb.result(binding) | |
347 | + end | |
348 | + | |
349 | + def generate_source_function_pnl_item_value() | |
350 | + script = <<-EOS | |
351 | +<%- self.generate_source_function_pnl_item_value_each() do |s| -%><%= s %><%- end -%> | |
352 | + EOS | |
353 | + | |
354 | + erb = ERB.new(script, nil, '-'); | |
355 | + erb.result(binding) | |
356 | + end | |
357 | + | |
358 | + def generate_source_function() | |
359 | + script = <<-EOS | |
360 | +<%= self.generate_source_function_function_name() %>{ | |
361 | + PNL_ITEM pnl_item[<%= number_items %>]; | |
362 | + PNID pnid0; | |
363 | + PNT p0 = {0x8000,0x8000}; | |
364 | + WEVENT wev0; | |
365 | + W stat,itemno; | |
366 | + <%= panel_result_type_name().upcase %> ret; | |
367 | + PANEL pnl = { | |
368 | + 2,0x48,0, | |
369 | + {{0, 0, <%= self.panel_padding_left + self.content_width + self.panel_padding_right %>, <%= self.panel_padding_top + self.content_height + self.panel_padding_bottom %>}}, | |
370 | + 0, | |
371 | + <%= number_items %>, | |
372 | + pnl_item | |
373 | + }; | |
374 | + | |
375 | +<%= self.generate_source_function_pnl_item_value() %> | |
376 | + pnid0 = pcre_pnl(&pnl, &p0); | |
377 | + if (pnid0 < 0) { | |
378 | + DP_ER("pcre_pnl error", pnid0); | |
379 | + return pnid0; | |
380 | + } | |
381 | + | |
382 | + for (;;) { | |
383 | + ret = -1; | |
384 | + stat = pact_pnl(pnid0, &wev0.e, &itemno); | |
385 | + switch (stat) { | |
386 | + case P_EVENT: | |
387 | + if (wev0.s.type == EV_DEVICE) { | |
388 | + oprc_dev(&wev0.e, NULL, 0); | |
389 | + } | |
390 | + continue; | |
391 | + default: | |
392 | +<%= self.generate_source_function_ret_handler() %> | |
393 | + if (itemno >= 0) { | |
394 | + continue; | |
395 | + } | |
396 | + case 0x5001: | |
397 | +<%= self.generate_source_function_ret_handler() %> | |
398 | + if (itemno >= 0) { | |
399 | + continue; | |
400 | + } | |
401 | + break; | |
402 | + } | |
403 | + if (ret != -1) { | |
404 | + break; | |
405 | + } | |
406 | + } | |
407 | + | |
408 | + pdel_pnl(pnid0); | |
409 | + | |
410 | + return ret; | |
411 | +} | |
412 | + | |
413 | + EOS | |
414 | + | |
415 | + erb = ERB.new(script, nil, '-'); | |
416 | + erb.result(binding) | |
417 | + end | |
418 | +end | |
419 | + | |
420 | +class PanelData | |
421 | + attr_accessor :yaml, :panels, :name | |
422 | + def initialize(yaml) | |
423 | + @yaml = yaml; | |
424 | + @panels = Array.new(); | |
425 | + yaml["panels"].each { |a| | |
426 | + p = Panel.new(a); | |
427 | + @panels.push(p); | |
428 | + }; | |
429 | + end | |
430 | + def lisence_header() | |
431 | + @yaml["generator"]["lisence_header"] | |
432 | + end | |
433 | + def lisence_source() | |
434 | + @yaml["generator"]["lisence_source"] | |
435 | + end | |
436 | + def filename_header() | |
437 | + @yaml["generator"]["output_header"] | |
438 | + end | |
439 | + | |
440 | + def generate_header() | |
441 | + script = <<-EOS | |
442 | +<%- @panels.each do |p| -%> | |
443 | +<%= p.generate_header_retval_definition() %> | |
444 | +<%= p.generate_header_function() %> | |
445 | +<%- end -%> | |
446 | + EOS | |
447 | + | |
448 | + erb = ERB.new(script, nil, '-'); | |
449 | + erb.result(binding) | |
450 | + end | |
451 | + def generate_source_include_files() | |
452 | + script = <<-EOS | |
453 | +#include "<%= self.filename_header() %>" | |
454 | + | |
455 | +#include <bstdio.h> | |
456 | +#include <bstdlib.h> | |
457 | +#include <tcode.h> | |
458 | +#include <tstring.h> | |
459 | +#include <btron/btron.h> | |
460 | +#include <btron/hmi.h> | |
461 | +#include <btron/vobj.h> | |
462 | + | |
463 | +#if PANEL_DEBUG | |
464 | +# define DP(arg) printf arg | |
465 | +# define DP_ER(msg, err) printf("%s (%d/%x)\\n", msg, err>>16, err) | |
466 | +#else | |
467 | +# define DP(arg) /**/ | |
468 | +# define DP_ER(msg, err) /**/ | |
469 | +#endif | |
470 | + | |
471 | + EOS | |
472 | + | |
473 | + erb = ERB.new(script, nil, '-'); | |
474 | + erb.result(binding) | |
475 | + end | |
476 | + def generate_source() | |
477 | + script = <<-EOS | |
478 | +<%- @panels.each do |p| -%> | |
479 | +<%= p.generate_source_function() %> | |
480 | +<%- end -%> | |
481 | + EOS | |
482 | + | |
483 | + erb = ERB.new(script, nil, '-'); | |
484 | + erb.result(binding) | |
485 | + end | |
486 | +end | |
487 | + | |
488 | +def generate_header(filename, data) | |
489 | + fd = File.open(filename, "w"); | |
490 | + fd.puts data.lisence_header(); | |
491 | + fd.puts <<-EOS | |
492 | + | |
493 | +/* This file is automatically generated. */ | |
494 | + | |
495 | +#include <basic.h> | |
496 | +#include <btron/dp.h> | |
497 | +#include <btron/hmi.h> | |
498 | + | |
499 | + EOS | |
500 | + fd.puts "#ifndef __" + filename.upcase.gsub(/\./, '_') + "__"; | |
501 | + fd.puts "#define __" + filename.upcase.gsub(/\./, '_') + "__"; | |
502 | + fd.puts "\n"; | |
503 | + fd.puts data.generate_header(); | |
504 | + fd.puts "#endif\n" | |
505 | + fd.close | |
506 | +end | |
507 | + | |
508 | +def generate_source(filename, data) | |
509 | + fd = File.open(filename, "w"); | |
510 | + fd.puts data.lisence_source(); | |
511 | + fd.puts <<-EOS | |
512 | + | |
513 | +/* This file is automatically generated. */ | |
514 | + | |
515 | + EOS | |
516 | + fd.puts data.generate_source_include_files(); | |
517 | + | |
518 | + fd.puts data.generate_source(); | |
519 | + fd.close | |
520 | +end | |
521 | + | |
522 | +$KCODE = "EUC" | |
523 | + | |
524 | +yaml = YAML.load_file(ARGV[0]); | |
525 | +data = PanelData.new(yaml); | |
526 | + | |
527 | +fname_header = yaml["generator"]["output_header"] | |
528 | +fname_source = yaml["generator"]["output_source"] | |
529 | + | |
530 | +generate_header(fname_header, data); | |
531 | +generate_source(fname_source, data); |