
class VRLayoutFrame
=begin
== VRLayoutFrame
   This is a base class for layout frames.

=== Methods
--- register(*controls)
    Registers controls for LayoutFrame
--- move(x,y,w,h)
    Resizes the layout frame size.
    This re-calculate the registered controls coordinates.
=end

  def initialize()
    @_vr_layoutclients=[]
    @_vr_lx,@_vr_ly,@_vr_lw,@_vr_lh = 0,0,10,10
  end

  def register(*cntl)
    @_vr_layoutclients.concat cntl
    _vr_relayout
  end

  def move(x,y,w,h)
    @_vr_lx,@_vr_ly,@_vr_lw,@_vr_lh = x,y,w,h
    _vr_relayout
  end

  def _vr_relayout
  end
end


class VRVertLayoutFrame < VRLayoutFrame
=begin
== VRVertLayoutFrame
   This is a frame that lays out its controls vertically.
   Use ((|register|)) and ((|move|)) method of VRLayoutFrame
=end

  def _vr_relayout
    return if @_vr_layoutclients.size==0
    height = @_vr_lh.to_f / @_vr_layoutclients.size
    @_vr_layoutclients.each_index do |i|
      @_vr_layoutclients[i].move @_vr_lx, @_vr_ly+height*i,@_vr_lw,height
    end
  end
end

class VRHorizLayoutFrame < VRLayoutFrame
=begin
== VRHorizLayoutFrame
   This is a frame that lays out its controls horizontally.
   Use ((|register|)) and ((|move|)) method of VRLayoutFrame
=end
  def _vr_relayout
    return if @_vr_layoutclients.size==0
    width = @_vr_lw.to_f / @_vr_layoutclients.size
    @_vr_layoutclients.each_index do |i|
      @_vr_layoutclients[i].move @_vr_lx+width*i, @_vr_ly,width,@_vr_lh
    end
  end
end

class VRFullsizeLayoutFrame < VRVertLayoutFrame
=begin
== VRFullsizeLayoutFrame
   This is a frame that lays out its one control full-sized.
   Use ((|register|)) and ((|move|)) method of VRLayoutFrame
   ((|register|)) method can be called once and accept only one control.
=end

  def register(re)
    super
    def self.register
      raise "register twice"
    end
  end
end

class VRGridLayoutFrame <VRLayoutFrame
  def initialize(xs,ys)
    super()
    @_vr_xsize=xs
    @_vr_ysize=ys
    @_vr_layoutclients = Array.new
  end
  def setDimention(xs,ys)
    @_vr_xsize=x
    @_vr_ysize=y
  end

  def register(cntl,x,y,w,h)
    @_vr_layoutclients.push [cntl,x,y,w,h]
    _vr_relayout
  end

  def _vr_relayout
    @_vr_layoutclients.each do |c|
      c[0].move( @_vr_lw/@_vr_xsize * c[1],
                 @_vr_lh/@_vr_ysize * c[2],
                 @_vr_lw/@_vr_xsize * c[3],
                 @_vr_lh/@_vr_ysize * c[4])
    end
  end
end

class VRTwoPaneFrame
  attr :ratio,1
  attr :separatorheight,1

  Cursor="Size"

  module VRTwoPaneFrameUsable
    attr :_vr_twopaneframes,1

    def _vr_twopaneframesinit
      return if @_vr_twopaneframes  # no init twice
      @_vr_twopaneframes = Array.new
      @_vr_current_tpframe=nil
      addHandler(
        WMsg::WM_LBUTTONUP,  "vrsepl2buttonup",  MSGTYPE::ARGINTSINTSINT,nil)
      addHandler(
        WMsg::WM_LBUTTONDOWN,"vrsepl2buttondown",MSGTYPE::ARGINTSINTSINT,nil)
      addHandler(
        WMsg::WM_MOUSEMOVE,  "vrsepl2mousemove",  MSGTYPE::ARGINTSINTSINT,nil)

      acceptEvents [
        WMsg::WM_LBUTTONUP,WMsg::WM_LBUTTONDOWN,WMsg::WM_MOUSEMOVE
       ]
    end

    def self_vrsepl2buttondown(s,x,y)
      @_vr_twopaneframes.each do |f|
        if f.hittest(x,y)
          f.setDragCur
          f.dragstart 
          @_vr_current_tpframe=f
        end
      end
    end

    def self_vrsepl2buttonup(s,x,y)
      @_vr_current_tpframe=nil
      @_vr_twopaneframes.each do |f|
        f.dragend
      end
    end

    def self_vrsepl2mousemove(s,x,y)
      @_vr_twopaneframes.each do |f|
        if f.hittest(x,y)
          f.setDragCur
        end
      end
      if @_vr_current_tpframe then
        @_vr_current_tpframe.splitterDragging(x,y)
      end
    end
  end

  def initialize(pane1,pane2)
    @pane1,@pane2 = pane1,pane2 
    @_vr_dragging=false
    @ratio=0.5
    @separatorheight=4
  end

  def hittest(x,y)
    return unless @_vr_lxs
    if (@_vr_lxs < x) and (x  < @_vr_lxe) and
       (@_vr_lys < y) and (y  < @_vr_lye) 
    then
      true
    else
      false
    end
  end

  def setDragCur
    @_vr_app.setCursor @_vr_dragcur if @_vr_app
  end

  def dragstart
    @parent.setCapture
    @_vr_dragging=true
  end

  def dragend
    return unless @_vr_dragging
    @parent.releaseCapture
    @_vr_dragging=false
    splitterDragEnd
  end

  def setup(parent)
    raise "setup twice" if defined? @parent
    @parent = parent
    @_vr_app = parent.instance_eval("@screen.application") # parent.application
    @_vr_dragcur = eval("@_vr_app::SysCursors::#{self.type::Cursor}()")
    parent.extend VRTwoPaneFrameUsable
    parent._vr_twopaneframesinit
    parent._vr_twopaneframes.push self
    self
  end

  def move(x,y,w,h)
    @_vr_lx,@_vr_ly,@_vr_lw,@_vr_lh = x,y,w,h
    self._vr_relayout
  end

  def splitterDragging(x,y) end
  def splitterDragEnd(x,y) end
  def _vr_relayout() raise "using base class #{self.type}" end
end

class VRVertTwoPaneFrame < VRTwoPaneFrame
  Cursor = "SizeNS"
  def splitterDragEnd
    _vr_relayout
  end
  def splitterDragging(x,y)
    return if y<@separatorheight+@_vr_ly or y>@_vr_ly+@_vr_lh-@separatorheight
    @ratio=(y-@_vr_ly).to_f/@_vr_lh
    _vr_relayout(y-@_vr_ly)
  end

  def _vr_relayout( ys = (@_vr_lh*@ratio).to_i)
    sh=(@separatorheight/2).to_i
    @_vr_lxs,@_vr_lxe = @_vr_lx,@_vr_lx+@_vr_lw
    @_vr_lys,@_vr_lye = @_vr_ly+ys-sh,@_vr_ly+ys+sh

    @pane1.move @_vr_lx,@_vr_ly,  @_vr_lw,ys-sh
    @pane2.move @_vr_lx,@_vr_lys+@separatorheight, @_vr_lw,@_vr_lh-ys-sh
  end
end

class VRHorizTwoPaneFrame < VRTwoPaneFrame
  Cursor = "SizeWE"
  def splitterDragEnd
    _vr_relayout
  end
  def splitterDragging(x,y)
    return if x<@separatorheight+@_vr_lx or x>@_vr_lx+@_vr_lw-@separatorheight
    @ratio=(x-@_vr_lx).to_f/@_vr_lw
    _vr_relayout(x-@_vr_lx)
  end

  def _vr_relayout( xs = (@_vr_lw*@ratio).to_i)
    sh=(@separatorheight/2).to_i
    @_vr_lxs,@_vr_lxe = @_vr_lx+xs-sh,@_vr_lx+xs+sh
    @_vr_lys,@_vr_lye = @_vr_ly,@_vr_ly+@_vr_lh

    @pane1.move @_vr_lx,@_vr_ly,  xs-sh,@_vr_lh
    @pane2.move @_vr_lxs+@separatorheight,@_vr_ly, @_vr_lw-xs-sh,@_vr_lh
  end
end
