Positioning and Layout of Controls

Web Application Flow

Managing Web Control Visibility

 

Layout: Windows vs. Web

Where it makes perfect sense to have absolute coordinate positioning of controls on Windows, the Web operates a little differently. Due to the nature of HTML and CSS, x & y coordinate positioning is something to be used sparingly. Instead, DataFlex offers 3 distinct ways of positioning your controls inside a web interface: Panels, Flow Layout and Grid Layout.

Panels are often used as a top-level way of organizing and designing your interface. From there, inside containers (including Panels) you will use either Flow or Grid Layout.

Panels

cWebPanel objects can be used to divide the layout of your view or dialog into regions:  top, bottom, left, right and center. Set the peRegion property to determine which region a web panel will occupy.

The following image illustrates a web view that is divided into Top, Bottom, Left, Right and center panels. Each panel then contains a single cWebLabel control.

The source code required to create this view is presented below:

Object oPanelView is a cWebView

    Set psCaption to "Multi Panel View"

    Set piHeight to 300

    Set piWidth to 300

    Object oTopPanel is a cWebPanel

        Set peRegion to prTop

        Set psBackgroundColor to "Blue"

        

        Object oTopLabel is a cWebLabel

            Set psCaption to "Top"

            Set psBackgroundColor to "#AAAAFF"

            Set peAlign to alignCenter

        End_Object

    End_Object

    Object oCenterPanel is a cWebPanel

        Set psBackgroundColor to "Orange"

        

        Object oCenterLabel is a cWebLabel

            Set psCaption to "Center"

            Set psBackgroundColor to "#FFDDAA"

            Set peAlign to alignCenter

            Set pbFillHeight to True

        End_Object

    End_Object

    Object oLeftPanel is a cWebPanel

        Set peRegion to prLeft

        Set psBackgroundColor to "#4343FB"

        Set piWidth to 60

        

        Object oLeftLabel is a cWebLabel

            Set psCaption to "Left"

            Set psBackgroundColor to "#AAAAFF"

            Set peAlign to alignCenter

            Set pbFillHeight to True

        End_Object

    End_Object

    Object oRightPanel is a cWebPanel

        Set peRegion to prRight

        Set psBackgroundColor to "#4343FB"

        Set piWidth to 60

        

        Object oRightLabel is a cWebLabel

            Set psCaption to "Right"

            Set psBackgroundColor to "#AAAAFF"

            Set peAlign to alignCenter

            Set pbFillHeight to True

        End_Object

    End_Object

    Object oBottomPanel is a cWebPanel

        Set peRegion to prBottom

        Set psBackgroundColor to "Blue"

        

        Object oBottomLabel is a cWebLabel

            Set psCaption to "Bottom"

            Set psBackgroundColor to "#AAAAFF"

            Set peAlign to alignCenter

        End_Object

    End_Object

End_Object

Set the piHeight property to set the height (in pixels) of top and bottom panels.

Set the piWidth property to set the width (in pixels) of left and right panels.

Set the pbResizable property to True for left, right, top or bottom panels to enable a “splitter” bar that allows the height of top and bottom panels or the width of left and right panels to be resized at run time.

Panel objects can contain one or more control objects (such as cWebButton or cWebForm).  The controls are contained within the panels and each panel organizes its controls into a separate flow layout.

 

There are some simple rules that must be followed when using panels:

cWebPanel objects cannot be siblings of web control objects such as cWebButton or cWebForm. Place web controls inside your cWebPanel objects.

• Each sibling cWebPanel must belong to a different region. For example a cWebView cannot have two top panels or two bottom panels as direct child objects.

• Each set of sibling cWebPanel objects must contain one (and only one) center panel (i.e. peRegion = prCenter). This is to ensure that the panels can correctly divide and occupy all of the space provided by their parent container. Top, bottom, left and right panels are optional.

 

Sub Panels

A more complex panel layout can be achieved by dividing panels into sub-panels. This is achieved by declaring a set of cWebPanel objects inside an existing panel.

The following image illustrates the previous web view where the right panel has been subdivided into right-top, right-center, and right-bottom.

 

The source code required to modify the right panel from the previous example is presented below:

Object oRightPanel is a cWebPanel

    Set peRegion to prRight

    Set piWidth to 60

    Object oRightTopPanel is a cWebPanel

        Set peRegion to prTop

        Set psBackgroundColor to "Red"

        

        Object oRTLabel is a cWebLabel

            Set psBackgroundColor to "#FFAAAA"

            Set psCaption to "RT"

            Set peAlign to alignCenter

        End_Object

    End_Object

    Object oRightCenterPanel is a cWebPanel

        Set psBackgroundColor to "Red"

        

        Object oRCLabel is a cWebLabel

            Set psBackgroundColor to "#FFAAAA"

            Set psCaption to "RC"

            Set peAlign to alignCenter

            Set pbFillHeight to True

        End_Object

    End_Object

    Object oRightBottomPanel is a cWebPanel

        Set peRegion to prBottom

        Set psBackgroundColor to "Red"

        

        Object oRBLabel is a cWebLabel

            Set psBackgroundColor to "#FFAAAA"

            Set psCaption to "RB"

            Set peAlign to alignCenter

        End_Object

    End_Object

End_Object

The rules which apply when dividing a view into panels also apply when dividing a panel into sub-panels.

There is no technical limit to how many layers of sub-panel you can create, however more than two levels of sub-panel division is probably of little practical use.

 

Flow Layout

Within Flow Layout, controls flow naturally from the top left to the bottom right of a container. The order of your controls within a container are as they appear in your code.

 

Columns in Flow Layout

To regulate the size and flow-positioning of controls, a container can be divided into any number of equal-width columns. Each child control will be positioned in its designated column and the control’s width will occupy one or more column widths.

Columns provide a fast and simple way to vertically align controls and to ensure that control widths line up evenly to fixed positions.

The following image illustrates a view where the horizontal position and widths of cWebForm controls fit into a view’s column layout.

 

Column Count

Set the piColumnCount property of the cWebView, cWebPanel or any other container object to determine how many columns it is divided into.

The fewer columns you have, the easier and faster it is to reorganize the layout of controls. The more columns you have, the more choice you will have over position and size of each control. According to best practice guidelines, a column count of 12 results in the best balance of configurability and simplicity.

 

Control Position and Width

Set piColumnIndex to determine which column the control occupies. Column numbering starts at 0. By default each controls' piColumnIndex is set to zero which means it will occupy the left-most layout column of its parent View (or panel).

Set piColumnSpan to determine the width of a control (and its label) as expressed by the number of layout columns that it spans. By default, most controls' piColumnSpan is set to zero which means that it spans all available columns.

The source code required to build the column layout shown in the previous image appears below:

Object oColumnLayout is a cWebView

    Set piWidth to 600

    Set psCaption to "Column Layout View"

    Set piColumnCount to 3

        

    Object oWebForm1 is a cWebForm

        Set piColumnSpan to 1

        Set psLabel to "Web Form 1:"

        Set piLabelOffset to 90

    End_Object

    Object oWebForm2 is a cWebForm

        Set piColumnSpan to 1

        Set piColumnIndex to 1

        Set psLabel to "Web Form 2:"

        Set piLabelOffset to 90

    End_Object

    Object oWebForm3 is a cWebForm

        Set piColumnSpan to 1

        Set piColumnIndex to 2

        Set psLabel to "Web Form 3:"

        Set piLabelOffset to 90

    End_Object

    Object oWebForm4 is a cWebForm

        Set piColumnSpan to 1

        Set psLabel to "Web Form 4:"

        Set piLabelOffset to 90

    End_Object

    Object oWebForm5 is a cWebForm

        Set piColumnSpan to 2

        Set piColumnIndex to 1

        Set psLabel to "Web Form 5:"

        Set piLabelOffset to 90

    End_Object

    Object oWebForm6 is a cWebForm

        Set piColumnSpan to 3

        Set psLabel to "Web Form 6:"

        Set piLabelOffset to 90

    End_Object

End_Object

 

In the above example the controls are arranged into three vertical columns. The cWebView object sets a piColumnCount of 3. The controls are either piColumnIndex of 0, 1 or 2 and piColumnSpan is set to 1, 2 or 3.

An alternative could be to set the piColumnCount to 9 instead of 3, then multiply each piColumnCount and piColumnIndex value in the above code by 3. This would produce an identical result but with the added flexibility of allowing a finer adjustment if you wanted to modify the layout later.

Realize that for controls which include a label (e.g cWebForm) the width of the control includes the width occupied by its label. The piLabelOffset property allows you to adjust the amount of space that is occupied by a control’s label (in pixels). Set piLabelOffset < 120 to reduce the label width, or > 120 to increase the label width.

The Studio’s Web View wizard provides a column layout tool that will help you to set the initial layout of your selected objects. The preview button allows you to review the layout visually. This is a good tool to learn the relationship between the piColumnCount, piColumnIndex, piColumnSpan and piLabelOffset properties.

There are some simple rules that govern how piColumnIndex and piColumnSpan are interpreted in a set of multiple controls…

• The piColumnIndex of a control cannot exceed the number of columns in the parent view or panel. Remember that piColumnIndex is 0-based so if the view’s piColumnCount = 9 then the control’s piColumnIndex must be between 0 and 8.

• If you declare two consecutive control objects (e.g. two cWebForm objects) both with the same piColumnIndex value, then they will both occupy the same column. Flow-layout rules then determine that one control will be positioned above the other. This is determined by the order the objects are declared in your code.

• If you want two consecutive control objects to occupy the same row in the layout then set the piColumnIndex of the second object to a value >= the first object’s piColumnIndex + piColumnSpan. For example review oWebForm1, oWebForm2 and oWebForm3 in the above example.

When you display a web view (or dialog) in the Studio’s WebApp Designer and select one of the web view’s web object in the Code Explorer, you can see the column index and column span occupied by that object.

The following image illustrates part of the Order Entry view in the previewer where the “Zip” cWebForm is selected and highlights its column index and column span.

 

Grid Layout

Introduced in DataFlex 2023, Grid Layout allows you to leverage the power of CSS Grid to gain more control over the vertical positioning of your controls. As the name suggests, Controls position themselves on a Grid that you configure at container level. Controls can be assigned specific rows and columns to occupy, granting a very fine level of control over a control’s exact position.

Setting up your grid: rows and columns

To get started with Grid Layout, the first step is to set up your Grid that your controls will place themselves on later. When switching to Grid Layout (by setting peLayoutType to ltGrid on the container), you get access to several additional properties besides those that govern the columns. Using these properties allows you to set up your grid by configuring your columns, but also your rows.

For the rows:

piRowCount

psRowHeights

piDefaultRowHeight

piColumnCount

psColumnWidths

psDefaultColumnWidth

 

Placing Your Controls

After setting up your grid, it is time to position your controls. This is done by assigning controls to populate specific cells. This assignment is determined by the value of several properties.

piRowIndex

piRowSpan

piColumnIndex

piColumnSpan

pbFillHeight

 

Grid or Flow?

Grid and Flow both have their place in Web UIs, and one is not specifically better than the other. Depending on the use case, you should use either Grid or Flow.

Use Flow when you…:

Use Grid when you…:

A cool thing is that you can mix-and-match Flow and Grid. You could for example have a View that is set to use Flow Layout, then inside make several groups that each use Grid Layout. The possibilities are endless!

 

Visual WebApp Designer

For both the Flow and the Grid Layout as well as for panels, a visual designer is available to help you with building your interfaces. The WebApp Designer can be shown or hidden via the Studio's View menu or by pressing F7.

Inside the designer, controls can be selected by clicking on them. A blue outline will highlight the currently selected control. From there, the functionality of the designer depends on whether the container is set to use Flow or Grid Layout.

The following image should give a good understanding of what certain buttons inside the designer do when set to Flow Layout

 

When moving controls and hovering over the designer, a black marker will indicate where the control will be positioned. Controls can be moved inside the designer, but also dragged from the class palette onto the designer itself.

For Grid Layout, the designer functions a little differently. First off, when selecting a container object with peLayoutType set to ltGrid, an icon will appear in the top right corner of the selection box. This toggles the Grid Overlay, where you can set up and configure the container’s grid.

The following image should give a good understanding of what is possible inside the designer when the grid overlay is active.

 

When moving a control and hovering it over a Grid Layout container, the overlay will automatically show and the cells the control will claim will be highlighted.

 

You may also notice that controls inside a Grid Layout container have a slightly different selection box when highlighted. Moving a control is simply done via the drag handle and when dropping on the highlighted cells the piColumnIndex and piRowIndex will be updated accordingly. Resizing is done via the icon on the bottom right of the selection box by dragging it, where again the Grid Overlay will show and highlight the cells the control will occupy after resizing at which point the piColumnSpan and piRowSpan will be updated to match the new width and/or height.

 

 

Previous Topic: Web Application Flow

Next Topic: Managing Web Control Visibility

 

See Also

Developing Web Applications