Commits

Jason McKesson  committed c8ff1d2

Added grid-based sizer support. Any container can use these.

  • Participants
  • Parent commits 4c1f39f

Comments (0)

Files changed (4)

File Docs/LuaGUI.xml

             <para>Container windows are windows that contain other windows. Containers can be nested
                 within other containers. Frame containers are container windows, but they cannot be
                 contained by any other container windows.</para>
-            <para>All container windows share a set of common attributes. These attributes define
-                how the windows they contain are arranged within the window.</para>
-            <para>Container elements can have an <literal>orient</literal> attribute. This attribute
-                defines the stacking direction of child windows of this container. It can be
-                        <quote><literal>horizontal</literal></quote> or
-                        <quote><literal>vertical</literal></quote>. If the orientation is
-                horizontal, then each child window will be placed left-to-right in this container,
-                in the order in which the windows appear in the XML file. If the orientation is
-                vertical, then each child will be stacked top-to-bottom, again in the order in which
-                the windows appear in the XML file. If this attribute is not present, then the
-                default is vertical.</para>
             <para>Unless otherwise noted, a container can contain any other container or control
                 element.</para>
             <para>Containers also count as controls; as such, they have all of the attributes that a
                 control can have.</para>
             <section>
+                <title>Child Arrangement</title>
+                <para>All container windows share a set of common attributes. These attributes
+                    define how the windows they contain are arranged within the window.</para>
+                <para>There are several sizing and positioning scheme that LuaGUI supports, based on
+                    wxWidget's sizers. The default is the box sizing scheme.</para>
+                <para>The box sizing scheme is controlled by the <literal>orient</literal>
+                    attribute. This attribute defines the stacking direction of child windows of
+                    this container. It can be <quote><literal>horizontal</literal></quote> or
+                            <quote><literal>vertical</literal></quote>. If the orientation is
+                    horizontal, then each child window will be placed left-to-right in this
+                    container, in the order in which the windows appear in the XML file. If the
+                    orientation is vertical, then each child will be stacked top-to-bottom, again in
+                    the order in which the windows appear in the XML file. If this attribute is not
+                    present, then the default is vertical.</para>
+                <para>Another arrangement scheme is the grid arrangement scheme. This arrangement is
+                    active if either the <literal>numCols</literal> or <literal>numRows</literal>
+                    scheme is present. Both can be present. The way it works is that the container's
+                    children are arranged in a grid. The number of columns in the grid is set by the
+                        <literal>numCols</literal> attribute, and the number of rows is set by the
+                        <literal>numRows</literal> attribute. If one of these is not set, or is set
+                    to zero, then the container can have any number of that attribute.</para>
+                <para>For example, if you set the container to have 4 columns, and it has 7
+                    children, then it will automatically have 2 rows. If you set the container to
+                    have 2 rows, and it has 5 children, then it will have 3 columns.</para>
+                <para>The entries in the grid are always filled in row-major order. That is, if you
+                    have a 2x3 grid, the second child will be in the first row, second column. The
+                    fourth child will be in the second row, first column. And so on.</para>
+                <para>A gap can be added between the columns and rows. The <literal>hGap</literal>
+                    attribute specifies the number of pixels between columns, while the
+                        <literal>vGap</literal> attribute specifies the number of pixels between
+                    rows.</para>
+                <para>The area given to each control can be portioned in one of two ways. The
+                    default way is to let each column and row be independent of each other. The
+                    width of any column is the largest width of any item in the column. And the
+                    height of a row is the largest height of any item in the row.</para>
+                <para>The other way is specified by setting the attribute
+                        <literal>fixedGrid</literal> to <quote><literal>true</literal></quote>. When
+                    this happens, the width of any column becomes the largest width of
+                        <emphasis>any</emphasis> item in the grid, regardless of what column it is.
+                    The same goes for rows. This means that each control gets as much space as the
+                    largest control, and the space for every cell in the grid is the same.</para>
+                <para>You cannot use box and grid sizing attributes on the same element.</para>
+            </section>
+            <section>
                 <title>Tabs</title>
                 <para>Tabs containers are defined by the <classname>tabs</classname> element. These
                     represent a series of windows, all of the same size, that take up the same area
             <section>
                 <title>User Defined</title>
                 <para>While this is a certainly usable subset of controls, it is not all of the
-                    controls in wxWindows. You can insert any element at the control level, as long
-                    as it has a <literal>script</literal> attribute. This attribute is a Lua chunk
-                    that will create the window, returning it. The parameters received by this
-                    function are in the script file. Because this is a low-level function, you will
-                    need to be familiar with how the LuaGUI script works. This will not be detailed
-                    in this file.</para>
+                    controls in wxWindows. You can insert an element named
+                        <classname>luacontrol</classname> at the control level. It must have a
+                        <literal>script</literal> attribute. This attribute is a Lua chunk that will
+                    create the window, returning it. The <classname>luacontrol</classname> element
+                    can have any attributes, and it can have any child control elements (including
+                    other <classname>luacontrol</classname> elements).</para>
+                <para>The parameters received by this function are in the script file. Because this
+                    is a low-level function, you will need to be familiar with how the LuaGUI script
+                    works. Due to the fluid nature of this feature, the specific parameters and
+                    their use will not be detailed in this documentation.</para>
             </section>
         </section>
         <section>
             <title>Window Layout and Layout Attributes</title>
-            <para>The <literal>orient</literal> attribute defines the layout direction of a
-                container control. A container that has a horizontal layout means that the controls
-                are stacked left-to-right. This also means that the height of this container will be
-                the height of the highest control in that container. The width of the container will
-                be the <emphasis>sum</emphasis> of the widths of the controls. The same goes for
-                vertical layout: the width is the width of the widest control, and the height is the
-                sum of the heights of the control.</para>
-            <para>Thus, the orientation defines one dimension that is the stacking direction and one
-                is the fixed direction. For a horizontal layout, the stacking direction is
-                left-to-right; for a vertical layout, this is top-to-bottom. The stacking direction
-                is also called the <glossterm>progression direction</glossterm></para>
+            <para>When doing layout, every window has a minimum size. This represents the smallest
+                size that the window needs. The layout system can give it more room than this, but
+                it will almost always give it at least this much room.</para>
+            <para>Depending on the layout scheme, a control can be assigned more than this room.
+                This room is called the <glossterm>available area</glossterm> for the control. The
+                layout attributes specify how to use this extra room.</para>
+            <para>When doing box layout, the system tries to tightly pack the attributes together in
+                the stacking direction. The stacking direction can be called the
+                    <glossterm>progression direction</glossterm>. The other direction is the fixed
+                direction. In a horizontal orientation, controls are stacked left-to-right. So the
+                left and right direction is the progression direction, and up/down is the fixed
+                direction. Vice-versa for vertical orientations.</para>
+            <para>The available area in the progression direction is always the minimum size the
+                control asks for, plus any padding. Thus, layout attributes that affect the
+                control's position within the available area in this direction have no visual
+                effect. However, the available area in the fixed direction is the size of the
+                largest control in that direction (or the size of the parent's area, whichever comes
+                first). So attributes that affect the control's position in this direction can have
+                an affect.</para>
+            <para>Grid layout works a bit differently. There is no progression direction or fixed
+                direction, even though it can seem that way by specifying only the number of columns
+                or rows. Instead, the available area for a control is based on the minimum sizes
+                (plus padding) for each control horizontally or vertically. Thus, it is possible for
+                a control to be smaller in both the horizontal and vertical direction in a
+                grid.</para>
             <para>Every non-frame window can have a number of layout attributes. These define
                 spacing, size, and how the size of controls react to the size of other controls in
                 the container.</para>
                     </glossdef>
                 </glossentry>
                 <glossentry>
-                    <glossterm>align</glossterm>
+                    <glossterm>align, halign</glossterm>
                     <glossdef>
-                        <para>This defines the position of the control in the fixed direction of the
-                            parent. The control can be anchored to one of the sides in the fixed
-                            direction, or centered.</para>
+                        <para>This defines the position of the control horizontally relative to the
+                            available area. The control can be anchored to one of the sides or
+                            centered horizontally.</para>
                         <para>If this value is <quote><literal>left</literal>,</quote> then the
-                            control is anchored to the left side of a vertical layout, or the top
-                            side of a horizontal layout. If this value is
+                            control is anchored to the left side. If this value is
                                     <quote><literal>right</literal></quote>, then the control is
-                            anchored to the right side of a vertical layout. If this value is
+                            anchored to the right side. If this value is
                                     <quote><literal>center</literal></quote>, then the control will
-                            be placed in the center of the vertical or horizontal layout.</para>
+                            be placed in the center horizontally.</para>
+                        <para>Note that, when in a horizontal box layout, these flags will not do a
+                            great deal.</para>
                         <para>Optional. Defaults to left alignment</para>
                     </glossdef>
                 </glossentry>
                 <glossentry>
+                    <glossterm>valign</glossterm>
+                    <glossdef>
+                        <para>This defines the position of the control vertically relative to the
+                            available area. The control can be anchored to the top, bottom, or
+                            centered vertically.</para>
+                        <para>If this value is <quote><literal>top</literal>,</quote> then the
+                            control is anchored to the top of the available area. If this value is
+                                    <quote><literal>bottom</literal>,</quote> then the control is
+                            anchored to the bottom of the available area. If the value is
+                                    <quote><literal>center</literal>,</quote> then the control will
+                            be placed in the center vertically.</para>
+                        <para>Note that, when in a vertical box layout, these flags will not do a
+                            great deal.</para>
+                        <para>Optional. Defaults to top alignment.</para>
+                    </glossdef>
+                </glossentry>
+                <glossentry>
                     <glossterm>expand</glossterm>
                     <glossdef>
                         <para>If this is set to <quote><literal>true</literal>,</quote> then the
-                            control's size will be expanded to fill all of the available space in
-                            the fixed direction.</para>
-                        <para>This overrides the width or height attribute. It also makes
-                                <literal>align</literal> useless, since the control will be the
-                            width or height of the container.</para>
+                            control's size will be expanded to fill all of the available
+                            area.</para>
+                        <para>This overrides the width or height attribute. It also makes the
+                            alignment attributes useless, since the control will be the width and
+                            height of the available area.</para>
                         <para>If this is set to <quote><literal>false</literal>,</quote> then the
-                            control's width or height will be taken from the appropriate
-                            attribute.</para>
+                            control's width or height will be taken from the appropriate attribute,
+                            or from the automatic calculations if those attributes are not
+                            present..</para>
                         <para>Optional. Defaults to <quote><literal>false</literal>.</quote></para>
                     </glossdef>
                 </glossentry>
                 <glossentry>
                     <glossterm>proportion</glossterm>
                     <glossdef>
-                        <para>Where <literal>expand</literal> and <literal>align</literal> control
-                            the space and position that the control takes up in the fixed direction,
-                                <literal>proportion</literal> controls how much of the space in the
-                            progression direction is taken up by the control. This is an integer
-                            value relative to all other controls in this parent.</para>
+                        <para>This attribute controls how much of the space in the progression
+                            direction is taken up by the control. It only has a function when using
+                            box layout. This is an integer value relative to all other controls that
+                            are children of this parent.</para>
                         <para>If this value is 0, then the control will take up its minimum size in
                             the progression direction. If it is non-zero, then the amount of space
                             that is taken up depends on the proportion values of all of the controls
                             proportion values (0, 1, 3, 0, 1), then the system guarantees that the
                             middle control will be 3x as big as the second and fifth controls. How
                             big they are relative to the two 0 proportions is not guaranteed.</para>
+                        <para>Thus, if you want a single control to take up all of the space left
+                            over, simply set its proportion to 1, and leave the others to the
+                            default of 0.</para>
                         <para>Remember: all of the controls with non-zero proportions will expand
                             and shrink with respect to the direct parent
                             <emphasis>only</emphasis>.</para>

File Docs/luagui.rnc

         
     lg.sizer =
         ## A container for controls that has no visuals for it.
-        element sizer { lg.sizer.attlist, lg.windows* }
+        element sizer { lg.sizer.elem.attlist, lg.windows* }
         
     lg.box =
         ## Creates a named box that has a border around it. Used to group controls.
         
     lg.controls =
         lg.button | lg.spacer | lg.checkbox | lg.checkbox3 | lg.static | lg.radiobuttons | lg.editbox |
-        lg.spinner | lg.slider | lg.listbox | lg.dropdown | lg.userdefined_control
+        lg.spinner | lg.slider | lg.listbox | lg.dropdown | lg.luacontrol
     
     lg.button =
         ## Creates a simple text button control.
         ## Creates a no button in the dialog panel.
         element no { lg.dialog.panel.btn.attlist }
 
-    lg.userdefined_control =
+    lg.luacontrol =
         ## Arbitrary controls that are defined by Lua functions.
-        element * { attribute script { lg.luafunction } }
+        element luacontrol
+        {
+            attribute script { lg.luafunction },
+            (attribute * - script {text})*,
+            lg.controls*
+        }
 }
 
 
     lg.frame.menubar.attlist = empty
     
     lg.menubar.menu.attlist =
-        lg.menu.name.attribute
-        lg.tip.attribute?,
+        lg.menu.name.attribute,
+        lg.tip.attribute?
     
     lg.menuitem.attlist =
         lg.menuitem.name.attribute,
     lg.collpane.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.text.attribute?,
         lg.collpane.collapsed.attribute?,
-        lg.orient.attribute?
+        lg.sizer.attlist
     
-    lg.sizer.attlist =
+    lg.sizer.elem.attlist =
         lg.size,
-        lg.sizing.attlist,
-        lg.orient.attribute?
+        lg.positioning.attlist,
+        lg.sizer.attlist
     
     lg.panel.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
-        lg.orient.attribute?,
+        lg.positioning.attlist,
+        lg.sizer.attlist,
         lg.aui.attlist
     
     lg.toolbar.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
-        lg.orient.attribute?,
+        lg.positioning.attlist,
+        lg.sizer.attlist,
         lg.aui.toolbar.attlist,
         lg.gripper.attribute?
     
         lg.text.attribute,
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.orient.attribute?
     
     lg.tab.attlist =
         lg.text.attribute,
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
-        lg.orient.attribute?
+        lg.positioning.attlist,
+        lg.sizer.attlist
     
     lg.tabs.attlist =
         lg.id.attribute?,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.tabs.onselchanged.attribute
         
     lg.button.attlist =
         lg.text.attribute,
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.button.enabled.attribute?,
         lg.button.action.attribute?
     
     lg.checkbox.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.text.attribute,
         lg.checkbox.default.attribute?,
         lg.checkbox.oncheck.attribute?,
     lg.checkbox3.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.text.attribute,
         lg.checkbox3.default.attribute?,
         lg.checkbox3.user.attribute?,
         lg.text.attribute,
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist
+        lg.positioning.attlist
     
     lg.radiobuttons.attlist =
         lg.orient.attribute?,
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.text.attribute,
         lg.radiobuttons.default.attribute?,
         lg.radiobuttons.action.attribute?
     lg.editbox.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.label.attlist,
         lg.editbox.multiline.attribute?,
         lg.editbox.readonly.attribute?,
     lg.spinner.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.label.attlist,
         lg.spinner.min.attribute?,
         lg.spinner.max.attribute?,
     lg.slider.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.label.attlist,
         lg.slider.min.attribute?,
         lg.slider.max.attribute?,
     lg.listbox.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.listbox.type.attribute?,
         lg.listbox.sort.attribute?,
         lg.listbox.oncreate.attribute?,
     lg.dropdown.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist,
+        lg.positioning.attlist,
         lg.label.attlist,
         lg.dropdown.sort.attribute?,
         lg.dropdown.oncreate.attribute?,
         lg.dropdown.onselchange.attribute?
     
-    lg.sizing.attlist =
-        lg.sizing.align.attribute?,
-        lg.sizing.expand.attribute?,
-        lg.sizing.proportion.attribute?,
-        (lg.sizing.border.attribute | lg.sizing.vborder.attribute | lg.sizing.hborder.attribute)?
+    lg.positioning.attlist =
+        (lg.positioning.align.attribute | lg.positioning.halign.attribute)?,
+        lg.positioning.valign.attribute?,
+        lg.positioning.expand.attribute?,
+        lg.positioning.proportion.attribute?,
+        (lg.positioning.border.attribute | lg.positioning.vborder.attribute | lg.positioning.hborder.attribute)?
+        
+    lg.sizer.attlist =
+        (
+            (
+                lg.gridsizer.numCols.attribute |
+                lg.gridsizer.numRows.attribute |
+                (lg.gridsizer.numCols.attribute, lg.gridsizer.numRows.attribute)),
+            lg.gridsizer.hGap.attribute?,
+            lg.gridsizer.vGap.attribute?,
+            lg.gridsizer.fixedGrid.attribute?)  |
+        (lg.orient.attribute?)
     
     lg.aui.attlist =
         lg.aui.title.attribute?,
     lg.std.control.attlist =
         lg.std.window.attlist,
         lg.size,
-        lg.sizing.attlist
+        lg.positioning.attlist
     
     lg.size =
         (lg.width.attribute?, lg.height.attribute?)
         lg.id.attribute,
         lg.resizeable.attribute?,
         lg.size,
-        lg.orient.attribute?
+        lg.sizer.attlist
 
     lg.dialog.panel.attlist =
-        lg.sizing.attlist
+        lg.positioning.attlist
 
     lg.dialog.panel.btn.attlist =
         lg.dialog.panel.script.attribute?
         ## wxNotebookEvent object as a parameter.
         attribute onselchanged { lg.luafunction }
     
-    lg.sizing.align.attribute =
+    lg.positioning.align.attribute =
         ## The alignment relative to the containing window/sizer.
         attribute align { "left" | "right" | "center" }
+        
+    lg.positioning.halign.attribute =
+        ## The horizontal alignment relative to the containing area.
+        attribute halign { "left" | "right" | "center" }
     
-    lg.sizing.expand.attribute =
+    lg.positioning.valign.attribute =
+        ## The vertical alignment relative to the containing area.
+        attribute valign { "top" | "bottom" | "center" }
+        
+
+    
+    lg.positioning.expand.attribute =
         ## If true, the size of the control will be expanded to fit the available space
         ## in the fixed direction.
         [ a:defaultValue = "false"]
         attribute expand { lg.data.boolean }
     
-    lg.sizing.proportion.attribute =
+    lg.positioning.proportion.attribute =
         ## Overrides the size in the progression direction when non-zero. If non-zero, then the progression
         ## direction size will be proportional to all other controls in this sizer. A value of 3
         ## will be 3x larger than those with a value of 1.
         ## is specified.
         attribute proportion { xsd:nonNegativeInteger }
     
-    lg.sizing.border.attribute =
+    lg.positioning.border.attribute =
         ## The size of the border around this control on all 4 sides.
         attribute border { xsd:nonNegativeInteger }
     
-    lg.sizing.vborder.attribute =
+    lg.positioning.vborder.attribute =
         ## The size of the border around this control on the top and bottom sides.
         attribute vborder { xsd:nonNegativeInteger }
     
-    lg.sizing.hborder.attribute =
+    lg.positioning.hborder.attribute =
         ## The size of the border around this control on the left and right sides.
         attribute hborder { xsd:nonNegativeInteger }
     
         [ a:defaultValue = "vertical" ]
         attribute orient { "horizontal" | "vertical" }
         
+    lg.gridsizer.numCols.attribute =
+        ## This represents the number of columns in a grid sizer. The presents of this
+        ## attribute means that the sizer used for child windows will be a grid sizer
+        ## with this many columns.
+        attribute numCols { xsd:nonNegativeInteger }
+        
+    lg.gridsizer.numRows.attribute =
+        ## The number of rows in a grid sizer.
+        [ a:defaultValue = "0" ]
+        attribute numRows { xsd:nonNegativeInteger }
+        
+    lg.gridsizer.hGap.attribute =
+        ## The gap, in pixels, between two adjacent columns of a grid sizer.
+        [ a:defaultValue = "0" ]
+        attribute hGap { xsd:nonNegativeInteger }
+        
+    lg.gridsizer.vGap.attribute =
+        ## The gap, in pixels, between two adjacent rows of a grid sizzer.
+        [ a:defaultValue = "0" ]
+        attribute vGap { xsd:nonNegativeInteger }
+        
+    lg.gridsizer.fixedGrid.attribute =
+        ## If true, then the grid sizer's entries will be of a fixed size. All grid items will
+        ## have the same width and height.
+        [ a:defaultValue = "false"]
+        attribute fixedGrid { lg.data.boolean }
+
+        
     lg.id.attribute =
         ## The identifier of the control. This identifier allows the user to find a particular
         ## control in script code. The return value of "wndlua.ParseFile" has an "idWnds" field.

File Testing/LuaGuiTest.xml

                 <checkbox border="2" text="See" default="true"/>
             </sizer>
         </toolbar>
-        <toolbar expand="true" gripper="false" proportion="0" height="100" direction="top" row="1">
-            <sizer orient="horizontal" expand="true">
-                <sizer orient="vertical" expand="true" border="3" width="100">
-                    <checkbox border="2" text="Param 1" default="true"/>
-                    <checkbox border="2" text="Param 2" default="true"/>
-                    <checkbox border="2" text="Param 3" default="true"/>
-                </sizer>
-                <sizer orient="vertical" expand="true" border="3" width="100">
-                    <checkbox border="2" text="Test Checkbox" oncheck='print("Checked!")' onuncheck='print("Unchecked!")'/>
-                    <checkbox border="2" text="Look" default="true"/>
-                    <checkbox border="2" text="See" default="true"/>
-                </sizer>
-            </sizer>
+        <toolbar expand="true" gripper="false" proportion="1" orient="vertical" height="100" direction="top" row="1">
+            <checkbox border="2" text="Param 1" default="true" align="center" proportion="1"/>
+            <checkbox border="2" text="Param 2" default="true"/>
+            <checkbox border="2" text="Param 3" default="true"/>
+            <checkbox border="2" text="Test Checkbox" oncheck='print("Checked!")' onuncheck='print("Unchecked!")'/>
+            <checkbox border="2" text="Look" default="true"/>
+            <checkbox border="2" text="See" default="true"/>
         </toolbar>
     </frame>
     <dialog id="dialog" title="Test Dialog" orient="vertical">

File Tools/LuaGUI.lua

 	return size;
 end
 
-local function GetSizerOrientation(currNode)
+local function GetBoxSizerOrientation(currNode)
 	local orientation = currNode:GetPropVal("orient", "vertical");
 	if(orientation == "horizontal") then
 		return wx.wxHORIZONTAL;
 	return orientation;
 end
 
-local function CreateDefaultSizer(currNode)
-	return wx.wxBoxSizer(GetSizerOrientation(currNode));
+local function CreateStandardSizer(currNode)
+	if(currNode:HasProp("numCols") or currNode:HasProp("numRows")) then
+		local bFixed = GetNodeBoolProp(currNode, "fixedGrid", false);
+		local numColumns = tonumber(currNode:GetPropVal("numCols", "0"));
+		local numRows = tonumber(currNode:GetPropVal("numRows", "0"));
+		local hGap = tonumber(currNode:GetPropVal("hGap", "0"));
+		local vGap = tonumber(currNode:GetPropVal("vGap", "0"));
+		
+		if(bFixed) then
+			return wx.wxGridSizer(numRows, numColumns, vGap, hGap);
+		else
+			return wx.wxFlexGridSizer(numRows, numColumns, vGap, hGap);
+		end
+	else
+		return wx.wxBoxSizer(GetBoxSizerOrientation(currNode));
+	end
 end
 
+local horizontalAlignmentFlags =
+{
+	left = wx.wxALIGN_LEFT,
+	right = wx.wxALIGN_RIGHT,
+	center = wx.wxALIGN_CENTER_HORIZONTAL,
+}
+
+local verticalAlignmentFlags =
+{
+	top = wx.wxALIGN_TOP,
+	bottom = wx.wxALIGN_BOTTOM,
+	center = wx.wxALIGN_CENTER_VERTICAL,
+}
+
 local function GetSizerFlags(currNode)
 	local flags = 0;
 	local border = 0;
 	local proportioned = 0;
 	local bHasProp, prop = currNode:GetPropVal("align");
 	if(bHasProp) then
-		if(prop == "left") then flags = flags + wx.wxALIGN_LEFT end;
-		if(prop == "right") then flags = flags + wx.wxALIGN_RIGHT end;
-		if(prop == "center") then flags = flags + wx.wxALIGN_CENTER end;
+		if(horizontalAlignmentFlags[prop]) then
+			flags = flags + horizontalAlignmentFlags[prop];
+		end
+	else
+		bHasProp, prop = currNode:GetPropVal("halign");
+		if(horizontalAlignmentFlags[prop]) then
+			flags = flags + horizontalAlignmentFlags[prop];
+		end
+	end
+
+	bHasProp, prop = currNode:GetPropVal("valign");
+	if(verticalAlignmentFlags[prop]) then
+		flags = flags + verticalAlignmentFlags[prop];
 	end
 	
 	if(GetNodeBoolProp(currNode, "expand", false)) then
 					local UserFunc = loadstring(script);
 					assert(type(UserFunc) == "function", "The user-defined function could not be compiled.");
 					local retWnd = UserFunc(parWnd, sizer, nextNode, notebook, auiNotebook,
-						ParseChildrenWithCallback);
+						{
+							["ParseChildrenWithCallback"] = ParseChildrenWithCallback,
+							["AddToSizer"] = AddToSizer,
+							["FinalizeControl"] = FinalizeControl,
+							["GetNodeSize"] = GetNodeSize,
+							["CreateStandardSizer"] = CreateStandardSizer,
+						});
 					if(ChildFunc) then ChildFunc(retWnd, nextNode) end;
 				end
 			end
 	
 	mainWnds[#mainWnds + 1] = wndData;
 	
-	frameWnd:SetSizer(CreateDefaultSizer(currNode));
+	frameWnd:SetSizer(CreateStandardSizer(currNode));
 	
 	frameWnd:Hide();
 	
 		currNode:GetPropVal("title", "Dialog"), wx.wxDefaultPosition,
 		GetNodeSize(currNode), style);
 
-	dialog:SetSizer(CreateDefaultSizer(currNode))
+	dialog:SetSizer(CreateStandardSizer(currNode))
 	
 	local bHasProp, wndId = currNode:GetPropVal("id");
 	
 
 function elementJumpTable.toolbar(parWnd, sizer, currNode, notebook, auiNotebook)
 	local size = GetNodeSize(currNode);
-	local mySizer = CreateDefaultSizer(currNode);
+	local mySizer = CreateStandardSizer(currNode);
 	mySizer:SetMinSize(size);
 	
 	local panel = wx.wxPanel(parWnd, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize,
 elementJumpTable.panel = elementJumpTable["toolbar"];
 
 function elementJumpTable.box(parWnd, sizer, currNode, notebook, auiNotebook)
-	local orient = GetSizerOrientation(currNode);
+	local orient = GetBoxSizerOrientation(currNode);
 	local size = GetNodeSize(currNode);
 	local staticBox = wx.wxStaticBox(parWnd, wx.wxID_ANY,
 		currNode:GetPropVal("text", "Box With No Name"), wx.wxDefaultPosition, size);
 		currNode:GetPropVal("text", "CP with no name"), wx.wxDefaultPosition, size,
 		bit.bor(wx.wxCP_DEFAULT_STYLE, 2)); --2 means wxCP_NO_TLW_RESIZE, which wxLua doesn't expose.
 		
-	local mySizer = CreateDefaultSizer(currNode);
+	local mySizer = CreateStandardSizer(currNode);
 --	mySizer:SetMinSize(size);
 	collpane:GetPane():SetSizer(mySizer);
 		
 
 function elementJumpTable.sizer(parWnd, sizer, currNode, notebook, auiNotebook)
 	local size = GetNodeSize(currNode);
-	local box = CreateDefaultSizer(currNode);
-	box:SetMinSize(size);
+	local newSizer = CreateStandardSizer(currNode);
+	newSizer:SetMinSize(size);
 
-	ParseChildrenWithCallback(parWnd, box, currNode, notebook, auiNotebook, nil);
+	ParseChildrenWithCallback(parWnd, newSizer, currNode, notebook, auiNotebook, nil);
 	
-	AddToSizer(currNode, box, sizer);
+	AddToSizer(currNode, newSizer, sizer);
 
 	return nil;
 end
 	local size = GetNodeSize(currNode);
 	local page = wx.wxPanel(parWnd, wx.wxID_ANY, wx.wxDefaultPosition, size,
 		wx.wxTAB_TRAVERSAL + wx.wxNO_BORDER);
-	page:SetSizer(CreateDefaultSizer(currNode));
+	page:SetSizer(CreateStandardSizer(currNode));
 
 	ParseChildrenWithCallback(page, page:GetSizer(), currNode, nil, nil, nil);
 	
 
 
 function elementJumpTable.radiobuttons(parWnd, sizer, currNode, notebook, auiNotebook)
-	local orientation = GetSizerOrientation(currNode);
+	local orientation = GetBoxSizerOrientation(currNode);
 	
 	if(orientation == wx.wxHORIZONTAL) then
 		orientation = wx.wxRA_SPECIFY_ROWS