FreshLib GUI templates
The GUI library in FreshLib (later FreshGUI) is OOP based and is designed to be portable across supported platforms.
The library is still not suitable for production, because misses enough features, but the API seems to be pretty stable, so I will try to incrementally document it in this article.
1. The templates
The templates engine of FreshGUI allows description of the GUI widget hierarchies in design time, combined with flexible assigning of the GUI objects parameters.
The base of the template is the macro ObjTemplate
defined following way:
macro ObjTemplate flags, class, name, [idparam] {
....
}
The parameters of the macro are:
flags
- contains some of the following flags, combined with OR: tfEnd, tfParent, tfChild;
tfParent
indicates that the next ObjTemplate definition will be the first of the children for the given element.
tfEnd
indicates that this element is the last child for its parent.
tfChild
indicates that this element is a child of its parent. Default value, can be ommited.
class
is the GUI element class. Must be descendant of TWindow in order to be handled properly by the templates engine.
name
the name of the GUI control (window). Can be NONE or some label name, existing or not. If the value is NONE, no variable is created.
If the label already exists, it is assumed that it points to dword variable and the created object instance will be written there.
If the label does not exists, it will be created as a dword variable.
idparam
- zero or more object parameters assignments. The syntax is "param_name = param_value"
. The specified values will be assigned
to the object instance during the template creation.
The values can be following types:
Number - it is handled as a dword value and is assigned to the parameter directly.
String enclosed in quotes or generally every byte string, as defined in db
directive. If contains more than one element,
must be enclosed in angled brackets. For example <"first line", 13, 10, "second", 13, 10>
.
Such strings are defined inside the template and pointer to its beginning is assigned to the object parameter.
Address (label) enclosed in squre brackets: [label]
- the value of the parameter is extracted from this address during the object creation.
Notice, that in run-time, this variable must contains the proper value before creating the object instance from the template.
Here is one example of usage for the templates for creating the main window of the program (from "freshlib/test_code0/TestTVmain.asm", the project "freshlib/test_code0/TestTV.fpr"):
TemplateMainForm:
ObjTemplate tfParent or tfEnd, TForm, frmMain, \
x = 100, \
y = 50, \
width = 418, \
height = 250, \
OnCreate = FormOnCreate, \
OnClose = MainFormOnClose, \
OnDestroy = FormOnDestroy, \
SplitGrid = SplitTest, \
Caption = 'The new GUI toolkit test form.'
ObjTemplate tfChild, TEdit, editDir, \
Text = "/home", \
MarginLeft= 2, \
MarginRight= 2, \
OnCreate = EditOnCreate, \
SplitCell = SplitTest.cellEdit, \
Visible = TRUE
ObjTemplate tfChild, TButton, btnArrowRight, \
Icon = [iconArrowRight], \
IconPosition = iposCenter, \
SplitCell = SplitTest.cellButton, \
OnClick = ReadFolderClick, \
Visible = TRUE
ObjTemplate tfChild or tfEnd, TTreeView, tvFolders, \
SplitCell = SplitTest.cellTree, \
Visible = TRUE
This example creates the following window:
2. Split grids
In the above example, you can notice, that the coordinates and sizes of the children widgets are not set. This is because
the Window frmMain
have assigned a split grid - structure that handles the layout of the window and positions and resizes
the children elements automatically.
The parent window have the SplitGrid assigned to the parameter SplitGrid
and the children have SplitCell
parameter assigned with
the cell of the grid they have to reside.
Below is the definition of the split grid, from the same test example:
SplitStart SplitTest
Split stVert or stJustGap , 4, 24, 16, 48
Split stHoriz or stOriginBR or stJustGap, 4, 64, 48, 200
Cell cellEdit
Cell cellButton
Cell cellTree
SplitEnd
The SplitGrid is defined by dividing the window client area horizontally of vertically until the needed layout is fully defined.
The SplitGrid has two types of elements: Split
and Cell
.
The Split
element always has two children elements - left and right
(or top and bottom). Every of the children elements can be Split
or Cell
element.
The Cell
element has no children and only can contain and handle some GUI widget.
The used macros are defined following way:
macro SplitStart name {}
macro SplitEnd {}
macro Split type, width, pos, min, max {}
macro Cell name {}
The SplitStart
defines the name for the whole splitgrid.
The SplitEnd
ends the definition and check for consistency. If the structure is not consistents it fills the missing children with
empty cells. In this case, a compile time warning message will be displayed.
The Cell
defines a name for the widget cell. The name is defined as a local name of the split grid name. (See in the above example for examples).
The Split
parameters are the following:
type
- one or several (combined by OR) values of:
stHoriz
- default, can be omitted. The cell is splitted horizontally on left and right parts.
stVert
- the cell is split vertically on top and bottom parts.
stRelative
- the sizes of the parts are specified in relative units instead of absolute. One unit is 1/32768 of the whole.
The relatively sized cells will change its size proportionally when the parent cell resizes. In contrary, on sizing the parent, only
the one of the absolutely sized cells will change.
stOriginBR
- The size is specified for the right/bottom cell of the split. When not specified, the left/top parts are sized.
stJustGap
- The cell is split but not user resizeable. If not specified, a draggable splitter control is placed in the gap between the parts of the cell.
If specified, the control is not placed and the user can't drag it in order to resize the parts.
width
- The width of the gap between the cell parts. Can be empty or draggable splitter control (`stJustGap`).
pos
- the initial size of the left/top part of the rectangle. (If stOriginBR
is specified, this is the size of the right/bottom part).
The units are pixels, or relative units (`stRelative`);
min
, max
- specify the minimal and maximal size of the left/top part of the cell. (or right/bottom if stOriginBR
is specified).
The units are the same as for pos
parameter.
3. Creating windows from templates.
Once the template is created, the instance of the window is created by calling the procedure defined following way:
proc CreateFromTemplate, .ptrTemplate, .parent
Here is how it looks on the above example template:
stdcall CreateFromTemplate, TemplateMainForm, 0
Notice that the pointer to the main window is returned in EBX register.
Pointers to the all created windows are stored in the respective name
variables in the template.
At the end, here is how the example program looks in action (the example source is in the repository):
Last modified on: 11.09.2016 10:02:22