37 A.06.01.a

37.1 Qt Support

37.1.1 Supported Platforms

The IDM for Qt is available in 32- and 64-bit versions for Qt 4.6 on Red Hat Enterprise Linux (RHEL) 5.5 and Qt 4.8 on RHEL 7. These versions are also executable on SUSE Enterprise Linux.

Qt itself is not included in the IDM for Qt. The required Qt versions can be installed via the package managers of the systems. If multiple Qt versions are installed on one system, attention must be paid to link with the correct version when building applications.

37.1.2 Error and Warning Messages

In the case of an inappropriate Qt version, the IDM outputs the error message WSIQT version mismatch.

Access to not yet implemented or unsupported objects, attributes and functions is indicated by messages such as …NOT-IMPLEMENTED… or …UNSUPPORTED… in the log file.

37.1.3 Special Features of Qt

Qt supports transparent colors and may use them in the default palette. This can lead to the fact that visible objects can not be operated, because an overlying object with a transparent background prevents their operation. For example, this case occurs with two overlapping statictexts of fixed size.

Because Qt supports different UI styles, colors (foreground, background) may vary in different styles or be ignored altogether. The appearance may vary depending on the UI style. In addition to colors, this also affects other display aspects, for example, existing or missing frames depending on the UI style.

The depiction of color gradients also depends very much on the object and the UI style.

Example

For a poptext with the style poptext or edittext and set .bgc in the UI style cleanlooks the background color is ignored by the pop-up list in the opened state.

37.1.4 Differences to Other IDM Versions (Compatibility)

This chapter describes differences from the versions of the ISA Dialog Manager for other toolkits. These differences are due to specific features of the Qt toolkit, which may also mean that the IDM uses capabilities of Qt that are not provided by the other toolkits.

37.1.4.1 Objects

37.1.4.1.1 Canvas

The canvas object has the option opt_graphicsview on Qt. It controls whether the canvas is implemented using a QFrame (opt_graphicsview = false) or a QGraphicsView (opt_graphicsview = true). The option is turned off by default. Then, it can be drawn directly into the QWidget in the expose event. If the option is turned on, no expose message will be forwarded to the canvas. For example, this mode, in which the QGraphicsView is the container of a QGraphicsScene, is used to add objects to the scene, which the scene then draws on its own.

Depending on the option value, there are differences in the DM_CanvasUserArgs, which is now defined as follows:

typedef struct {
  DM_ID  object;
  int    reason;
  #  ifdef QCOREEVENT_H
       QEvent*  event;
  #  else
       DM_Pointer  event;
  #  endif
  #  ifdef QWIDGET_H
       QWidget*  widget;  // depending on opt_graphicsview
                          // QFrame* or QGraphicsView*
       QWidget*  window;
  #  else
       DM_Pointer  widget;
       DM_Pointer  window;
  #  endif
  #  ifdef QFONT_H
       QFont*  font;
  #  else
       DM_Pointer  font;
  #  endif
  #  ifdef QCOLOR_H
       QColor*  fgc;
       QColor*  bgc;
  #  else
       DM_Pointer  fgc;
       DM_Pointer  bgc;
  #  endif
  DM_Int2     x;
  DM_Int2     y;
  DM_UInt2    width;
  DM_UInt2    height;
  DM_Pointer  userdata;
} DM_CanvasUserArgs;

In addition, .fgc, .bgc, and .font are passed to the canvas function because in some cases they must be explicitly set when drawing or adding new objects.

The canvas object has a new option opt_addevents. The option is turned off by default. When turned on, it causes all QEvents to invoke the canvas function in addition to the usual calls to the canvas function. For example, you can react to a MouseMove. The reason, which in this case is given to the canvas function, is CCR_event.

37.1.4.1.2 Edittext

There are behavioral differences between single-line and multi-line edittexts in regard to the depiction of the selection on focus loss. In single-line mode, the selection is removed and, like the cursor position, is no longer displayed. When the focus is regained, the IDM restores the selection. In multi-line mode, the selection remains on focus loss.

Depending on the UI style, the presentation of the focus frame may be limited in the single-line edittext.

The edittext has the option .options[opt_html] on Qt, which controls its HTML capability.

37.1.4.1.3 Filereq

The attribute .text[enum] is not supported by the IDM for Qt, analogous to the IDM for Windows.

When displayed via the querybox or DM_Querybox functions, the file or directory dialog is displayed centered in the desktop or window – if one is specified as a parameter.

The option .options[opt_createprompt] is not supported. When combining .mustexist = true with .options[fro_overwriteprompt] = true, no dialog will be displayed to confirm overwriting.

Multiple selection is only possible for existing files. If .multisel = true, .mustexist is ignored.

The use of .bgc, .fgc and .font is possible, but it is not recommended.

To filter the displayed files, a file type list can be specified. The different file types are separated by tabs \t. For each file type, multiple patterns *.<suffix> can be given. The patterns are separated by spaces or semicolons, the list of patterns should be enclosed in parentheses. The Windows format of the file type list, with a tab between the name of the file type and the associated patterns, without parentheses around the pattern list, is also supported. Both variants lead to the display of the pattern list in parentheses after the name of the file type.

Example

.pattern := "IDM Files (*.dlg *.idm *.mod)\tIDM Interfaces (*.if)\tAll (*.*)";
.pattern := "IDM Files\t*.dlg;*.idm;*mod\tIDM Interfaces\t*.if\tAll\t*.*;

Both assignments produce the following selection list:

IDM Files (*.dlg; *.idm; *.mod)
IDM Interfaces (*.if)
All (*.*)
37.1.4.1.4 Image

The color .bgc is used if .imagebgc is not specified for internally defined tiles and to color transparent areas of external tiles.

With .borderwidth = 0, the image gets the style flat, meaning that no frame is drawn. However, pressing the mouse button draws a frame to represent the pressed state.

37.1.4.1.5 Menubox, Menuitem, Menusep

The colors of the menu bar in a window are determined by the attributes .menubgc and .menufgc. The colors of the menuitems and sub-menus in pop-up menus as well as in menu bars are determined by .bgc and .fgc of the menubox. This means that the background and foreground color of individual menuitems cannot be changed.

Keyboard navigation behaves differently depending on the UI style. In general, the current entry can always be selected with Enter. With regard to the selection with Space, however, there are differences:

Table 19-5: Behavioral differences of menus in different UI styles

UI Style

Behavior

cleanlooks, plastique, windows

It is jumped to the first menuitem. No selection happens, the menu remains open.

motif, cde

A select event is triggered for the current menuitem. The menu will be closed.

gtk+

Nothing happens, the menu remains open.

37.1.4.1.6 Messagebox

The attribute .sysmodal is not supported by the IDM for Qt.

For the .icon attribute, the display symbols listed in “Table 19-6” are available whose appearance is determined by the selected UI style.

Table 19-6: Icon values and display symbols

.icon Value

Display Symbol

icon_asterisk

i

icon_error

x

icon_exclamation

!

icon_hand

like icon_error

icon_information

like icon_asterisk

icon_query

?

icon_question

like icon_query

icon_warning

like icon_exclamation

noicon

none

37.1.4.1.7 Poptext

On Qt, a maximum of 10 entries are displayed in an open poptext by default. If the poptext list contains more than 10 entries, then a scrollbar is additionally displayed in the list.

The .showitem attribute is ignored in the mac and gtk+ UI styles. In UI style cleanlooks, .showitem is ignored with .style = poptext, here always the complete list is displayed.

With .style = listbox, .showitem is completely ignored.

With the styles poptext and edittext, navigating through the open list using the arrow keys does not automatically select the accessed entry. A final selection must be completed with Enter. This is Qt default behavior.

37.1.4.1.8 Progressbar

The option .option[continuous] is not supported. Qt draws the progress bar depending on the used UI style (cleanlooks, plastique etc.). By default, a continuous bar is drawn in which a subdivision is indicated by color change. However, once you set .fgc, the bar will be drawn continuously in that color.

The .borderwidth attribute is not supported.

The attribute .textfgc is applied. As soon as the bar runs under the caption, the font is displayed in the background color .bgc.

The progressbar with .value = .minvalue displays a small piece of the bar on the left and the text 0%. It is only displayed completely empty if .value = -1. Then, however, no value is displayed in percent.

37.1.4.1.9 Scrollbar

In certain UI styles (e. g. cleanlooks) with .arrows = false a part of the background (left or above the slider) is colored.

37.1.4.1.10 Setup

In the IDM for Qt, the attribute .toolkit has the enum value toolkit_qt and .toolkit_string has the value Qt.

The setup object has the new attributes .colorname[integer], .cursorname[integer] and .fontname[integer], which contain lists of the available color names, cursor names and fonts (see chapters “colorname[integer]” to “fontname[integer]”).

The attribute .toolhelp for influencing the display duration is not supported. Additionally, the toolhelp appearance cannot be changed using .options[opt_balloon_toolhelp].

37.1.4.1.11 Spinbox

The .direction attribute and the horizontal alignment of the arrows are not supported.

37.1.4.1.12 Statusbar

Qt ignores the width of the statusbar children. Apart from the last visible child, the child objects are always as wide as necessary for the complete presentation of their content. Therefore, the attribute .alignment has no visible effect except for the last visible child.

Tabulators to center or right-justify the text of .statushelp are not supported.

37.1.4.1.13 Tablefield

In an extremely small tablefield, where the line and column headers cannot be displayed completely, scroll bars are available. These have no effect, however.

The tablefield has an empty line or empty column at the bottom and on the right, which fill the free area when scrolling all the way up or to the right. If the tablefield is dimensioned such that the last content row or content column can not be displayed completely, then the user can scroll to this empty row or empty column. This position cannot be queried or set programmatically.

The selection model of Qt is used, so there may be slight differences to the other window systems. However, the behavior is Qt-typical. If with the attribute .selection multiple of the elements sel_column, sel_row and sel_single have the value true, then sel_single is used. The element sel_header is ignored, the header is always selected.

The border of the tablefield can only be switched off via .borderwidth = 0 and switched on via .borderwidth = 1. The color and partly the width of the border cannot be influenced.

The following attributes are not yet implemented in this version:

37.1.4.1.14 Toolbar

The toolbar can have two different forms on Qt, which are set via the .style attribute. By default, the style toolbar is active, which visually matches the familiar toolbars.

Table 19-7: Attribute .style of the toolbar

Value

Description

.style = toolbar

(default value)

Conventional toolbar, corresponding to the well-known IDM toolbar.

.style = notepage

Toolbars use a dock area that lies between toolbars and inner area. Tabbed toolbars and nested toolbars are possible (see chapter “Window” object).

“Figure 19-14” shows the division of a window with different toolbars in the docked and undocked state. Tb16 and Tb18 as well as Tb19 and Tb20 are tabbed toolbarsthat share their space. Tb17 is a nested toolbar embedded in the second row of the right pane.

Figure 19-14: Toolbar types in the IDM for Qt

The style notepage allows to nest multiple toolbars in in one docking area and arrange them as tabs (see chapter “Window”, “Table 19-9” for the corresponding control options). The toolbars then have a title bar and can be undocked and closed using their title buttons.

Toolbars of different styles defined in the same docking area cannot be mixed and are grouped according to their style. Toolbars with the style toolbar are always positioned at the outer edge of the window and toolbars with the style notepage are always positioned between the client area of the window and the toolbars with the style toolbar (see “Figure 19-15”).

Figure 19-15: Toolbars of different styles in the lower docking area (dock_down)

Toolbars cannot be positioned with spaces between them. The attribute .autoalign has no function.

Toolbars with the toolbar style cannot be resized with the mouse and do not create move events when moved.

The attribute .sizeable behaves when true like the attribute .autosize, that is, the entire available width or height is filled. If false, the set size is retained under all circumstances.

Toolbars are not automatically wrapped in the next row or column if not all of them fit into the given window width or height. In this case, Qt enlarges the window accordingly to accommodate all toolbars. A new row or column can only be forced through the .dock_line attribute.

For toolbars with the notepage style, positioning depends on the opt_nested_docks and opt_tabbed_docks window options. If both options are deactivated (default), then .dock_line is ignored and all toolbars are arranged side by side (horizontal) or one above the other (vertically).

If the option opt_nested_docks is active, then .dock_line is considered. Nesting is always relative to the previous toolbar of the same docking area. In “Figure 19-16” the toolbars eins, zwei and drei each have .dock_line = 1, vier has .dock_line = 2 and is embedded into „drei“.

Figure 19-16: Toolbars with style notepage and opt_nested_docks active

If the opt_tabbed_docks option is active, all toolbars with the same .dock_line are displayed as consecutive tab pages (“Figure 19-17”).

Figure 19-17: Toolbars with style notepage and opt_tabbed_docks active

Depending on the UI style, no boundary from the client area may be displayed for .style = notepage.

When switching between horizontal and vertical docking, the width and height are not reversed, because depending on the type of the toolbar, changes of orientation may already occur during the move.

The attributes .height[] and .width[] are only supported and applied in the notepage style.

37.1.4.1.14.1 Behavior

With tabbed toolbars, activating a tab or the associated visualization sends an activate event (similar to notebook and notepage).

Sending events such as activate, deactive, close, move and resize strongly depends on the Qt toolbar object in use. Internal states such as User is still dragging cannot be taken into account.

“Table 19-8” summarizes the differences and limitations of the toolbar in the IDM for Qt.

Table 19-8: Differences and limitations of the toolbar

.style

Conditions

Limitations and Differences

all

 

.autoalign is not supported.

all

.sizeraster = true and
.docking <> dock_window

Toolbar area is not adjusted to grid size.

all

.dock_offset > 0 and
.docking <> dock_window

Toolbars cannot be positioned at a distance (whitespace).

notepage

 

.max_height, .max_width, .min_height, and .min_width have no effect.

toolbar

.sizeable = true and
.docking <> dock_window

No size bar; toolbar size can only be influenced in one direction (depending on the docking position). The size in the other direction is determined by the maximum width or height.

Behavior corresponds to .autosize = true.

toolbar

.sizeable = true and
.docking = dock_window

Toolbar size cannot be changed.

toolbar

.autosize = true and
.docking <> dock_window

Maximum possible width or height.

toolbar

.docking <> dock_window and set minimum or maximum width or height

Minimum and maximum sizes do not affect the overall size of the toolbar, but cut content or create empty areas.

toolbar

 

No activate and deactivate events.

toolbar

Move while preserving the docking state with .docking = dock_window

No moveevents.

37.1.4.1.15 Window

The window object has four additional options for supporting toolbars and tabbed docks, as well as sizing and positioning a window to be Qt-compliant.

Table 19-9: Options of the window object

.options[…] Value

Default Value

Meaning

opt_window_size

false

true: Size specifications (.width, .height, minimum and maximum values) refer to the entire window, including menu bar, toolbars, tabbed widgets and status bar, but without decoration (title bar, margins).

false: Size specifications refer to the interior (client area) of the window.

opt_animated

false

true: Animated, interactive moving of toolbars. However, this leads to significantly more resize and move events.

false: No animations when moving toolbars.

opt_nested_docks

false

The option only affects toolbars with the notepage style.

true: Adjacent, multi-row docks are possible. However, this leads to a not so clear operation with interactions and shifts.

false: Only single-row docks are possible.

opt_tabbed_docks

false

The option only affects toolbars with the notepage style.

true: Tabbed docks that share the space are possible. Tabbed docks can be operated similar to notebooks and notepages (see chapter “Toolbar”).

false: Tabbed docks are not possible.

As on Motif (and unlike Microsoft Windows), on Qt the .sensitive attribute does not affect the title bar of the window. Even if .sensitive = false (and the window content is no longer operable), the title bar functions (close, move, minimize, maximize…) can still be used.

The attribute .moveablehas no effect on Qt. Windows can always be moved.

In general, the IDM for Qt generates significantly more move and resize events than the other IDM versions, because for each pixel to be increased, decreased, or moved a corresponding event is triggered. There is no reliable way to determine the state and end of the actions.

Some window states can only be changed by internally clobbering, which triggers activate and deactivate events, however.

It may still happen that size specifications in certain constellations are not correctly put into effect (e.g. when changing them in the minimized state). Currently, the behavior may vary depending on the Window Manager (for example, when minimizing).

37.1.4.2 Resources

37.1.4.2.1 Mnemonics

The following objects support mnemonics:

37.1.4.2.2 Color
37.1.4.2.2.1 Color Identifiers and Null Color

As color identifiers all SVG color names can be used (http://www.w3.org/TR/SVG/types.html#ColorKeywords), where upper and lower case is ignored. When using these color names (for example, green), the colors are realized according to the SVG color names of the W3C. Therefore, some colors differ in tone and intensity from the X11 colors.

In addition, the following Qt default colors depending on the current settings are available:

Normal and active states are identical.

The identifier DEFAULT serves as null color. If this color is assigned, the respective color is reset to the corresponding default color (depending on the current system settings).

37.1.4.2.2.2 Gradients

Color resources support gradients on Qt. These are defined as follows:

color {<Identifier>} gradient("<kind>[,<arg>]");

The parameter <kind> defines the gradient type. Only one gradient type may be specified.

The other parameters may include:

These gradient types are available:

Table 19-10: Types of gradients

Gradient

Definition

Explanation

linear

gradient("Linear, ...")

gradient("LinearV, ...")

vertical gradient

gradient("LinearH, ...")

horizontal gradient

radial

gradient("Radial, ...")

gradient("Radial, <R>, ...")

radial gradient with default radius 50%

radial gradient with supplementary parameter radius R%

radius is given as a percentage of the available space

conical

gradient("Conical, ...")

gradient("Conical, <S>, ...")

conical gradient with start at 90°

conical gradient with supplementary parameter S°, which indicates the starting angle

The color definitions are always appended after the gradient type and any supplementary parameters. You can use color names, HTML notation, and the rgb(…), hls(…), and grey(…) notations known for color resources.

In addition, a stop point can be specified for each color definition, which determines the weighting of the color. A stop point is a percentage with an optional percentage sign that always precedes each color and affects how much space that color occupies in the gradient. A gradient starts at 0% and ends at 100%, based on the area it fills. The specification … , 20%, green, ... means, for example, that after 20% of the area to be filled, the color green is set. If no other color is set for the 0–20% range, the first 20% of the range is colored green. If another color is already set before 20%, then a transition between this color and green is displayed.

Stop points should always be set in ascending order. If several colors are defined with the same stop point, the color that is furthest at the end of the parameter list applies. For example, the definition .... , 20%, green, 40%, blue, 20%, red, ... produces a gradient with a shade of red at 20%, which changes to a blue tone that is shown as saturated at 40%.

Examples

gradient("Linear, green, yellow, red");  named colors, evenly distributed
gradient("Linear, #00FFFF, #00FF00, #FF0000");  HTML notation,
                                                colors evenly distributed
gradient("Linear,red, #00FF00, rgb(0,0,255)");  mixed notations,
                                                colors evenly distributed
gradient("Linear, 20%, green, 60%, yellow, 80%, red");  named colors with
                                                        percentage stop points
gradient("Linear, 20, green, 60, yellow, 80 ,red");  the % sign at the
                                                     stop points is optional

Notes

Qt allows the setting of gradients in most places, but does not necessarily apply them. Whether a gradient is displayed depends very much on the object and the UI style. In this case, areas (e.g. backgrounds) are usually unproblematic, with delicate structures (e.g. texts) the gradient is often replaced by a single color. For grouping objects, gradients as a background are usually displayed.

37.1.4.2.3 Cursor

There are the following named cursors where the corresponding Qt CursorShape is loaded:

The appearance of the cursors may vary depending on the UI style.

37.1.4.2.4 Font

Fonts can be defined in the following ways:

X Logical Font Description (XLFD)

"-adobe-helvetica-medium-r-normal--12-*-*-*-p-*-iso8859-1"
"*adobe-helvetica-bold-r-normal-*-100-*-iso8859-1"

Notes

Attention

Qt Style with Comma-separated Parameter List

Family, PointSize, PixelSize, QFont::StyleHint, QFont::Weight, QFont::Style,
Flag underline, Flag strikeout, Flag pixedPitch, Flag rawMode
"Helvetica, 12, -1, 5, 75, 1, 0, 0, 0, 0"

Not all parameters have to be specified, "Helvetica, 12" is sufficient, for example.

Font with Independent Display Attributes (Size and Style)

"Helvetica", 12, bold

The styles bold, italic and oblique are supported.

Qt style specifications can be combined with independent display attributes:

"Helvetica, 12", bold

37.1.4.3 Attributes

37.1.4.3.1 colorname[integer]

Attribute of the setup object that contains a list with the names of the colors available in the WSI.

 

Identifier

Data Type

Rule Language

.colorname[integer]

string

C

AT_colorname

DT_string

COBOL

AT-colorname

DT-string

Classification

object-specific attribute

Objects

setup

Index data type

integer

Access

get

Default value

changed event

no

Inheritance

no

Availability

IDM for Qt only, since IDM version A.06.01.a.

37.1.4.3.2 cursorname[integer]

Attribute of the setup object that contains a list with the names of the cursors available at the WSI.

 

Identifier

Data Type

Rule Language

.cursorname[integer]

string

C

AT_cursorname

DT_string

COBOL

AT-cursorname

DT-string

Classification

object-specific attribute

Objects

setup

Index data type

integer

Access

get

Default value

changed event

no

Inheritance

no

Availability

IDM for Qt only, since IDM version A.06.01.a.

37.1.4.3.3 fontname[integer]

Attribute of the setup object that contains a list with the names of the fonts available in the WSI.

 

Identifier

Data Type

Rule Language

.fontname[integer]

string

C

AT_fontname

DT_string

COBOL

AT-fontname

DT-string

Classification

object-specific attribute

Objects

setup

Index data type

integer

Access

get

Default value

changed event

no

Inheritance

no

Availability

IDM for Qt only, since IDM version A.06.01.a.

37.1.4.3.4 picture and picture_hilite

If in listbox and poptext a tile is only set for .picture_hilite, but not for .picture, then Qt will display the tile defined in .picture_hilite (or a slight modification of it) even in the unselected state. Qt always tries to provide images for all states for the list entries. If the image is missing for a state, Qt generates it from the images provided.

37.1.4.3.5 statushelp

When hovering over different objects with the mouse, the corresponding status texts are displayed when changing from a parent object to a child object. However, if the mouse is moved back from the child to the parent object, the status text of the parent object will not be displayed again.

37.1.4.4 Interface Function DM_PictureHandler

The structure DM_PicInfo on Qt corresponds to that on Motif.

typedef struct {
  ...
  #  if defined(MOTIF) || defined(QT)
       DM_UInt2    type;        // image type
       DM_Pointer  image;       // pointer to the image data
       DM_Pointer  trans_mask;  // pointer to the transparency mask
  #  endif
  ...
} DM_PicInfo;

Image type (type) can be one of the following values:

The data type of image and trans_mask must match the specified image type.

37.1.5 Known Issues and Limitations of this Release

37.1.5.1 Qt 4.6

We recommend – also for reasons of stability – to use the Qt version 4.8:

37.1.5.2 Borders

If an object that has a border with style border_plain (or border_compat and .borderwidth > 1) is horizontally negatively positioned, or if it is made visible within a virtual area by horizontal scrolling, then a diagonal line or notch ( in the background color of the father) may exist in the lower right corner of its borders.

37.1.5.3 Events

It can still happen that an object without intermediate focus loss receives multiple focus events. Certain attribute changes that require internal recreation of objects (clobbering) still influence the event processing.

37.1.5.4 Drag-and-Drop

The following explanations refer to the drag-and-drop with the mouse.

The resources source and target as well as the data transfer between applications or objects have been implemented with the classes and events offered by Qt. The functionality is similar to Microsoft Windows, with only the types type_text and type_object supported. The cursors displayed during drag-and-drop (while dragging, dropping possible or impossible) are controlled by Qt and depend on the UI style.

Possible responses of some objects to drag-and-drop actions (for example, unwanted scrolling of listbox and treeview while dragging with the mouse) are currently not considered.

37.1.5.5 Command Line Option -IDMserver

The IDM for Qt displays the following information with the command line option:

37.2 Border Attributes

37.2.1 New Features

Up to now, object borders were rendered in different forms depending on the WSI and its possibilities and influenced the position and extent of an object in different ways.

As of IDM version 6, the handling and application of border attributes and their effects on the appearance and geometry of an object have been standardized – also in terms of the portability of dialogs.

Starting with IDM Version 6, the user has at hand a largely uniform availability, implementation and enhancement of the border attributes as well as their effects on appearance and geometry across all WSI's.

This ensures better portability of dialogs to other WSI's, which was previously not the case due to the sometimes significant differences in geometry implementation and representation between the individual WSI's or resulted in more complex porting work.

The new attribute .borderstyle now provides the user with extended design options for the style and characteristics of borders at certain objects.

37.2.2 Border Design

The attribute .borderstyle is decisive for the border style of an object. Possible style options are: border off, toolkit border, line-shaped border, raised 3D border, and sunken 3D border.

Figure 19-18: Border styles

The following objects have the attribute .borderstyle:

The value range for the objects edittext, image, progressbar, statusbar, toolbar, and window is restricted to the two values border off and toolkit border.

The .borderstyle attribute is closely related to the attributes .borderwidth and .bordercolor. In the style of a line-shaped border, .borderwidth and .bordercolor affect the width and color of the border. With the two 3D border styles, the width of the frame can be influenced via .borderwidth.

The attribute .borderstyle always takes precedence over the attributes .borderwidth and .bordercolor. That is, .borderwidth and .bordercolor are only observed if permitted by the .borderstyle set.

Examples

groupbox Gb 
{
  .borderstyle border_plain;  // simple line-shaped border
  .borderwidth 5;             // frame is 5 pixels wide
  .bordercolor CoRed;         // frame is drawn in red
}
 
groupbox Gb2 
{
  .borderstyle border_none;  // switch off border
  .borderwidth 5;            // remains without effect, because without border
  .bordercolor CoRed;        // remains without effect, because without border
}
 
groupbox Gb3 
{
  .borderstyle border_toolkit;  // default toolkit border of the WSI
  .borderwidth 5;               // remains without effect as WSI draws
  .bordercolor CoRed;           // remains without effect as WSI draws
}
 
groupbox Gb4 
{
  .borderstyle border_plain;  // simple line-shaped border
  .borderwidth 0;             // is converted to the standard border width
                              // of the WSI
  .bordercolor CoRed;         // border is drawn in red
}

Objects that do not support the .borderstyle attribute but have the attributes .borderwidth and .bordercolor from the history can still set and read these attributes, but they no longer affect the graphical display of these objects.

37.2.2.1 Compatibility Regarding Design

Existing dialogs are started in a compatibility mode. This means that objects, which have .borderwidth or .bordercolor set and now also support the new .borderstyle attribute, are rendered according to how IDM 5 works. That is, no visible changes occur for the affected objects.

In this case, the .borderstyle attribute is set to border_compat. However, the user is encouraged to adapt .borderstyle of these objects accordingly to a desired variant, since the compatibility mode border_compat may be omitted in the future. The compatibility mode border_compat cannot be actively set by the user.

There are objects for which setting borders is no longer supported and the rendering is left entirely to the WSI. These include listbox, notebook, notepage, tablefield, and treeview.

For these objects, where .borderwidth and .bordercolor are no longer supported, a warning message about obsolete attribute settings is output. The settings are no longer observed by the WSI and show no effects. The user should rewrite the places where these warnings now appear, since in future versions these attributes may be omitted from these objects.

37.2.2.2 Motif-Option .options[opt_xmborder_compat]

.borderwidth at the tablefield now has the default value 0 instead of former 1. This only has effects on Motif. There is the compatibility option .options [opt_xmborder_compat] available for Motif to convert the tablefield back to its former representation. A setting of .borderwidth = 1 also leads to the previous appearance, however, an additional warning message appears because .borderwidth will no longer be supported for the tablefield in the future.

37.2.2.3 WSI Limitations and Specifics

37.2.2.3.1 Motif

The toolkit border of the groupbox is a 3D border.

Objects with a virtual area – these include the groupbox with .vwidth or .vheight and the layoutbox – cannot display the border_raised and border_sunken border styles; instead, a border is drawn that corresponds to the border_plain style and can therefore also apply the correct .borderwidth. Only a groupbox without a virtual area is not restricted.

Since there may be drawing problems on Motif when an object has position 0 or negative, drawing of the border is omitted in this case.

37.2.2.3.2 Windows

The objects canvas and rectangle had 3-dimensional, colored borders in the IDM 5. These borders are only available in border_compat border style. With the new border styles, there are either 3-dimensional borders in the system color or flat, colored borders.

The objects notepage and tablefield have no .borderstyle attribute and thus no compatibility to the IDM 5 The tablefield object now has a default border width and the object notepage no longer has a border of its own.

The height of the poptext object was calculated 2 pixels too high in the IDM 5 when Visual Styles were active. This is now corrected, except in the style listbox, where the height already was correct.

The styles border_raised and border_sunken require a minimum width of 2 pixels in order to display feedback if necessary. That is, if the user has specified a .borderwidth of 0 or 1 pixel here, the border will still be drawn with 2 pixels.

37.2.2.3.3 Qt

For the following objects, the attribute .borderstyle has no effect at all:

The spinbox object always draws a border on Qt. The attribute .borderstyle only determines where this border is drawn. With border_none the border is drawn inside the object, with .borderstyle = border_toolkit outside.

The frames are determined and drawn significantly by the set UI style. The appearance may vary depending on the UI style.

37.2.3 Geometry

Across all WSI's, grouping objects now always draw their frame outside the object.

The geometry calculation – no matter whether normal or with grid – is performed according to previous rules and based on the reference points .xleft and .ytop as well as .xright and .ybottom.

However, these points as well as .width and .height only define the object position and size excluding the border. They define the client area of the grouping object. This provides the maximum available space for the child objects. The border is drawn by the WSI on the outside around this dimension.

Figure 19-19: Position and size of grouping objects with borders (example border_plain)

The exception to this is the window object, whose positioning and dimensions remain unchanged.

Example

Groupbox Gb {
  .width  100;  // The inner area of the groupbox has a size of
  .height 50;   // 100x50 pixels.
  .xleft  20;   // The outermost point of the interior is [20,15].
  .ytop   15;
  .borderstyle border_plain;
  .borderwidth 5;
}
// => The actual size of the object including the border is 110x60
//    (width + left border + right border and height + upper border +
//    lower border). Outer point on the top left is [15,10].

For non-grouping objects, there are no changes regarding the geometry. They continue to draw their borders inside. The attributes .xleft and .ytop as well as .xright and .ybottom thus define the outermost points, .width und .height the entire size of the object.

Figure 19-20: Positionierung und Größe bei einfachen Objekten

37.2.3.1 Compatibility Regarding Positioning

On Motif, there may be a slight shift of grouping objects in existing dialogs because the real size of grouping objects with borders is now larger than before and the real position is shifted one border width to the left and up. But this also means that the client area of such grouping objects is now larger and offers more space for its children.

Furthermore, this results in several groupboxes, which are nested via.xauto = 0 and .yauto = 0, now optimally use the space and themselves, as well as their children are no longer displayed cropped.

Figure 19-21: Nested groupboxes in IDM 5 (left) and in IDM 6 (right)

37.2.3.2 Command Line Option -IDMborder5_compat

On Motif, objects with negative coordinates and their children are partly not navigable and focusable. This also applies if the object is only partially out of the visible area. This is a limitation of the WSI.

Because borders of grouping objects are now always drawn outside, resulting in a position shift, it is possible that grouping objects and their children in existing dialogs may suddenly no longer be navigable, for example, because the border has been moved into the negative. Therefore, a geometry compatibility mode is introduced via a command line option ‑IDMborder5_compat, which computes the geometry according to IDM 5 rules.

On Microsoft Windows, there are a number of compatibility options that are no longer evaluated. If existing dialogs cannot be adjusted immediately, the evaluation of these compatibility options can be reactivated via the command line option ‑IDMborder5_compat. The following options (attribute .options[]) are affected:

In addition, the height of the poptext object is calculated as in IDM 5.

The border5_compat mode can also be activated through setting the environment variable IDM_BORDER5_COMPAT.

37.2.4 Attribute .borderstyle

This attribute defines the style, i.e. the representation and characteristics of the borders of an object.

 

Identifier

Data Type

Rule Language

.borderstyle

enum

C

AT_borderstyle

DT_enum

COBOL

AT-borderstyle

DT-enum

Classification

layout attribute

Access

get, set

Default value

border_compat

changed event

yes

Inheritance

yes

The following value range is predefined:

Value

Meaning

border_compat

compatibility mode

border_none

no borders are drawn around the object

border_plain

the border is drawn as a simple, flat line around the object, can be influenced in width and color *

border_raised

the border is drawn as a 3D border around the object, the border is heightened outwards and can be influenced in its width *

border_sunken

the border is drawn as a 3D border around the object, the border is deepened inwards and can be influenced in its width *

border_toolkit

the toolkit border is drawn as designated by the WSI for the particular object

* if supported by the respective WSI

Table 19-11: Support of the .borderstyle attribute

Object

Support of .borderstyle

canvas

Attribute is supported.

groupbox

Attribute is supported.

layoutbox

Attribute is supported.

rectangle

Attribute is supported.

splitbox

Attribute is supported.

edittext

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

image

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

progressbar

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

spinbox

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

statusbar

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

toolbar

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

window

Attribute is supported, but only border_none and border_toolkit are permitted. border_plain, border_raised and border_sunken are mapped to border_toolkit.

checkbox

Attribute is not supported.

control

Attribute is not supported.

listbox

Attribute is not supported.

notebook

Attribute is not supported.

notepage

Attribute is not supported.

poptext

Attribute is not supported.

pushbutton

Attribute is not supported.

radiobutton

Attribute is not supported.

scrollbar

Attribute is not supported.

statictext

Attribute is not supported.

tablefield

Attribute is not supported.

treeview

Attribute is not supported.

37.2.5 Enhancements in the Editor

Using the Properties tool palette, you can select the Borderstyle of an object on the Layout tab in the Object pane, provided that this object supports the attribute.

Figure 19-22: Modifying .borderstyle in the IDM Editor

Since the compatibility mode cannot be set actively, the user receives an error message on Apply after switching to border_compat.

To restore the default border_compat it is recommended to uncheck the box next to Borderstyle. Thus the standard is applied again (unless one of the parents has set a different value, then this is inherited).

37.3 New Objects datetime and listview

37.3.1 datetime

The datetime object (class name dmw_datetime) provides a simple and intuitive way to enter dates and times. It can display date or time values or both in different formats. Besides keyboard input, the user can change the values, for example by selecting a date from a calendar (upper datetime object in “Figure 19-23”) or using spin buttons (lower datetime object in “Figure 19-23”). In addition, the user can be enabled to set the value to indefinite using a checkbox (right part of “Figure 19-23”).

Figure 19-23: datetime objects

“Figure 19-24” shows a datetime object with the calendar unfolded. The appearance of the calendar can be adjusted by several attributes. For example, in the right part of “Figure 19-24”, the numbers of the calendar weeks and the current date are displayed in the calendar.

Figure 19-24: datetime object with opened calendar

The presentation of the date and time values can be controlled using a format string. You can use predefined system formats or define own display formats using the corresponding formatting characters. In both cases, the language and region settings of the system are taken into account (for example, for the month names). “Figure 19-25” shows datetime objects with formats that contain extra, non-editable text in addition to parts of the date or time.

Figure 19-25: datetime objects with different formats

Availability

37.3.1.1 Definition

{ export | reexport } { model } dmw_datetime { <Identifier> }
{
  <standard attributes>
  <geometry attributes>
  <hierarchy attributes>
  <layout attributes>
  <text attributes>
  <object-specific attributes>
}

Events

changed

deselect

extevent

focus

help

select

Children

None

Parent

groupbox

layoutbox

notepage

splitbox

toolbar

window

Menu

Pop-up Menu

37.3.1.2 Description of Events

37.3.1.2.1 deselect

The deselect event occurs when the datetime has lost the focus. This is an indication that the user has completed entering or selecting the date or time. However, it should be noted that this event is not only triggered by direct user actions, but may also occur as a side effect of other actions:

Note

Opening a menu or pop-up does not necessarily move the focus. Therefore, it cannot be predicted whether a deselect event will occur for these actions. For example, a deselect event may not be triggered until the select event rule of a menuitem is executed, if it is triggered at all.

37.3.1.2.2 select

The select event will occur each time the content of the .value attribute changes. The event can be triggered by various actions of the user:

This means that multiple select events will typically occur before the user has entered, set or selected the final value. Therefore, the event rule for the select event should not perform any extensive actions.

The .real_modified attribute can be used to check whether the value of the datetime has actually changed due to the user actions, compared to the value of the datetime when it received the focus.

The select event may also occur if .minvalue or .maxvalue are violated. This depends on the system object, but here too a content change of .value must be present.

37.3.1.3 Attribute Overview

Attribute

Short Description

Data Type

Default

Access

C

I

get

set

.allowundefined

acceptance of indefinite values

boolean

false

x

x

x

x

.calendaralignment

position of the calendar

integer
(-1, 0, 1)

1

x

x

x

x

.format

display format

string

""

x

x

x

x

.maxvalue

maximum value

string

""

x

x

x

x

.minvalue

minimum value

string

""

x

x

x

x

.real_modified

indicates actual change of .value

boolean

 

x

.shortdaynames

display of short weekday names

boolean

false

x

x

x

x

.style

value input through a fold-out calendar or a spinbox

class
(poptext, spinbox)

poptext

x

x

x

x

.today

display of current date

boolean

true

x

x

x

x

.todaymarker

highlighting of current date

boolean

true

x

x

x

x

.trailingdates

display days of previous and next month

boolean

true

x

x

x

x

.value

date and/or time value

string

""

x

x

x

x

.weeknumbers

display of calendar week

boolean

false

x

x

x

x

C

changed event on modification

I

Attribute is inherited

37.3.1.4 Description of Attributes

37.3.1.4.1 .allowundefined

This attribute determines whether the user can set the value of the object to indefinite.

 

Identifier

Data Type

Rule Language

.allowundefined

boolean

C

AT_allowundefined

DT_boolean

COBOL

AT-allowundefined

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

false

changed event

yes

Inheritance

yes

If the attribute has the value true, a checkbox is displayed in the datetime. Deactivating the checkbox sets the value to indefinite. The attribute .value then has the value "".

With .allowundefined = true, invalid values of .value cause the checkbox to be activated.

Value range

true

The content of .value can be set to indefinite by the user. To do so, a checkbox is displayed in the datetime.

false

The user can not set .value to indefinite ("").

Note

Changing .allowundefined in the visible state may lead to a reset of the object.

37.3.1.4.2 .calendaralignment

This attribute defines the position of the fold-out calendar relative to the object.

 

Identifier

Data Type

Rule Language

.calendaralignment

integer

C

AT_calendaralignment

DT_integer

COBOL

AT-calendaralignment

DT-integer

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

1

changed event

yes

Inheritance

yes

Value range

1

The calendar is left aligned (default).

0

The calendar is centered.

This value is not supported; the default value is used.

-1

The calendar is right aligned.

37.3.1.4.3 .format

This attribute defines the display format of the datetime object.

 

Identifier

Data Type

Rule Language

.format

string, object (text)

C

AT_format

DT_string, DT_text

COBOL

AT-format

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

Value range

""

short date format (like "widget:d")

widget:d

system format: short date format

widget:dd

system format: short date format with 4-digit year

widget:ddd

system format: long date format

widget:t

system format: time format

<format_string>

format string for defining the display format

System formats

The system formats depend on the language and region settings of the operating system. They completely determine the display format and cannot be combined with each other or with format strings. For example, no caption can be added to a system format.

Format strings

Format strings consist of formatting characters that define which parts of a date are displayed and how those parts are displayed.

Table 19-12: Formatting characters of the datetime object

Formatting Character

Display

d

day with as many digits as necessary

dd

day with 2 digits, possibly with leading 0

ddd

name of the weekday (language-dependent), abbreviated to 3 characters

dddd

full name of the weekday (language-dependent)

h

hour in 12-hour format with as many digits as necessary

hh

hour in 12-hour format with 2 digits, possibly with leading 0

H

hour in 24-hour format with as many digits as necessary

HH

hour in 24-hour format with 2 digits, possibly with leading 0

m

minute with as many digits as necessary

mm

minute with 2 digits, possibly with leading 0

M

month with as many digits as necessary

MM

month with 2 digits, possibly with leading 0

MMM

month name (language-dependent), abbreviated to 3 characters

MMMM

full month name (language-dependent)

s

second with as many digits as necessary

ss

second with 2 digits, possibly with leading 0

t

morning or afternoon indicator (language-dependent, in English AM and PM) with one character; use is not recommended.

tt

morning or afternoon indicator (language-dependent, in English AM and PM) with 2 characters

yy

year with 2 digits

yyyy

year with 4 digits

Any characters other than the formatting characters mentioned are included in the display. Characters to be displayed may optionally be enclosed in single quotes ('). They must be enclosed in single quotes if they are equivalent to a formatting character. To display a single quotation mark, it must be doubled in the format string ('').

Example

The format string 'Today is 'dddd', 'MMM dd', 'yyyyy produces the following output: Today is Friday, Jul 04, 2014.

Notes

  • If the format string is incorrect, the system-dependent standard format is used (corresponds to .format ="").
  • The labels and symbols displayed for ddd, dddd, MMM, MMMM, t, and tt are determined by the language and region settings of the system.
  • With long display texts, it may happen that no calendar symbol is displayed on the button for opening the calendar.
37.3.1.4.4 .maxvalue

This attribute determines the maximum value.

 

Identifier

Data Type

Rule Language

.maxvalue

string, object (text)

C

AT_maxvalue

DT_string, DT_text

COBOL

AT-maxvalue

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

Value range

""

No maximum value set.

<value_string>

Sets the contained date or time value as the maximum value.

The syntax and evaluation of the string are described in the chapter “.value”.

The attribute defines the largest value that can be entered or selected by the user. An existing content of .value is usually not corrected to comply with .maxvalue. It is also not defined whether the displayed value is corrected when the datetime is made visible.

37.3.1.4.5 .minvalue

This attribute determines the minimum value.

 

Identifier

Data Type

Rule Language

.minvalue

string, object (text)

C

AT_minvalue

DT_string, DT_text

COBOL

AT-minvalue

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

Value range

""

No minimum value set.

<value_string>

Sets the contained date or time value as the minimum value.

The syntax and evaluation of the string are described in the chapter “.value”.

The attribute defines the smallest value that can be entered or selected by the user. An existing content of .value is usually not corrected to comply with .minvalue. It is also not defined whether the displayed value is corrected when the datetime is made visible.

37.3.1.4.6 .real_modfied

Indicates whether the .value attribute has changed since the focus was obtained.

 

Identifier

Data Type

Rule Language

.real_modified

boolean

C

AT_real_modified

DT_boolean

COBOL

AT-real-modified

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get

Default value

changed event

no

Inheritance

no

Setting the .value attribute resets .real_modified to false.

On an invisible datetime object, .real_modified is always false.

Value range

false

The content of .value is unchanged.

true

The content of .value has changed.

37.3.1.4.7 .shortdaynames

This attribute determines whether short weekday names are displayed in the fold-out calendar.

 

Identifier

Data Type

Rule Language

.shortdaynames

boolean

C

AT_shortdaynames

DT_boolean

COBOL

AT-shortdaynames

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

false

changed event

yes

Inheritance

yes

The attribute is only effective as of Windows Vista.

Value range

false

Normal weekday names are displayed in the calendar.

true

Short weekday names are displayed in the calendar.

Note

In German there is no difference between short and normal weekday names.

37.3.1.4.8 .style

The attribute determines the appearance and the method of operation at the datetime object.

 

Identifier

Data Type

Rule Language

.style

class

C

AT_style

DT_class

COBOL

AT-style

DT-class

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

poptext

changed event

yes

Inheritance

yes

Value range

Value

Description

poptext

To select a date, a calendar can be opened.

spinbox

Values can be set using a spinbox.

Note

Changing the attribute in the visible state leads to a reset of the object and should be avoided.

37.3.1.4.9 .today

The attribute determines whether the current date is displayed at the bottom of the fold-out calendar.

 

Identifier

Data Type

Rule Language

.today

boolean

C

AT_today

DT_boolean

COBOL

AT-today

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

true

changed event

yes

Inheritance

yes

The attribute is only effective as of Windows Vista.

Value range

false

The current date is not displayed in the calendar.

true

The current date is displayed at the bottom of the calendar.

37.3.1.4.10 .todaymarker

This attribute controls whether the current date is marked in the fold-out calendar.

 

Identifier

Data Type

Rule Language

.todaymarker

boolean

C

AT_todaymarker

DT_boolean

COBOL

AT-todaymarker

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

true

changed event

yes

Inheritance

yes

The attribute is only effective as of Windows Vista.

Value range

false

The current date is not marked in the calendar.

true

The current date is marked in the calendar.

37.3.1.4.11 .trailingdates

This attribute controls whether the fold-out calendar displays the days adjacent to the current month.

 

Identifier

Data Type

Rule Language

.trailingdates

boolean

C

AT_trailingdates

DT_boolean

COBOL

AT-trailingdates

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

true

changed event

yes

Inheritance

yes

The attribute is only effective as of Windows Vista.

Value range

false

The calendar only shows the days of the set month.

true

The calendar also shows days of the previous and following month, so that the weeks are always displayed in full.

37.3.1.4.12 .value

This attribute defines the value of the datetime object.

 

Identifier

Data Type

Rule Language

.value

string, object (text)

C

AT_value

DT_string, DT_text

COBOL

AT-value

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

Value range

""
The current date or time is displayed.
<value_string>
Sets the contained date or time value.

Syntax and Evaluation of the Value String

The value is evaluated according to the “Definition of Time Spans” for the timer object, whereby the following absolute time definition is permitted:

<Value>     ::= {<Datevalue>}{ <TimeValue>}
<DateValue> ::= {<day>}.{<month>}.{<year>}
<TimeValue> ::= {<hour>}:{<minute>}{:{<second>}}

Deviating from the definition of time spans for the timer, it is permitted to specify only a date.

The datetime uses the Gregorian calendar. The value range extends from 01/01/1601 00:00:00 to 12/31/9999 23:59:59. Two-digit years are mapped to the time range 1970 to 2069.

When the user selects, sets or enters a value in the datetime, .value contains this value in full format dd.MM.yyyyy HH:mm:ss (see attribute .format). When a change occurs, a select event is triggered.

Parts not specified are completed in the display by the corresponding values of the current system date or the current system time. For example, for a missing year, the current year is inserted.

If the value string is syntactically incorrect, the current date or time is displayed (as with "").

Examples

The current date is 06/25/2014 and the current time is 11:53:07.

Value String

Displayed Value

12.1.

01/12/2014 11:53:07

Year and time are supplemented from the current values.

12.1

06/25/2014 11:53:07

Value string is syntactically incorrect. Current date and time are displayed.

If the value string is syntactically correct but does not represent a valid date or time (for example 29.2.2013 or 33.33.33), then it is undefined what is shown in the datetime. If the system returns an error, the current date or time is displayed. Otherwise, the system displays what it has made of the value string.

If .value ="" or is erroneous and the .allowundefined attribute has the value true, then the value is shown as indefinite (checkbox unchecked).

The additions and corrections made by the object for displaying the value do not change the attribute value. That is, .value keeps its set content until the user selects, sets or enters a value in the datetime.

The current date and time are calculated on visualization. In addition, they are calculated when in the visible state .value is set to a different value that the object adds or corrects for display (for example ""). Again, the attribute value is usually not adjusted to the shown value. Repeated setting of the same value (also of "") therefore does not represent a change in value, so in this case there is no update of the displayed value either.

37.3.1.4.13 .weeknumbers

This attribute controls whether the calendar week numbers are displayed in the fold-out calendar.

 

Identifier

Data Type

Rule Language

.weeknumbers

boolean

C

AT_weeknumbers

DT_boolean

COBOL

AT-weeknumbers

DT-boolean

Classification

object-specific attribute

Objects

dmw_datetime

Access

get, set

Default value

false

changed event

yes

Inheritance

yes

The attribute is only effective as of Windows Vista.

Value range

false

No calendar weeks are indicated in the calendar..

true

Calendar weeks are indicated in the calendar..

Note

The first calendar week of a year is the first week with at least 4 days in that year.

37.3.2 listview

The listview (class name dmw_listview) is an advanced list object that supports various display types. The object is known in principle by the Windows Explorer, where it is used to display the directories of the file system.

The following figures show the different display types of the listview object:

  1. The icon view displays large icons along with a caption. The first content column is used as the caption.

    Figure 19-26: Icon view with large icons of the listview

  2. The small icon view is very similar to the icon view, the only difference is that small icons are used.

    Figure 19-27: Icon view with small icons of the listview

  3. The list view also uses the small icons and the caption, but the items are arranged in a list from top to bottom. If necessary, additional columns are added.

    Figure 19-28: List view of the listview

  4. The detail view displays all available information in a table. Now the listview object resembles a table.

    Figure 19-29: Detail view of the listview

  5. The tile view is like the list view, but shows large icons. The caption appears next to them.

    Figure 19-30: Tile view of the listview

Availability

37.3.2.1 Definition

{ export | reexport } { model } dmw_listview { <Identifier> }
{
  <standard attributes>
  <geometry attributes>
  <hierarchy attributes>
  <layout attributes>
  <text attributes>
  <object-specific attributes>
}

Events

activate

changed

dbselect

deactivate

extevent

focus

help

resize

select

Children

None

Parent

groupbox

layoutbox

notepage

splitbox

toolbar

window

Menu

Pop-up Menu

37.3.2.2 Description of Events

37.3.2.2.1 activate

The activate event is triggered when a list item is selected (.selected[I] := true).

The .index attribute of thisevent contains the index of the item that was selected. The data type of thisevent.index is index and thus consistent with the select event. The column value of thisevent.index is always 1, since only this column has a selection status.

37.3.2.2.2 dbselect

The dbselect event occurs when a double-click is carried out in the listview.

The .index attribute of thisevent contains the index of the item that was clicked. The data type of thisevent.index is index and thus consistent with the select event. If no item was hit, thisevent.index is not set.

The header in the detail view (column headings) does not have a double-click event.

37.3.2.2.3 deactivate

The deactivate event is triggered when a list item loses its selection (.selected[I] := false).

The .index attribute of thisevent contains the index of the item that has lost its selection. The data type of thisevent.index is index and thus consistent with the select event. The column value of thisevent.index is always 1, since only this column has a selection status.

37.3.2.2.4 resize

The resize event occurs when a column width has been changed in the detail view.

The event does not arise for columns whose width has been set to 0 and is calculated by the listview.

37.3.2.2.5 select

The select event occurs when a click is carried out in the listview.

The .index attribute of thisevent contains the index of the item that was clicked. The data type of thisevent.index is index and thus consistent with the activate event. The column value can be different from 1 only in the detail view.

If no item was hit, thisevent.index is not set. When the header (column headings) of the detail view is clicked, the row value of thisevent.index is 0.

37.3.2.3 Attribute Overview

Attribute

Short Description

Data Type

Default

Access

C

I

get

set

.colcount

number of columns

integer

1

x

x

x

x

.coltitle[integer]

column headings

string

""

x

x

x

x

.colwidth[integer]

column widths in the detail view

integer

0

x

x

x

x

.content[index]

list entries, caption in column 1

string

""

x

x

x

x

.mincolwidth[integer]

minimum column width in the detail view

integer

0

x

x

x

x

.picheight

height of the large icons

integer

0

x

x

x

x

.picture[integer]

large icons

object
(tile)

""

x

x

x

x

.picwidth

width of the large icons

integer

0

x

x

x

x

.rowcount

number of rows

integer

0

x

x

x

x

.selected[integer]

selection of the list entries

boolean

false

x

x

x

x

.smallpicheight

height of the small icons

integer

0

x

x

x

x

.smallpicture[integer]

small icons

object
(tile)

""

x

x

x

x

.smallpicwidth

width of the small icons

integer

0

x

x

x

x

.style

presentation mode

integer
(0…4),

string

0

x

x

x

x

C

changed event on modification

I

Attribute is inherited

37.3.2.4 Description of Attributes

37.3.2.4.1 .colcount

The attribute defines the number of columns in the detail view.

 

Identifier

Data Type

Rule Language

.colcount

integer

C

AT_colcount

DT_integer

COBOL

AT-colcount

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

1

changed event

yes

Inheritance

yes

Value range

0

Clears the listview object.

> 0

Number of columns in the detail view.

The value of .colcount can be implicitly increased by adding one new column to .content at a time.

Column 1 is shown in all views.

For invalid values, the default value 1 is used. The attribute value is not changed, however.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.2 .coltitle[integer]

This attribute is used to set the column headings in the detail view.

 

Identifier

Data Type

Rule Language

.coltitle[integer]

string, object (text)

C

AT_coltitle

DT_string, DT_text

COBOL

AT-coltitle

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

The value range of the index is 0 … .colcountt, where the value with index 0 is used as default value for not set values in the range 1 … .colcount.

If no heading is defined for a column and no default value .coltitle[0] is defined either, then this column is displayed without a column heading.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.3 .colwidth[integer]

This attribute defines the column widths in the detail view.

 

Identifier

Data Type

Rule Language

.colwidth[integer]

integer

C

AT_colwidth

DT_integer

COBOL

AT-colwidth

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

The value range of the index is 0 … .colcountt, where the value with index 0 is used as default value for not set values in the range 1 … .colcount.

Value range

0

The column width is calculated by the listview.

The set value 0 is retained until the user changes the column width interactively.

> 0

Width of the respective column in the detail view.

For invalid values, the default value 0 is used. However, the attribute value is not changed.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.4 .content[index]

The attribute defines the list items of the listview.

 

Identifier

Data Type

Rule Language

.content[index]

string, object (text)

C

AT_content

DT_string, DT_text

COBOL

AT-content

DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_listview

Index data type index

Access

get, set

Default value

""

changed event

yes

Inheritance

yes

For write access (set), values of the data type string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type string.

The value range of the index is [0,1] … [.rowcount,.colcount], where the value with index [0,C] is used as default value for not set values in the range [1,C] … [.rowcount,C].

Column 1 is the caption of the list item that will be shown in all views. The other columns are only displayed in the detail view.

If no content is defined for .content[R,C] and no default value .content[0,C] is set, then nothing is displayed, but the item still exists.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.5 .mincolwidth[integer]

The attribute specifies the minimum column widths in the detail view of the listview object. Users cannot interactively make the columns narrower than defined in this attribute.

 

Identifier

Data Type

Rule Language

.mincolwidth[integer]

integer

C

AT_mincolwidth

DT_integer

COBOL

AT-mincolwidth

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

The value range of the index is 0 … .colcountt, where the value with index 0 is used as default value for not set values in the range 1 … .colcount.

Value range

0

No minimum column width.

The user can hide the column by dragging the right edge of the column header to the left edge of the column with the mouse button pressed. The column can be shown again by pressing the mouse button in the column header of the next column slightly to the right of the left column edge and dragging the mouse to the right while holding down the button. Pay attention to the different shape of the mouse pointer directly above the left column edge and slightly to the right of it.

> 0

Minimum column width that the user can interactively set in the detail view.

For invalid values, the default value 0 is used. However, the attribute value is not changed.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.6 .picheight

This attribute defines the height of the large icons.

 

Identifier

Data Type

Rule Language

.picheight

integer

C

AT_picheight

DT_integer

COBOL

AT-picheight

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

Value range

0

The width .picwidth is used. If this is also 0, the size of the icons is determined by the system.

> 0

Height of the large icons.

The large icons will be shown in the icon view (.style = "icon", .style = "picture") and in the tile view (.style = "tile").

For invalid values, the default value 0 is used. However, the attribute value is not changed.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.7 .picture[integer]

The attribute defines the large icon for each list item.

 

Identifier

Data Type

Rule Language

.picture[integer]

object (tile)

C

AT_picture

DT_tile

COBOL

AT-picture

DT-tile

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

null

changed event

yes

Inheritance

yes

The value range of the index is 0 … .rowcountt, where the value with index 0 is used as default value for not set values in the range 1 … .rowcount.

Value range

null

The displayed icon is derived as follows:

  • If .picture[0] <> null, the icon defined there is used.
  • If .picture[0] = null, then the small icon is shown enlarged (.smallpicture[I] or .smallpicture[0], depending on presence).
  • If there is neither a large nor a small icon, the item is displayed without an icon.

tile

Resource that contains the large icon.

The large icon will be shown in the icon view (.style = "icon", .style = "picture") and in the tile view (.style = "tile").

Large and small icons belong together and should represent the same information. Both icons can only be referenced together. Therefore, different combinations should be avoided, as each combination will consume additional memory.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.8 .picwidth

This attribute defines the width of the large icons.

 

Identifier

Data Type

Rule Language

.picwidth

integer

C

AT_picwidth

DT_integer

COBOL

AT-picwidth

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

Value range

0

The width of the icons is determined by the system.

> 0

Width of the large icons.

The large icons will be shown in the icon view (.style = "icon", .style = "picture") and in the tile view (.style = "tile").

For invalid values, the default value 0 is used. However, the attribute value is not changed.

If .picheight = 0 then .picwidth also determines the height of the large icons.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.9 .rowcount

This attribute defines the number of list items.

 

Identifier

Data Type

Rule Language

.rowcount

integer

C

AT_rowcount

DT_integer

COBOL

AT-rowcount

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

The value range of .rowcount is 0 … n (n > 0).

The value of .rowcount can be implicitly increased by adding one new row to .content at a time.

For invalid values, the default value 0 is used. The attribute value is not changed, however.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.10 .selected[integer]

This attribute determines for each list item of the listview object whether it is selected.

 

Identifier

Data Type

Rule Language

.selected[integer]

boolean

C

AT_selected

DT_boolean

COBOL

AT-selected

DT-boolean

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

false

changed event

yes

Inheritance

yes

The value range of the index is 0 … .rowcountt, where the value with index 0 is used as default value for not set values in the range 1 … .rowcount.

Value range

false

The list item is not selected.

true

The list item is selected.

The attribute will be modified through user interaction (activate and deactivate events).

Note

The appearance of selected items depends on the system. This applies in particular to the visibility of the selection when the listview does not have the focus.

37.3.2.4.11 .smallpicheight

This attribute defines the height of the small icons.

 

Identifier

Data Type

Rule Language

.smallpicheight

integer

C

AT_smallpicheight

DT_integer

COBOL

AT-smallpicheight

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

0
The width .smallpicwidth is used. If this is also 0, the size of the icons is determined by the system.
> 0
Height of the small icons.

The small icons will be shown in the small icon view (.style = "smallicon", .style = "smallpicture"), in the list view (.style = "list") and in the detail view (.style = "detail", .style = "report").

For invalid values, the default value 0 is used. However, the attribute value is not changed.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.12 .smallpicture[integer]

The attribute defines the small icon for each list item.

 

Identifier

Data Type

Rule Language

.smallpicture[integer]

object (tile)

C

AT_smallpicture

DT_tile

COBOL

AT-smallpicture

DT-tile

Classification

object-specific attribute

Objects

dmw_listview

Index data type integer

Access

get, set

Default value

null

changed event

yes

Inheritance

yes

The value range of the index is 0 … .rowcountt, where the value with index 0 is used as default value for not set values in the range 1 … .rowcount.

Value range

null

The displayed icon is derived as follows:

  • If .smallpicture[0] <> null, the icon defined there is used.
  • If .smallpicture[0] = null, then the small icon is shown downsized (.picture[I] or .picture[0], depending on presence).
  • If there is neither a small nor a large icon, the item is displayed without an icon.

tile

Resource that contains the small icon.

The small icons will be shown in the small icon view (.style = "smallicon", .style = "smallpicture"), in the list view (.style = "list") and in the detail view (.style = "detail", .style = "report").

Small and large icons belong together and should represent the same information. Both icons can only be referenced together. Therefore, different combinations should be avoided, as each combination will consume additional memory.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.13 .smallpicwidth

This attribute defines the width of the small icons.

 

Identifier

Data Type

Rule Language

.smallpicwidth

integer

C

AT_smallpicwidth

DT_integer

COBOL

AT-smallpicwidth

DT-integer

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

Value range

0

The width of the icons is determined by the system.

> 0

Width of the small icons.

The small icons will be shown in the small icon view (.style = "smallicon", .style = "smallpicture"), in the list view (.style = "list") and in the detail view (.style = "detail", .style = "report").

For invalid values, the default value 0 is used. However, the attribute value is not changed.

If .smallpicheight = 0 then .smallpicwidth also determines the height of the small icons.

Changing the attribute in the visible state may cause the object to flicker.

37.3.2.4.14 .style

This attribute determines the presentation mode of the listview.

 

Identifier

Data Type

Rule Language

.style

integer, string, object (text)

C

AT_style

DT_integer, DT_string, DT_text

COBOL

AT-style

DT-integer, DT-string, DT-text

Classification

object-specific attribute

Objects

dmw_listview

Access

get, set

Default value

0

changed event

yes

Inheritance

yes

For write access (set), values of the data type integer, string and text resources can be specified. text resources are automatically converted to string.

Read access (get) always returns a value of the data type integer.

Value range

Value

Description

integer

string

0

"icon"
"picture"

Icon view with large icons.

Arrangement of list items first from left to right, then from top to bottom.

The icon is placed above the item's caption.

1

"smallicon"
"smallpicture"

Icon view with small icons.

Arrangement of list items first from left to right, then from top to bottom.

The icon is placed to the left of the item's caption.

2

"list"

List view with small icons.

Arrangement of list items first from top to bottom, then from left to right.

The icon is placed to the left of the item's caption.

3

"detail"
"report"

List with small icons where the list items are arranged one below the other.

A small icon is shown to the left of the caption.

For each list item, detailed information is displayed in several columns.

The presentation resembles a table.

4

"tile"

Display of the list items as tiles with large icons on the left and captions on the right.

Arrangement of the list items one below the other.

For invalid values, the default value 0 is used. However, the attribute value is not changed.

37.4 Enhancement of the USW Interface

37.4.1 UC_InqName

The data type UC_InqName has been extended:

typedef enum {
  UC_I_undef = 0,
  ...
  UC_I_notify,
  UC_I_replace  // since IDM version A.06.01.a
} UC_InqName;

37.4.2 UC_API

The structure UC_API has been extended:

typedef struct {
  DM_UInt1 version;
  ...
  UC_ControlFunc          control;          // since IDM version A.05.02.g
  UC_GetToolkitDataExFunc getToolkitDataEx  // since IDM version A.06.01.a
} UC_API;

37.4.3 UC_InqArg

The structure UC_InqArg has been extended:

typedef struct {
  DM_InqName name;
  union {
    ...
    UC_Notify  notify;
    UC_Replace replace;  // since IDM version A.06.01.a
  } arg;
} UC_InqArg;

37.4.4 UC_Replace

Notification that the definition of a used IDM resource has changed. It is up to the WSI when and for which resources UC_Inquire is called with UC_I_Replace.

typedef struct {
  DM_ID dmid;
} UC_Replace;

The element dmid indicates the resource that has been changed.

37.4.5 getToolkitDataEx

Function for retrieving toolkit data (e.g. resources).

typedef FPTR (DML_default DM_EXPORT *UC_GetToolkitDataExFunc)
  __((DM_ID        dmid,
      DM_Attribute attr,
      FPTR         data,
      DM_Options   options));

Parameters

DM_ID dmid

Identifier of the object.

DM_Attribute attr

IDM attribute to be queried.

FPTR data

Pointer to additional data, if not used this must be NULL.

DM_Options options

IDM option, currently none available.

Return value

Depending on the kind of value being queried, this function returns the corresponding values converted to FPTR (see C interface function DM_GetToolkitDataEx).

37.4.6 UC_Inquire

Inquiry

Input

Output

name == UC_I_Replace

The UW class can handle the notification that a resource has been changed.

arg.replace.dmid

The IDM-ID of the resource that has changed.

none

37.5 Data Types for Collections

37.5.1 Enhancement of the Data Types

The following new collection data types are now allowed in the IDM. Please note that only scalar types are permitted for the addressing as well as for the addressed single values. Therefore a structure of multidimensional lists is not possible.

Table 19-13: Data types for collections

Data Type

Meaning

list

This data type defines a list of arbitrary values in the addressing range 0 … 231. Via 0 the default value is addressed, which is inherited by all list values. This data type is intended and optimized for the manipulation of lists in the Rule Language.

vector

This data type defines a list that contains values of the same type. There is no default value. Therefore, the addressing range is from 1 … 231. This data type is especially intended for communication with object attributes and is not optimized for fast manipulation.

refvec

This data type defines a list that contains only values of type object. The addressing range is 1 … 231 and does not provide a default value. Each object ID is only included once, a null is not added to the list.

matrix

This data type defines a two-dimensional array whose values can be addressed with the index data type. If the specified row (first value of the index) or the column (second value of the index) is 0, it is a default value that is passed on in the addressing order [0,0] → [row,0] → [0,column] → [row,column].

hash

This data type defines an associative array with any scalar addressing range and arbitrary values and an optional default value that is returned for an access that does not contain a key.

Similar to predefined vector and matrix attributes like .content[], .userdata[] etc. an expansion of collections directly after their last element is possible and allowed.

However, it is not possible to use these collection data types for user-defined attributes. User-defined and predefined attributes do not have a unique assignment (attributes exist on an object in both a scalar and a field variant) and allow for unindexed access to the default value.

37.5.2 Extension of the Expressions

List and Hashes

Collections with the data types hash, list, matrix, refvec or vector can be defined using the following syntax within the rule code. A definition in the static part of a dialog or module is not possible with expressions, only constant values may be used. Without explicitly specifying a list data type, a list of the data type list is created. When the reference operator => is used, a hash (associative array) is automatically created, with the expression before => defining the key or index, and the second defining the value.

Attention

For compatibility reasons, index expression takes priority. Thus, to build a two-element list of two integer values, the list data type should be prepended.

Syntax

<list> = [ <data type> ] '[' [ <expression> { ',' <expression> } ] ']'
<hash list> = [ <data type> ] '[' [ <expression> '=>' <expression>
    { ',' <expression> '=>' <expression> } ] ']'

Examples

[1, .xleft, 17+4, Wi.Pb]
["CBS" => 2, itoa(7) => 7]
matrix[ [1,1]=>"first name", [1,2]=>"last name", [1,3]=>"telephone no." ]

37.5.3 List Size and Default Values

In principle, each collection data type has a current size, which results from the values set. There are no value gaps in this currently valid indexing range, only unset values (see also the descriptions of itemcount(), countof()).

In order to achieve consistency with the previous static local variables, the data types hash, list and matrix allow for a default value.

This is displayed at unset value positions within the currently valid indexing range up to the current size. For hash data types, if the default value is set, it is returned for all possible indexings.

The sequence of access to the default values for an unset value at the position <row>,<col> in a matrix M is M[<row>,<col>]M[0,<col>] → M[<row>,0]M[0,0].

The access sequence to the default value for an unset value at <index> in a list L is L[<Index>]L[0].

37.5.4 Access and Assignment of Collections

The indexed values (items) of a collection are accessed via the [] operation, just as known for local variables or predefined and user-defined attributes.

Without the [] operation, the entire value is fetched or set.

Attention

It should be noted that accessing a user-defined or predefined attribute without the [] index fetches or sets the default value or scalar attribute. To fetch or set all values of an attribute, the functions getvector() or setvector() should be used.

Examples

variable list Primes := [2,3,5,7,11,13];
variable vector[integer] Numbers;
variable hash Months := [1=>"Jan", 2=>"Feb", 3=>"Mar"];

print Primes[1];
Months[4] := "Apr";
Numbers := Primes;
Primes[0] := -1;
Primes := [17, 19, 23];

Output of collections via print or sprintf() is also possible. However, no default values are output. For the data types hash and matrix the output is including the index.

Specific Features of refvec

It should also be noted that the refvec data type is handled in a special way because it ensures uniqueness of the values and does not store null values.

With an indexed assignment of an already existing object ID, the object ID at this position is replaced and afterward uniqueness is ensured, which may also result in a shift of the already existing object ID to another position and a reduction of the refvec list.

In case of an indexed assignment of a null, the object ID is deleted from the refvec list and the following object IDs advance, which in turn results in a reduction of the refvec list.

37.5.5 Automatic Conversion

In assignments or parameter calls, collections are automatically converted to the required list type. All values without index are copied in their natural order, including the default values if possible, e.g. [0] for a list variable will be passed on if the target type also has a default value.

Exception

When assigning a hash with index data type to a matrix, the index will be taken over. With the reverse assignment of a matrix to a hash, the index will also be transferred. To prevent this, the built-in function values() should be used.

37.5.6 Performance

In general, it should be considered that the use of collections (entire values) within expressions initially requires the values to be copied, but then in reading operations only references of this list are used, i.e. without further copying. This ensures the necessary performance when working with collections. Passing on to application functions or manipulation by built-in functions, however, requires another copy action, possibly with a code page conversion of string values.

For this reason, it should be kept in mind that complex expressions that process collections may well temporarily lead to large amounts of data. Coding and splitting of expressions should take into account the maximum list sizes.

37.5.7 Local and Global Variable

The new collection data types are available for local and global variables now. It is also possible to initialize a global collection with constant values.

Until now, local, static variables could also be an array or an associative array, which only could be initialized in a very limited way. Collection data types are now allowed for both local and local static variables. The initialization expression is no longer restricted.

Attention Behavior Change

The existing notation of arrays and associative arrays for static local variables is still allowed and mapped to the data types list or hash. The static initialization via .<identifier>[<index>] := <value>; after the variable part is no longer possible to ensure consistency with other local variables! The initial value sets the entire value of the variable, not just the default value!

Example

dialog D

variable hash Prices := [ "iMac" => 1300, "Samsung Tab" => 300 ];
variable vector[string] Weekdays := ["Mon","Tue","Wed"];

on dialog start
{
  variable string Stations[integer] := [1=>"ABC", 2=>"CBS"];
  variable hash Stations2 := [3=>"NBC", 4=>"HBO"];
  static variable list AllStations := join(Stations,Stations2);
  /* No longer allowed:
   * variable string Stations[integer] := "UNKNOWN";
   * .Stations[1] := "ABC";
   * or
   * static variable integer AssArray[string] := -1;
   * Instead possible:
   * static variable integer AssArray[string] := [nothing=>-1];
   */
  exit();
}

37.5.8 Relational Operators

For collections, only the relational operators = and <> are allowed.

Equality prevails under the following conditions:

  1. The data type must be the same.
  2. All contained values or index/value pairs must be equal, including the default values.
  3. The number of values contained and their positions must be the same.

Comparison between a string and a text ID is done on a string basis.

When using relational operators, particular attention should be paid to the data type.

Example

dialog D
window Wi {
  listbox Lb {
    .content[1] "Sat";
    .content[2] "Sun";
  }
}
on dialog start {
  variable list WeekendDays := ["Sat", "Sun"];
  variable hash DayNumber := ["Sat"=>6,"Sun"=>7];
  variable list Days;

  print WeekendDays = getvector(Lb, .content);
  print vector["Sat","Sun"] = getvector(Lb, .content);
  print values(WeekendDays) = values(getvector(Lb, .content));
  print WeekendDays = keys(DayNumber);
  Days := WeekendDays;
  WeekendDays[0] := "??";
  print Days=WeekendDays;
  exit();
}

Output

false => Different data types (list<>vector)
true
true
true
false => WeekendDays has a default value, but Days does not!

37.5.9 Uninitialized variables

As before, the IDM behaves differently when accessing uninitialized values. If an uninitialized local or static variable is accessed, nothing is returned. When accessing an uninitialized global variable ( equivalent to a variable object) or a user-defined attribute, access is denied with a cannot get value error.

37.5.10 New and Modified Built-in Functions

37.5.10.1 itemcount()

This function returns the number of indexed values in a collection. The default value(s) are excluded from that number. Together with indexat() and valueat() it is thus easy to loop through any collection.

Typically, countof() and itemcount() return the same result for values of the data types refvec, vector, and list. However, itemcount() offers the more generic use, whereas countof() is better suited for structured, type-adapted use.

Definition

integer itemcount
(
  anyvalue Value input
)

Parameters

anyvalue Value input
This parameter specifies the value for which the number shall be determined.

Return value

0

The passed value is scalar or an empty collection.

1 … 231

Number of values in the collection without the default values.

Example

dialog D

on dialog start
{
  variable matrix Matrix := [
    [0,0] => "-?-",
    [1,1] => "germany",
    [1,2] => "berlin",
    [2,1] => "france"
    /* [2,2] => inherited from default [0,0] */ ];
  variable integer I;
  variable anyvalue Idx;

  /* print the Matrix values [1,1] [1,2] ... [2,2] */
  for I:=1 to itemcount(Matrix) do
    Idx := indexat(Matrix, I);
    print sprintf("%s : %s", Idx, Matrix[Idx]);
  endfor
  exit();
}

Output

"[1,1] : germany"
"[1,2] : berlin"
"[2,1] : france"
"[2,2] : -?-"

See also

indexat(), valueat(), countof(), .itemcount[<A>], :index(), DM_ValueCount()

37.5.10.2 countof()

This function returns the size of a collection. This is usually the highest index value.

Typically, countof() and itemcount() return the same result for values of the data types refvec, vector, and list. However, itemcount() offers the more generic use, whereas countof() is better suited for structured, type-adapted use.

anyvalue countof
(
  anyvalue Value input
)

Parameters

anyvalue Value input
This parameter specifies the value for which the indexing type or the highest index value shall be determined.

Return value

nothing

The passed value is scalar.

1 … 231

Highest index of the passed list (data types list, vector, refvec).

[0 … 65535,0 … 65535]

Highest index of the passed matrix.

anyvalue

Data type of the index of the passed associative array (data type hash).

Example

dialog D

on dialog start
{
  variable matrix Matrix := [
    [0,0] => "-?-",
    [1,1] => "germany",
    [1,2] => "berlin",
    [2,1] => "france"
    /* [2,2] => inherited from default [0,0] */ ];
  variable integer Row, Col;
  variable anyvalue Count, Idx;

  /* print the Matrix values [0,0] [0,1] ... [2,2] */
  Count := countof(Matrix);
  for Row:=0 to first(Count) do
    for Col:=0 to second(Count) do
      Idx := [Row,Col];
      print sprintf("%s : %s", Idx, Matrix[Idx]);
    endfor
  endfor
  exit();
}

See also

valueat(), itemcount(), .count[<A>], :index(), DM_ValueCount()

37.5.10.3 indexat()

This function returns the index of a collection at a specific position. The allowed positions are 1 … itemcount() and thus allow a loop through all indexed values.

For values of type list, refvec and vector, the position is identical to the actual index. For a hash value, there is no defined order of the indexes returned. For matrix values, the increasing positions are mapped in a sequence where all ( column) values of a row are arranged in ascending order.

The function returns an error (fail) if the position is outside the allowed range or if the Value parameter is not a collection.

Definition

anyvalue indexat
(
  anyvalue Value input,
  integer  Pos   input
)

Parameters

anyvalue Value input
This parameter specifies the value list from which the index shall be queried.
integer Pos input
Position for which the index value shall be determined.

Return value

Index value at the position passed as parameter.

Example

dialog D

on dialog start
{
  variable matrix Matrix := [
    [0,0] => "-?-",
    [1,1] => "germany",
    [1,2] => "berlin",
    [2,1] => "france" ];
  variable integer Pos;

  /* print the Matrix elements [1,1] [1,2] ... [2,2] */
  for Pos:=1 to itemcount(Matrix) do
    print sprintf("%s : %s", indexat(Matrix, Pos), valueat(Matrix, Pos));
  endfor
  exit();
}

See also

itemcount(), valueat(), keys(), :index(), DM_ValueIndex()

37.5.10.4 valueat()

This function returns the indexed value in a collection at the specified position. The allowed positions are 1 … itemcount() and thus allow looping through all indexed values without knowing the actual index.

The function returns an error (fail) if the position is outside the allowed range or if the Value parameter is not a collection.

Definition

anyvalue valueat
(
  anyvalue Value input,
  integer  Pos   input
)

Parameters

anyvalue Value input
This parameter specifies the value list from which the indexed value shall be determined.
integer Pos input
Position for which the indexed value shall be determined.

Return value

Value found in the collection at the position passed as a parameter.

Example

dialog D

on dialog start
{
  variable matrix Matrix := [
    [0,0] => "-?-",
    [1,1] => "germany",
    [1,2] => "berlin",
    [2,1] => "france" ];
  variable integer Pos;

  /* print the Matrix elements [1,1] [1,2] ... [2,2] */
  for Pos:=1 to itemcount(Matrix) do
    print sprintf("%s : %s", indexat(Matrix, Pos), valueat(Matrix, Pos));
  endfor
  exit();
}

See also

indexat(), values(), :index(), DM_ValueGet(), DM_ValueIndex()

37.5.10.5 keys()

This function returns a list of all index values in a collection. The indexes of the default values are not included in the list. If a scalar is specified as parameter, an empty list is returned.

Definition

list keys
(
  anyvalue Value input
)

Parameters

anyvalue Value input
This parameter specifies the value on which the function is applied.

Return value

A list containing all indexes of a collection.

Example

dialog D

on dialog start
{
  variable matrix Matrix := [
    [0,0] => "-?-",
    [1,1] => "germany",
    [1,2] => "berlin",
    [2,1] => "france" ];
  variable anyvalue Idx;

  /* print the Matrix elements [1,1] [1,2] ... [2,2] */
  foreach Idx in keys(Matrix) do
    print sprintf("%s : %s", Idx, Matrix[Idx]);
  endfor
  exit();
}

See also

indexat(), itemcount(), countof(), values(), foreach

37.5.10.6 values()

This function returns a list of all values in a collection. Default values are not included. Applied to a scalar value, this is returned as a list.

Definition

anyvalue values
(
  anyvalue Value input
)

Parameters

anyvalue Value input
This parameter specifies the value on which the function is applied.

Return value

A list containing all values of a collection without the default values.

For a scalar parameter, a list containing only this parameter is returned.

Example

dialog D

on dialog start
{
  variable hash DomainHash := [
    ".de" => "germany",
    ".us" => "usa",
    ".fr" => "france",
    ".uk" => "united kingdom" ];
  variable string Country;

  /* print all country names from the DomainHash */
  foreach Country in values(DomainHash) do
    print Country;
  endfor
  exit();
}

Output

"germany"
"france"
"united kingdom"
"usa"

See also

valueat(), :index(), DM_ValueCount()

37.5.10.7 join()

This function creates a new value list from the specified parameters. The type of the value list is determined by the first call parameter. If this is a collection or a collection data type (list, vector, refvec, hash, matrix), the resulting value list has the same type. A data type as the first parameter value never is included in the result list. If the specified parameters are collections, only the values (without default values) are used. Scalar values are added to the resulting value list.

The order of the values in the resulting value list will correspond to the order of the parameters and for collections to their natural order (see indexat()).

Indexing is usually done by incrementing the last index value or the number of values (see countof() and itemcount()). That is, the values in the result list usually get an indexing by 1, 2, 3, … or [1,1], [1,2], [1,3], ….

If the result list type and the parameter value are both a hash, the index of the hash values is adopted. Added scalar parameters will get the increased itemcount() value of the result list as index.

When using refvec as the result list type, it should be noted that an error (fail) occurs if a value is not of the data type object.

Definition

anyvalue join
(
      anyvalue Value input
  { , anyvalue Par2  input }
  ...
  { , anyvalue Par16 input }
)

Parameters

anyvalue Value input
This parameter specifies the value on which the function is applied. The parameter is also used to determine the type for the result list.
anyvalue Par2 input

anyvalue Par16 input
Additional optional parameters on which the function is applied.

Return value

A collection containing all values from the passed parameters. If the first parameter is a collection data type or a collection, the returned collection has this data type. A data type as the first parameter is not included in the returned collection.

Modification as of IDM Version A.06.01.b When Passing the Data Type string as First Parameter

If the data type string is passed as first argument to the function join(), the subsequent arguments are converted to the data type string and then concatenated. If the subsequent arguments are collections, first their values are concatenated to a string in the natural order of the index.

If the first argument is a data type that is neither string nor a collection data type, join() returns an error.

Example

dialog D

on dialog start
{
  variable hash DomainHash := [
    ".de" =>" germany",
    ".us" => "usa",
    ".fr" => "france",
    ".uk" => "united kingdom" ];
  variable list Countries;
  variable hash Domains;

  /* join the values to a list */
  Countries := join(list, DomainHash, "norway", "spain");
  /* join the values and keys into a hash */
  Domains := join(DomainHash, [".us" => "united states of america"]);

  print Countries;
  print Domains;

  exit();
}

Output

["norway","spain","germany","usa","france","united kingdom"]
[".de"=>"germany",".us"=>"united states of america",".fr"=>"france",
".uk"=>"united kingdom"]

See also

keys(), DM_ValueChange()

37.5.10.8 find()

This function searches for a specified value in a list of values and returns the first found index where this search value can be found.

The search never includes the default element (e.g. index [0] or [0,0]).

By specifying a start and end index, the search can be restricted. The valid values are:

When searching for strings it is also possible to search case-insensitive or for the first occurrence as prefix.

Since the indices of hashes are not subject to any order, only an integer value in the range 1 … itemcount() should be specified as index, which indicates the position of the start or end element.

For two-dimensional arrays (similar to the :find() method for .content[] at the tablefield), specifying an index range [Sy,Sx] to [Ey,Ex] restricts the search scope to the range [min(Sy,Ey),min(Sx,Ex)] … [max(Sy,Ey),max(Sx,Ex)]. Thus the restriction to rows and columns is easily possible.

Definition

anyvalue find
(
      anyvalue ListValue  input,
      anyvalue Value      input
  { , anyvalue StartIndex input
  { , anyvalue EndIndex   input } }
  { , boolean  CaseSensitive := false       input }
  { , enum     MatchType     := match_exact input }
)

Parameters

anyvalue ListValue input
In this parameter, a list value is expected in which to search.
anyvalue Value input
The value specified in this parameter is searched for. Only values are compared whose types are equal or can be converted (a text is converted to a string for this purpose).
anyvalue StartIndex input
This optional parameter specifies the start index from which to search for the value in the collection. If no value is specified here, 1 is assumed for one-dimensional and [1,1] for two-dimensional collections.
anyvalue EndIndex input
This optional parameter specifies the end index up to which the collection shall be searched for the value. This argument is only permitted if a start index has also been specified.
boolean CaseSensitive := false input
This optional parameter only applies to string values and defines whether the search should be case-sensitive or not. The default value is false.
enum MatchType := match_exact input

This optional parameter only applies to string values and defines how to search for strings. Valid values are:

MatchType

Meaning

match_begin

Finds the first string in the collection that starts with the search string.

match_first

Finds the string in the collection whose beginning has the largest match with the search string. If the collection contains a string that matches the search string exactly, its index will be returned.

match_exact (default value)

Finds the first string in the collection that exactly matches the string that is searched for.

match_substr

Finds the first string in the collection that contains the string that is searched for.

Return value

0

Item was not found in the passed list (data types list, vector, refvec).

[0,0]

Item was not found in the passed matrix.

nothing

Item was not found in the passed associative array (data type hash).

otherwise

Index of the item in the passed collection. The value returned has the index data type of the collection passed.

Fault behavior

The function call fails if the ListValue parameter is not a collection, the index ranges are outside the valid range, or another invalid parameter value exists.

Remark

If the StartIndex and EndIndex parameters have a data type other than integer when searching in hashes, the position of the start and end elements is calculated from the specified indexes. In this respect, searching in hashes with the find() function differs from searching in associative arrays with the :find() method.

Example

dialog D

on dialog start
{
  variable hash Hash := [
    "030"  => "berlin",
    "0711" => "stuttgart",
    "089"  => "munich" ];
  variable matrix Matrix := [
    [1,1] => "area code", [1,2] => "call number",
    [2,1] => 089,         [2,2] => 713400,
    [3,1] => 0711,        [3,2] => 805439 ];
  variable anyvalue Idx;

  Idx := find(Hash, "stuttgart");
  if Idx <> nothing then
    print "Found: stuttgart => " + Idx;
    Idx := find(Matrix, atoi(Idx), [2,1], [3,1]);
    if Idx <> [0,0] then
      print "Call: " + Matrix[first(Idx),2];
    endif
  endif
  exit();
}

See also

sort(), :find()

37.5.10.9 sort()

This function returns a sorted copy of a given list value. Only the values are sorted, not the indexes. Therefore, a sorting of values is also possible for associative arrays (hash data type).

Sorting is carried out grouped by the data types of the value elements, ascending by the ordinal of the data types and values. When sorting texts or strings, comparison is always done using the string data type, which is more suitable for sorting.

Sorting can be controlled like this:

Definition

anyvalue sort
(
      anyvalue ListValue input
  { , boolean  Reverse  := false       input }
  { , enum     SortType := sort_binary input }
)

Parameters

anyvalue ListValue input
This parameter specifies the list value to be sorted.
boolean Reverse := false input
If this optional parameter is set to true, sorting is carried out in descending order. The default value is false, which corresponds to an ascending sort.
enum SortType := sort_binary input

This optional parameter only applies to item values that have the data type string or are temporarily converted to a string for sorting. Permitted values are:

SortType

Meaning

sort_binary (default value)

Sorting based on the Unicode character code.

sort_linguistic

Sorting based on the language and region settings (locale) of the system.

Depending on the system settings and the set code page, upper and lower case as well as umlauts are taken into account.

For Unix or Linux we recommend using the UTF8 locale.

Since this sort requires code page conversions, it is slower than sort_binary.

See also

Documentation of locale, LC_CTYPE, LC_COLLATE, strcoll for your operating system.

Return value

Sorted collection of the same data type as the passed collection.

Fault behavior

The function call fails if the ListValue parameter is not a collection or another parameter has an invalid value.

Example

// UTF8
dialog D

on dialog start
{
  variable list List := [ "Äcker", "Bande", "Bäcker", "binden",
                          "Bund", "Aachen", "an" ];
  variable string S;

  foreach S in sort(List, sort_linguistic) do
    print S;
  endfor
  exit();
}

/* returns: Aachen Äcker an Bäcker Bande binden Bund */

See also

find(), keys(), values()

37.5.10.10 min()

This function returns the smallest integer value found in all its call parameters.

The call parameters may be scalar integer values or collections (vector, list, matrix, hash). For the latter, the indexed elements (without the default values) are used to determine the minimum value.

Definition

integer min
(
      anyvalue Par1  input
  { , anyvalue Par2  input }
  ...
  { , anyvalue Par16 input }
)

Parameters

anyvalue Par1 input
anyvalue Par2 input

anyvalue Par16 input
These parameters specify the values on which the function is applied.

Return value

The smallest integer value to be found will be returned.

Fault behavior

The function call fails if the arguments do not contain a scalar integer value or if arguments or their elements contain a value that is not an integer value.

Example

dialog D

on dialog start
{
  variable list List := [17, 3, 23, 5];

  print min(List, 24, 4);  /* print 3 */
  exit();
}

See also

max()

37.5.10.11 max()

This function returns the largest integer value found in all its call parameters.

The call parameters may be scalar integer values or collections (vector, list, matrix, hash). For the latter, the indexed elements (without the default values) are used to determine the maximum value.

Definition

integer max
(
      anyvalue Par1  input
  { , anyvalue Par2  input }
  ...
  { , anyvalue Par16 input }
)

Parameters

anyvalue Par1 input
anyvalue Par2 input

anyvalue Par16 input
These parameters specify the values on which the function is applied.

Return value

The largest integer value to be found will be returned.

Fault behavior

The function call fails if the arguments do not contain a scalar integer value or if arguments or their elements contain a value that is not an integer value.

Example

dialog D

on dialog start
{
  variable list List := [17, 3, 23, 5];

  print max(List, 24, 4);  /* print 24 */
  exit();
}

See also

min()

37.5.10.12 getvector()

This function may be used to obtain the entire value of vector or matrix attributes (both user-defined and predefined), i.e. a list of all indexed values, or a section thereof, in a vector.

Definition

vector getvector
(
      object    Object     input,
      attribute Attribute  input
  { , anyvalue  FirstIndex input
  { , anyvalue  LastIndex  input } }
)

Parameters

object Object input
This parameter defines the object whose attribute values shall be queried.
attribute Attribute input
This parameter defines the attribute to be queried.
anyvalue FirstIndex input
This optional parameter defines the start index as of which the element values are retrieved. For one-dimensional array attributes an integer value should be specified, for two-dimensional arrays an index value. The default value for one-dimensional array attributes is the integer value 1, for two-dimensional arrays the index value [1,1].
anyvalue LastIndex input
This optional parameter specifies the end index up to which the values from the attribute are taken into the resulting value list. Again, an integer value is expected for one-dimensional array attributes and an index value for two-dimensional arrays. If no LastIndex parameter is specified, all values up to the end of the array are included. The LastIndex value should be after the FirstIndex value.

Return value

The indexed values determined from the object attribute are returned as a value list with type vector.

Fault behavior

The function call fails for an invalid object or attribute or for an invalid index range.

Example

dialog D
{
  string Extra[integer];
  .Extra[1] := "Anna";
  .Extra[2] := "William";
}

window Wi
{
  .title "Names";
  
  listbox Lb
  {
     .xauto 0;  .yauto 0;
     .content[1] "..NAMES..";
     .content[2] "Irene";
     .content[3] "David";
     .content[4] "Henry";
  }
  
  on close { exit(); }
}

on dialog start {
  variable vector Names;

  Names := join(getvector(Lb, .content, 2), getvector(D,.Extra));
  setvector(Lb, .content, sort(Names), 2);
}

See also

setvector(), DM_GetVectorValue(), DM_SetVectorValue()

37.5.10.13 setvector()

This function may be used to modify vector attributes (predefined or user-defined). It is possible to assign new values to the attribute as a whole or to only a continuous portion of it.

Definition

boolean setvector
(
      object    Object     input,
      attribute Attribute  input,
      vector    NewValue   input
  { , anyvalue  FirstIndex input
  { , anyvalue  LastIndex  input } }
  { , boolean   SendEvent := true input }
)

Parameters

object Object input
This parameter defines the object whose attribute values shall be modified.
attribute Attribute input
This parameter defines the attribute to be set.
vector Value input
This parameter specifies the value list that will be assigned to the vector attribute.
anyvalue FirstIndex input
This optional parameter defines the start index as of which the element values are modified. For one-dimensional array attributes an integer value should be specified, for two-dimensional arrays an index value. The default value for one-dimensional array attributes is the integer value 1, for two-dimensional arrays the index value [1,1].
anyvalue LastIndex input

This optional parameter specifies the end index up to which the values of the attribute are are modified through the values from the value list. Again, an integer value is expected for one-dimensional array attributes and an index value for two-dimensional arrays. The LastIndex value should be after the FirstIndex value.

If no LastIndex parameter is specified (default value nothing), the size of the Value vector defines the number up to which the vector attribute is modified. The subsequent element values of the attribute are then truncated.

boolean SendEvent := true input
This optional parameter controls whether setting the attribute should trigger an attribute-changed event. The default value is true, which causes the changed event to be sent for the attribute. If the parameter value is false, no event is sent.

Return value

true

Attribute has been modified.

false

Modification of the attribute could not be completed.

Fault behavior

The function call fails for an invalid object or attribute, for an invalid index range or if setting is not possible e.g. due to a mismatch between attribute type and value type.

Example

dialog D

window Wi
{
  .title "Cities";
  .width 300;

  tablefield TfCities
  {
    .xauto 0;  .yauto 0;
    .rowheight[0] 25;  .colwidth[0] 80;
    .rowcount 1;  .colcount 2;
    .rowheader 1;
    .direction 2;
  }

  on close { exit(); }
}

on dialog start
{
  variable hash Capitals := [
    "germany" => "berlin",
    "france"  => "paris",
    "england" => "london" ];

  // fill the title row
  setvector(TfCities, .content, ["Country", "City"]);
  // fill the country and city column
  setvector(TfCities, .field, keys(Capitals), [1,1],
            [itemcount(Capitals),1]);
  setvector(TfCities, .field, values(Capitals), [1,2]);
}

See also

DM_SetVectorValue()

37.5.11 Loop Construct foreach

This construct is used to create loops that iterate over all elements of a collection.

Syntax

foreach <Counter> in <Expression> do
  <Statements>
endfor

The loop terminates with an error if the <Expression> is not a collection or the loop value cannot be assigned to the <Counter>. The <Expression> is evaluated only once initially. The control variable <Counter> may be changed within the <Statements>. A change of the control variable does not affect the number of cycles or the value of the control variable in the next cycle.

Example

dialog D
window Wi
{
  listbox Lb
  {
    .xauto 0;  .yauto 0;
  }
  on close { exit(); }
}

on dialog start
{
  variable list StationList:= ["ABC", "CBS", "NBC", "ESPN"];
  variable string Station;

  foreach Station in StationList do
    Lb.content[Lb.itemcount+1] := Station;
  endfor
}

37.5.12 C Interface Enhancement

Collections can now also be used as arguments or return values of C functions (does not apply to COBOL) or for Datamodel callbacks.

Another new feature is that the data type index (DT_index) is now allowed as return type for C functions.

37.5.12.1 Extension of the DM_Value Structure for Collection Data Types

Name

Allocated Element

Meaning

DT_list

pointer

Value list

DT_hash

pointer

Associative array

DT_vector

pointer

Array of the same value type

DT_matrix

pointer

Two-dimensional array

DT_refvec

pointer

Reference list of DM_ID values where the same ID can only occur once

In principle, DM_Value structures, which may or should contain collections, must only be manipulated and queried via special DM functions, since the IDM allocates memory and manages strings for this purpose.

See also

DM_ValueInit(), DM_ValueChange(), DM_ValueGet(), DM_ValueCount(), DM_ValueIndex() and DM_ValueReturn()

To facilitate the handling of the DM_Value structure and strings (DM_String) in C functions, the following concept has been introduced.

The C interface of the IDM can distinguish value references (DM_Value* and DM_String*) according to their use or initialize them for a special use:

  1. The value reference is an argument of the function call and yet unmanaged.
  2. The value reference is a static or global value and is managed by the IDM.
  3. The value reference is a local value managed by the IDM. Returning it to the IDM is allowed. After the function call is completed, it will be released.
  4. The value reference refers to a value managed by the IDM that is invalid, for example because it has been manipulated improperly by the user.
  5. The value reference refers to an unmanaged value (sort like up to now).

This concept is supported by the functions of the kind DM_Value*() and DM_*Return(). It allows the manipulation of values (e.g. changing a string, adding values to a list or hash), the access of elements or indexes of value lists as well as the return of value lists or strings without having to care explicitly about the administration and allocation.

Rules for Usage

For values and DM_Value structures of the kind 1–3 the following must be observed:

As values managed by the IDM may also contain strings, it should be noted that these strings are held and returned in the application code page. Changing this code page by a DM_Control() call does not change the code page of the managed strings. The application code page should therefore be set correctly as early as possible.

The following functions can only be used for local and distributed (DDM) C functions. Their use in format functions is not permitted.

A faulty manipulation of a value managed by the IDM or a status change by the user will be reported in the C interface, when recognized, by the error codes DME_InvalidContext or DME_BadContext. Usually input and output parameters should not point to the same value reference either, which in turn is indicated by a DME_InvalidArg error.

Managed local value references are cleaned up after the corresponding function call and, where necessary, substructures and strings are released.

For particularly time-critical functions, the use of managed values and strings should probably be avoided or the time behavior should be checked, since their use will in any case mean an increased administration overhead in the IDM.

37.5.13 New and Modified C Interface Functions

37.5.13.1 DM_ValueInit

With this function a value reference can be converted into a local or global value reference managed by the IDM. This allows the further manipulation of the value by DM_Value…() functions and its transfer as parameter or return value.

The value reference is initialized with the appropriate type. The collection data types DT_list, DT_vector, DT_hash, DT_matrix and DT_refvec are also permitted.

If the value reference is initialized as static or global via the DMF_StaticValueoption, access is also possible outside the function call. Value lists and strings are not released at the end of the function. The initialization of arguments as static or global managed value references is not allowed.

String values are initialized with the NULL pointer. Collections are created without element values. All other value types are also initialized with a 0 value.

The function DM_ValueChange() can be used to add or change values or part values respectively elements. A reinitialization using DM_ValueInit() is also possible.

DM_Boolean DML_default DM_EXPORT DM_ValueInit
(
  DM_Value   *value,
  DM_Type     type,
  DM_Value   *count,
  DM_Options  options
)

Parameters

-> DM_Value *value

This is the value reference to be initialized.

-> DM_Type type

This parameter specifies the requested initial type.

-> DM_Value *count

In this parameter the initial size of collections like list or matrix can be specified or the appropriate value type for vector values.

-> DM_Options options

Option

Meaning

0

The value reference will be initialized as a local value.

DMF_StaticValue

The value reference will be initialized as a global, static value.

Return value

DM_TRUE

The function has been completed successfully so the value reference is initialized.

DM_FALSE

The value reference could not be initialized.

Example

Dialog File

dialog Dialog

function void     AppendToList(anyvalue List input output, anyvalue Value);
function anyvalue FindMinMax(anyvalue IntegerList);
function string   ListToString(anyvalue List);
function void     SetElemSep(string Sep);

on dialog start
{
   variable vector[string] WeekDays:=["Mo","Tu","Wed","Thu","Fri","Sat"];
   variable list DaysPerWeek := [31,30,28,27];

   SetElemSep(" , ");
   AppendToList(WeekDays,"Sun");
   print ListToString(WeekDays);
   print FindMinMax(DaysPerWeek);
   exit();
}

C Part

...

static DM_String elemSep = NULL;

void DML_default DM_ENTRY SetElemSep(DM_String sep)
{
  DM_StringInit(&elemSep, DMF_StaticValue);
  DM_StringChange(&elemSep, sep, 0);
}

DM_Value* DML_default DM_ENTRY FindMinMax(DM_Value *IntegerList)
{
  DM_Value subval, minMaxList;  /* managed local values */
  DM_UInt  count;
  DM_UInt  minValueCount=0, maxValueCount=0;
  DM_Value index, mindex, data;  /* unmanaged values */

  /* initialize local managed values */
  DM_ValueInit(&subval, DT_void, NULL, 0);
  DM_ValueInit(&minMaxList, DT_list, NULL, 0);

  /* determine the itemcount of the list */
  count = DM_ValueCount(IntegerList, NULL, 0);
  index.type = DT_integer;
  index.value.integer = 1;

  while(count>0)
  {
    /* loop through the index 1,2,3,... */
    if (DM_ValueGet(IntegerList, &index, &subval, 0)
        && subval.type == DT_integer)
    {
      if (minValueCount==0 || subval.value.integer<minValue)
      {
        minValueCount++;
        /* store maximum value at [1] in minMaxList */
        mindex.type = DT_integer;
        mindex.value.integer = 1;
        DM_ValueChange(&minMaxList, &mindex, &subval, 0);
      }
      if (maxValueCount==0 || subval.value.integer>maxValue)
      {
        maxValueCount++;
        /* store maximum value at [2] in minMaxList */
        mindex.type = DT_integer;
        mindex.value.integer = 2;
        DM_ValueChange(&minMaxList, &mindex, &subval, 0);
      }
    }
    count--;
    index.value.integer++;
  }
  /* return the minMaxList (without compiler warnings) */
  return DM_ValueReturn(&minMaxList, 0);
}

...

void DML_default DM_ENTRY AppendToList(DM_Value *List, DM_Value *Value)
{
  DM_Value newList;

  /* demonstrate the returning of a list-value by two ways * /
  if (List->type == DT_list || List->type == DT_vector)
  {
    /* 1) returning a manipulated argument (auto-management) */
    DM_ValueChange(List, NULL, Value, DMF_AppendValue);
  }
  else
  {
    /* 2) creation of a managed local list-value */
    DM_ValueInit(&newList, DT_list, NULL, 0);
    DM_ValueChange(&newList, NULL, List, DMF_AppendValue);
    DM_ValueChange(&newList, NULL, Value, DMF_AppendValue);
    *List = newList;
  }
}

DM_String DML_default DM_ENTRY ListToString(DM_Value *List)
{
  DM_Value  index;
  DM_Value  value;
  DM_UInt   count;
  DM_String retString;

  /* initialize the managed values */
  DM_ValueInit(&index, DT_void, NULL, 0);
  DM_ValueInit(&value, DT_void, NULL, 0);
  DM_StringInit(&retString, 0);

  count = DM_ValueCount(List, NULL, 0);
  while(count>0)
  {
    if (DM_ValueIndex(List, count--, &index, 0)
        && DM_ValueGet(List, &index, &value, 0)
        && value.type == DT_string)
    {
      DM_StringChange(&retString, value.value.string, DMF_AppendValue);
      if (count>0)
        DM_StringChange(&retString, elemSep, DMF_AppendValue);
    }
  }
  return DM_StringReturn(retString, 0);
}

37.5.13.2 DM_ValueChange

With this function a value reference managed by IDM may be manipulated. Either the entire value can be replaced or a single element value in a collection.

There is an automatic conversion of unmanaged value references into managed value references. If the option DMF_StaticValue is set in this case, a static respectively global managed value reference is created. For better control the explicit use of DM_ValueInit() is recommended.

If the value parameter is a collection, e.g. of type DT_vector, DT_list, DT_hash, DT_matrix or DT_refvec, an element value can be substituted by specifying the index parameter. Similar to predefined attributes, a collection can be extended by incrementing the index with +1. For associative arrays, simply a not yet assigned index key may be used.

If a collection in the data parameter is assigned to the target as a whole (i.e. with NULL as index parameter), the entire value with all value elements is copied. The conversion of an argument into a locally managed value also requires a complete copying to allow further manipulation.

DM_Boolean DML_default DM_EXPORT DM_ValueChange
(
  DM_Value   *value,
  DM_Value   *index,
  DM_Value   *data,
  DM_Options  options
)

Parameters

-> DM_Value * value

This parameter refers to the value reference to be changed. If it is not yet managed by the IDM, it is converted to a managed value reference.

-> DM_Value * index

This parameter can be used to change element values in collections and specifies the index. Otherwise, it should be set to NULL. This parameter does not need to be a managed value reference.

-> DM_Value * data

This parameter defines the value to be set. It may be a managed or an unmanaged value reference. If this value is NULL, the value or element is set to DT_undefined.

-> DM_Options options

These are the options available:

Option

Meaning

DMF_StaticValue

When the value parameter is automatically converted into a managed value reference, it is treated as a static respectively global value reference.

DMF_AppendValue

For collections, the data value from data is appended at the end. The index must be NULL for this.

DMF_SortBinary

In collections, the newly set value is finally sorted. May be used in combination with DMF_SortReverse.

DMF_SortLinguistic

In collections, the newly set value is finally sorted, for strings according to linguistic rules (see the function sort()). May be used in combination with DMF_SortReverse.

DMF_SortReverse

In collections, the newly set value is finally sorted in reverse order.

Return value

DM_TRUE

The function has been completed successfully, setting the value succeeded or the value had already been set.

DM_FALSE

Value could not be set. This may be due to an faulty call, an unmanaged or invalid value reference, or an incorrect indexing.

Example

Dialog File

dialog YourDialog
function anyvalue FindData(hash DataHash, string Pattern,
                           anyvalue FirstIndex output);

on dialog start
{
  variable hash Stations := ["1"=>"ABC","2"=>"CBS","9"=>"HBO"];
  variable anyvalue Idx;

  print "Found(D)=" + FindData(Stations,"D",Idx);
  print " at " + Idx;
  exit();
}

C Part

...

static DM_Value InvalidIndex;
static DM_Value InvalidValue;

DM_Value * DML_default DM_ENTRY FindData(DM_Value *DataHash, DM_String Pattern,
                                         DM_Value *FirstIndex)
{
  DM_Value index;
  DM_Value value;

  /* initialize the managed values */
  DM_ValueInit(&index, DT_void, NULL, 0);
  DM_ValueInit(&value, DT_void, NULL, 0);
  DM_StringInit(&retString, 0);

  count = DM_ValueCount(DataHash, NULL, 0);
  while(count>0)
  {
    /* loop through the hash */
    if (DM_ValueIndex(DataHash, count--, &index, 0)
        && DM_ValueGet(DataHash, &index, &value, DMF_GetLocalString)
        && value.type == DT_string)
    {
      if (strstr(value.value.string, Pattern))
      {
        /* return the first found index & value */
        DM_ValueChange(FirstIndex, NULL, &index, 0);
        return DM_ValueReturn(&value, 0);
      }
    }
  }

  /* return the invalid index & value */
  DM_ValueChange(FirstIndex, NULL, &InvalidIndex, 0);
  return &InvalidValue;
}

...

int DML_c AppMain __2((int, argc), (char **,argv))
{
  DM_Value data;

  ...

  data.type = DT_string;
  data.value.string = "NO-VALUE";
  DM_ValueChange(&InvalidValue, NULL, &data, DMF_StaticValue);
  data.type = DT_string;
  data.value.string = "INVALID-INDEX";
  DM_ValueChange(&InvalidIndex, NULL, &data, DMF_StaticValue);

  ...

  DM_StartDialog(...)

37.5.13.3 DM_ValueGet

This function allows to retrieve a single element value that belongs to a defined index from collections.

If the given index is NULL, the entire value is returned, which usually means copying the value.

If the retvalue parameter is an unmanaged value, it remains unmanaged. When strings are returned, they are only stored in a temporary buffer which may be cleared or overwritten the next time a DM function without the DMF_DontFreeLastStrings option is called.

DM_Boolean DML_default DM_EXPORT DM_ValueGet
(
  DM_Value   *value,
  DM_Value   *index,
  DM_Value   *retvalue,
  DM_Options  options
)

Parameters

-> DM_Value* value

This parameter refers to the value reference from which the element value is retrieved. It should be a managed value reference or function argument.

-> DM_Value * index

This parameter sets the index for which the element value is retrieved. This parameter does not need to be a managed value. If the parameter is set to NULL, the value parameter is copied into the return parameter retvalue.

-> DM_Value * retvalue

This parameter defines the value to be set. It may be a managed or an unmanaged value reference. If this value is NULL, the value or element is set to DT_undefined.

-> DM_Options options

These are the options available:

Option

Meaning

DMF_StaticValue

When the value parameter is automatically converted into a managed value reference, it is treated as a static respectively global value reference.

DMF_GetLocalString

This option means that text values (IDs of type DT_text) should be returned as strings in the currently set language.

DMF_GetMasterString

This option means that text values (IDs of type DT_text) should be returned as a strings in the development language, regardless of which language the user is currently working with.

DMF_DontFreeLastStrings

Strings are usually passed to the application in a temporary buffer, which is retained until the next call to the IDM. If strings in the application shall be valid longer, the option DMF_DontFreeLastStrings has to be set. Then the memory will not be released until an IDM function returning a string from the IDM to the applicationis called without this option.

Return value

DM_TRUE

Getting the value has been successful.

DM_FALSE

The value could not be retrieved. This may be due to an faulty call, an unmanaged or invalid value reference, or an incorrect indexing.

Example

See DM_ValueChange(), DM_ValueCount(), DM_ValueIndex()

37.5.13.4 DM_ValueCount

Returns the number of values in a collection (without the default values). It is also possible to return the index type or the highest index value.

The returned value indicates the number of values (without the default values). Thus, in combination with the DM_ValueIndex() function, loops over all indexed values respectively elements can be implemented easily.

Depending on the value parameter, the following results may occur:

value Type

retvalue Return Type

Remark

DT_refvec, DT_list, DT_vector

DT_integer

Highest index value

DT_matrix

DT_index

Highest index value

DT_hash

DT_datatype

Any index type (anyvalue)

otherwise

DT_void

Non-indexed value

DM_UInt DML_default DM_EXPORT DM_ValueCount
(
  DM_Value   *value,
  DM_Value   *retvalue,
  DM_Options  options
)

Parameters

-> DM_Value* value

This parameter refers to the value reference from which the number of values is fetched. It should be a managed value reference or function argument.

-> DM_Value * retvalue

If this parameter is not NULL, the count value is returned in it. This may be a managed value reference, however this is not mandatory.

-> DM_Options options

These are the options available:

Option

Meaning

DMF_GetLocalString

This option means that text values (IDs of type DT_text) should be returned as strings in the currently set language.

DMF_GetMasterString

This option means that text values (IDs of type DT_text) should be returned as a strings in the development language, regardless of which language the user is currently working with.

DMF_DontFreeLastStrings

Strings are usually passed to the application in a temporary buffer, which is retained until the next call to the IDM. If strings in the application shall be valid longer, the option DMF_DontFreeLastStrings has to be set. Then the memory will not be released until an IDM function returning a string from the IDM to the applicationis called without this option.

Return value

0 … INT_MAX

Number of values (excluding the default values with the indexes [0], [0,*] or [*,0]).

retvalue

Highest index value, may be either void (scalar value), an integer value (one-dimensional array), an index value (two-dimensional array), or a data type (associative array).

Example

Dialog File

dialog YourDialog
function integer CountIntegers(anyvalue List);

on dialog start
{
  variable matrix M := [
    [0,0]=>-1,[1,1]=>"ZIP",[1,2]=>"City",[2,1]=>60654,[2,2]=>"Chicago" ];
  print "#Integers in Hash: " + CountInteger(M);
  exit();
}

C Part

...

static DM_Value InvalidIndex;
static DM_Value InvalidValue;

DM_Integer DML_default DM_ENTRY CountInteger(DM_Value *List)
{
  DM_Value   index;
  DM_Value   count;
  DM_Value   value;
  DM_Integer icount = 0;

  /* initialize the managed values */
  if (DM_ValueCount(List, &count, 0)>0 && List->type == DT_matrix
      && count->type == DT_index)
  {
    index.type = DT_index;
    index.value.index.first = 0;
    index.value.index.second = 1;

    /* loop through [0,1],[1,1],[2,1],... */
    while(index.value.index.first<=count.value.index.second)
    {
      if (DM_ValueGet(List, &index, &value, 0)
          && value.type == DT_integer)
        icount++;
      index.value.index.first++;
    }
  }
  return icount;
}

See also

itemcount(), countof(), DM_ValueGet(), DM_ValueIndex(), DM_ValueChange()

37.5.13.5 DM_ValueIndex

This function can be used to determine the corresponding index for a position in a collection. This is especially important for values of type DT_hash and DT_matrix in order to access all respective indexes the easiest way. The function only allows access to indexes that do not belong to default values.

The returned index can be stored in a managed retvalue parameter value or in an unmanaged one. In the latter case, the string value is allocated in the temporary buffer if necessary.

DM_UInt DML_default DM_EXPORT DM_ValueIndex
(
  DM_Value   *value,
  DM_UInt     indexpos,
  DM_Value   *retvalue,
  DM_Options  options
)

Parameters

-> DM_Value* value

This parameter refers to the value reference from which the index for the position will be retrieved. It must be a managed value reference or function argument.

-> DM_UInt indexpos

This parameter defines the position of the index and should be in the range 0 < indexpos <= DM_ValueCount().

-> DM_Value * retvalue

Wenn dieser Parameter nicht NULL ist, wird hier der entsprechende Index abgelegt. Es kann sich dabei um eine gemanagte oder auch um eine ungemanagte Wertereferenz handeln.

If this parameter is not NULL, the retrieved index is stored here. This may be a managed or an unmanaged value reference.

-> DM_Options options

These are the options available:

Option

Meaning

DMF_GetLocalString

This option means that text values (IDs of type DT_text) should be returned as strings in the currently set language.

DMF_GetMasterString

This option means that text values (IDs of type DT_text) should be returned as a strings in the development language, regardless of which language the user is currently working with.

DMF_DontFreeLastStrings

Strings are usually passed to the application in a temporary buffer, which is retained until the next call to the IDM. If strings in the application shall be valid longer, the option DMF_DontFreeLastStrings has to be set. Then the memory will not be released until an IDM function returning a string from the IDM to the applicationis called without this option.

Return value

DM_TRUE

The value has an index at this position; the obtained index can afterward be found in *retvalue if retvalue != NULL.

DM_FALSE

The index could not be determined. This may be due to an faulty call, an unmanaged or invalid value reference, or an incorrect position.

Example

See DM_ValueChange()

See also

itemcount(), countof(), :index(), DM_ValueGet(), DM_ValueIndex(), DM_ValueChange(), DM_ValueCount()

37.5.13.6 DM_ValueReturn

This function is used to safely return local DM_Value values from a function. When local variables and structures are used in a C function, they are invalid after they have been returned. This function can safely and easily return a local DM_Value variable.

If necessary, a temporary copy of the value to return is created (e.g. the string in it is copied) for this purpose. There is no copying for managed value references. In this case the returned DM_Value pointer should be passed to the caller with return.

DM_Value* DML_default DM_EXPORT DM_ValueReturn
(
  DM_Value   *value,
  DM_Options  options
)

Parameters

-> DM_Value* value

This parameter refers to the value reference that shall be returned. It may be a managed value reference, however this is not mandatory.

-> DM_Options options

Should be set to 0 since no options are available.

Return value

A pointer to a valid DM_Value structure is returned or NULL in case of an error. An error may occur, for instance, if the function is called in the wrong runstate, the managed string is invalid or copying failed.

Please Note

The functions DM_ValueInit() and DM_ValueChange() can be used to return output parameters.

Example

Dialog File

dialog YourDialog
function anyvalue StringOf(integer I);

on dialog start
{
  print StringOf(123);
  print StringOf(-42);
  exit();
}

C Part

...

DM_Value * DML_default DM_ENTRY StringOf(DM_Integer I)
{
  char     buf[10];
  DM_Value data;
  DM_Value negative;

  if (I>=0)
  {
    /* return an unmanaged value */
    sprintf(buf, "%d", (int)I);
    data.type = DT_string;
    data.value.string = buf;
    /* wrong: return &data => data is a local structure! */
    return DM_ValueReturn(&data, 0);
  }
  else
  {
    /* return a managed value */
    DM_ValueInit(&negative, DT_string, NULL, 0);  /* can be omitted */
    data.type = DT_string;
    data.value.string = "!!negative!!";
    DM_ValueChange(&negative, NULL, &data, 0);
    /* return &negative; => possible but generates compiler warning! */
    return DM_ValueReturn(&negative);
  }
}

See also

itemcount(), countof(), :index(), DM_ValueGet(), DM_ValueIndex(), DM_ValueChange(), DM_ValueCount()

37.5.13.7 DM_StringInit

This function converts a string into a local or global respectively static string managed by the IDM. This allows further manipulation of the string with the DM_StringChange() function, as well as simplified handling as parameter or return value. The IDM then manages the memory for the string.

For managed strings, only read access of the string characters or the string pointer is allowed. Releasing via DM_Free() is not allowed!

This function initializes the string with NULL.

By specifying the DMF_StaticValue option, the string is treated as static and is not released after the function returns, as it is usually the case for local strings.

Generally, only string arguments and local or global strings can be managed.

DM_Boolean DML_default DM_EXPORT DM_StringInit
(
  DM_String * pstring,
  DM_Options  options
)

Parameters

-> DM_String * pstring

This parameter refers to the string pointer that shall be initialized and managed.

-> DM_Options options

These are the options available:

Option

Meaning

DMF_StaticValue

The pstring parameter will be initialized as a static or global string reference.

Return value

DM_TRUE

The string has been initialized successfully and is now managed.

DM_FALSE

The string could not be managed or initialized.

Example

Dialog File

dialog YourDialog
function string FormatString(integer Op, string String);

on dialog start
{
  print FormatString (-1, "**");          // set decoration
  print FormatString (0, "hello world");  // print with decoration
  exit();
}

C Part

...

DM_String DML_default DM_ENTRY FormatString (DM_Integer Op, DM_String String)
{
  static DM_String decoration = NULL;
  DM_String newstring;

  if (!decoration)
  {
    /* static initialization */
    DM_StringInit(&decoration, DMF_StaticValue);
    DM_StringChange(&decoration, "-", 0);
    /* above can be done simpler via:
     * DM_StringChange(&decoraton, "-", DMF_StaticValue);
     */
  }

  switch(Op)
  {
  case -1: /* change decoration */
    DM_StringChange(&decoration, String);
    return &decoration;
  case 1:  /* decor only at the beginning */
    DM_StringChange(&newString, decoration, 0);
    DM_StringChange(&newString, String, DMF_AppendValue);
    break;
  case 2:  /* decor only at the end */
    DM_StringChange(&newString, String, 0);
    DM_StringChange(&newString, decoration, DMF_AppendValue);
    break;
  default:
    DM_StringChange(&newString, decoration, 0);
    DM_StringChange(&newString, String, DMF_AppendValue);
    DM_StringChange(&newString, decoration, DMF_AppendValue);
    break;
  }
  return newstring;
  /* also possible: return DM_StringReturn(&newstring, 0); */
}

See also

DM_ValueInit(), DM_StringChange(), DM_StringReturn()

37.5.13.8 DM_StringChange

This function can be used to modify or manipulate a managed string.

Besides the mere replacement of the string, it is possible to concatenate strings via the DMF_AppendValue option.

If the pstring parameter is a yet unmanaged string, it is copied and from then on managed by the IDM. If the option DMF_StaticValue has been set, the string will be treated as a static or global string and not be released as usual when the function returns.

Generally, only string arguments and local or global strings can be managed.

DM_Boolean DML_default DM_EXPORT DM_StringChange
(
  DM_String * pstring,
  DM_String   newstring,
  DM_Options  options
)

Parameters

<-> DM_String * pstring

This parameter refers to the string reference that shall be manipulated. It may already be a managed string, however this is not mandatory.

-> DM_String newstring

This parameter refers to the string which shall be assigned or appended to the string reference (pstring parameter).

-> DM_Options options

These are the options available:

Option

Meaning

DMF_StaticValue

When the pstring parameter is automatically converted into a managed string reference, it is treated as a static respectively global string reference.

DMF_AppendValue

The string in the newstring parameter is appended to the string in the pstring parameter.

Return value

DM_TRUE

The string has been manipulated successfully.

DM_FALSE

An error occurred. This may be due to a wrong runstate on call or an invalid string reference.

Example

See DM_StringReturn()

See also

DM_StringInit(), DM_StringReturn(), DM_ValueChange()

37.5.13.9 DM_StringReturn

This function is used to safely return local strings (DM_String values) from a function. When local variables and structures are used in a C function, they are invalid after they have been returned. This function can safely and easily return a local string.

If necessary, a temporary copy created (e.g. the string in it is copied) for this purpose. There is no copying for managed value references. In this case the returned DM_String pointer should be passed to the caller with return.

DM_String DML_default DM_EXPORT DM_StringReturn
(
  DM_String * pstring,
  DM_Options  options
)

Parameters

-> DM_String * pstring

This parameter refers to the string that will be returned. It may be a managed string, however this is not mandatory.

-> DM_Options options

Should be set to 0 since no options are available.

Return value

A valid string to return by a function is returned or NULL in case of an error. An error may occur, for instance, if the function is called in the wrong runstate, the managed string is invalid or copying failed.

Please Note

The functions DM_StringInit() and DM_StringChange() can be used to return output string parameters.

Example

Dialog File

dialog YourDialog
function anyvalue StringOf(integer I);

on dialog start
{
  print StringOf(123);
  print StringOf(-42);
  exit();
}

C Part

...

DM_String DML_default DM_ENTRY StringOf(DM_Integer I)
{
  char      buf[10];
  DM_String data;
  DM_String negative;

  if (I>=0)
  {
    /* return an unmanaged local string */
    sprintf(buf, "%d", (int)I);
    data = buf;
    /* wrong: return data; => buf is a local char array! */
    return DM_StringReturn(&data, 0);
  }
  else
  {
    /* return a managed string */
    DM_StringInit(&negative, 0);  /* can be omitted */
    DM_StringChange(&negative, "!!negative", &data, 0);
    return DM_StringReturn(&negative);
    /* return &negative; => also possible for managed strings! */
  }
}

See also

DM_ValueReturn(), DM_IndexReturn(), DM_StringInit(), DM_StringChange()

37.5.13.10 DM_IndexReturn

This function is used to safely return local index values (DM_Index) from a function. When local variables and structures are used in a C function, they are invalid after they have been returned. This function can safely and easily return a local index.

For this purpose, a temporary copy is created.

DM_Index * DML_default DM_EXPORT DM_IndexReturn
(
  DM_Index   *pindex,
  DM_Options  options
)

Parameters

-> DM_Index * pindex

This parameter refers to the index that shall be returned.

-> DM_Options options

Should be set to 0 since no options are available.

Return value

Zurückgegeben wird ein für die Funktionsrückgabe gültiger Zeiger auf eine DM_Index-Struktur oder NULL im Fehlerfall. Ein Fehler kann z.B. vorliegen, wenn die Funktion im falschen runstate aufgerufen wird oder das Kopieren nicht ausgeführt werden konnte.

A pointer to a valid DM_Index structure is returned or NULL in case of an error. An error may occur, for instance, if the function is called in the wrong runstate or copying failed.

Example

Dialog File

dialog YourDialog
function index SwapIndex(index Idx);

on dialog start
{
  print SwapIndex([1,3]);
  exit();
}

C Part

...

DM_Index* DML_default DM_ENTRY StringOf(DM_Index* Idx)
{
  DM_Index newIdx;
  newIdx.first = Idx->second;
  newIdx.second = Idx->first;

  /* wrong: return &newIdx; => newIdx is local! */
  return DM_IndexReturn(&newIdx, 0);
}

See also

DM_ValueReturn(), DM_StringReturn()

37.6 Datamodel

37.6.1 Motivation

The introduction of the new Datamodel in the IDM is motivated through achieving an improved separation between user interface objects and the application layer, which provides the data for the representation.

The main characteristics of its design are:

37.6.2 Introduction

With the newly introduced Datamodel, the IDM allows a separation into the three components Model1, View and Presenter according to the MVP design pattern with adaptation to the peculiarities and requirements of the Rule Language.

Model

Manages the data and its underlying logic. Is typically close to or in the application layer. A model can manage several data, which are considered as indexed attributes by the IDM and thus may contain scalars, vectors and matrices.

For instance, a record object with user-defined attributes and methods.

View

Visual representation of the data for display, input or modification. The data schema is the same as for the model: indexed attributes thus containing scalars, vectors or matrices.

For instance, an edittext object using a format for input and output.

Presenter

The logic to control the connection between Model and View or to link multiple Views.

For instance in the form of event rules to assign the new data value at the View to the Model when editing is finished.

Brief notice on terms: In this documentation Datamodel (in one word) is used for the concept derived from MVP whereas Data Model (in two words) stands for an actual Model.

In contrast to existing MVP concepts in Java or Qt, the IDM approach allows for transparent handling without restricting the linking and without the need to differentiate between content or selection. Whether a Model controls the content of an edittext, the color of a certain table cell, or the active item in a list is solely left up to the application or dialog programmer.

Figure 19-31: Architectural pattern Model-View-Presenter

In the IDM, the linking between Model and View as well as the most important control functions of the Presenter are defined by a few attributes:

Table 19-14: Datamodel attributes

Attribute

Meaning

.datamodel

Reference to the Model at the View

.dataget

Defines the linking of a View attribute with a Model attribute for display

.dataset

Defines the linking of a View attribute with a Model attribute for assignment

.dataindex

Provides control over the aggregation of View and Model attributes

.datamap

Enables the mapping of attributes to resolve ambiguities

.dataoptions

Control options for the Presenter logic

An example for linking a dialog interface (View) with a Data Model for the display of personal information with name, gender and child names might look like this:

dialog D
record RecPerson {
  string  Name   := "Jane Q. Public";
  boolean Female := true;
  string Children[integer];
  .Children[1] := "Amy";
  .Children[2] := "Peter";
}
window Wi {
  .title "Datamodel Example RecPerson";
  .width 200;
  .height 200;
  /* Linking of all View objects to the Model RecPerson */
  .datamodel RecPerson;

  edittext EtName
  {
    .xauto 0;
    /* .content is linked to RecPerson.name */
    .dataget .Name;
  }

  checkbox CbGender
  {
    .ytop 30;
    .text "Female";
    /* .active is filled from RecPerson.Female */
    .dataget .Female;
  }

  listbox LbChildren
  {
    .ytop 60;
    .xauto 0;  .yauto 0;
    /* .content[] is filled from RecPerson.Children[] */
    .dataget .Children;
  }

  on close { exit(); }
}

The Datamodel approach in IDM takes some of the Presenter logic off the shoulders of the application programmer, hence the above example works without any further rules. The filling of the interface objects EtName, CbGender and LbChildren is done by the IDM through the linking set by the attribute definitions of .datamodel and .dataget. Furthermore, the above example takes advantage of the additional value passing feature from parent to child, which applies to the attributes .datamodel and .dataoptions.

The following diagram is intended to illustrate these automatisms and to show what controlling and influencing options the dialog programmer has for the components View and Presenter as well as the application programmer for the Model component.

Figure 19-32: Linking between Model, View and Presenter

Table 19-15: Propagation of changes between Model, View and Presenter

Method, Function

Component

 

:represent()

View

The View object is populated with the data from the Model and, if necessary, data values are prepared for display

:apply()

View

The View object returns the data to the Model; if necessary, data values are prepared for assignment

Dialog event

View, Presenter

Changes of the View are signaled

:propagate()

Model

The data from the Model component is relayed to the linked View objects for display

:collect()

Model

The Model component retrieves all values from the linked View objects

DM_DataChanged()
or attribute assignment

Model

The Model component signals a modification of the data

.dataoptions[]

Presenter, Model

Control options for the automatic synchronization between Model and View

The Presenter logic in the IDM currently comprises four automatisms:

  1. If a View object with a linkage to a Model becomes visible (map), it fetches the data shortly before it gets visible (enabled by default).
  2. If a View object with a linkage to a Model becomes invisible (unmap), it assigns the data to the linked model (disabled by default).
  3. A dialog event on a View object with a link to a Model, which indicates a modification of a coupled attribute, assigns the data to the linked Model (disabled by default).
  4. Modifications of the data on a Model, e.g. signaled by a datachanged event, lead to a propagation of the changes to the linked View objects if these are visible (enabled by default).

37.6.3 Linkage Between Model and View

In principle, the Datamodel is designed in a way that the Model is not aware which View objects are using it. The data schema for Model and View is the same: indexed attributes to enable scalars, vectors and matrices.

The .datamodel attribute is used to link a view with a model:

object .datamodel[<View attribute>] <Model ID>

For data transfer from the Model to the View, it also has to be defined which attribute of the Model should be retrieved.

attribute .dataget[<View attribute>] <Model attribute>

To define the data transfer back from the View to the Model, the following attribute is used:

attribute .dataset[<View attribute>] <Model attribute>

This way, it can be exactly determined what in the View object is populated through a Model and what is reassigned to the Model. By indexing the .datamodel attribute, it is also possible to use multiple Data Models for different attributes.

View attributes are typically, but not necessarily, actual attributes of the View object, e.g. .content for an edittext used as a View object. In order to achieve a better distinction between View and Model attributes, it is recommended to use user-defined attributes as Model attributes.

To activate the linkage respectively make it effective, the .datamodel attribute must always be set without index, as well as a linking with .dataget or .dataset (with or without index).

This is an example for the use of multiple Models (Data Models: RecUsers, RecManager, VarValid, LbUsers) by multiple Views (listbox LbUsers, edittext EtName, pushbutton PbKill).

dialog D
record RecUsers
{
  string Name[integer];
  .Name[1] := "miller";
  .Name[2] := "smith";
  .Name[3] := "moreno";
  string Rights[integer];
  .Rights[1] := "guest";
  .Rights[2] := "user";
  .Rights[3] := "root";
}

record RecManager
{
  string CurrUser := "moreno";
  boolean IsAdmin := true;
  rule boolean ChangeUser(string Name)
  {
    variable anyvalue Idx;
    Idx := RecUsers:find(.Name, Name);
    if typeof(Idx) = integer then
      this.CurrUser := Name;
      this.IsAdmin := stringpos(RecUsers.Rights[Idx], "root") > 0;
      return true;
    endif
    return false;
  }
}

color CoError "red";
variable object VarError := true;

window Wi
{
  .title "Datamodel Model-View Coupling";
  .width 200;  .height 200;
  boolean Valid := false;

  listbox LbUsers
  {
    .xauto 0;  .yauto 0;
    .ybottom 60;
    .datamodel RecUsers;
    .datamodel[.activeitem] RecManager;
    .dataget .Name;
    .dataget[.activeitem] .CurrUser;
    on select, .activeitem changed
    {
      EtName.dataindex[.content] := this.activeitem;
      VarError := null;
      RecManager:ChangeUser(EtName.content);
    }

    :represent()
    {
      if Attribute = .activeitem then
        Value := this:find(.content, Value);
      endif
      pass this:super();
    }
  }

  edittext EtName
  {
    .yauto -1;  .xauto 0;
    .ybottom 30;
    .datamodel LbUsers;
    .datamodel[.bgc] VarError;
    .dataget .content;
    .dataget[.bgc] .value;
    .dataindex[.content] 0;
    on deselect_enter
    {
      if not RecManager:ChangeUser(this.content) then
        VarError := CoError;
      endif
    }
  }

  pushbutton PbKill
  {
    .yauto -1;
    .text "Kill All Processes";
    .sensitive false;
    .datamodel RecManager;
    .dataget[.sensitive] .IsAdmin;
  }

  on close { exit(); }
}

To make the definition of common links between View and Model attributes as straightforward as possible, the IDM default linkages may be utilized ( as can be seen in the example for EtName, where .datamodel and .dataget are used without index). These defaults are described in the table below:

Table 19-16: Default linkages of View attributes

Object Class

Default View Attribute
for .dataget

Default View Attribute
for .dataset

pushbutton
statictext
messagebox

.text

checkbox
radiobutton
timer

.active

.active

image
menuitem

.text

.active

filereq

.value

.value

listbox
treeview
tablefield

.content

.activeitem

notepage

.title

edittext

.content

.content

poptext

.text

.activeitem

progressbar

.curvalue

scrollbar
spinbox

.curvalue

.curvalue

menubox
toolbar
window

.title

The above example shows another particular feature. Once a visible object is used as Data Model (the View component EtName is linked to the Model LbUsers).

Basically, the IDM supports all object classes that allow user-defined attributes as Data Model, as well as global variables and functions with the function type datafunc. Linking multiple Models is also possible. For visible (visual) objects, however, one thing should be kept in mind: the user interaction does not trigger changed events for attributes and therefore also no automatic propagation of changes to the Model. This needs to be done explicitly or through the appropriate synchronization setting.

As View objects, as well any object classes that allow user-defined attributes are supported. However, the synchronization automatisms between model and view are designed for view objects to be instances with a visual representation.

37.6.4 Sequence and Value Aggregation

To populate a View object, a correct sequence is required when setting the View attributes. They are set by the IDM in a predefined, class-specific sequence (as in the attribute list of the object) to take the dependencies between the attributes into account. For a poptext, as an example, the sequence

…, .itemcount, …, .text[], …, .activitem, …, .userdata[], …

applies to observe the dependency of .text[], .activeitem and .userdata[] upon the .itemcount attribute. However, this sequence can only be observed for the representation ( that is, a synchronization triggered at the View component, e.g. via :represent()). The IDM has no influence on the sequence when the synchronization is triggered by the Model component, e.g. when using the DM_DataChanged() function.

If a Data Model is linked to all four attributes, first the number of elements is set, then the texts, then the active element is altered and finally the .userdata[] field is set.

In principle, the IDM does not prohibit using user-defined attributes as View attributes, but cannot ensure a consistent sequence for them. User-defined attributes and predefined attributes that do not belong to the object class are always handled after the predefined attributes for which the object class determines the sequence.

There are different kinds of value aggregation, i.e. the relation of data values between Model and View:

Figure 19-33: Relations between Model and View

There are two attributes to enable these kinds of relations:

anyvalue .dataindex[<View or Model attribute>] <index>
attribute .datamap[<View attribute>] <View attribute>

The .dataindex[] attribute is used to select a value from a value list and to transform indexed values. It should be noted that the attributes may occur as scalar, array, associative array or matrix (two-dimensional array), but access always only allows a vector (i.e. a one-dimensional array).

When assigning collections (value count <n>) to a vector attribute (one-dimensional or two-dimensional), the following transformations are carried out depending on the index:

Table 19-17: Index transformations when assigning collections

Index

Assignment

[0,<col>]

[1,<col>] … [<n>,<col>]

[<row>,0]

[<row>,1] … [<row>,<n>]

[<row>,<col>]

[<row>,<col>]

0

1 … <n>

<row>

<row>

void

void

others

void

The .datamap[] attribute allows merging data values (from one or more Data Models), which shall be mapped to exactly one View attribute. The main field of application will be two-dimensional attributes as found on the tablefield object. For this purpose, a virtual View attribute is used, which is then mapped to an actual View attribute by means of the .datamap[] attribute. Any predefined or user-defined attribute may serve as a virtual attribute, but it may be preferable to use an existing attribute on the View object to influence the sequence for a complete representation of all model values.

Example

The following example illustrates these different kinds of relations. For instance, the View object PtMonth is linked to the entire content of the attribute .MonthName[] from the Model object RecDate. In contrast, the View object StCurMonth displays only the 3rd item from the RecDate.FullMonthName[] array.

For the View object TfCurWeek, the data linkage is quite more complex. The weekday names from RecDate.DayName[7] are distributed to the header row (elements [1,1] … [1,7]) by the linkage .dataindex[.content] [1,0];. To link the week numbers into the table, the .field attribute is used by means of the definitions .dataget[.field] .WeekNr; and .dataindex[.field] [0,8];. Since there is a header row set through .rowheader 1;, the week numbers are written to the elements [2,8] … [6.8]. For marking the current day, the virtual attribute .text is used, for what a mapping .datamap[.text] .content; has been established to direct the marker text into the field .content[4,3.

dialog D
record RecDate
{
  integer CurMonth := 3;
  integer CurDay := 23;
  integer CurWeekDay := 3;

  string DayName[7];
  .DayName[1] := "Mon";
  ...
  string MonthName[12];
  .MonthName[1] := "Jan";
  ...
  string FullMonthName[12];
  .FullMonthName[1] := "January";
  ...
  integer WeekNr[5];
  .WeekNr[1] := 9;
  ...
}

window WiData 
{
  .title "Datamodel: index-coupling";
  .width 600;  .height 400;
  .datamodel RecDate;

  poptext PtMonth
  {
    .xauto 0;
    .dataget .MonthName;  /* fills poptext.text[] with "Jan","Feb","Mar",... */
    .dataget[.userdata] .FullMonthName;  /* fill full names into .userdata[] */
    .dataget[.activeitem] .CurMonth;
  }

  statictext StCurMonth
  {
    .ytop 30;
    .xauto 0;
    .alignment 0;
    .dataget .FullMonthName;
    /* fills statictext.text with "Mar" by Model index */
    .dataindex[.FullMonthName] 3;
  }

  tablefield TfCurWeek
  {
    .xauto 0;  .yauto 0;
    .ytop 60;
    .rowheight[0] 30;  .colwidth[0] 60;
    .colcount 8;  .rowcount 6;
    .content[1,8] "Week";
    .rowheader 1;
    .dataget[.content] .DayName;
    .dataindex[.content] [1,0];  /* fill "Mon"... to first row via View index */
    .dataget[.field] .WeekNr;  /* map to .field attribute to fill week no.    */
    .dataindex[.field] [0,8];  /* vertical into last column below the header  */
    .datamodel[.text] Marker;  /* mark a specific day using the               */
    .dataget[.text] .value;    /* .datamap attribute, because it goes into    */
    .datamap[.text] .content;  /* the already used View attribute .content!   */
    .dataindex[.text] [4,3];
  }

  on close { exit(); }
}

The screenshot for it looks like this:

Figure 19-34: A tablefield populated from different Data Models

It is crucial to understand this fact:

Data exchange between Model and View works via the existing mechanisms of the IDM, i.e. setvalue(), getvalue(), setvector() und getvector(). This implies that the exchanged data values are either scalar or vectorial.

If the change of a Model attribute is signaled (e.g. in a custom data function by calling the DM_DataChanged() function), this usually yields a Model index as an indication for the changed detail (typically of type void, integer or index). Since this change signaling is processed by the IDM as a datachanged event, multiple changes are combined into the overall change (void index) respectively redundant events are omitted.

In conjunction with the ability to influence the value aggregation through the .dataindex[] attribute, this has several consequences and particularities to be considered:

  1. Complete population of a two-dimensional attribute (e.g. .content[] at the tablefield) is possible without problems if the alignment as well as the number of columns and rows match the data length. The table size is adjusted through the setvector() functionality.

    However, single value modifications can only be updated at the correct cell in the tablefield if the Data Model issues a change notification with the respective index.

    Transfer of a two-dimensional array with its row and column form to an arbitrary position in a tablefield is however not possible, only the signaling of value changes at any position.

  2. With the use of .dataindex[] at the tablefield, a scalar or vector data value can be moved to an explicitly defined cell, row or column. Automatic cell extension happens according to the rules of setvalue() or setvector() and therefore also depends on the index transformation. Please note that user-defined attributes (e.g. arrays) do not support automatic extension.
  3. The same applies to vector and matrix attributes as they exist on listbox, treeview and poptext.
  4. The index for a Model attribute is used to avoid unnecessary propagation of value changes (e.g. a change of Data.Attr[5] is of no relevance for View objects linked to Data.Attr[2] only).
  5. When using void (default value for .dataindex[]) for the index transformation, propagation of the Model index – signaled by a datachanged event – is performed depending on the attribute type (scalar, vectorial, two-dimensional) up to the presentation by :represent(). Among others this is used in the example randomcolors.dlg to link color values from an associative array to the .bgc[] attribute of a tablefield object. However, this also means that linkages with different value dimensions (e.g. an array is mapped to a scalar) result in a value update depending on the index of the last change - which is usually not surprising. A possible solution is to use the correct index for the View and Model attributes by means of the .dataindex[] attribute.
  6. Setting default values (index [0], [0,0], [0,*] or [*,0]) of the involved Model and View attributes is not possible.

The following examples (located in the examples/datamodel/ subdirectory of the IDM installation directory) are worth a look at the source code as well as the trace file during execution:

relations.dlg

Demonstrates various value aggregations of scalar or vector data values in a listbox object with and without adaptation of the .content[] field as well as the effect of single changes.

Figure 19-35: Value aggregations for list objects, example relations.dlg

matrixrel.dlg

Demonstrates several simple and complex value aggregations of different data values into a tablefield object.

Figure 19-36: Value aggregations for tablefields, example matrixrel.dlg

numbers.dlg

Demonstrates the complete population of a tablefield object with a header row, including automatic row count adjustment.

Figure 19-37: Populating an entire tablefield, example numbers.dlg

puzzle.dlg

Demonstrates populating a tablefield from a record as a Data Model or with a data function (local or remote).

Figure 19-38: Populating a tablefield from record and data function, example puzzle.dlg

37.6.5 Synchronization Between Model and View

Automatic synchronization between Model and View is controlled by the .dataoptions[] attribute.

Table 19-18: Options for synchronization between Model and View

Attribute Index

Default

Component

Meaning

dopt_represent_on_map

true

View

Immediately before the View is made visible, the data values are fetched from the Model components and set on the View object.

dopt_represent_on_init

false

View

During object initialization (:init method), the data values are retrieved and set on the View object.

dopt_apply_on_unmap

false

View

Immediately before the View is made invisible, the data values are fetched from the View object and assigned to the linked Model components.

dopt_apply_on_event

false

View

If a user interaction triggers a dialog event which indicates a possible change of a View attribute, this is assigned to the linked Model components.

dopt_propagate_on_start

true

Model

When a dialog or module is started, the data from the Model objects is forwarded to the linked View components.

dopt_propagate_on_changed

true

Model

Modifications to a Model attribute are forwarded to the linked View components.

A key feature of the Datamodel is that data changes are always signaled and processed asynchronously via the event processing. For example, if the Data Model (Model object) is a record or another object with user-defined or predefined attributes, an attribute change, which is signaled by a datachanged event, is transmitted to the linked View objects so that they can update themselves. The dialog programmer can suppress a changed event with the operation ::=, but never a datachanged event.

A global variable may be used as a Model component as well, but does not allow controlling the synchronization. Variable values s are always propagated when the dialog or module is started and when the variable value is changed.

When .dataoptions[dopt_apply_on_unmap] := true; is used on a dialogbox, messagebox or filereq via a querybox call, the data values are only transferred from the View to the Model in case of a positive confirmation (button_ok or button_yes).

Manual intervention is not necessary in most cases. However if required, manual synchronization can be accomplished using the following methods:

Table 19-19: Manually callable Datamodel methods

Method

Component

Function

:represent()

View

The data of all linked Model attributes (.dataget) is retrieved and assigned to the View object

:apply()

View

The data from all linked View attributes (.dataset) is fetched and assigned to the Models

:propagate()

Model

The Model object communicates a change of all its Model attributes to the View objects that have a linkage.

:collect()

Model

The Model object fetches all data from the linked View objects to assign it to its Model attributes.

Synchronization only happens between instances, never with Default objects or Models.

For optimized synchronization of partial values, there is another particular feature. If a value change is signaled, the index of this value change is forwarded so that only this single value needs to be updated by the View component.

Example

Through a timer object, random colors are picked and assigned to random table cells.

dialog D
color CoRed "red";
color CoYellow "yellow";
color CoGreen "green";
color CoBlue "blue";

timer TiRandomColors {
  .active true;
  .starttime "+00:00:00";
  .incrtime "+00:00:00'100";
  object Color[index] := null;

  on select
  {
    variable index RandIndex := [1 + random(5),1 + random(5)];
    variable object RandColor := D.color[1 + random(D.count[.color])];
    /* change the color at a specific index */
    this.Color[RandIndex] := RandColor;
  }
}

window Wi
 {
  .title "Datamodel - random colors";
  .width 400;  .height 400;

  tablefield Tf
  {
    .xauto 0;  .yauto 0;
    .rowcount 5;  .colcount 5;
    .colwidth[0] 60;  .rowheight[0] 30;
    .dataoptions[dopt_represent_on_map] false;  /* avoid initial :represent() */
    .datamodel TiRandomColors;
    .dataget[.bgc] .Color;
  }
}

This is the screenshot for it:

Figure 19-39: Randomly colored tablefield cells with a timer as Data Model

37.6.6 Conversion and Conversion Methods

During synchronization between Model and View components, data values are exchanged, which usually means setting or querying attributes (similar to , getvalue(), setvector(), getvector()). Intervention of the application programmer by redefinition of the :set() and :get() methods is not possible.

However, on the View component it is possible to exert influence by means of the redefinable methods :represent(<Value>, <Attribute>, <Index>) and :retrieve(<Attribute>, <Index>).

When attributes are set at the View component, the IDM default handling normally performs a type conversion to the target data type. The following example demonstrates how a special handling for the View attribute .activeitem is achieved through redefinition.

Example

An airport list is displayed in the listbox Lb. The redefined methods :represent() and :retrieve() ensure a correct conversion from and to an IATA code.

dialog D
record RecAirport
{
  string Name[4];
  string IATA[4];
  .Name[1] := "Hartsfield Jackson Atlanta International";
  .IATA[1] := "ATL";
  .Name[2] := "Dubai International";
  .IATA[2] := "DXB";
  .Name[3] := "Stuttgart";
  .IATA[3] := "STR";
  .Name[4] := "Orkney Islands";
  .IATA[4] := "KOI";
  string NearestIATA := "STR";
  string Selected := "";
}

window Wi
{
  .title "Airports";
  .width 200;  .height 200;

  listbox Lb
  {
    .xauto 0;  .yauto 0;
    .ybottom 30;
    .dataoptions[dopt_apply_on_event] true;
    .datamodel RecAirport;
    .dataget .Name;
    .dataget[.userdata] .IATA;
    .dataget[.activeitem] .NearestIATA;
    .dataset[.activeitem] .Selected;

    :represent()
    {
      if Attribute = .activeitem then
        Value := this:find(.userdata, Value);
      endif
      pass this:super();
    }

    :retrieve()
    {
      if Attribute = .activeitem then
        return this.userdata[this.activeitem];
      endif
      pass this:super();
    }
  }

  edittext Et
  {
    .yauto -1;  .xauto 0;
    .editable false;
    .datamodel RecAirport;
    .dataget .Selected;
  }

  on close { exit(); }
}

This is the screenshot for it:

Figure 19-40: Window of the example dialog for overwriting :represent() and :retrieve()

37.6.7 Actions

In order to make manipulation functions of the Model component generally available for the Presenter logic, the concept of actions is used. These are methods with parameters which are provided by the Data Models. They can be invoked via the :calldata() method.

37.6.8 Tracing

The following trace codes have been introduced to reveal the synchronization processes between Data Models and presentation objects (Views) and to detect possible application errors.

Trace Code

Meaning

[CD]

Call Data to track the call for synchronization between View and Model. Typically :get() and :set() on the Model object as well as :represent() and :apply() on the View object are traced.

[CE]

Data Changed Event – Event that signals a change on the Data Model, typically triggered by setting an attribute or calling the application function DM_DataChanged().

37.6.9 Constraints

The IDM rejects modifications of the data linking or of the synchronization control (attributes .datamodel, .dataget, .dataset, .datamap, .dataindex, .dataoptions) while being within a redefinable method :represent() or :retrieve() or within a call of a data function.

Likewise the IDM rejects changes to the attributes .visible or .mapped if these are executed during synchronization of the View component and the IDM currently is in the state of converting visibility or invisibility.

37.6.10 Attribute Classification and Datamodel Attributes

The new attributes .datamodel, .dataget, .dataset, .dataindex, .datamap and .dataoptions constitute a class of attributes that define the linkage of View and Model components and control synchronization.

37.6.10.1 .datamodel

 

Identifier

Data Type

Rule Language

.datamodel[attribute]

object

C

AT_datamodel

DT_object

COBOL

AT-datamodel

DT-object

Classification

Datamodel attribute

Index data type

attribute

Access

get, set

Default value

changed event

no

Inheritance

yes

With this attribute, the linkage of the object (View component) to a Data Model (Model component) is defined. The attribute has to be defined at the View component.

The index can be an attribute that specifies the View attribute for which the Data Model shall be used. Without an index, the Data Model applies to all View attributes.

An active linkage requires at least the definition of a Data Model without index and a linking of the View attribute with a Model attribute through .dataget or .dataset.

Precedence over the usual inheritance of the attribute value takes the superseding by a set value at the closest parent object (without dialog or module).

37.6.10.2 .dataget

 

Identifier

Data Type

Rule Language

.dataget[attribute]

attribute

C

AT_dataget

DT_attribute

COBOL

AT-dataget

DT-attribute

Classification

Datamodel attribute

Index data type

attribute

Access

get, set

Default value

changed event

no

Inheritance

yes

This attribute defines the linking of a View attribute, specified as index, to a Model attribute, specified as value, for fetching the value from the Model component and representing it by the View component.

Without an index, the class-specific standard attribute is used (see table in chapter “Linkage Between Model and View”). The attribute has to be defined at the View component.

Data is exchanged according to the synchronization rules of the involved Model and View components and is only active if there is a Data Model set in the .datamodel attribute.

37.6.10.3 .dataset

 

Identifier

Data Type

Rule Language

.dataset[attribute]

attribute

C

AT_dataset

DT_attribute

COBOL

AT-dataset

DT-attribute

Classification

Datamodel attribute

Index data type

attribute

Access

get, set

Default value

changed event

no

Inheritance

yes

This attribute defines the linking of a View attribute, specified as index, to a Model attribute, specified as value, for fetching the value from the View component and assigning it at the Model component.

Without an index, the class-specific standard attribute is used (see table in chapter “Linkage Between Model and View”). The attribute has to be defined at the View component.

Data is exchanged according to the synchronization rules of the involved Model and View components and is only active if there is a Data Model set in the .datamodel attribute.

37.6.10.4 .dataindex

 

Identifier

Data Type

Rule Language

.dataindex[attribute]

attribute

C

AT_dataindex

DT_attribute

COBOL

AT-dataindex

DT-attribute

Classification

Datamodel attribute

Index data type

attribute

Access

get, set

Default value

changed event

no

Inheritance

yes

This attribute defines, in addition to the linkage of attributes between Model and View components, an index that further refines access to the attribute in order to enable the different kinds of relations (see chapter “Sequence and Value Aggregation”).

Any View or Model attribute may be used as index. This attribute has to be set at the View component.

37.6.10.5 .datamap

 

Identifier

Data Type

Rule Language

.datamap[attribute]

attribute

C

AT_datamap

DT_attribute

COBOL

AT-datamap

DT-attribute

Classification

Datamodel attribute

Index data type

attribute

Access

get, set

Default value

changed event

no

Inheritance

yes

This attribute defines an additional mapping of attributes when linking attributes between View and Model components. This definition may become necessary if several Data Models shall write their data values into a single attribute of the View component in order to allow the relation kind merging (see also chapter “Sequence and Value Aggregation”).

Any View or Model attribute may be used as index. This attribute has to be set at the View component.

37.6.10.6 .dataoptions

 

Identifier

Data Type

Rule Language

.dataoptions[enum]

boolean

C

AT_dataoptions

DT_boolean

COBOL

AT-dataoptions

DT-boolean

Classification

Datamodel attribute

Index data type

enum

Access

get, set

Default value

changed event

no

Inheritance

yes

This attribute defines the automatic synchronization between the Model and View components. Please refer to chapter “Synchronization Between Model and View” for details.

Attribute Index

Default

Component

Meaning

dopt_represent_on_map

true

View

Immediately before the View is made visible, the data values are fetched from the Model components and set on the View object.

dopt_represent_on_init

false

View

During object initialization (:init method), the data values are retrieved and set on the View object.

dopt_apply_on_unmap

false

View

Immediately before the View is made invisible, the data values are fetched from the View object and assigned to the linked Model components.

dopt_apply_on_event

false

View

If a user interaction triggers a dialog event which indicates a possible change of a View attribute, this is assigned to the linked Model components.

dopt_propagate_on_start

true

Model

When a dialog or module is started, the data from the Model objects is forwarded to the linked View components.

dopt_propagate_on_changed

true

Model

Modifications to a Model attribute are forwarded to the linked View components.

This attribute exists on all object classes that allow user-defined attributes, but possibly not with all indexes. The indexes dopt_apply_on_unmap, dopt_represent_on_map and dopt_apply_on_event are available on visual objects only.

37.6.11 Datamodel Methods

37.6.11.1 :apply()

When calling this method on a View component, all data values of View attributes that are linked to Model components are read ( using a :retrieve() call) and assigned to the corresponding Model components.

By specifying the optional parameters, the restriction to a special view attribute or to a special indexed single value is possible. Without parameters :apply() will also be invoked on all children and their children.

Normally calling this method should not be necessary because synchronization between View and Model is controlled through the .dataoptions[] attribute.

Linkage to the Model component must have been established with the attributes .datamodel and .dataset.

There will be no error message if the object has no linked attributes or the optionally specified attribute does not exist or is not linked.

Definition

void :apply
(
  { attribute Attribute input { , anyvalue  Index input } } |
  { anyvalue  Index     input }
)

Parameters

attribute Attribute input
This optional parameter specifies the View attribute to be retrieved and assigned to the corresponding Model component.
anyvalue Index input
This optional parameter specifies the index value to be used for getting the value from the View object.

Example

In the following example dialog, the content string is assigned to the Data Model using the :apply() method on the edittext or on the window. The statictext at the bottom of the window shows the current value of the Data Model VarString.

dialog D
accelerator AcF5 "F5";
variable string VarString := "Friday";

window Wi
{
  .title ":apply demo";
  .width 200;

  child edittext Et
  {
    .xauto 0;
    .xright 80;
    .datamodel VarString;
    .dataset .value;
    .content "Saturday";
    .toolhelp "Press F5 to apply";
    
    on key AcF5
    {
      this:apply(.content);
    }
  }

  child pushbutton Pb
  {
    .xauto -1;
    .width 80;
    .text "Apply";

    on select
    {
      this.window:apply();
    }
  }

  child statictext St
  {
    .xauto 0;
    .yauto -1;
    .datamodel VarString;
    .dataget .value;
  }

  on close { exit(); }
}

37.6.11.2 :collect()

Calling this method on a Model component retrieves all data values from the View components that have linked attributes. For this, :retrieve() is invoked for the respective View attributes to determine their data values and assign them to the Data Model.

Normally calling this method should not be necessary because synchronization between View and Model is controlled through the .dataoptions[] attribute.

Linkage to the Model component must have been established with the attributes .datamodel and .dataset.

There is no error message if the object has no reference by a View component or no linked attributes.

Definition

void :collect
(
)

Example

dialog D
record Rec 
{
  .dataoptions[dopt_propagate_on_start] false;
  string  FirstName := "";
  string  LastName  := "";
  boolean Female    := false;
}

timer Ti
{
  .starttime "+00:00:02";
  .incrtime "+00:00:01";
  .active true;

  on select
  {
    Rec:collect();  /* read data explictly (from EtFirst/LastName&CbFemale) */
  }
}

window Wi
{
  .title ":collect demo";
  .width 200;  .height 200;
  .xleft 250;
  .datamodel Rec;
  .dataoptions[dopt_represent_on_map] false;

  statictext
  {
    .text "First Name"; .width 100;
  }

  edittext EtFirstName
  {
    .content "Ina";
    .xauto 0;
    .xleft 100;
    .dataset .FirstName;
  }

  statictext
 {
    .text "Last Name";  .width 100;  .ytop 30;
  }

  edittext EtLastName
  {
    .ytop 30;
    .xauto 0;  .xleft 100;
    .content "Bausch";
    .dataset .LastName;
  }

  checkbox CbFemale
  {
    .ytop 60;
    .text "Female";
    .active true;
  }

  statusbar Sb
  {
    statictext StFirstName
    {
      .width 100;
      .dataget .FirstName;
    }

    statictext StLastName
    {
      .dataget .LastName;
      .text "Update in 2 secs";
    }
  }

  on close { exit(); }
}

37.6.11.3 :propagate()

When this method is called on a Model component, all linked View components are requested to update their View attributes which are linked to this Model object.

Normally calling this method should not be necessary because synchronization between View and Model is controlled through the .dataoptions[] attribute.

Linkage must have been established with the attributes .datamodel and .dataset on the View component.

There will be no error message if the Model object has no linked attributes.

Definition

void :propagate
(
)

Example

dialog D

timer Ti
{
  .starttime "+00:00:03";
  .incrtime "+00:00:01";
  .active true;
  string Time := "??:??";
  integer Min:=0;
  integer Sec:=0;
  integer Counter := 100;
  .dataoptions[dopt_propagate_on_start] false;
  .dataoptions[dopt_propagate_on_changed] false;

  on select
  {
    this.Counter := this.Counter-1;
    if this.Counter<0 then
      exit();
      return;
    endif
    if this.Sec=59 then
      this.Min := (this.Min + 1) % 60;
    endif
    this.Sec := (this.Sec + 1) % 60;
    this.Time := sprintf("%02d:%02d", this.Min, this.Sec);
    this:propagate();  /* propagate explicitly every second */
  }
}

window WiTime
{
  .width 200;
  .title ":propagate demo";
  .datamodel Ti;
  .dataoptions[dopt_represent_on_map] false;

  statictext StMin
  {
    .xauto 0;
    .dataget .Time;
  }

  statictext StCounter
  {
    .xauto 0;
    .ytop 50;
    .dataget .Counter;
    .text "Please wait...";

    :represent()
    {
      if Attribute=.text then
        Value := "Time to exit: "+Value;
      endif
      return this:super();
    }
  }

  on close { exit(); }
}

window WiMinSec
{
  .title ":propagate demo - min/sec";
  .width 200;  .height 200;
  .xleft 250;

  tablefield Tf
  {
    .xauto 0;  .yauto 0;
    .rowcount 2;  .colcount 2;
    .rowheader 1;
    .colwidth[0] 50;  .rowheight[0] 30;
    .content[1,1] "Min";
    .content[1,2] "Sec";
    .dataoptions[dopt_represent_on_map] false;
    .datamodel Ti;
    .dataget[.field] .Sec;
    .dataget[.content] .Min;
    .dataindex[.field] [1,2];
    .dataindex[.content] [2,1];
  }

  on close { exit(); }
}

37.6.11.4 :represent()

This method has two functions.

  1. When called without parameters, all linked attributes at the View component are updated. This happens for all children and their children as well.

    This is done by retrieving the data value for each View attribute from the corresponding Model component and invoking the internal and redefinable :represent() method (with parameters Value, Attribute, Index) to represent it through the object.

    Linkage to the Model component must have been established with the attributes .datamodel and .dataset.

    Important

    Direct invocation with parameters is not supported by the IDM.

  2. The redefinable :represent() method enables the dialog programmer to intervene before the actual assignment of the data value to the presentation object. This allows to interpose required conversions or transformations. The redefined method should be completed with pass this:super(); to ensure the normal behavior of the IDM respectively make use of the automatic type conversion.

    Note

    The redefinable method :set() is not invoked for assigning data values to the presentation object.

Definition

void :represent
(
)

Redefinable Method

void :represent
(
  anyvalue  Value     input,
  attribute Attribute input,
  anyvalue  Index     input
)

Parameters

anyvalue Value input
This parameter contains the data value to be presented.
attribute Attribute input
This parameter indicates the View attribute where the data value shall be represented.
anyvaluet Index input
This parameter defines the index value for presenting the data value in the View attribute.

Example

dialog D
default statictext { .sensitive false; }

record Rec
{
  .dataoptions[dopt_propagate_on_start] false;
  string Name := "Henry Walter";
  string ZIP  := "80246";
}

window Wi
{
  .title ":represent demo";
  .width 200;  .height 150;
  .datamodel Rec;
  .dataoptions[dopt_represent_on_map] false;

  statictext
  { .text "Name"; .width 100; }

  edittext EtName
  {
    .xauto 0;  .xleft 100;
    .dataget .Name;
    .dataset .Name;

    on deselect_enter
    {
      this:apply();
    }
  }

  statictext
  { .text "ZIP";  .width 100;  .ytop 30; }

  edittext EtZIP
  {
    .ytop 30;  .xauto 0;  .xleft 100;
    .dataget .ZIP;
    .dataset .ZIP;
    .format "XNNN";

    on deselect_enter
    {
      this:apply();
    }
  }

  statictext
  { .text "State";  .width 100;  .ytop 60; }

  poptext PtState
  {
    .ytop 60;
    .xauto 0;  .xleft 100;
    .dataget[.activeitem] .ZIP;
    .dataset[.activeitem] .ZIP;
    .text[1]  "???";  .text[2]  "PA";
    .text[3]  "FL";   .text[4]  "IN";
    .text[5]  "WY";   .text[6]  "KY";
    .text[7]  "NE";   .text[8]  "MA";
    .text[9]  "CO";   .text[10] "TX";
    .text[11] "AK";

    :represent() 
    {
      /* convert the XNNN-string into an index */
      if Attribute=.activeitem then
        Value := 2 + atoi("0" + substring("" + Value, 2, 1));
      endif
      pass this:super();
    }

    :retrieve()
    {
      if Attribute = .activeitem then
        if this.activeitem > 1 then
          return sprintf("%s%d%02d",
                         substring(this.text[this.activeitem], 1, 1),
                         this.activeitem - 2,
                         random(100));
        else
          return "";
        endif
      endif
      pass this:super();
    }

    on select
    {
      this:apply();
    }
  }

  pushbutton PbRepresent
  {
    .text "Represent";
    .yauto -1;
    .width 100;  .xleft 50;

    on select
    {
      this.window:represent();  /* explicit represent of all views */
    }
  }

  statusbar Sb
  {
    statictext StInfo
    {
      .dataget .Name;
      .dataget[.At] .ZIP;
      string Name := "";
      string ZIP := "";

      :represent()
      {
        /* merge .Text & .At into a single string */
        case Attribute
        in .text:
          this.Name := toupper(Value);
        in .At:
          this.ZIP := Value;
        in .text, .At:
          this.text := sprintf("%s @ %s", this.Name, this.ZIP);
          return;
        endcase
        pass this:super();
      }
    }
  }

  on close { exit(); }
}

37.6.11.5 :retrieve()

This redefinable method is invoked for synchronization between View and Model components in the presentation object to retrieve the data value for a View attribute. This also happens implicitly when the :apply() or :collect() methods are called.

Important

Direct invocation is not supported by the IDM.

The default behavior of the method is to return the respective attribute as a single value or aggregated entire value. The redefinable method :get() is not invoked to retrieve the data values of the presentation object. This means that in the default behavior, always the actual attribute values are retrieved. Indexed attributes return the data value as a vector when the entire value is accessed (see also the setvector() and getvector() functions).

By redefining this method, its default behavior can be omitted or extended so that the values may be adapted.

Linkage to the Model component must have been established with the attributes .datamodel and .dataset.

Definition

anyvalue :retrieve
(
  attribute Attribute input,
  anyvalue  Index     input
)

Parameters

attribute Attribute input
This parameter defines the View attribute whose data value is to be queried.
anyvalue Index input
This parameter indicates the index value to be used when accessing the data value of the View attribute at the presentation object.

Return value

Data value appropriate to the attribute and index specification.

Example

See method :represent()

37.6.11.6 :calldata()

When this method is called, all Data Models defined at the called object and its children with the .datamodel attribute are gathered and an action in form of a method with arguments is invoked only once for each Data Model.

With this method, at a View object an action can be triggered on the involved Data Models without having detailed knowledge about the defined Model objects.

A return value or feedback, e.g. if the method does not exist on the Data Models, is not provided.

Definition

void :calldata
(
      method   Method input
  { , anyvalue Arg1   input }
  ...
  { , anyvalue Arg15  input }
)

Parameters

method Method input
This parameter defines the method to be invoked on the involved Data Models.
anyvalue Arg1 input

anyvalue Arg15 input
These optional parameters contain the arguments used for the method invocation.

Example

dialog D

record RecPart
{
  string Name[5] := "";
  .Name[1] := "car";
  .Name[2] := "wheel";
  .Name[3] := "seat";
  .Name[4] := "front pane";
  .Name[5] := "break pedal";

  rule void Add()
  {
    variable integer Idx := this.count[.Name] + 1;
    this.count[.Name] := Idx;
    this.Name[Idx] := "part#" + Idx;
  }
}

record RecLevel
{
  integer Level[5] := 0;

  rule void Add()
  {
    this.count[.Level] := this.count[.Level] + 1;
  }

  rule void Indent(integer Idx)
  {
    if Idx>0 andthen Idx<=this.count[.Level] then
      this.Level[Idx] := (this.Level[Idx]+1) % 5;
    endif
  }
}

window Wi
{
  .height 200;
  .title ":calldata demo";
  .datamodel RecPart;

  treeview Tv
  {
    .xauto 0;
    .yauto 0; .ybottom 30;
    .datamodel[.level] RecLevel;
    .dataget[.content] .Name;
    .dataget[.level] .Level;
    .open[0] true;
  }

  pushbutton PbIndent
  {
    .yauto -1;
    .text "Indent >";

    on select
    {
      this.window:calldata(:Indent, Tv.activeitem);
    }
  }

  pushbutton PbAdd
  {
    .xauto -1;  .yauto -1;
    .text "Add";

    on select
    {
      this.window:calldata(:Add);
    }
  }

  on close { exit(); }
}

37.6.12 Data Function

37.6.12.1 Rule Language

Definition

{ export | reexport } function datafunc { <language> } <function name> ();

The parameters of a data function are predefined by the ISA Dialog Manager and cannot be changed by the user.

These functions can be specified in the .datamodel attribute of all objects that also support user-defined attributes. A data function can serve as a Data Model (Model component) to provide the presentation objects with data values. The function is called when data values shall be synchronized, i.e. either to retrieve data values from the Data Model or to assign them.

Data functions can only be implemented in C/C++ and are not supported for the application language COBOL. However, a data function may be implemented on the DDM server side.

Vergleichen Sie hierzu bitte auch das Kapitel “C Interface” sowie die Attribute .datamodel, .dataget, .dataset und .dataoptions.

Please also refer to the chapter “C Interface” as well as the attributes .datamodel, .dataget, .dataset and .dataoptions.

37.6.12.2 C Interface

Functions that are declared as data functions in the dialog description must be declared in C as follows:

DM_Boolean DML_default DML_CALLBACK <function name> (DM_DataArgs *args);

if the function is defined as

{ export | reexport } function datafunc <function name> ();

in the dialog script

or as

DM_Boolean DML_c DML_CALLBACK <function name> (DM_DataArgs *args);

if the function is defined as

{ export | reexport } function c datafunc <function name> ();

in the dialog script.

The parameter of this function is predefined by the ISA Dialog Manager and cannot be changed. It represents a Data Model (Model component) that provides the presentation objects (View component) with data values or stores and manages them.

This function is called when a synchronization between View and Model components is required. This may either happen automatically, according to the control options in the .dataoptions[]attribute of the involved components. The call can also be triggered by explicit invocation of the :collect(), :propagate(), :apply() and :represent() methods. For each Model attribute there is a separate call.

37.6.12.3 Example

Dialog File

dialog D
function datafunc FuncData();
function void     Reverse(integer Idx);

window Wi
{
  .title "Datafunc demo";
  .width 200;  .height 300;

  edittext Et
  {
    .datamodel FuncData;
    .dataget .text;
    .dataset .text;
    .xauto 0;
    .xright 80;
  }

  pushbutton PbAdd
  {
    .text "Add";
    .xauto -1;
    .width 80;

    on select
    {
      this.window:apply();
    }
  }

  listbox Lb
  {
    .xauto 0;  .yauto 0;
    .ytop 30;  .ybottom 30;
    .datamodel FuncData;
    .dataget .content;

    on select
    {
      PbReverse.sensitive := true;
    }
  }

  pushbutton PbReverse
  {
    .xauto 0;  .yauto -1;
    .text "Reverse element";
    .sensitive false;

    on select
    {
      Reverse(Lb.activeitem);
    }
  }

  on close { exit(); }
}

C File

#ifdef VMS
#  define EXITOK    1
#  define EXITERROR 0
#else
#  define EXITOK    0
#  define EXITERROR 1
#endif

#include <IDMuser.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "datafuncfm.h"

#define DIALOGFILE "~:datafunc.dlg"

static DM_ID     data_id = (DM_ID)0;
static DM_Value  data_vec;
static DM_String data_str;

void DML_default DM_CALLBACK FuncData __1((DM_DataArgs *, args))
{
  if (!data_id)
    data_id = args->object;
  switch (args->task)
  {
  case MT_get:
    switch(args->attribute)
    {
    case AT_text:
      args->retval.type = DT_string;
      args->retval.value.string = data_str;
      break;
    case AT_content:
      if (args->index.type == DT_void)
      {
        args->retval = data_vec;
      }
      else if (args->index.type == DT_integer)
      {
        DM_ValueGet(&data_vec, &args->index, &args->retval, 0);
      }
      break;
    default:
      break;
    }
    break;
  case MT_set:
    switch(args->attribute)
    {
    case AT_text:
      if (args->data.type == DT_string)
      {
        if (DM_ValueChange(&data_vec, NULL, &args->data, DMF_AppendValue))
          DM_DataChanged(data_id, AT_content, NULL, DMF_Verbose);
      }
      break;
    default:
      break;
    }
    break;
  default:
    break;
  }
}

void DML_default DM_ENTRY Reverse __1((DM_Integer, Idx))
{
  DM_Value  index, data;
  char     *cp,    ch;
  size_t    len,   i;

  DM_ValueInit(&data, DT_void, NULL, 0);
  index.type = DT_integer;
  index.value.integer = Idx;
  if (DM_ValueGet(&data_vec, &index, &data, 0) && data.type == DT_string)
  {
    if (DM_StringChange(&data_str, data.value.string, 0))
      DM_DataChanged(data_id, AT_text, NULL, DMF_Verbose);

    /* reverse the string */
    cp = data.value.string;
    if (cp)
    {
      len = strlen(cp);
      if (len>2)
      {
        len--;
        for (i=0; len>0 && i<len/2; i++)
        {
          ch = cp[i];
          cp[i] = cp[len-i];
          cp[len-i] = ch;
        }
      }
    }
    if (DM_ValueChange(&data_vec, &index, &data, 0) && data_id)
      DM_DataChanged(data_id, AT_content, &index, DMF_Verbose);
  }
}

int DML_c AppMain __2((int, argc), (char **,argv))
{
  DM_ID dialogID;
  DM_Value data;

  /* initialize the Dialog Manager */
  if (!DM_Initialize (&argc, argv, 0))
  {
    DM_TraceMessage("Could not initialize.", 0);
    return (1);
  }

  /* load the dialog file */
  switch(argc)
  {
  case 1:
    dialogID = DM_LoadDialog (DIALOGFILE,0);
    break;
  case 2:
    dialogID = DM_LoadDialog (argv[1],0);
    break;
  default:
    DM_TraceMessage("Too many arguments.", 0);
    return(EXITERROR);
    break;
  }
  if (!dialogID)
  {
    DM_TraceMessage("Could not load dialog.", 0);
    return(EXITERROR);
  }

  data.type = DT_type;
  data.value.type = DT_string;
  DM_ValueInit(&data_vec, DT_vector, &data, DMF_StaticValue);

  data.type = DT_string;
  data.value.string = "^ Enter a string";
  DM_ValueChange(&data_vec, NULL, &data, DMF_AppendValue);
  data.value.string = "and press 'Add'";
  DM_ValueChange(&data_vec, NULL, &data, DMF_AppendValue);

  DM_StringInit(&data_str, DMF_StaticValue);
  DM_StringChange(&data_str, "Change me!", 0);

  /* install table of application functions */
  if (!BindFunctions_D (dialogID, dialogID, 0))
    DM_TraceMessage ("There are some functions missing.", 0);

  /* start the dialog and enter event loop */
  if (DM_StartDialog (dialogID, 0))
    DM_EventLoop (0);
  else
    return (EXITERROR);

  return (EXITOK);
}

37.6.12.4 Data Function Structure DM_DataArgs

This structure is always passed as a parameter to data functions.

typedef struct
{
  DM_ID        object;
  DM_Method    task;

  DM_Attribute attribute;
  DM_String    identifier;

  DM_Value     index;
  DM_Value     data;
  DM_Value     retval;
} DM_DataArgs;

Meaning of elements

DM_ID object

In this element, the object ID of the Data Model is passed to the data function.

DM_Method task

This element specifies the reason for the call. Currently the following values are possible: MT_get and MT_set.

DM_Attribute attribute

For the call reasons MT_get and MT_set, this element contains the attribute on which the function shall be applied.

DM_String identifier

This element contains the attribute identifier from the attribute element as a string to facilitate the implementation for user-defined attributes.

DM_Value index

This element contains the index value for the attribute access that the call reason MT_get or MT_set refers to. If the index element has the data type DT_void, it refers to the entire value. For indexed data values, the relationship kinds and also the processing of incomplete index values (e.g. [0], [?,0] oder [0,?]) should be taken into account.

DM_Value data

For the call reason MT_set, this element contains the data value to be processed by the data function.

DM_Value retval

For the call reason MT_get, in this element the data value for the specified attribute and the given index has to be returned.

37.6.13 Application Function DM_DataChanged

This function is used to signal that the value of the specified attribute (Model attribute) has changed on a particular Data Model (Model component). This change is put into event processing as a datachanged event. Not until further event processing the linked presentation objects (View components) are triggered to fetch the new data values and have them displayed.

DM_Boolean DML_default DM_EXPORT DM_DataChanged
(
  DM_ID        object,
  DM_Attribute attribute,
  DM_Value  *  index,
  DM_Options   options
)

Parameters

-> DM_ID object

This is the object ID of the Data Model object where a data value has changed.

-> DM_Attribute attribute

This parameter indicates the attribute of the Data Model that has changed.

-> DM_Value *index

This parameter defines the index of the modified attribute. If it is NULL, this indicates a change of all single values.

-> DM_Options options

Option

Meaning

0

There will be no tracing of this function.

DMF_Verbose

Activates tracing of this function.

Return value

DM_TRUE

Modification has been successfully stored as datachanged event.

DM_FALSE

No event could be created.

Example

See “Data Function”

37.7 Compatibility

The network protocol has changed, older versions are no longer compatible with this version.

C, C++, and COBOL sources have to be recompiled because internal structures have changed.

The binary format has changed. Binary files have to be regenerated.

37.8 Unix

New: The platform RHEL7.0 (kernel 3.10.0, 32- & 64-bit, gcc4.8.2, GLIBC_2.14) with Qt 4.8.5 is supported.

New: The additional installation option -desktop integrates the IDM into the desktop.

On Linux machines with GNOME desktop and default paths for .desktop entries, MIME types and icons, the -desktop option can be used in addition to integrate the Editor, Debugger and Help into the start menu and to register IDM-specific file types (MIME types). This requires root privileges. For starting programs from the application menu, the IDM applications need to be in the standard search path however. There is no explicit definition of IDM_HOMEDIR necessary for it.

The installation script install.sh uninstalls an existing IDM version including documentation and examples using the uninstall script lib/IDM/uninstall.sh.

37.9 Motif

New: The attributes .alignment, .spacing and .tilestyle on the image object are now supported. On Motif, the default value for .spacing on the image object is 2.

New: The statusbar object is now supported on Motif as well.

Changed: The standard height calculation ( for .height = 0) of the spinbox now takes into account the set font. The height is calculated such that an edittext with the same font and with .borderwidth = 0 will fit in and the text will be cropped vertically.

37.10 Windows

Changed: The options .options[opt_wntsizebug_compat] and .options[opt_w2kprefsize_compat] are no longer evaluated. If dialog scripts have not yet been adapted, the new border attribute .borderstyle must be disabled with the command line option ‑IDMborder5_compat. Furthermore, .options[opt_wntsizebug_compat] now explicitly needs to be set to true because the new default value is false.

37.10.1 Change of .toolkit_version on Microsoft Windows

On Microsoft Windows, the attribute .toolkit_version of the setup object no longer returns the Windows version for which the IDM was compiled, but the version of the Common Controls DLL (comctl32.dll). This DLL determines the appearance of the user interface objects, thus now a value is returned that provides information about the appearance and layout (e.g. border widths) of the interface.

The version is coded as a decimal number:

major_version * 100 + minor_version

In addition, the following predefined values may occur:

0

No Common Controls DLL available.

400

Version could not be determined since the Common Controls DLL is older than version 4.71.

471

Common Controls DLL has version 4.71 or version could not be determined because an error occurred when calling DllGetVersion.

582

Common Controls DLL has version 5.82 or version is 6.00 or higher and Visual Styles are disabled.

>= 600

Visual Styles are enabled.

37.10.2 Remark on the Window Object

The border width of the window may vary depending on which subsystem version was specified when linking the application. A difference has been noticed on Windows 7 for windows with .sizeable = false.

The linker option /SUBSYSTEM:WINDOWS,5.01 for 32-bit programs or .…,5.02 for 64-bit programs produces border widths like on Windows XP. In Visual Studio, the linker option can be set in the project properties in LinkerSystem by entering 5.01 or 5.02 as Minimum Required Version. Further information can be found in the Microsoft help for the Linker and Visual Studio.

37.11 Core

12228: A crash that occurred when completely deleting an input formatted with scanf format and /tzp options with special number constellations is now avoided.

12056 (Changed): Compilation errors could occur because the IDM include files had redefined keywords.

Attention

There still must be paid attention to the correct order of the include files.

To avoid keyword problems, potential and obsolete keywords have been removed from the include files IDMuser.h, IDMcpp.h, and IDMusw.h.

Keyword

IDM Definition

pascal

DML_pascal

cdecl

DML_c

near

(1)

far

(1)

huge

(1)

(1) There is no IDM definition for it.

Furthermore, all IDM data types now start with DM_. Thus the following data types are omitted:

Old Data Type

New Data Type

PTR

DM_Pointer

FPTR

DM_Pointer

NPTR

DM_Pointer

schar

DM_Int1

uchar

DM_UInt1

ushort

DM_UInt2

uint

DM_UInt

ulong

DM_UInt4

boolean

DM_Boolean

DM_boolean

DM_Boolean

SOCKET

DM_Socket (1)

(1) On Unix int was used instead of SOCKET, but DM_Socket should be used too.

The old data types can be enabled by defining the preprocessor symbol DM_5_COMPAT_TYPES.

All constants now also start with DM_. The following constants should be replaced successively:

Old Constant

New Constant

TRUE

DM_TRUE

FALSE

DM_FALSE

FAILURE

DM_FAILURE

The old constants can be enabled by defining the preprocessor symbol DM_5_COMPAT_CONSTANTS. If there are problems with TRUE, FALSE, or FAILURE, the definition can be avoided with the preprocessor symbol DM_OMIT_BOOL_CONSTANTS.

The following preprocessor symbols are no longer used, with the new ones already being used in IDM 5:

Old Symbol

Current Symbol

DOS

WIN32

WSIWINXP

WSIWIN=0x501

WSIWIN32

(1)

WSIWINVISTA

(2)

(1) IDM for Windows 2000 is no longer supported.

(2) There was no IDM for Windows Vista.

11987: DM_GetValue() now returns a proper UTF16 empty string when the queried attribute is set to null.

11353: The IDM now enforces that there is a set label (inherited label not sufficient) for exported objects (directly below the module) when generating the Interface file.

Setting a label for exported objects is absolutely mandatory to enable correct Interface generation and module reloading. If during Interface generation the IDM encounters an exported object without a label, an error message is output.

11319 (changed): The attribute .options[opt_old_select] at the tablefield now has the default value false.

9108 (changed): The attribute .options[opt_old_select] at the poptext now has the default value false.

New: The slot management has been enhanced so that an invalid access to a destroyed object may be recognized and reported by the dumpstate (dumpstate()) or debug() output. This only works reliably for the last 250 destroyed objects if there is no creation in between. Since the object was destroyed, only the class can be returned.

The dumpstate functionality now also outputs IDM objects in the SLOTS section for which an invalid access was attempted after their destruction. These typically can be recognized by the property refs=0, lock=0, drop=1 and object="Unknown ID". However, the output of these invalid accesses can only be made for the last 250 destroyed objects and is affected by objects created in the meantime. An access to an invalid object ID is taken by the IDM as a clue to output a dumpstate when exiting the application respectively to include the SLOTS section.

New: A HINTS section has been added to the dumpstate output.

New: For better problem analysis, the Queue Full warning now includes details about the event.

37.12 Editor

Changed: In the Rule Vocabulary, built-in functions and methods are now separated.