(These examples require a Shoes that's no older than a week or two.)

On Sun, Jun 08, 2008 at 08:29:55AM +0900, Martin DeMello wrote:
> 1. A component consisting of a series of existing components hooked
> together to act as a single widget

In Shoes, you inherit from the Widget class and you can paint
your own custom widgets or combine pre-existing ones.

Like, for instance, Shoes doesn't come with a file input field like
HTML does.  But you can combine an `edit_line` and a `button`.

  class Browse < Widget
    def initialize
      @name = edit_line
      @find =
        button("Browse...").click do
          @name.text = ask_open_file
        end
    end
    def filename
      @name.text
    end
  end

  Shoes.app do
    browse
  end

When you inherit from Widget, you get a free lowercased method added
to Shoes for inserting that widget into any "stack" or "flow" (like
HTML divs, basically.)

And since the widget itself is a "flow", you can move the whole widget
as a single component.  So you can call `move(x, y)` or `show` or
`hide` on the object returned by the `browse` method.

> 2. A component built 'from scratch' atop a canvas, that is, handling
> its own drawing and event management

Too easy, Shoes has painting nailed.  I've worked hard to get things
on par with Processing.  See the `samples` directory for a clock
widget and a calculator and a dictionary and you'll find a lot more
out on the web.

> 3. A component combining a canvas and existing widgets

So a combo of #1 and #2?  Well, okay, so taking the `Browse` example
from earlier, we could add a background and a border.  This just
illustrates that all widgets are drawn on a canvas anyway.

  class Browse < Widget
    def initialize
      flow do
        background "#09F"
        border "#FFF"
        @name = edit_line
        @find =
          button("Browse...").click do
            @name.text = ask_open_file
          end
      end
    end
  end

> 4. A container that takes a collection of widgets and lays them out
> according to some userdefined algorithm

I'll have to think about this one.  Shoes already has a 'wrapbox'
called a `flow`, but I can see why you'd want to lay things out
yourself.

Okay, let's see.  So let's try a `cascade` layout that positions
everything diagonally from the element previous to it.

  class Cascade < Widget
    def initialize &blk
      instance_eval &blk
    end
    def draw(a,b)
      x, y = 0, 0
      contents.each do |e|
        if x != e.left && y != e.top
          e.move x, y
        end
        x += e.height
        y += e.width
      end
      super(a,b)
    end
  end
  
  Shoes.app do
    cascade do
      button "1"
      button "2"
      button "3"
    end
  end

The `initialize` part works because every widget is just a canvas anyway.
And the `draw` method is called every time there's a repaint.

That's a bit clunky.  But proves that it can be done.

> Examples (more welcomed):
> 
> 1. An icon widget, that combines  a picture and a textfield
> underneath, with config options to turn either off or size the image,
> make the text editable, etc
> 2. A speedometer-type dial with a configurable range and tick interval
> 3. A box that holds a component and paints a customised border around it
> 4. A pure-ruby implementation of a wrapbox
> (http://zem.novylen.net/ruby/wrapboxdemo.png)

I'll work on some really nice answers to these.  This is a fantastic exercise.

_why