Modules
Migrating to Layout Manager

Modules

 Migrating Dialogs
 
 Migrating Tool Settings
 

Detailed Description

Introduction

A Dialog Layout Manager has been added to the MDL Dialog Manager in CONNECT Edition PowerPlatform. The Layout Manager provides a simple and powerful way of automatically arranging child items within a dialog to ensure they make good use of the available space. "Layouts" automatically position and resize items when the amount of space available for them changes, ensuring that they are consistently arranged and that the user interface as a whole remains usable. A dialog has one top-level parent layout, and numerous child layouts can be nested to achieve the overall layout for the dialog. PowerPlatform includes a number of layout types and a set of layout management classes that are used to describe how items are laid out in an application's user interface. Layout specifications may also be included in an MDL dialog's resource definition.

There are 5 different layout types available in the MDL Layout Manager:

  1. GridLayout

    Lays out items in rows and columns. The GridLayout is the most capable and flexible layout. Many dialogs start with the GridLayout then nest other layouts that arrange smaller groups of items. This type of layout is also known as a "Table" layout.

  2. StackLayout

    Lines up items horizontally or vertically. The Vertical StackLayout can be used as the main layout, especially for Tool Settings. The Horizontal StackLayout is typically used for small sections of a larger, more complex dialog This type of layout is also called a "Box" layout.

  3. FlowLayout

    Lines up items horizontally as space permits. When there is no longer space on a single line for all items, it wraps the remainder on subsequent lines below. This type of layout is also called a "Wrap" layout..

  4. SplitterLayout

    Puts items on either side of a Sash, or Splitter, control. The SplitterLayout can be either horizontal or vertical.

  5. DockLayout

    Puts items along the top, bottom, left or right edge. This type of layout is also called a "Border" layout.

Layout Manager Concepts

There are a number of concepts related to the Layout Manager. An understanding of these concepts is important in order to achieve the best results possible. For details of these concepts, see LayoutManagerConcepts.

Guiding Principles

Each Dialog and Tool Settings will be different, but there are a number of guiding principles that should be followed when using the Layout Manager.

Main Dialog Layouts - Grid, VStack or Dock

The GridLayout, VStackLayout or DockLayout are usually used as the main layout for a dialog. The GridLayout is probably the most capable and flexible layout and uses rows and columns. If your dialog is very "blocky", this may be best to start out with. But if the dialog is more free flowing from top to bottom, the VStackLayout might be better as the main layout. The third choice would be the DockLayout, which might be appropriate for a dialog with a menu bar and status bar.

Main Tool Settings Layout - VStack

The VStackLayout is usually used as the main layout for Tool Settings. When the Tool Settings dialog is docked, it can be any height set by the user. To guarantee that the items are positioned correctly vertically in that scenario, a STRETCH(1) item should be the last item in the VStackLayout in order to prevent the items from being spacing apart too much.

Use Nested Layouts

When specifying the layout of a dialog, numerous layouts can be nested to achieve the overall layout for the dialog. Although the dialog may start with a GridLayout or VStackLayout, you should nest the layouts as deeply as needed to accomplish the overall layout for the dialog. Use a nested FlowLayout to accomplish a "Toolbar" layout. Use a nested HStackLayout for OK/Cancel buttons. Use a nested GridLayout for "Label: Editor" or "Toggle Label: Editor" layouts.

For Toolbar buttons in a dialog, use a FlowLayout

A FlowLayout lines up items horizontally as space permits. When there is no longer space on a single line for all items, it wraps the remainder on subsequent lines below. This is perfect for a set of buttons that act as a Toolbar on a dialog. You may also place Separator items between items within the FlowLayout.

Use Stretch Factor or Stretch Item before overriding Size Policy

Before overriding the Size Policy of an item, consider using a Stretch Factor or Stretch item. The default Size Policies for the items have been established to cover most usages of the items. Therefore, careful thought should be given before overriding that policy. Stretch Factors are very useful in a number of situations. They can be used to push buttons to the right, center content within a StackLayout, push content up from the bottom, prevent items from stretching in a Grid Row, and push items to either side of a StackLayout. So use of the Stretch Factor should especially be considered before attempting to override an item's Size Policy.

Common Techniques and How To

There are a number of common techniques that can be used in many situations when using the Layout Manager.

Allow for a Separator across a dialog

Use a VStackLayout with no margins as the main layout when a Dialog or Tool Settings contains a Separator item that needs to span across the dialog. You will use nested layouts that do have the standard margins and spacing to accomplish the consistent spacing.

. . .
{AUTO_XYWH, Separator, 0, ON, SEPARATOR_HORIZONTAL, "", ""},
. . .

Allow a ListBox item to be flush with the dialog edges

Use a VStackLayout with no margins as the main layout when a Dialog or Tool Settings contains a ListBox item that needs to be flush with the left and/or right edge of the dialog.

. . .
{{ AUTO_XY, VIEWGROUP_LIST_WIDTH, 0}, ListBox, LISTID_VIEWGROUP_ViewGroups, NO_ITEMARGS},
. . .
END_LAYOUT

Allow a MenuBar item to be flush with the dialog edges

Use a VStackLayout with no margins as the main layout when a Dialog contains a MenuBar item that needs to be flush with the left and right edges of the dialog. Also, it is recommended to you use the MenuBarX, which includes an MENUBARATTR_TALL attribute and gives more height to the menu bar.

DItem_MenuBarXRsc MENUBARID_AppMenu =
{
{
{PulldownMenu, PULLDOWNMENUID_AppMenu, "", 0, ""},
}
};
{AUTO_XYWH, MenuBarX, MENUID_AppMenu, NO_ITEMARGS},
. . .
END_LAYOUT

Position OK and Cancel Push Buttons in the lower right corner

To position the OK and Cancel buttons in the lower right corner of a modal dialog, in a nested HStackLayout at the bottom of a modal dialog, insert a STRETCH(1) item before the OK and Cancel buttons. The HSTACKLAYOUTID_DialogButtons HStackLayout from ustation.rsc may be used for this purpose.

BEGIN_HSTACK_LAYOUT(HSTACKLAYOUTID_DialogButtons, "")
{{ AUTO_XY, BUTTON_LARGEWIDTH, 0}, PushButton, PUSHBUTTONID_VIEWGROUP_Apply, NO_ITEMARGS},
{{ AUTO_XY, BUTTON_LARGEWIDTH, 0}, PushButton, PUSHBUTTONID_VIEWGROUP_Close, NO_ITEMARGS},

Center content when using an HStack

To center content in an HStackLayout, insert a STRETCH(1) on either side of those items.

BEGIN_HSTACK_LAYOUT(HSTACKLAYOUTID_DialogButtons, "")

Prevent unwanted vertical expansion when using a VStack

To prevent unwanted VStackLayout item expansion, insert a STRETCH(1) as the last item in a VStackLayout to push the items above to their normal size and position. This is required for the Tool Settings.

. . .

Prevent unwanted horizontal expansion when using a HStack

To prevent unwanted HStackLayout item expansion, insert a STRETCH(1) as the last item in an HStackLayout to push the items to the left to their normal size and position.

. . .

Prevent unwanted horizontal expansion in a GridRow

If you want to prevent the columns in a GridRow from expanding too much when a dialog resizes, you can include an extra GridColumnRsc with an increased Stretch Factor in the GridLayoutRsc definition. In this situation, the extra column in the GridRows can remain empty.

// Used for "Toggle Label: SettingsItem" formatting. Has a stretch at the end to prevent row stretching.
GridLayoutRsc GRIDLAYOUTID_3ColsToggleLabelSetting =
{
{XC_3_2, XC_3_2, XC_3_2, XC_3_2}, // Margins - Left, Top, Right, Bottom
XC, YC/3, // HSpacing, VSpacing
{ // Column Definitions
{0, "toggleColumn3"}, // Stretch, SharedSizeGroup
{0, "labelColumn3"},
{0, "settingColumn3"},
{1, "stretchColumn3"}, // Extra column with a Stretch Factor of 1 to prevent unwanted expansion
}
};

Push items to the sides of an HStack

If you want to push items to the side in an HStackLayout, include a STRETCH(1) item in the middle of the items.

BEGIN_HSTACK_LAYOUT(HSTACKLAYOUTID_DialogButtons, "")
{{ AUTO_XY, BUTTON_LARGEWIDTH, 0}, PushButton, PUSHBUTTONID_MyButton, ON, 0, "", ""},
{{ AUTO_XY, BUTTON_LARGEWIDTH, 0}, PushButton, PUSHBUTTONID_Close, ON, 0, "", ""},

Add space before or after an item

To add some space before or after an item, you may put a SPACING item before or after the item. The unit of measurement for the SPACING macro is Dialog Coordinates. There are standard spacing values in dlogbox.r.h, such as GROUPBOX_GAP and SECTION_GAP, which we recommend you use rather than a non-standard calculation that uses XC and YC directly.

BEGIN_HSTACK_LAYOUT(HSTACKLAYOUT_LabeledItem, "")
{AUTO_XYWH, Label, 0, ON, LABEL_LINKNEXT | ALIGN_RIGHT, "", ""},
{AUTO_XYWH, Text, TEXTID_RefDialogRotation, ON, 0, "", ""},

Make one item resizable

To make one item resizable within a resizable dialog, set the stretch override to '1' for the item and/or containing layout. In the following example, the ListBox and its containing HStackLayout are set as resizable vertically and horizontally with the stretch='1' override. Whereas, the other content on the dialog will stay at more of a fixed size, only growing as needed according to their Size Policies.

{AUTO_XYWH, ListBox, LISTBOXID_ToolBoxes, ON, 0, "", "stretch='1'"},
. . .
. . .
. . .
. . .
END_LAYOUT

Position and Size an item's label

To correctly position and size the label for a dialog item using the Layout Manager, use a separate Label with a LABEL_LINKPREV or LABEL_LINKNEXT attribute in the itemArg field. LABEL_LINKPREV will pull the label string from the previous item, and LABEL_LINKNEXT will pull the label string from the next item. Using this technique, the two items are "linked" for focus model purposes. This allows the main item to keep the label in its resource definition in case it is used outside a layout, but also allows the Label item to "link" to it and specify an independent column and size policy for layout purposes. The label string can grow independently and will automatically be accommodated by the Layout Manager. You may also specify alignment for the Label using ALIGN_LEFT (default), ALIGN_CENTER or ALIGN_RIGHT.

LABEL_LINKPREV

BEGIN_GRID_LAYOUT(GRIDLAYOUTID_3ColsToggleLabelSetting, "")
GRID_ROW(0, "")
{{AUTO_XY, 0, 0}, ToggleButton, TOGGLEID_Length, ON, 0, "", ""},
{{AUTO_XY, W10, 0}, Label, 0, ON, LABEL_LINKPREV, "", ""}, // Pull label from ToggleButton
{{AUTO_XY, W10, 0}, Text, TEXTID_Length, ON, 0, "", ""},
. . .
END_LAYOUT

LABEL_LINKNEXT

BEGIN_GRID_LAYOUT(GRIDLAYOUTID_2ColsLabelSetting, "")
GRID_ROW(0, "")
{{AUTO_XY, W10, 0}, Label, 0, ON, LABEL_LINKNEXT | ALIGN_RIGHT, "", ""}, // Pull label from OptionButton
. . .
END_LAYOUT

There are convenience macros defined in dlogbox.r.h that simplify working with Labels for layout. These include:

Labeled Item in a FlowLayout

To correctly position and size an item and label within a FlowLayout, use a nested HStackLayout within the FlowLayout and use the LABEL_LINKNEXT attribute on the Label. You may also put a SPACING item before the Label to give it more room. To center the Label and linked Item vertically, add a verticalAlignment override of 'center' to the HStackLayout.

BEGIN_FLOW_LAYOUT(FLOWLAYOUTID_IconButtons, "")
. . .
BEGIN_HSTACK_LAYOUT(HSTACKLAYOUT_LabeledItem, "verticalAlignment='center'")
{AUTO_XYWH, Label, 0, ON, LABEL_LINKNEXT | ALIGN_RIGHT, "", ""},
{AUTO_XYWH, Text, TEXTID_RefDialogRotation, ON, 0, "", ""},
. . .

Set the Minimum Size for a ListBox

Since the Size Policy for a ListBox (also the Tree a few others) is 'Preferred, Preferred', the ListBox size can be shrunk down to its minimum size. To set the minimum size for the dialog, set the EXTINTATTR_MINWIDTH and EXTINTATTR_MINHEIGHT extended attributes in the resource definition of the ListBox. The unit of measurement for these extended attributes is Dialog Coordinates. Therefore, XC and YC may be used.

DItem_ListBoxRsc LISTBOXID_ToolBoxes =
{
NOHELP, MHELP, HOOKID_ListBoxStd, NOARG,
10, 0, "",
{
{30*XC, 60, 0, TXT_Show_ToolBoxes},
}
}
extendedIntAttributes
{{
}};

Span a cell across multiple columns

To span a GridLayout cell across multiple columns, use the colSpan='value' override for an item. The value for colSpan= may either be the number of columns to span or a '*', which mean span to the end of the row. In the example below, the 2nd column in the 2nd GridRow spans across the 2nd and 3rd columns.

BEGIN_GRID_LAYOUT(GRIDLAYOUTID_3ColsToggleLabelSetting, "")
GRID_ROW(0, "")
{{AUTO_XY, 0, 0}, ToggleButton, TOGGLEID_UseFence, ON, CMD_CHANGE_ATTRIBUTES, "", ""},
{{AUTO_XY, CA_CKBX_CX*XC, 0}, Label, 0, ON, LABEL_LINKPREV, "", ""},
{{AUTO_XY, CA_CTRL_CX*XC, 0}, OptionButton, OPTIONBUTTONID_LockFenceMode, ON, 0, "\0", ""},
GRID_ROW(0, "")
{{AUTO_XY, 0, 0}, ToggleButton, TOGGLEBUTTONID_MakeCopy, ON, 0, "", ""},
{{AUTO_XY, CA_CKBX_CX*XC, 0}, Label, 0, ON, LABEL_LINKPREV, "", "colSpan='*'"},
. . .
END_LAYOUT

Copyright © 2017 Bentley Systems, Incorporated. All rights reserved.