Form structure
The Hello world! example of the previous chapter follows the general structure of the form initialization code:
- Create an empty form:
form = simian.gui.Form()
- Add components to it from top to bottom:
- Create the component with default property values.
- Change property values of the component where necessary.
- Return a
struct
/dict
with aform
field that contains the form.- Optionally specify a
navbar
field to set thelogo
andtitle
of the application.
- Optionally specify a
Components are created by using:
comp = component.<name>(<key>, <parent>)
In this call:
name
is the name of any class incomponent
that is not theComponent
class. TheComponent
is an abstract superclass of all implemented components, so it cannot be used directly. For a full list of available components, see Components and subsections.key
is a unique string by which the component can be recognized. In MATLAB it must be a valid structure field name, which can be checked usingisvarname(<key>)
(Python does not have this restriction). In order to prevent unexpected behavior, it is advised to use globally unique component keys within the form.parent
is an optional parent to which the new component must be added. You can add the new component directly to the form just like in the Hello world! example. Alternatively, you could add the component to a parent component such as a panel or table. More information on nesting of components can be found in Component nesting.
You can choose to import the component
package to prevent having to use it for the creation of every single component. The syntax then becomes:
import simian.gui_v2_0_0.component.*
comp = <name>(<key>, <parent>);
from simian.gui.component import *
comp = <name>(<key>, <parent>)
There are over 35 different components that follow the same pattern. Each of these is described in the Components section and subsections.
Adding components from table
When each component is constructed individually, the code can quickly become very lengthy. In order to keep the overview, components can be specified in a MATLAB table or Pandas DataFrame (in Python) by using the utils.addComponentsFromTable
function. It takes two input arguments:
parent
: aForm
orComponent
that can have subcomponents (i.e. it has acomponents
property),table
: a MATLAB table or Pandas DataFrame.
It returns the created components in a struct/dict.
The table or DataFrame may have the following columns:
- key: Component key (mandatory). Must be a valid variable name and unique per level.
- type/class: Component type or class for creating the component (mandatory).
- level: Nesting level. Top level components (relative to parent) have level 1. Nested components, e.g. in a Panel, increment with 1. If the column is not present, all levels will be set to 1.
- options: Struct/dictionary with options, may contain any property that can be set to the component. Use
missing
/None
to leave unspecified. If the column is not present, all options will be set tomissing
/None
. Keys/fields 'defaultValue', 'label', 'tooltip', 'type', and 'key' are ignored, as these are columns of the table. - defaultValue: The default value for the component, must be of a valid data type for the component type. Use
missing
/None
to leave unspecified. If the column is not present, all default values will be set tomissing
/None
. - label: Label for the component. Use
missing
/None
to leave unspecified. If the column is not present, all labels will be set tomissing
/None
. - tooltip: Tooltip for the component. Use
missing
/None
to leave unspecified. If the column is not present, all tooltips will be set tomissing
/None
.
Although in general only components can be added to the table, there are some other type
/class
values that can be added:
- column for adding the actual columns to a
Columns
component. In the options, awidth
field with an integer value must be specified. The total of the column widths must add up to 12. - tab for adding the actual tabs to a
Tabs
component. The label will be shown on the tab. - tablerow for adding rows to a
Table
component. Can only be added to a Table. - tablecell for adding a
TableCell
to atablerow
. TheTableCell
can contain other components.
Validation, conditionals and logic can be added to the returned components as usual (see here), or they can be added via the options
struct/dict that is put in the table.
The struct/dict that is returned uses the keys specified in the table definition as fields/keys. If keys in the table are not unique, then only the last component with the non-unique key will be in the output.
Example
This example shows a simple form built using a table/DataFrame. It consists of a panel that is added to the form and four components that are added to the panel, using the level column. The options struct/dict is used for multiple components, further reducing the amount of code required for building the form.
function payload = guiInit(metaData)
form = Form();
componentStruct = createLayout(form);
fillColumn(componentStruct.left, "From");
fillColumn(componentStruct.right, "To");
payload.form = form;
end
function componentStruct = createLayout(form)
columnOptions.width = 6;
componentSpecs = {
% key class level options
"locations", "Columns", 1, missing
"left", "Column", 2, columnOptions
"right", "Column", 2, columnOptions
};
componentTable = cell2table(componentSpecs, 'VariableNames', ["key", "class", "level", "options"]);
componentStruct = utils.addComponentsFromTable(form, componentTable);
end
function fillColumn(column, label)
key = lower(label);
sharedOptions.labelPosition = "left-left";
componentSpecs = {
% key class level options defaultValue label
key + "Panel", "Panel", 1, missing, missing, label
key, "Container", 2, missing, missing, missing
"name", "TextField", 3, sharedOptions, "Breda", "Name"
"latitude", "Number", 3, sharedOptions, 51.5883621, "Latitude"
"longitude", "Number", 3, sharedOptions, 4.7760251, "Longitude"
};
componentTable = cell2table(componentSpecs, 'VariableNames', ["key", "class", "level", "options", "defaultValue", "label"]);
utils.addComponentsFromTable(column, componentTable);
end
def gui_init(_meta_data: dict) -> dict:
form = Form()
component_dict = _create_layout(form)
_fill_column(component_dict["left"], "From")
_fill_column(component_dict["right"], "To")
return {"form": form}
def _create_layout(form: Form) -> dict:
column_options = {"width": 6}
component_specs = [
# key class level options
[ "locations", "Columns", 1, None ],
[ "left", "Column", 2, column_options ],
[ "right", "Column", 2, column_options ],
]
component_table = DataFrame(
data=component_specs,
columns=["key", "class", "level", "options"],
dtype=object,
)
return utils.addComponentsFromTable(form, component_table)
def _fill_column(column: component.Columns, label: str) -> None:
key = label.lower()
shared_options = {"labelPosition": "left-left"}
component_specs = [
# key class level options defaultValue label
[ key + "Panel", "Panel", 1, None, None, label ],
[ key, "Container", 2, None, None, None ],
[ "name", "TextField", 3, shared_options, "Breda", "Name" ],
[ "latitude", "Number", 3, shared_options, 51.5883621, "Latitude" ],
[ "longitude", "Number", 3, shared_options, 4.7760251, "Longitude" ],
]
component_table = DataFrame(
data=component_specs,
columns=["key", "class", "level", "options", "defaultValue", "label"],
dtype=object,
)
utils.addComponentsFromTable(column, component_table)