DXRubyWSでのアプリ開発を考える

DXRubyWSの目標の一つとしてGUIアプリを簡単に作るというのがある。現状では、そのためのGUIまわりの基本的な実装ができている程度であり、ぶっちゃけGUIアプリが作りやすいとお世辞にも言える状態ではない。
具体例を示そう。

require 'dxruby'
require_relative '../lib/dxrubyws'
require_relative '../lib/standardgui'
require_relative '../lib/fontcache'

Window.width, Window.height = 640, 480

module WS
  class Form1 < WSWindow
    def initialize(*param)
      super(*param)
      tb = WSTextBox.new(20, 20, 160, 20)
      tb.text = "0"
      self.client.add_control(tb, :textbox1)

      btn = WSButton.new(20, 60, 160, 20, "button1")
      self.client.add_control(btn, :button1)
      btn.add_handler(:click) do
        WS.desktop.add_control(WSMessageBox.new("*8400", (tb.text.to_i * 8400).to_s))
      end
    end
  end
end

win = WS::Form1.new(100,100,200,120)
WS.desktop.add_control(win)

Window.loop do
  WS.update
end

このコードはForm1クラスを作ってテキストボックスとボタンを配置する。テキストボックスに適当な数字を入力してボタンを押すと、メッセージボックスで8400倍した数字が表示される。実用的なアプリかはさておき、コードは非常にわかりにくい。なぜこうなってしまうのか。
現在のWSは全体的に0から行き当たりばったりで作ったコードなせいで、コントロール制御周りが複雑になっている。まあ、コントロールを作るというレベルの話であれば多少複雑でも(どうせコントロールを作る人が限られるという意味で)いいのだが、GUIアプリというのはユーザ定義のウィンドウというコントロールを作成する作業であるわけで、結局これが複雑になってしまう。
コントロールを作るには、initializeで配下のコントロールを生成し、そのコントロールのハンドラなどを一通り定義してやる必要がある。特殊なシグナルやイベント処理はメソッドを定義することになるが、それ以外はほぼ全てinitializeに書くことになる。いまのところは。
ユーザ定義のウィンドウをこの方式で作る場合、アプリ全体の挙動をinitializeの中に書くことになってしまうのである。これは大きな問題だ。
解決策のひとつは、ユーザ定義のウィンドウをデザイン部分とアプリ部分に分割することである。例えばこのように。

require 'dxruby'
require_relative '../lib/dxrubyws'
require_relative '../lib/standardgui'
require_relative '../lib/fontcache'

Window.width, Window.height = 640, 480

# フォーム定義コード
module WS
  class Form1 < WSWindow
    def initialize(*param)
      super(*param)
      @textbox1 = WSTextBox.new(20, 20, 160, 20)
      self.client.add_control(@textbox1)

      @button1 = WSButton.new(20, 60, 160, 20, "button1")
      self.client.add_control(@button1)
      @button1.add_handler(:click) do |obj, tx, ty|
        self.button1_click(tx, ty)
      end
      init
    end
  end
end
# フォーム定義コードここまで

# アプリコード
module WS
  class Form1
    def init
      @textbox1.text = "0"
    end

    def button1_click(tx, ty)
      WS.desktop.add_control(WSMessageBox.new("*8400", (@textbox1.text.to_i * 8400).to_s))
    end
  end
end
# アプリコードここまで

# メイン処理
win = WS::Form1.new(100,100,200,120)
WS.desktop.add_control(win)

Window.loop do
  WS.update
end

フォーム定義コード側にinitializeを置き、コントロールの生成と配置、シグナルの設定(中身はメソッド呼び出しだけ)をして、initを呼ぶ。アプリコードは同じクラスを再オープンしてinitとシグナル処理の中身を定義する。
この例では同じソースに書いてあるが、フォーム定義コードは別ソースにしてフォームデザイナから自動出力してやれば、なんとなく統合GUI開発環境っぽい雰囲気になるだろう。
まあ、例が貧弱すぎて問題点の指摘をするレベルでもないから何とも言えないが、これだけで万事うまく行くとも思えない感じではある。もうちょいアプリを作る経験が無いとわからないところだが、少なくともこういう感じの形を標準化してWSでアプリを書くときはこのようにする、みたいな指針を作れるとやりやすくなるんじゃないかと考えている。