Skip to content

Positioning and Layout of Controls

Related topics: 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 differently. Due to the nature of HTML and CSS, x/y coordinate positioning should be used sparingly. Instead, DataFlex offers three distinct ways of positioning 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. Inside containers (including Panels) you will then 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 shown 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/bottom panels or the width of left/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.

Rules 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 ensures 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

You can create more complex panel layouts by declaring a set of cWebPanel objects inside an existing panel (sub-panels).

The following image illustrates the previous 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:

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 same rules that 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-panels you can create; however, more than two levels of sub-panel division is usually 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 is the order in which 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.

  • Fewer columns make it easier and faster to reorganize layout.
  • More columns provide more choices for precise position and size.
  • Best practice: a column count of 12 provides a good 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 control's piColumnIndex is 0 (left-most column).
  • Set piColumnSpan to determine the width of a control (and its label) as the number of layout columns it spans. By default, most controls' piColumnSpan is 0, which means it spans all available columns.
  • For controls with a label (e.g. cWebForm), the width of the control includes the width occupied by its label. Use piLabelOffset to adjust the amount of space occupied by a control’s label (in pixels). Set piLabelOffset < 120 to reduce the label width, or > 120 to increase the label width.

Example code for the column layout shown above:

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

Notes and rules:

  • The piColumnIndex of a control cannot exceed the number of columns in the parent view or panel. Remember piColumnIndex is 0-based (e.g. for piColumnCount = 9, valid piColumnIndex is 0–8).
  • If two consecutive controls have the same piColumnIndex they will occupy the same column; flow layout rules determine whether one is above the other based on declaration order.
  • To place two consecutive controls on the same row, set the second control's piColumnIndex to a value >= the first control’s piColumnIndex + piColumnSpan.

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

Grid Layout

Introduced in DataFlex 2023, Grid Layout leverages CSS Grid to provide more control over vertical positioning. Controls position themselves on a grid that you configure at container level. Controls can be assigned specific rows and columns, granting fine-grained control over their exact positions.

Setting up your grid: rows and columns

Switch a container to Grid Layout by setting peLayoutType to ltGrid. This exposes additional properties for configuring rows and columns.

Row-related properties

  • piRowCount
  • Sets the minimal number of rows to display in the container. If controls span more rows than specified, additional rows are automatically generated.

  • psRowHeights

  • Format: ROWINDEX/VALUE ROWINDEX/VALUE ...
  • Example: 1/75 3/1fr 4/20%
  • Allows custom row heights to be specified, overriding the default row height.
  • Accepted values:
    • Exact pixel values (e.g. 50)
    • Percentages (e.g. 20%)
    • Fractions (e.g. 1fr, 4fr)
    • Advanced clauses (e.g. minmax(), max-content) — see CSS Grid documentation for more details: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout
  • Note: CSS Grid is 1-based in standard CSS, but the DataFlex Grid Layout implementation is 0-based.

  • piDefaultRowHeight

  • Default: 20 (pixels)
  • Sets the default minimum row height for rows not specified via psRowHeights. Default-height rows claim this minimum pixel height and can grow according to their content.
  • Accepted formats: pixels, percentages, fractions, and advanced CSS Grid clauses (see above).

Column-related properties

  • piColumnCount
  • Works the same as in Flow Layout.

  • psColumnWidths

  • Format: COLUMNINDEX/VALUE COLUMNINDEX/VALUE ...
  • Example: 1/75 3/1fr 4/20%
  • Allows custom column widths to be specified, overriding the default column width. Accepted values are the same types as for rows (pixels, percentages, fractions, advanced CSS Grid clauses).

  • psDefaultColumnWidth

  • Default: 1fr
  • Sets the default width value for columns not specified via psColumnWidths. The default 1fr causes each unspecified column to be the same width (similar to Flow Layout). Accepted formats: pixels, percentages, fractions, advanced CSS Grid clauses.

Refer to the CSS Grid documentation for advanced sizing options: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout

Placing Your Controls

After configuring the grid, position controls by assigning them to specific cells. The relevant properties:

  • piRowIndex
  • Default: -1
  • Positions the control at the specified row index on the grid. If not set, CSS Grid will attempt to fill gaps automatically. Note: DataFlex Grid Layout is 0-based.

  • piRowSpan

  • Causes a control to span multiple rows. Whether the control visibly fills the spanned rows depends on its height or pbFillHeight.

  • piColumnIndex

  • Default: -1
  • Positions the control at the specified column index on the grid. If not set, CSS Grid will attempt to fill gaps automatically. Note: DataFlex Grid Layout is 0-based.

  • piColumnSpan

  • Causes a control to span one or more columns. Unlike Flow Layout where 0 can mean "span remaining space", in Grid Layout 0 causes the control to occupy one column (use explicit span values to span more).

  • pbFillHeight

  • If True, the control attempts to size its height to its allocated rows (fills the assigned rows). Combine pbFillHeight with rows defined as fractions (e.g. 1fr) to achieve fill behavior similar to Flow Layout.
  • If False, the control attempts to retain its natural height, determined by CSS, piHeight, piMinHeight, or a combination.

Grid or Flow?

Both Grid and Flow have their place:

Use Flow when you: - Want controls to flow naturally from top-left to bottom-right as ordered in code - Want containers to dynamically size to their content (useful with fill-height controls) - Want gaps in layout to fill naturally when showing/hiding controls or for mobile displays

Use Grid when you: - Want more control over vertical positioning - Want controls to align horizontally by respecting row heights - Want to dictate exact control positions

You can mix Flow and Grid. For example, a View can use Flow Layout and contain groups that each use Grid Layout.

Visual WebApp Designer

A visual designer is available for Flow, Grid and Panels. The WebApp Designer can be shown/hidden via the Studio's View menu or by pressing F7.

  • Controls are selected by clicking; the selected control is highlighted with a blue outline.
  • In Flow Layout, moving controls shows a black marker indicating the drop position. Controls can be moved inside the designer or dragged from the class palette onto the designer.
  • In Grid Layout, a Grid Overlay icon appears in the top-right of the container selection box. The overlay lets you set up and configure the container’s grid. When moving a control over a Grid container, the overlay highlights the cells the control will claim.
  • In Grid Layout, controls have a different selection box. Move using the drag handle; drop to update piColumnIndex and piRowIndex. Resize via the bottom-right icon to update piColumnSpan and piRowSpan.

For more on the designer, see: WebApp Designer


Previous Topic: Web Application Flow
Next Topic: Managing Web Control Visibility

See Also