Chapter 2: Window and Widget Sizing



2.1: Introduction

One of the most critical aspects of implementing a GUI is directing the sizes of the widgets. Following a brute-force approach, it is certainly possible to numerically specify exact fixed locations (such as may be expected from a builder), but the surprising flexibility of the EW/WDS (Lewd) system allows for much more elegant and fluid interfaces.


First we will start with explicit location specification and move on to several automated mechanisms.



2.2: Normal Sizing



2.2.1: SetGeometry()

The primary specification of size and location is through the function EW_Node::SetGeometry(long x,long y,long w,long h). EW_Node is inherited by EW_Window and EW_Widget. Remember that WDS requires that you use the derived WDS_Widget instead of EW_Widget, so we may refer to it directly.


Any node geometry can be set with SetGeometry(), but the geometry can be altered by many mechanisms that will be described. An EW_Window is specified relative to the lower-left corner of the screen. An EW_Widget is specified relative to its parent node, either a window or widget. Widgets are arranged in a hierarchy. Each widget may have 0 or 1 parents and 0 or more children. Widgets that do not have a chain of ancestors that reach to a window (and, from such, an event context) cannot receive events and cannot be drawn without subverting the standard event processing mechanism.


Without any additional factors each widget is drawn and operated on relative to its parent node and with the size given.



2.2.2: Resize()

In addition to EW_Node, EW_Widget inherits from EW_SizeConstraints. This class provides a minimum, maximum, and preferred size in the X and Y dimensions. A size less than 0 (by convention: -1) indicates "don't care". These values are used when the widget is given the opportunity to resize.


After an event is processed, widgets are given the opportunity to resize themselves and to direct their children to resize.


Only in rare cases do parents forcefully resize their children using SetGeometry(). Instead, they use a EW_Resize object which also inherits from EW_SizeConstraints.


The parent can set these values to tell the child what size it would like. The child uses these values along with its own. Although, a widget's virtual Resize() is free to do what it wants, Resize() functions generally call EW_Widget::CheckSize(EW_Resize *resize) which goes through the following procedure (excluding some additional mechanisms to be mentioned later):



This procedure is independent in the X and Y dimensions.





2.3: Bounding

The function EW_Widget::SetBounds(long dir,long set) allows some deviations from the basic Checksize() mechanism.


The bound EW_BOUNDS_USE_MAX directs the mechanism to use the maximum given by the resize from the parent. It is rarely, if ever, used at this time.


The bound EW_BOUNDS_FILL_PARENT directs the mechanism to use the size of the parent. This only really makes sense if the parent is a borderless widget and this is the only child, such as within a scope.


The bound EW_BOUNDS_IGNORE_PARENT directs the mechanism to ignore the maximum and preferred sizes from the parent's resize. This is very useful for widgets that are set manually, such as a WDS_Button or WDS_GetString. Several widgets in WDS such as these, set this flag by default.



2.4: Widget Auto-sizing (from self)

Many widgets can determine their size by their specific contents and the context in which they exist. This is generally only applicable to widgets who do not normally have children, such as buttons, get-strings, and pick-lists.


You can specify auto-sizing in the X and Y dimensions independently using WDS_Widget::SetGeneralFlags(). The mechanism uses the border style, label, and annotation to determine the size. Not that this setting can optionally affect the min and max size in addition to just the pref size. For example, auto-sizing widgets in a partition should probably use the setting that also affects min and max size since the partition recognizes that as an indicator that the size is fixed. But, widgets in a form using uniformity may not wish to alter the min and max sizes since it would defeat the uniformity.



2.5: Node Auto-sizing (from children)

Nodes (widgets and windows both) have the ability to auto-size based on their children. You can specify auto-sizing in the X and Y dimensions independently using EW_Node::SetNodeSizing(). The size of the node is determined by the extent of its children.


WDS_Form has its own child-based sizing mechanism, so it should not use node auto-sizing.


WDS_Partition should not use node auto-sizing along its direction of partitioning. If the children are all fixed in size, the partition will already size itself to fit the children. There is no conflict with node auto-sizing in the non-partitioning direction.


Note that due to limitations of many window managers, it is recommended that window-type nodes should always have the same setting in both directions. Stated differently, a window should auto-size in both directions or neither direction, never just vertically or just horizontally.


Note also the node auto-sizing provides a concept to build an interface by pushing space requirements up the hierarchy instead of using available space that trickles down the hierarchy. One result is that window sizes can be only as large as required.


Auto-sized windows are not resizable using the interactive operations of the window manager.


Care should be taken when using muliple types of auto-sizing in a hierarchy. For example, if a child expects to get a size from a parent who tries to size around that child, there is no stable resolution. This usually results in rapidly flashing interfaces or widgets that move on their own.



2.6: Form Auto-sizing

WDS_Form has its own independent mechanism to size based on the children. Using WDS_Form:SetSizing(dir,WDS_SIZING_FIT_CHILDREN) for dir of EW_HORIZONTAL or EW_VERTICAL can set this flag for either or both dimensions.


WDS_Form's mechanism is much more useful in its particular needs since it is also closely concerned with placing its children.



2.7: Form-based Centering and Uniformity

WDS_Form has the capability of repositioning it children to its center.


WDS_Form can also instigate all its children to have the same size using its uniformity capability. This is done by giving a resize minimum equal to the largest dimension(s) of its children. Note that a resize minimum is not blocked by a bound of EW_BOUNDS_IGNORE_PARENT.