Hi all,

I'm trying to write a custom widget in shoes which is similar to a radio
button, but is drawn using shapes to get a particular appearance.

All works nicely except for placement. Shoes doesn't seem to realize what
size the object is, so no space ends up being allocated for it (width &
height of 0).

The sample code below draws three of these, but they all get drawn in the
same space. If I include a para or something, they get moved around - but I
would prefer shoes to recognize the width of the oval & position everything
accordingly.

Thanks,

Daniel

Width = 12
Height = 14

OutlineColor = "#000000"
OutlineWidth = 2
DeselectedColor = "#CCCCCC"

class Shoes::Onedot < Shoes::Widget
  attr_reader :selected_color
  attr_reader :selected
  
  def initialize(opts = {})
    super()
    selected = opts[:selected]
    selected_color = opts[:selected_color]
    
    stroke OutlineColor
    strokewidth OutlineWidth
    @oval = oval(top, left, Width, Height)
    draw_dot
    @oval.click do
      toggle
    end
  end

  def change(&block)
    @on_changed = block
  end
  
  def draw(container, boolean)
    super(container, boolean)
  end
  
  def draw_dot
    @oval.fill = (selected ? selected_color || royalblue : DeselectedColor)
  end
  
  def selected_color=(value)
    @selected_color = value
    draw_dot
  end
  
  def selected=(value)
    @selected = value
    changed
  end
  
  def toggle
    # For some reason, selected= doesn't work properly...
    @selected = !selected
    changed
  end
  
  private
  
  def changed
    if @on_changed then
      if @on_changed.arity == 0 then
        @on_changed.call
      else
        @on_changed.call(selected)
      end
    end
    draw_dot
  end
  
end


Shoes.app do
  
  stack do
    sampledot = onedot
    sampledot.selected = true
    sampledot.selected_color = tomato
  end
  
  stack do
    flow(:width => "100%") do
      dot2 = onedot
      dot3 = onedot
    end
  end
  
end

Reply via email to