(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