Desktop applications with Haxe and Waxe – Part 4: Sizers

Posted on May 21, 2012

2


One of the fundamental concepts of wxWidgets is “sizers” – utility classes that are very useful for building a working user interface. The following article is heavily based on this one: What do these sizer things do? that can be found via the wxWidgets tutorials page. All credits to Brian Victor, the original orirginator!

So, let’s start with a simple winodw containing a panel with two buttons. In a blank directory, create the following SizerTest.hx:

import wx.BoxSizer;
import wx.Button;
import wx.Frame;
import wx.Panel;

class SizerTest {
    public function new() {
        var frame = ApplicationMain.frame;
        var panel = Panel.create(frame);

        var btnBig = Button.create(panel, null, 'A really really big button');
        var btnTiny = Button.create(panel, null, 'Tiny button');

        var sizer = BoxSizer.create(true);
        panel.setSizer(sizer);
        sizer.add(btnBig);
        sizer.add(btnTiny);
    }

    static public function main() {
        new SizerTest();
    }
}

To be able to compile, we also need a SizerTest.nmml file containing the NME precompiler information:

<?xml version="1.0" encoding="utf-8"?>
<project>
<app
file="SizerTest"
title="SizerTest"
package="any.thing.test"
version="1.0"
company="waxe"
main="SizerTest"
/>

<window
width="600"
height="400"
orientation="landscape"
fps="24"
background="0xffffff"
resizeable="true"
hardware="true"
/>

<haxelib name="waxe" />

<ndll name="waxe" haxelib="waxe" />
<ndll name="std" />
<ndll name="zlib" />
<ndll name="regexp" />

</project>

When compiling using the following command in the working directory…

> haxelib run nme test SizerTest.nmml neko

you should see a window where the larger button covers the tiny one. Not pretty!

NOTE: If you want to compile to c++ target…

> haxelib run nme test SizerTest.nmml windows

…you have to alter the ApplicationMain.hx template file as seen in Part 1 of this series.

Introducing sizers

So, let’s add a sizer helper tool for handling the layout. Add the following lines before the end of the new() constructor method:

        var sizer = wx.BoxSizer.create(true);
        panel.setSizer(sizer);

The first line creates the sizer for us, and the second one tells the panel that there’s a sizer that will take care of the “household cleaning”.

But we also need to tell the sizer what items to look after. Add the following lines:

        sizer.add(btnBig);
        sizer.add(btnTiny);

Now after compiling, and you should see something like the following:

Try altering the box sizer instance creation line, setting its create(inVertical:Bool) parameter to false…

        var sizer = BoxSizer.create(false);

…and you should see a horizontal version of the layout work:

In addition to the layout cleaning work, the sizer itself is able to inform about the minimal size needed to hold the components it watches. First, switch back to vertical mode, and then add the following line:

        sizer.setSizeHints(frame);

Now, after compiling, you should see that the current application window – the frame – has listened to the information given by the sizer, and adapted its size boundaries to the sizer area:

Sizer proportions

So, lets go back to where we add the buttons to the sizer, and add some information there. Change the lines…

        sizer.add(btnBig);
        sizer.add(btnTiny);

…to:

        sizer.add(btnBig,  1);
        sizer.add(btnTiny, 3);

After compilation, you will see something like this:

By using the second parameter in the sizer.add() method – proportion:Int – we’re  telling the sizer to keep the vertical proportions of our two buttons to 1:3. If you resize the window, you can see how the sizer adapts the size of the buttons to keep these 1:3 proportions:

Try altering the proportion values, and notice the corresponding sizing behavour after compiling!

What if you want a component to keep its original size, while the ohers are adjusted? Then set the proportion value to zero:

        sizer.add(btnBig,  0); // <-- Keeps original size!
        sizer.add(btnTiny, 3); // <-- Resizes

Very useful for textfields etc where a proportional resize would look very strange.

Alignment and borders with sizer flags

Now time for the third parameter in Sizer.add method: the flag parameter. The wx.Sizer class defines flag constants that we can combine to alter the sizer behaviour. Try changing the btnTiny instantiation line to the following…

        sizer.add(btnTiny, 3, wx.Sizer.ALIGN_RIGHT);

…and to this:

        sizer.add(btnTiny, 3, wx.Sizer.EXPAND);

The alignment/expand flag can be used in combination with border flags. If so, the fourth parameter defines the border size in pixels. Try the following:

        sizer.add(btnTiny, 3, wx.Sizer.EXPAND | wx.Sizer.BORDER_LEFT, 8);

or this one

        sizer.add(btnTiny, 3, wx.Sizer.EXPAND | wx.Sizer.BORDER_LEFT 
        | wx.Sizer.BORDER_TOP, 8);

If the border is to be used all around the component, we can use Sizer.BORDER_ALL flag for that:

        sizer.add(btnTiny, 3, wx.Sizer.EXPAND | wx.Sizer.BORDER_ALL, 8);

About these ads
Tagged:
Posted in: Haxe, Waxe