# Goals and vision

Some people like to design UI using a powerful editor, some like to programmatically program UI. Both approaches have its benefits.

Our vision is to design UIs using a powerful, yet easy to use IDE that enables the developer to create complicated, sophisticated enterprise applications easily. SCADE IDE is very powerful for 1.0 version, and we are planing to improve it make and make it even more fun to develop with. We have tons of new features in mind, plus at the same time constantly improvement speed and usability of the existing features.

For those who like programmatic UI design, SCADE should also support this approach nicely. In this chapter, we describe how to _use only code_ to create a cross platform mobile apps with a nice UI. This demo is done using our IDE, but not using the page editor. I will come up with a Sublime tutorial as well, or perhaps someone who reads this likes to contribute a Sublime/Atom version of this tutorial.

# Learning goals

The reader shall learn how to create a hierarchy of containers and widgets to develop the app and how to configure the layout so that the containers and widgets render properly. The details for each widget are discussed in the specific user guide and not part of this guide.

Sourcecode

Please see the ** UgProgrammaticUIDev** project for the source code created in this chapter. See [Installing examples](🔗) for information on how to download the examples from https://github.com/scadedoc/UgExamples/tree/master/UgProgrammaticUIDev

# Basics

A few reminder for getting started quicker in the Swift editor:

  • To **search the class hierarchy**, type Command + Shift + T. Use case use * and ? as wildcards

  • To **inspect a class**, press COMMAND and hover over the class, press the link

  • A widget is always a container, but a container doesn't need to be a widget

  • Widgets are controls such as buttons, checkboxes, map controls etc.

# Recommendations

An understanding how components, different containers and visual elements interact and work with each other is extremely helpful for writing code. We would highly recommend to get familiar with the page editor before writing code for generating the UI.

# Hello World

  1. Create an empty new SCADE project and open the main.page.swift

  2. The following code adds a button and prints out text when pressed.

  3. It is **mandatory** to set the **layoutData** property using the **SCDLayoutGridData** class

  4. You append the elements you want to add to the **children** property


(Script tags will be stripped)


Always set layoutData attribute

The **most important thing to remember** is to always set the SCDLayoutGridData in the **layoutData** attribute for each widget. Without it, the **code will crash. **We will change the API in the near future and make the constructor require an argument of type SCDLayoutGridData going forward.

Make sure row and column are set correctly

Another issue we currently have if you define layoutData where the **row** and **column** exceeds the parent container, it will also crash silently. We address this soon.

## Button

SCADE supports the regular button, i.e. UIButton in iOS and android.widget.Button on Android. Creating the button is easy:

  • Use SCDWidgetsButton.create()

  • Set the button text (or a bitmap)

  • Set the handler to do something when the button is pressed



The variable e is of type **SCDWidgetsEvent** and has a variable **target**, which contains the reference to the object that caused the event.



Now lets configure SCDLayoutGridData to position the button in the middle of the screen. The SCDLayoutGridData will be discussed in detail later on, but for now, the code is pretty self explanatory.



Running the code, you will see the button nicely centered in the middle of the screen.

  • the **gridData.row = 0 **places the button into the first row

  • the layout manager renders both rows, but the second row is empty, therefore taking up no space

  • the button fully grabs the available space and is displayed as centered with the space available

(Script tags will be stripped)


# Understanding layout

Widgets are rendered within a container of a certain type. The following types determine the layout. Containers can be nested within each other (put one container within another).

Please also see [Layout Manager](🔗) for introduction into layout. This table gives an overview of all your layout types:

ViewClassComment
Grid layoutSCDWidgetsGridViewCreates an n x m matrix of cells. The height / width of each row and column depends on the width / height of its largest cell.
Horizontal layoutSCDWidgetsListViewArranges the elements of the container from left to right.
Vertical layoutSCDWidgetsRowViewArranges the elements of the container from top to botton.
XY LayoutSCDWidgetsXYViewExact positioning of widgets using (x,y). This view should be used for special cases, in general using the above three makes more sense and allows support on all devices, with the layout done be by layout manager.

## Steps for configuring layout

In order to correctly configure the layout of a widget/container, you follow these steps

  1. **Mandatory**. Set **layoutData** attribute to tell the layout manager how to render the widget within the parent

  2. Configure **layout** attribute to tell the layout manager how to render the children within the widget/container

  3. Set **column** and **row** attribute for each widget so that the layout manager knows where the widgets are placed.

  4. **Mandatory** Add the control to its parent using **parent.children.append**(<widget/container>) for the current control and **<currentControl>.children.append**(<widget/container>) for alll widgets you want to add to the widget.

## 1. Set layoutData with SCDLayoutGridData

The SCDLayoutGridData class is used to inform the layout manager about the behavior of the control within its parent container



The layout manager reads the layoutData property and uses it to position the control within the parent container.. Therefore, **it always needs to be set**. Introspecting the class using _Command + Hover + Click_, we see the main attributes:

AttributeValues******_******Description
columnIntThe column the widget is located in
rowIntThe row the widget is located in
horizontalAlignmentleft,center,rightThe position of the widget within its bounding box.
verticalAlignmenttop, middle, bottomThe position of the widget within its bounding box
isGrabHorizontalSpacetrue / falseShall the widget be greedy and occupy as much space as possible horizontally ?
isGrabVerticalSpacetrue / falseShall the widget be greedy and occupy as much space as possible vertically ?
widthConstraintwrap_content / match_parentMake the bounding box so that it wraps the widget (wrap_content) or maximize so that it makes use of the parent's space (match_parent)
heightConstraintwrap_content / match_parentMake the bounding box so that it wraps the widget (wrap_content) or maximize so that it makes use of the parent's space (match_parent)
isExcludetrue / **false** If the layout manager should exclude this widget when rendering the page. Default is false.

## 2. Setting layout

The **layout** attribute determines how the **children** are rendered within the container. In most cases, we use the **SCDLayoutGridLayout** class and all you need to do is to set the numbers of columns and rows used. Per default, rows == columns == 1. In this example, we configure the page to have a 2x1 matrix:



## 3. Setting row and column attribute

In order to tell the container where which widget is located, each widget has a row and column attribute as part of the SCDLayoutDataGrid structure that you need to set. The default is (0,0). You need to set this for all views (Grid, Horizontal, Vertical) but the XYView.

ViewAttribute to set
Grid viewSet both **row** and **column**
Horizontal viewSet **column** only
Vertical viewSet **row** only

For instance, we configured the **layoutData.row **attribute to be 0 in order to place the button into the first row.



## 4. Add controls to parent



## Mother of all containers - SCDWidgetsContainer

All these views are inherited from **SCDWidgetsContainer**. This class inherited a lot of behavior from some other classes.

AttributeValues******___******Description
isVisibletrue/falseIf the element is shown or not. If set to false, the element is not shown, **BUT** still part of the rendering logic. So for instance if you have a bitmap and set it to _isVisible = false_, the bitmap will not render BUT it will still occupy the space in the container.
isEnabledtrue / falseEnable or disable widget
layoutDataPossible values are _ SCDLayoutGridData _ SCDLayoutXYLayoutData**Mandatory**. Always needs to be set. Determines the layout of the container as part of a larger container, i.e how this container is positioned within its parent.
layoutPossible values are * SCDLayoutGridLayoutDetermines the layout of the children of the container, i.e. the layout of all widgets within this container.
size.widthWidth of bounding box of widget in pixels
size.heigthHeight of bounding box of widget in pixels
location.xX location
location.yY location
contentSize.widthwidth of actual widget
contentSize.heightheight of actual widget

# Hello World continued

## Text style

To set the style of a text, use the SCDWidgetsFontStyle class as described here:



## Dynamically adding a widget, i.e. Bitmap

To make our HelloWorld a little bit more interesting, we add the image dynamically whenever we press the button. Please see here [Bitmap control](🔗) for details on loading a bitmap:



The interesting part here is setting the row to 1. Doing this, we tell the bitmap that it belongs into the second row of the view. We then append the bitmap to the current page.

(Script tags will be stripped)


# Text entry example

This example consists of a header with label, a text entry grid and a bottom with a button inside:

(Script tags will be stripped)


## The header

The header consists of a row view with a label inside. We configured it to use minimal space and have a red background.

The row view has been used for demonstration purposes and as a good practice in case you want to add other elements, but you could use the label only.



## Textentry form

The form part consists of a 2x3 grid. We changed the margin and set the row to 1, making it appear in row 2 of the main page:

(Script tags will be stripped)


## Textbox

The textbox has the usual text attribute. Furthermore, the tabindex is used to set the sequence in which textfields are entered. The widthConstraint is set to **match_parent**, using the maximum available space of the parent (isGrabHorizontalSpace is set to **true** by configureLayoutData)



## The bottom

Nothing new here. Make sure that row is set to 2 to position this row view in the 3rd row of the main page:



# List control example

For full details on the list control, please see [List control](🔗)

(Script tags will be stripped)


Now lets programmatically create a list control. As with the creation through the IDE page editor, you need to follow two steps

  1. Step 1: Configure the template of the list control, i.e. add all controls that are displayed for each row of the list

  2. Step 2: Populate the rows with data

In comparison to the IDE, you cannot use data binding here, but have to set the data directly. We might add this capability to the API in later versions.

## Step 1 : ListControl & template

The class representing a list control is **SCDWidgetsList**. We configure it to use the entire space and then use **_template?.element?.children** to set the container/control describing the row.



There is nothing special about the creation of the template. You just arrange the controls you want inside a container. The following code adds two labels into a row view:



## Step 2: Setting the data

In the second step, you set the data that shows up in the list control.

  • Population needs to happen in the **show** method

  • First, populate the **<listcontrol>.items** array. It usually hold all the data that is used for data binding. Defining bindings through code is not supported yet, but for each row in the list control, you need to add an entry into the array.

  • Second, you need to set the values for each row. The rows in the list control are displayed using the **<listcontrol>.elements** array (which we set using the setValues method)



The elements in the list control are of type **SCDWidgetsListElement**. Use **element.children[0]** to access the first children in the respective element. This in our case is our SCDWidgetsRowView created in createTemplate(). Then drill down and access the labels to set the first and last name:



# Dynamic Button grid example

Here another example of how to configure a grid of buttons. The number of columns and rows can be set during runtime.

(Script tags will be stripped)


The main steps are

  • Start out with configuring the main page into a 1x2 grid, where the first cell holds another grid containing the buttons, and the second cell holds a simple container with a button

  • Create a grid container. Configure the layout of the container using the **SCDLayoutGridLayout** class and set the layout using the **rows** and **columns** properties.

  • We used **colorOfButtons** data structure to hold the color for the button placed in a specific cell.



# Other

## API documentation question

Where the heck do i find a complete API documentation??? Sorry, we are a little late concerning this, and will generate documentation automatically in our next release. For now, please inspect the class hierarchy yourself using the shortcuts mentioned here [Shortcuts](🔗)