KONTRA Gergely wrote:> Well, what do you think about layouts in wxwindows will look like in the
> future?
The fundamentals won''t change, but we can create some friendlier wxRuby
wrappers to hide some of the complicated bits.
wxWindows originally used pixel-placement to position all the controls.
Automatic layouts were added later, which is probably why they feel a
little strange. Basically, each widget (also known as a control), such
as a button, is assigned a parent window when it is created. But then it
is also added to a "sizer" which takes care of the size and position.
These sizers can be added to each other, to create nested layouts, so it
is almost a second, parallel hierarchy in addition to the parent/child
window relationship. This is different from GTK and Java''s Swing.
The other thing that adds complexity is that several common methods have
parameters that are rarely used, but they are required because some
often-needed parameters come after them in the signature. This can be
solved by adding new API calls, in addition to the existing calls that
are direct wraps of the C++ API.
> For now, just try to compre a simple example, build the
> following screen in both wxruby and ruby-gtk2.
> A labeled frame (text inside) and a button below.
>
> +---+--------------------------------+---+---+---+
> | - | GUI example | _ | # | X |
> +---+--------------------------------+---+---+---+
> | ,--frame-------------------------------------, |
> | | Some text | |
> | `--------------------------------------------'' |
> | +------+ |
> | | OK | |
> | +------+ |
> +------------------------------------------------+
>
> Can it be simplified in wxruby? Maybe some helper functions should be
> written to enable easy packing? Ideas?
Interesting choice. I created a wxRuby app that looks roughly like this,
and uploaded it here:
http://www.qualitycode.com/temp/gergely.rb
(Note: This URL is temporary, and will be removed at some point, so you
might want to save a copy of this sample code on your local system if
you want to refer back to it.)
I''ll point out a few of the more interesting parts of the sample code.
1. You''ll notice that I use Wx:: in many places, rather than putting a
single "include Wx" at the top of the file. I prefer to be explicit,
but
either way is fine.
2. Notice the way they handle the "frame" outlined box, which I refer
to
as a GroupBox, since that''s what MS Windows calls it. Instead of having
a control to handle the outer part which *contains* the inner control,
wxRuby has both controls be sibling children of the parent dialog.
The positioning is handled by a special StaticBoxSizer. This is the kind
of special case that wxWindows has more of, and GTK has fewer of. I
created a SimpleGroupBox control to hide the complexity from the main
code. Note that this "group box" is really a sizer, and not a
control/widget.
3. I pass -1 as the id in almost every case, so wxRuby will assign an
id. It would be nice to not have to pass it, but it is the second
parameter in C++ so we have kept that in wxRuby (so far). The only place
I care about the ID is in the evt_button call later, and I can just ask
the control what it''s id is. Sometimes that''s not appropriate,
though.
4. The Dialog constructor, like most of the Window family of classes,
requires you to pass a position and size before the flags. When using
automatic layout, you rarely want to pass a position or size, so it
would be nice to avoid having to pass the default constants.
5. The dialog you proposed can be described as a vertical box, with the
"frame" and "some text" at the top, and the ok button at the
bottom.
This implies that we will use a BoxSizer to do the layout, with the
VERTICAL orientation.
6. We add two things to this main sizer: the group box, and the ok
button. Again, we have to pass a rarely-used parameter (the zero), which
in this case indicates that if there is extra VERTICAL space available,
what proportion of that extra space should this control receive.
Within each add call, we also pass a set of flags to the sizer, which
are a bit confusing. These flags control both "border" padding
location(s), and the alignment within the available space, or if the
control should grow HORIZONTALLY if extra space is available.
It took me a while to figure out that the second parameter controls
growth in the BoxSizer''s orientation, while the EXPAND flag controls
growth in the other direction.
7. The call to set_sizer is what forces the dialog to layout its
children (the static box, the static text, and the button) appropriately.
8. In this case, I force the dialog to be 300x150, so the title bar text
("GUI example") will be visible. An alternative to the set_size call
would be to use the sizer.set_size_hints call, which would make the
dialog be exactly large enough to fit the contents.
9. We need to handle the close event, or else the program will just hang
when this dialog is closed using the system menu or the X box. When we
see a close event, we''ll invoke the onClose method.
10. We also want to handle the ok button event, also calling onClose.
11. Every wxRuby program needs an app. And the app currently *must* have
an OnInit call. This is typical of framework libraries, such as
wxWindows and FOX, as opposed to widget toolkits like FLTK and GTK.
Whew!
I hope that helps everyone understand a bit more about wxRuby, and some
of the places where wxRuby can improve over wxWindows itself. It might
also give someone some material to put into a tutorial (hint! hint!)
I should also mention that once you understand how wxRuby works, it''s
really pretty easy to create some complex layouts, as I did with my
Redwood email program. This screenshot is a good example:
http://www.qualitycode.com/images/redwood-main.png
Kevin