標準のレイアウトフレームが不満なので、簡単なレイアウトフレームを作ってみる

背景

おれは仕事用のツールをrubyで作ることが多いんだけれども、近頃はプロジェクトメンバに使ってもらうツールを作る機会も増えてきた。
自分で使うならまだしも、使ってもらうとなるとCUIでは不親切。GUIを作りたい気持ちが出てくるもんだ。

そこで、前々から存在は知っていたけれども使ったことがなかった、VisualuRubyに手を出した。

イベントを拾うのはらくちん

イベントを拾うのはホントにらくちん。
[xxx_clicked]等のメソッドを定義するだけでイベントを拾える。VBちっくで超らくちん。

あとはコントロールの配置!

超単純なGUIならまだしも、単純なGUIでも、コントロールの配置は超めんどくさい、と思う。
単純なツールを作りたいだけなのに、めちゃめちゃめんどくさい。


雪見酒さんが作っているFormDesignerというソフトも便利そうだったけども、
VRTextをはっつけて移動すると挙動不審になるのには困った。


レイアウトフレームやレイアウトマネージャも使ってみたが、微妙。

VRHorizLayoutFrameやVRVertLayoutFrameとか使ってみたけど、
レイアウトフレーム内で全てのコントロールの幅や高さが揃っちゃうし、
意図したカンジになってくれないんだ。

そこで本題

思い立って、コントロールの幅や高さを変えないレイアウトフレームを作ってみた。
また、中に入っているコントロールのサイズにより、レイアウトフレームのサイズを拡張する。
なんとなくHTMLちっくなレイアウトができる。


まだ実戦投入はしてない(そもそもVisualuRubyもまだ実戦投入はしてない)けれども、なかなか便利そうだから公開してみる。
もうちょいらくらくにできそうな気がするので、やる気がある限り突き詰めてみる。

こんな画面を作れる

ソース
#!ruby -Ks
$KCODE="s"

require "yaml"
require "vr/vrcontrol"
require "vr/vrlayout2"

class MyLayoutFrame < VRLayoutFrame
  attr_accessor :padding

  def w
    @_vr_lw
  end

  def h
    @_vr_lh
  end
  
  def initialize
    super
    @padding = 4
  end
end

class MyHorizLayoutFrame < MyLayoutFrame
  def _vr_relayout
    x = 0
    @_vr_layoutclients.each do |i|
      i.move(@_vr_lx + x, @_vr_ly, i.w, i.h)
      x += i.w + @padding
      @_vr_lw = x
      @_vr_lh = [@_vr_lh, i.h].max
    end
  end
end

class MyVertLayoutFrame < MyLayoutFrame
  def _vr_relayout
    y = 0
    @_vr_layoutclients.each do |i|
      i.move(@_vr_lx, @_vr_ly + y, i.w, i.h)
      y += i.h + @padding
      @_vr_lw = [@_vr_lw, i.w].max
      @_vr_lh = y
    end
  end
end

class Form < VRForm
  def construct
    #
    # メモ
    #  位置はレイアウトフレームが決めてくれるから、
    #  addControlではサイズのみを指定すればよい(位置はx=0, y=0でよい)
    #

    addControl(VREdit, "edit", "", 0, 0, 120, 24)
    addControl(VRButton, "button", "検索", 0, 0, 50, 24)
    @lm1 = MyHorizLayoutFrame.new
    @lm1.register(@edit, @button)
    
    addControl(VRText, "text", "", 0, 0, 400, 200)
    @lm2 = MyHorizLayoutFrame.new
    @lm2.register(@text)
    
    addControl(VRButton, "xxxbutton1", "機能1", 0, 0, 100, 24)
    addControl(VRButton, "xxxbutton2", "機能2", 0, 0, 100, 24)
    addControl(VRButton, "xxxbutton3", "機能3", 0, 0, 100, 24)
    @lm3 = MyHorizLayoutFrame.new
    @lm3.register(@xxxbutton1, @xxxbutton2, @xxxbutton3)
    
    @lm = MyVertLayoutFrame.new
    @lm.register(@lm1, @lm2, @lm3)

    self.caption = "レイアウトフレームのテスト"
    self.move(0, 0, 408, 286)
  end
end

VRLocalScreen.start(Form)