Can your GUI framework do this?

View: New views
10 Messages — Rating Filter:   Alert me  

Can your GUI framework do this?

by Martin DeMello :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

One of the most interesting facets of a desktop GUI system is how easy
it makes it to go off the beaten track, particularly how well you can
add "first class" components to the system. (Using 'first class' here
to mean 'on an equal footing with the widgets supplied by the
toolkit'). Also, as a ruby programmer, I'd naturally rather not drop
down into C (or Java) to do this. I'm trying to collect examples of
the following four tasks (which I will then assemble and put up on the
web as another datapoint in the eternal GUI debate :)):

1. A component consisting of a series of existing components hooked
together to act as a single widget
2. A component built 'from scratch' atop a canvas, that is, handling
its own drawing and event management
3. A component combining a canvas and existing widgets
4. A container that takes a collection of widgets and lays them out
according to some userdefined algorithm

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)

martin


Re: Can your GUI framework do this?

by _why :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

(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


Re: Can your GUI framework do this?

by Martin DeMello :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, Jun 7, 2008 at 10:50 PM, _why <why@...> wrote:
>
> I'll work on some really nice answers to these.  This is a fantastic exercise.

Looking forward to them. The code looks very slick - "check out shoes"
just moved all the way up my todo list :)

martin


Re: Can your GUI framework do this?

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin DeMello wrote:

> One of the most interesting facets of a desktop GUI system is how easy
> it makes it to go off the beaten track, particularly how well you can
> add "first class" components to the system. (Using 'first class' here
> to mean 'on an equal footing with the widgets supplied by the
> toolkit'). Also, as a ruby programmer, I'd naturally rather not drop
> down into C (or Java) to do this. I'm trying to collect examples of
> the following four tasks (which I will then assemble and put up on the
> web as another datapoint in the eternal GUI debate :)):
>
> 1. A component consisting of a series of existing components hooked
> together to act as a single widget
> 2. A component built 'from scratch' atop a canvas, that is, handling
> its own drawing and event management
> 3. A component combining a canvas and existing widgets
> 4. A container that takes a collection of widgets and lays them out
> according to some userdefined algorithm
>
> 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)

Swing can certainly do all this, and with layout tools like Netbeans
Matisse you can do almost all of it drag-and-drop (though obviously
implementing your own component atop a canvase requires code).

I could try to dig up some examples of doing this in Ruby, but I would
wager the Monkeybars guys have some already. In general, it's pretty easy.

- Charlie


Parent Message unknown Re: Can your GUI framework do this?

by Logan Barnett :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin,
I'm one of the contributors to Monkeybars, which is our JRuby GUI  
framework that sits on top of Swing.
Here's how Monkeybars handles this:
1. A component consisting of a series of existing components hooked
together to act as a single widget
In Swing, it is typical to inherit from the component that gets you  
closest to what you want, and add stuff to there. What you are  
thinking of is probably a JPanel. While you could inherit from a  
JPanel, put in the functionality or other components that you wanted,  
and drop it in where you wanted to use it, we feel there's a better  
way. Monkeybars uses MVC's delegation of responsibilities to help us  
out with testing and  keep the code more sensible. As such, we felt  
the best way to approach this would be by providing mechanisms that  
allow one MVC tuple (your top level window) to nest other MVC tuples  
(reusable components). This means that controllers communicate with  
other controllers. Views interact with simple view components  
directly, but not complicated "partials".
Here's your example: 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"

In Monkeybars, the picture/text field grouping would be handled by its  
own model, view, and controller. This is how you'd tie that in:
class MainView < ApplicationView
   # nesting defines how the component will be added or removed when  
add_nested_controller or
   # remove_nested_controller is called. This nesting is one of the  
simpler ones that just drops in the
   # component as is. There are more complicated variations that allow  
you to write all code you want to
   # determine layout specific arguments, positioning, and layout  
validation.
   nest :sub_view => :image_name, :view => :image_name_panel
end

class MainController < ApplicationController
   def load
     @text_image_controller = TextImageController.create_instance
     # this will kick off the nesting for any nesting with a sub_view  
of :image_name
     add_nested_controller :image_name, @text_image_controller
   end
end

2. A component built 'from scratch' atop a canvas, that is, handling
its own drawing and event management
Since we're using Swing, one could override the paintComponent method  
on the Swing component used in the view. We've done some of this to  
render real-time animated graphs with peak bars and graph transitions.  
We even have it so each graph bar has it's own tooltip text.
Here's your example: A speedometer-type dial with a configurable range  
and tick interval
In this case, I'd write my own view component by hand (typically we  
use a designer for it).
A speedometer could be made by using some of the Java2D stuff out  
there during paintComponent. The needle could be drawn with simple  
line methods where you specify start and end coordinates. The ticks  
could be drawn similarly as partial lines. I'd imagine some trig would  
be involved in the calculations. I would also check to see if any Java  
folks had already done this, as Java/Swing have been around for a long  
time.

3. A component combining a canvas and existing widgets
I'd want to make the painted canvas widget into a nested controller,  
so my canvas wouldn't have to care about stomping on other components  
when it redraws itself.
For your example: A box that holds a component and paints a customised  
border around it
This is actually pretty simple in Monkeybars. You can just set the  
boarder of many (if not all) Swing components. We have a live example  
using this that you can run via Java Web Start here:
http://www.happycamperstudios.com/monkeybars/twit/Twit-and-Twitter.jnlp
Here's the snippet that makes the drop-shadow border happen:
@image = Java::javax.swing.JLabel.new
@image.border = Java::org.jdesktop.swingx.border.DropShadowBorder.new
The drop shadow comes from the SwingX library.
I'd also like to note that example won us the GUI part of the script  
bowl competition at Java One (us being JRuby).
4. A container that takes a collection of widgets and lays them out
according to some userdefined algorithm
There's a ton of ways to do this using Swing using Layouts.
Your example: A pure-ruby implementation of a wrapbox
(http://zem.novylen.net/ruby/wrapboxdemo.png)
This works out of the box just by using a FlowLayout in your  
container. That can be as simple as this:
@main_view_component.layout = Java::javax::swing::FlowLayout.new

Some other stuff:
Monkeybars has a lot of options for configuring view mappings. View  
mappings define how data moves from your model to the components in  
your view, as well as how your components' data moves into your model.

One thing that was really important to us in Monkeybars was that for  
moderate to large projects, a large update method in a controller that  
intimately knew about the components used made testing incredibly  
painful. We designed Monkeybars such that most communication between  
the view and controller is done through the model via the mappings  
mentioned above. Controllers may also send signals to the view for  
lightweight or secondary renderings. There is no direct communication,  
however. This makes testing super easy.

You _could_ write Java if you wanted, but we haven't run into  
occurrences where Java (the language) is needed. You could write all  
of your designs by hand in Ruby, which is fine. My preferred approach  
is to use a designer tool, such as Netbeans.
Do you really want to lay something like this out by hand?
http://www.happycamperstudios.com/monkeybars/charlotte%20interface.png


Swing is a part of Monkeybars. We provide some simplified ways to  
communicate with it (such as implicit event handlers). However,  
Monkeybars doesn't shield you from Swing. This is both a pro and a  
con. Swing is a powerful library, but it also has a lot of quirks.  
Thanks to the folks at JRuby, we have Rubyized methods to all of our  
Java proxies, and some nice implicit type conversions that make  
integrating with Java look fairly natural. Monkeybars just makes Swing  
more palatable, and provides a nice quarantine zone to place all of  
your Swing code (in the view).

You're in JRuby, and that means you're in Java. Java buys you a built-
in JIT engine. JRuby's team has told everyone to flag occurrences  
where MRI is faster as bugs. You also can run your code on any machine  
with Java installed, and it's hard to find machines without Java.  
Monkeybars itself is just a jar that happens to be a library. No Ruby  
installation is needed! Leveraging Rawr you can also wrap your jars  
in .exes or .app files. You can even use Java Web Start to hand  
someone a link and the app will auto-install/update and run. You could  
also integrate Monkeybars into your existing Java app, and start  
writing all of your new code in Ruby. Java also has a lot of mature  
code out there, as it has been around for a long time. One personal  
experience I had was using SNMP. Ruby's SNMP library is great for  
getting you started, but falls apart when you need to use the more  
secure SNMPv3. SNMP4J has been around for a while, and is still active.

I know a lot of the Ruby community has some bitterness towards Java,  
but this isn't Java the language we're using here, it's Java the  
platform. I encourage anyone interested in GUI development to take a  
peak at our examples and screencasts:
http://monkeybars.rubyforge.org/
http://monkeybars.rubyforge.org/tutorials.html

-Logan


Re: Can your GUI framework do this?

by Marc Heiler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> I know a lot of the Ruby community has some bitterness towards Java,
> but this isn't Java the language we're using here, it's Java the
> platform.

I dont think there is any bitterness. Just when you use ruby for long
you will feel that Java is more verbose, and less flexible. Other than
that, I dont think there is any real "bitterness" or similar.


Realistically I think Ruby should rather be compared to i.e. perl, php,
python.

The static languages (Java C C++ C# D) out there are always much more
verbose compared to ruby.
--
Posted via http://www.ruby-forum.com/.


Re: Can your GUI framework do this?

by Hidetoshi NAGAI :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

From: "Martin DeMello" <martindemello@...>
Subject: Can your GUI framework do this?
Date: Sun, 8 Jun 2008 08:29:55 +0900
Message-ID: <f93a6bcc0806071631g4d2bc263tce130e8f3c2f7e81@...>
> Examples (more welcomed):

On Ruby/Tk,

> 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

Use a TkLabel widget.

> 2. A speedometer-type dial with a configurable range and tick interval

Use (install) Tcl/Tk's VU extension.
Ruby/Tk has a wrapper library for the extension.

> 3. A box that holds a component and paints a customised border around it

Probably, a TkFrame widget is enough to do this.

> 4. A pure-ruby implementation of a wrapbox

Use a TkText widget and TkTextWindow objects.
--
Hidetoshi NAGAI (nagai@...)


Re: Can your GUI framework do this?

by Martin DeMello :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Jun 26, 2008 at 7:13 AM, Marc Heiler <shevegen@...> wrote:
>
> The static languages (Java C C++ C# D) out there are always much more
> verbose compared to ruby.

D actually does a pretty good job of supplying "high level" features
like rich datatypes with literal constructors and full fledged lexical
closures. Those two can add up to a huge verbosity reduction.

martin


Re: Can your GUI framework do this?

by Martin DeMello :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Jun 25, 2008 at 2:44 PM, Logan Barnett <logustus@...> wrote:
> Martin,
> I'm one of the contributors to Monkeybars, which is our JRuby GUI framework
> that sits on top of Swing.
> Here's how Monkeybars handles this:

Thanks for the examples - Monkeybars looks pretty cool.

> 4. A container that takes a collection of widgets and lays them out
> according to some userdefined algorithm
> There's a ton of ways to do this using Swing using Layouts.
> Your example: A pure-ruby implementation of a wrapbox
> (http://zem.novylen.net/ruby/wrapboxdemo.png)
> This works out of the box just by using a FlowLayout in your container. That
> can be as simple as this:
> @main_view_component.layout = Java::javax::swing::FlowLayout.new

Yes, but my point was, can you define your own Layout in ruby?

> You _could_ write Java if you wanted, but we haven't run into occurrences
> where Java (the language) is needed. You could write all of your designs by
> hand in Ruby, which is fine. My preferred approach is to use a designer
> tool, such as Netbeans.
> Do you really want to lay something like this out by hand?
> http://www.happycamperstudios.com/monkeybars/charlotte%20interface.png

Actually, I do :) My preferred approach is to build widgets from the
bottom up, so that if I want to experiment with the layout later I can
do it easily in the code. Does netbeans use the "interface definition
file" approach or does it generate actual code from your UI?


> You're in JRuby, and that means you're in Java. Java buys you a built-in JIT
> engine. JRuby's team has told everyone to flag occurrences where MRI is
> faster as bugs. You also can run your code on any machine with Java
> installed, and it's hard to find machines without Java. Monkeybars itself is
> just a jar that happens to be a library. No Ruby installation is needed!
> Leveraging Rawr you can also wrap your jars in .exes or .app files.

This is indeed a huge plus.

> I know a lot of the Ruby community has some bitterness towards Java, but
> this isn't Java the language we're using here, it's Java the platform. I
> encourage anyone interested in GUI development to take a peak at our
> examples and screencasts:

No real bitterness - it's just a language I'd prefer not to use. The
JVM itself I'm all for.

martin


Re: Can your GUI framework do this?

by david_koontz :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martin DeMello wrote:
Yes, but my point was, can you define your own Layout in ruby?
Yes you can define a new Swing layout manager with 100% Ruby code, just as you can do most anything doable in Java from JRuby.  I would say though, that is is highly unlikely that you would need to do so.  There are a great variety of layout managers and most are pretty sophisticated, I surely wouldn't take on writing a non-trivial one myself.  If you are looking for a very flexible layout manager designed for people doing layouts by hand I'd suggest the MiG layout manager (http://www.miglayout.com/).  You can see the author's presentation at this year's Java One here: http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-4928.pdf

Martin DeMello wrote:
> You _could_ write Java if you wanted, but we haven't run into occurrences
> where Java (the language) is needed. You could write all of your designs by
> hand in Ruby, which is fine. My preferred approach is to use a designer
> tool, such as Netbeans.
> Do you really want to lay something like this out by hand?
> http://www.happycamperstudios.com/monkeybars/charlotte%20interface.png

Actually, I do :) My preferred approach is to build widgets from the
bottom up, so that if I want to experiment with the layout later I can
do it easily in the code. Does netbeans use the "interface definition
file" approach or does it generate actual code from your UI?
Netbeans generates straight Java code, which you normally would never need to touch.  As for building a widget from the "bottom up" do you have any examples?  I've built several "widgets" using the graphical deisgner.  In Swing they tend to be JPanel + some components + logic (the logic of course would all be in Ruby) which makes the visual designer even more useful.  If you're doing a super custom component involving doing your own drawing, that is accomplished easily enough in straight Ruby code.  In either of these situations I fail to see how having a visual designer in any way slows you down.

David