Although there are plenty of cross-platform widget systems, each brings
its own set of problems to the table, be it in terms of size,
appearance, simplicity, or behavior. Seeking as always to unify and
simplify systems, ENIGMA brings its own widget API to the table. This
document serves as its official specification.
Functions in this API will be defined under the wgt_
C-Namespace. All instantiation functions shall
return an integer by which the new widget can be identified.
Bear in mind that this is a pretty intertwined mess, and should be
regarded as such.
The wgt_window_create(w,h) shall
create an invisible window of a specified size. Windows can contain at
most one container or widget, as per the GTK design.
The widget API shall provide two container classes; dynamic and static.
The names describe their behavior in placement, not in allocation.
The dynamic container shall allow the user to specify a text-based
layout for widgets to be added. The layout is generated from a string
representing individually labeled cells. A cell is given dimensions
based on the smallest chain of adjacent labels. For example, consider
this string:
"AAAAAAAA#"
"AAAAAAAA#"
"BBBBCCCC#"
"BBBBDDEF"
Should a layout be constructed from that string, it would contain six
cells of progressively decreasing size, Cell 'A' being the largest,
cells 'E' and 'F' being smallest.
This layout has not been implemented in any widget system. The
Static layout class allows for absolute placement of any number of
additional widgets at absolute coordinates inside the layout.
Each widget shall provide a function to indicate the preferred size.
The following widgets shall be offered:
While many languages provide callback systems to handle widget presses,
EDL does not yet have this functionality, and is presently not
thread-safe. Until this changes, a purely static method of handling
widget events must be used. The widget system shall be responsible for
handling events at the C++ level and keeping track of their occurrence
until the EDL half can accept them through wrapper functions.
Each widget defines its own wrappers.
Menus shall be specified using three interfaces; simplified,
intermediate, and procedural. The former two formats shall accept a
single string specifying the entire contents of the menu. The latter
shall use functions to construct menus requiring stock images, or for
menu factories.
As in the GML specification, simplified menu strings contain only
plain-text items separated by the pipe character ("|"). An underscore
before a character denotes a shortcut. A single hyphen as an item name
indicates a separator. This standard is used by
show_menu().
Ex: "Item 1|Item 2|Item 3|-|Exit"
Similar to the 'Simplified' spec, Intermediate shall offer more menu
features using macros at the beginning or end of items. This standard is
used by show_menu_ext().
Ex: "Item 1|Item 2|Item 3|-|>Submenu|/Item 4|Item 5|\<|[]Checkbox
with Item 6|[*]Checked box for Item 7|-|()Radio with Item
8|(*)Ticked Radio with Item 9|Item 10"
It is unlikely that a procedural interface will actually be implemented
as no method has yet been determined for specifying icons or other
fancier menu resources that genuinely require such a format.
All widgets, including layout containers, shall be able to be tested for
existence using wgt_exists().
Each widget not offering its own size function may be assigned a
requested (but not forced, absolute) size using
wgt_set_size().
Any widget may be destroyed with
widget_destroy(wgt).
Windows shall be managed using layout managers, as in Java.
Presently, the only defined layout manager is Table.
As it is the only layout manager currently defined, a table layout is
created with the function
wgt_layout_create. This layout is
dynamically resizable--it will allocate space to widgets in the window
as needed to condense into the allotted space, and will calculate the
minimum required space to hold its children. This layout will not allow
the window to be reduced past that size.
This layout is planned. It does not yet exist and may never exists. The
plan for this layout is simply to allow the user to place all child
windows manually and size them accordingly.
A unified widget system became a necessary part of ENIGMA when Design
Mode was introduced in R3. The original, called
"Build Mode", utilized Win32API to create its own window. To allow this
to work on each platform without serious recoding, the system was
unified. Code for a replica of the original "Build Mode" layout is as
follows, using the new system:
To create the window (EDL/GML):
local int window = wgt_window_create(480, 96);
local int layout = wgt_layout_create(window,
"OOOOOOO#"
"PUXYWHS#"
"FRGGIIS"
, 2, 2);
local int cbbobj, bpause, bfreeze, bundo, bredo, bstop, tegx, tegy, tegw, tegh, cbgrid, cbiso;
wgt_layout_insert_widget(layout, "O", cbbobj = wgt_combobox_create("object0|object1|object2|cat|hat|box|wall|toilet|cloud|mushroom"));
wgt_layout_insert_widget(layout, "P", bpause = wgt_button_create("Pause"));
wgt_layout_insert_widget(layout, "F", bfreeze = wgt_button_create("Freeze"));
wgt_layout_insert_widget(layout, "U", bundo = wgt_button_create("Undo"));
wgt_layout_insert_widget(layout, "R", bredo = wgt_button_create("Redo"));
wgt_layout_insert_widget(layout, "X", tegx = wgt_textline_create("X",3));
wgt_layout_insert_widget(layout, "Y", tegy = wgt_textline_create("Y",3));
wgt_layout_insert_widget(layout, "W", tegw = wgt_textline_create("W",3));
wgt_layout_insert_widget(layout, "H", tegh = wgt_textline_create("H",3));
wgt_layout_insert_widget(layout, "G", cbgrid = wgt_checkbox_create("Grid"));
wgt_layout_insert_widget(layout, "I", cbiso = wgt_checkbox_create("Iso"));
wgt_layout_insert_widget(layout, "S", bstop = wgt_button_create("Stop"));
wgt_window_show(window);
local int i = 101;
To monitor the window:
if (!wgt_exists(window))
return 0;
if (wgt_button_get_pressed(bstop)) exit(0);
else if (wgt_button_get_pressed(bpause)) room_caption = "Color chose: " + string(get_color($FF0000));
else if (wgt_button_get_pressed(bfreeze)) room_caption = "Combobox selection: " + wgt_combobox_get_selected_text(cbbobj) + "["_+_string(wgt_combobox_get_selection(cbbobj))_+_"](" + string(wgt_combobox_get_selection(cbbobj)) + ")";
else if (wgt_button_get_pressed(bundo)) room_caption = "File chose: '"+get_open_filename("Images|*.png; *.jpg; *.jpeg; *.gif|Sources|*.c; *.cpp|Headers|*.h; *.hpp","tacos.png") + "'";
else if (wgt_button_get_pressed(bredo)) room_caption = "Menu result: " + string(show_menu_ext(32,32,"test|of|menus|-|>Project|/Save|Close|<|[]Checkbox|[*]Checked|-|()Radio|(*)Radiod|etc"));
else if (i++ > 100)
{
room_caption = string(wgt_checkbox_get_checked(cbgrid) ? "Drawing ":"Ignoring ")
+ (wgt_checkbox_get_checked(cbiso) ? "an isometric" : "a rectilinear")
+ " grid of size " + wgt_textline_get_text(tegx) + " * " + wgt_textline_get_text(tegy)
+ " starting at (" + wgt_textline_get_text(tegw) + ", " + wgt_textline_get_text(tegh) + ")"
;
i=101;
return 0;
} else return 0;
i = 0;