OSDN Git Service

implement simple panel generator.
authorornse01 <ornse01@users.sourceforge.jp>
Wed, 2 May 2012 08:28:57 +0000 (08:28 +0000)
committerornse01 <ornse01@users.sourceforge.jp>
Wed, 2 May 2012 08:28:57 +0000 (08:28 +0000)
git-svn-id: http://svn.sourceforge.jp/svnroot/bchan/bchanf/trunk@457 20a0b8eb-f62a-4a12-8fe1-b598822500fb

src/tools/panel_generator.rb [new file with mode: 0644]

diff --git a/src/tools/panel_generator.rb b/src/tools/panel_generator.rb
new file mode 100644 (file)
index 0000000..3af9965
--- /dev/null
@@ -0,0 +1,531 @@
+#
+# panel_generator.rb
+#
+# Copyright (c) 2012 project bchan
+#
+# This software is provided 'as-is', without any express or implied
+# warranty. In no event will the authors be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+#    claim that you wrote the original software. If you use this software
+#    in a product, an acknowledgment in the product documentation would be
+#    appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be
+#    misrepresented as being the original software.
+#
+# 3. This notice may not be removed or altered from any source
+#    distribution.
+#
+
+require 'yaml'
+require 'erb'
+require 'jcode'
+
+def conv_euc_to_TCArray(str)
+  ret = Array.new();
+  str.each_char do |x|
+    i = x.length - 1;
+    val = 0;
+    x.each_byte do |ch|
+      val += ch << (8 * i);
+      i -= 1;
+    end
+    ret.push(val & 0x7f7f);
+  end 
+  ret;
+end
+
+def conv_TCArray_to_hex_definition(a)
+  str = String.new();
+  a.each do |x|
+    str += "0x" + x.to_s(16) + ", "
+  end
+  str += "TNULL";
+end
+
+def calc_euc_to_TCArray_length(str)
+  str = conv_euc_to_TCArray(str);
+  return str.length;
+end
+
+class PanelItem
+  attr_accessor :yaml
+  def initialize(yaml)
+    @yaml = yaml;
+  end
+  def type
+    @yaml["type"]
+  end
+  def name
+    @yaml["name"]
+  end
+  def item_text()
+    @yaml["text"]
+  end
+  def width
+    if @yaml["size"] != nil and @yaml["size"]["h"]
+      return @yaml["size"]["h"]
+    end
+  end
+  def height
+    if @yaml["size"] != nil and @yaml["size"]["v"]
+      return @yaml["size"]["v"]
+    end
+  end
+  def item_text_to_hex_definition()
+    conv_TCArray_to_hex_definition(conv_euc_to_TCArray(@yaml["text"]));
+  end
+  def item_text_length_in_TC
+    return calc_euc_to_TCArray_length(@yaml["text"]);
+  end
+
+  def generate_pnl_item_value(i, left, top)
+    return "";
+  end
+end
+
+class PanelFixedTextItem < PanelItem
+  def width
+    w = super;
+    if w != nil
+      return w;
+    end
+    return 16 * item_text_length_in_TC;
+  end
+  def height
+    h = super;
+    if h != nil
+      return h;
+    end
+    return 16;
+  end
+
+  def generate_pnl_item_value(i, left, top)
+    script = <<-EOS
+       pnl_item[<%= i %>].itype = TEXT_ITEM|ATR_TEXT;
+       pnl_item[<%= i %>].info = 0;
+       pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height %>}};
+       pnl_item[<%= i %>].desc = 0;
+       pnl_item[<%= i %>].dnum = 0;
+       pnl_item[<%= i %>].ptr = (H*)(TC[]){<%= self.item_text_to_hex_definition() %>};
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+end
+
+class PanelNullItem < PanelItem
+  def generate_pnl_item_value(i, left, top)
+    script = <<-EOS
+       pnl_item[<%= i %>].itype = NULL_ITEM;
+       pnl_item[<%= i %>].info = 0;
+       pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height %>}};
+       pnl_item[<%= i %>].desc = 0;
+       pnl_item[<%= i %>].dnum = 0;
+       pnl_item[<%= i %>].ptr = NULL;
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+end
+
+class PanelButtonItem < PanelItem
+  def width
+    w = super;
+    if w != nil
+      return w;
+    end
+    return 16 * item_text_length_in_TC + 16;
+  end
+  def height
+    h = super;
+    if h != nil
+      return h;
+    end
+    return 24;
+  end
+
+  def generate_pnl_item_value(i, left, top)
+    script = <<-EOS
+       pnl_item[<%= i %>].itype = PARTS_ITEM;
+       pnl_item[<%= i %>].info = 0;
+       pnl_item[<%= i %>].ir = (RECT){{<%= left %>,<%= top %>,<%= left %>+<%= self.width %>,<%= top %>+<%= self.height%>}};
+       pnl_item[<%= i %>].desc = 0;
+       pnl_item[<%= i %>].dnum = 0;
+       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}};
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+end
+
+def generate_parts(type, a)
+  case type
+  when "fixedtext"
+    return PanelFixedTextItem.new(a);
+  when "null_item"
+    return PanelNullItem.new(a);
+  when "button"
+    return PanelButtonItem.new(a);
+  end
+end
+
+class PanelLine
+  attr_accessor :yaml, :items
+  def initialize(yaml)
+    @yaml = yaml;
+    @items = Array.new();
+    if yaml["items"] != nil
+      yaml["items"].each { |a|
+        i = generate_parts(a["type"], a)
+        @items.push(i);
+      };
+    end
+  end
+
+  def height
+    h = 0;
+    @items.each { |item|
+      if h < item.height
+        h = item.height;
+      end
+    }
+    return h;
+  end
+  def width
+    w = 0;
+    @items.each { |item|
+      w += item.width;
+    }
+    return w;
+  end
+end
+
+class Panel
+  attr_accessor :yaml, :lines, :margin_left, :margin_top, :margin_right, :margine_bottom, :panel_padding_left, :panel_padding_top, :panel_padding_right, :panel_padding_bottom
+  def initialize(yaml)
+    @yaml = yaml;
+    @lines = Array.new();
+    if yaml["lines"] != nil
+      yaml["lines"].each { |a|
+        l = PanelLine.new(a);
+        @lines.push(l);
+      };
+    end
+    @margin_left = 4;
+    @margin_top = 4;
+    @margin_right = 4;
+    @margin_bottom = 4;
+    @panel_padding_left = 20;
+    @panel_padding_top = 20;
+    @panel_padding_right = 20;
+    @panel_padding_bottom = 20;
+  end
+  def panel_name()
+    @yaml["panel_name"]
+  end
+  def panel_function_name()
+    self.panel_name();
+  end
+  def panel_result_type_name()
+    self.panel_name().upcase + "_RESULT";
+  end
+  def panel_arguments()
+    ""
+  end
+
+  def each_item()
+    @lines.each { |l|
+      l.items.each { |i|
+        yield(i);
+      }
+    }
+  end
+  def number_items
+    n = 0;
+    each_item() { |i|
+      n += 1;
+    }
+    return n;
+  end
+  def each_item_type(type)
+    @lines.each { |l|
+      l.items.each { |i|
+        if i.type == type
+          yield(i);
+        end
+      }
+    }
+  end
+
+  def content_width
+    w = @margin_left + @margin_right;
+    @lines.each { |line|
+      w2 = @margin_left + line.width + @margin_right;
+      if w2 > w
+        w = w2
+      end
+    }
+    return w;
+  end
+  def content_height
+    h = 0;
+    @lines.each { |line|
+      h += @margin_top + line.height + @margin_bottom;
+    }
+    return h;
+  end
+
+  def generate_header_retval_definition()
+    script = <<-EOS
+enum <%= panel_result_type_name() %>_ {
+<%- self.each_item_type("button") do |i| -%>
+       <%= panel_result_type_name().upcase %>_<%= i.name().upcase %>,
+<%- end -%>
+};
+typedef enum <%= panel_result_type_name() %>_ <%= panel_result_type_name() %>;
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+  def generate_header_function()
+    script = <<-EOS
+IMPORT <%= panel_result_type_name() %> <%= panel_function_name() %>(<%= panel_arguments() %>);
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+
+  def generate_source_function_pnl_item_value_each()
+    n = 0;
+    left = @panel_padding_left + @margin_left;
+    top = @panel_padding_top + @margin_top;
+    @lines.each { |l|
+      l.items.each { |i|
+        s = i.generate_pnl_item_value(n, left, top);
+        yield(s);
+        n += 1;
+        left += i.width + @margin_right + @margin_left;
+      }
+      left = @panel_padding_left + @margin_left;
+      top += l.height + @margin_bottom + @margin_top;
+    }
+  end
+  def generate_source_function_ret_handler()
+    n = 0;
+    script = <<-EOS
+<%- self.each_item() do |i| -%><%- if i.type == "button" -%>
+                       if (itemno == (<%= n %> + 1)) {
+                               ret = <%= panel_result_type_name().upcase %>_<%= i.name().upcase %>;
+                               break;
+                       }
+<%- end -%><%- n += 1 -%><%- end -%>
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+
+  def generate_source_function_function_name()
+    script = <<-EOS
+EXPORT <%= panel_result_type_name() %> <%= panel_function_name() %>(<%= panel_arguments() %>)
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+
+  def generate_source_function_pnl_item_value()
+    script = <<-EOS
+<%- self.generate_source_function_pnl_item_value_each() do |s| -%><%= s %><%- end -%>
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+
+  def generate_source_function()
+    script = <<-EOS
+<%= self.generate_source_function_function_name() %>{
+       PNL_ITEM pnl_item[<%= number_items %>];
+       PNID pnid0;
+       PNT p0 = {0x8000,0x8000};
+       WEVENT wev0;
+       W stat,itemno;
+       <%= panel_result_type_name().upcase %> ret;
+       PANEL pnl = {
+               2,0x48,0,
+               {{0, 0, <%= self.panel_padding_left + self.content_width + self.panel_padding_right %>, <%= self.panel_padding_top + self.content_height + self.panel_padding_bottom %>}},
+               0,
+               <%= number_items %>,
+               pnl_item
+       };
+
+<%= self.generate_source_function_pnl_item_value() %>
+       pnid0 = pcre_pnl(&pnl, &p0);
+       if (pnid0 < 0) {
+               DP_ER("pcre_pnl error", pnid0);
+               return pnid0;
+       }
+
+       for (;;) {
+               ret = -1;
+               stat = pact_pnl(pnid0, &wev0.e, &itemno);
+               switch (stat) {
+               case    P_EVENT:
+                       if (wev0.s.type == EV_DEVICE) {
+                               oprc_dev(&wev0.e, NULL, 0);
+                       }
+                       continue;
+               default:
+<%= self.generate_source_function_ret_handler() %>
+                       if (itemno >= 0) {
+                               continue;
+                       }
+               case    0x5001:
+<%= self.generate_source_function_ret_handler() %>
+                       if (itemno >= 0) {
+                               continue;
+                       }
+                       break;
+               }
+               if (ret != -1) {
+                       break;
+               }
+       }
+
+       pdel_pnl(pnid0);
+
+       return ret;
+}
+
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+end
+
+class PanelData
+  attr_accessor :yaml, :panels, :name
+  def initialize(yaml)
+    @yaml = yaml;
+    @panels = Array.new();
+    yaml["panels"].each { |a|
+      p = Panel.new(a);
+      @panels.push(p);
+    };
+  end
+  def lisence_header()
+    @yaml["generator"]["lisence_header"]
+  end
+  def lisence_source()
+    @yaml["generator"]["lisence_source"]
+  end
+  def filename_header()
+    @yaml["generator"]["output_header"]
+  end
+
+  def generate_header()
+    script = <<-EOS
+<%- @panels.each do |p| -%>
+<%= p.generate_header_retval_definition() %>
+<%= p.generate_header_function() %>
+<%- end -%>
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+  def generate_source_include_files()
+    script = <<-EOS
+#include    "<%= self.filename_header() %>"
+
+#include       <bstdio.h>
+#include       <bstdlib.h>
+#include       <tcode.h>
+#include       <tstring.h>
+#include       <btron/btron.h>
+#include       <btron/hmi.h>
+#include       <btron/vobj.h>
+
+#if PANEL_DEBUG
+# define DP(arg) printf arg
+# define DP_ER(msg, err) printf("%s (%d/%x)\\n", msg, err>>16, err)
+#else
+# define DP(arg) /**/
+# define DP_ER(msg, err) /**/
+#endif
+
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+  def generate_source()
+    script = <<-EOS
+<%- @panels.each do |p| -%>
+<%= p.generate_source_function() %>
+<%- end -%>
+    EOS
+
+    erb = ERB.new(script, nil, '-');
+    erb.result(binding)
+  end
+end
+
+def generate_header(filename, data)
+  fd = File.open(filename, "w");
+  fd.puts data.lisence_header();
+  fd.puts <<-EOS
+
+/* This file is automatically generated. */
+
+#include    <basic.h>
+#include       <btron/dp.h>
+#include       <btron/hmi.h>
+
+  EOS
+  fd.puts "#ifndef __" + filename.upcase.gsub(/\./, '_') + "__";
+  fd.puts "#define __" + filename.upcase.gsub(/\./, '_') + "__";
+  fd.puts "\n";
+  fd.puts data.generate_header();
+  fd.puts "#endif\n"
+  fd.close
+end
+
+def generate_source(filename, data)
+  fd = File.open(filename, "w");
+  fd.puts data.lisence_source();
+  fd.puts <<-EOS
+
+/* This file is automatically generated. */
+
+  EOS
+  fd.puts data.generate_source_include_files();
+
+  fd.puts data.generate_source();
+  fd.close
+end 
+
+$KCODE = "EUC"
+
+yaml = YAML.load_file(ARGV[0]);
+data = PanelData.new(yaml);
+
+fname_header = yaml["generator"]["output_header"]
+fname_source = yaml["generator"]["output_source"]
+
+generate_header(fname_header, data);
+generate_source(fname_source, data);