2022 April Release

app.ducx User Interface LanguagePermanent link for this heading

The Fabasoft app.ducx user interface language allows you to define forms, form pages, menu items and other user interface elements for your object classes.

A user interface model block consists of import declarations and user interface model elements. The userinterface keyword denotes a user interface model block. It must be followed by the reference of your software component and curly braces.

User interface model files have the extension .ducx-ui.

Syntax

userinterface softwarecomponent
{
  // Import declarations
  import softwarecomponent;

  // User interface model elements (forms, form pages, ...)
  ...
}

Defining Forms and Form PagesPermanent link for this heading

Forms and form pages will be used in many situations:

  • Forms determine which properties should be displayed in the attribute editor when the “Properties“ menu item is invoked by the user.
  • Forms determine which properties are available in the search dialog when the user invokes the “Find“ menu item.
  • Forms determine which object lists are displayed for “Compound Objects“ in the web client when browsing the object hierarchy (this is called “Explore“ mode). Compound objects may have multiple lists. These lists are presented to the user either in a dashboard view or via multiple tabs depending upon the user interface used.
  • Forms determine which object lists should be used as child nodes of a compound object in the “Navigation” tool (tree view).
  • Forms determine which properties may be added to as columns to the detail view of an object list.
  • Forms determine which properties should be shown in the IntelliHelp window.
  • Forms are used to define which properties should be shown in the card, content or preview view.
  • And finally forms and pages are used in dialogs.

Note: The Fabasoft app.ducx user interface language distinguishes two types of forms. The default are forms that consist of one or multiple form pages (form and formpage). These forms can be used for all situations described above. Alternatively, there are so called desk forms (deskform) which only define a dataset and can only be used for restricting the lists displayed in explore mode and in the tree view. It is not recommended to use desk forms anymore.

Defining a FormPermanent link for this heading

Syntax

form reference {
  audience = audience;
  // New form pages can be defined inline
  formpage reference {
    audience = audience;
    dataset {
      class;
      property;
      ...
    }
  }
  // Existing form pages can be reused by adding their references to the
  // form block in the order they should appear on the form

  reference;
}

A form consists of form pages holding the properties that should be displayed. Form pages can either be defined inline or existing form pages can be reused.

The form keyword is used to define a form. It must be followed by a reference and curly braces.

Defining the Audience for a FormPermanent link for this heading

The audience keyword is used to define the target audience of a form. The following table shows the possible values that can be assigned to audience. When audience is not specified implicitly enduser is the target audience.

Audience

Description

enduser

The form is usable by all users. The ACL COOSYSTEM@1.1:DefaultAdministratorACL is assigned to the form.

administrator

The form is usable by administrators only. The ACL COOSYSTEM@1.1:DefaultDeveloperACL is assigned to the form.

Defining the Title, a Heading, and a Description for a FormPermanent link for this heading

When a form is used in a dialog or in the attribute editor (which uses dialogs for reading and changing properties, too) you may define a title for the form, a page headline and a page description. In a confirm dialog only a title and a description will be displayed.

For more information about title, heading and descriptions in dialogs please refer to chapter “Defining the Title, a Heading, and a Description of a Dialog”.

The property formcaption stores the multilingual text that may be displayed as title. It stores one string for each supported language. An entry in the multilingual files is only generated if explicitly used.

The property formpagelabel stores the multilingual text that may be displayed as name of a tab in multi-tab dialogs or as headline in a single tab dialog. It stores one string for each supported language. An entry in the multilingual files is generated automatically.

The property formpagedescription stores the multilingual text that explains the data shown on the form page in more detail. It stores one string for each supported language. An entry in the multilingual files is only generated if explicitly used.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  form FormInvoice {
    formcaption = {}
    formpage PageInvoiceData {
      formpagedescription = {}
      ...
  }
}

Adding Form Pages to a FormPermanent link for this heading

Each form can consist of multiple form pages that can either be reused or defined inside the form block.

The formpage keyword is used to define a new form page inside the form block. For reusing an existing form page, you just need to provide the reference of the form page followed by a semicolon.

The order of the form pages in the form block also determines their order on the form when it is displayed in the user interface.

Enabling the Generic ViewPermanent link for this heading

When enabling the generic view, properties that are not explicitly assigned to a form page are displayed on a system-generated form page. The name of the system-generated form page corresponds to the name of the object class the properties belong to.

To enable the generic view for a form, COOATTREDIT@1.1:formgeneric can be set to true. In this case, it is not necessary to define any form pages as all properties of the object class of the current object are displayed in a generic manner. In the generic view, the order of the properties on the system-generated form page is determined by the object class definition.

Inheriting Form Pages From Base ClassesPermanent link for this heading

When setting inherit to true, the form pages inherited from the base classes are displayed after the form pages defined in the current form.

When setting inheritfrom to a class, the form pages inherited from this class and its base classes are displayed. This setting is evaluated after the property inherit.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  form FormInvoice {
    audience = enduser;
    inherit = true;
    inheritfrom = CompoundObject;

    formpage PageInvoiceGeneral {
      audience = enduser;
      symbol = SymbolInvoice;
      dataset {
        invoicestate;
        invoiceorder;
      }
    }

    formpage PageInvoiceDates {
      audience = enduser;
      symbol = SymbolInvoiceDates;
      dataset {
        invoicedate;
        invoicepaymentdate;
      }
    }
  }
}

Defining a Form PagePermanent link for this heading

A form page is defined in a formpage block that must be nested within a form block. The formpage keyword must be followed by the reference of the form page and curly braces.

A form page consists of a dataset block holding the properties and classes which can be used in the layout definition to be displayed, an optional layout definition, and some general settings concerning the symbol displayed on the tab and the target audience.

Reusing an Existing Form PagePermanent link for this heading

As starting point for a new layout an existing form page can be used. To do that open the “Software Component References” folder and click “Copy Layout” on the context menu of a form page to put the layout of this form into the clipboard. If the selected form page has no XML layout an error message is shown.

Then switch to the form designer of the new form page and click “Paste Layout” on the context menu.

Assigning a Symbol to a Form PagePermanent link for this heading

The symbol keyword is used to assign a symbol to a form page. The symbol referenced by the symbol assignment is displayed on the tab of the form page.

Note:

  • The first page of the property editor form always displays the symbol of the corresponding object class, ignoring the symbol specified on the form page. Thus, form pages can easily be reused for different object classes.
  • The Fabasoft app.ducx resource language must be used for defining custom symbols. However, you can also reuse existing symbols. For further information on defining symbols, refer to chapter “Defining Symbols”.

Defining the Audience for a Form PagePermanent link for this heading

As is the case for a form, the audience keyword is used to define the target audience of a form page. For the possible values that can be assigned to audience see chapter “Defining the Audience for a Form”.

Please note that when a form is presented to an end-user that contains a form page with audience set to administrator, the form page in question is not displayed.

Adding Properties to a Form PagePermanent link for this heading

The dataset keyword is used to assign properties or fields to a form page.

All properties displayed on a form page must be listed in the dataset block nested within the formpage block. Semicolons must be used to separate multiple entries.

If a class has been added to the dataset block, all defined properties of only this class can be used in the layout. Inherited properties have to be added explicitly.

Adding Fields to a Form PagePermanent link for this heading

Fabasoft app.ducx also allows you to reference fields in the dataset block nested within the formpage block. You may only use fields that have been defined in a fields block using the Fabasoft app.ducx object model language, and each field referenced in the dataset block must be preceded by the keyword field.

Fields may be utilized to temporarily compute values that should not be stored persistently.

The optional get and set keywords allow you to define get and set expressions for calculating the field value. The get expression is evaluated before a field is displayed. The set expression is calculated when leaving the form page displaying a field or when clicking a branch (e.g. “Apply“).

When a get or set expression of a field is evaluated, the local scope this contains the vApp state dictionary. The global scope ::this contains a dictionary holding the keys listed in the following table.

Key

Description

root

The root key stores the current object.

attribute

The attribute key stores the object representing the field.

parent

The parent key stores the parent object of the current object.

value

The value key stores the current value of the field.

Note: This key is only available for set expressions.

isedit

The isedit key is true if the field is evaluated on an editable form page.

isvalue

The isvalue key is true if the field is evaluated on a standard form page, not a form page for a search.

isdashboard

The isdashboard key is true if the field is evaluated in a dashboard view.

Laying Out Properties on a Form PagePermanent link for this heading

A formpage block can contain an optional layout block that allows you to define a specific layout of controls on the form page.

The layout block contains a list of controls. If controls must be displayed side by side, these controls are grouped together within a row block. You can use the keywords listed in the following table to influence the way the property is displayed and behaves.

Keyword

Description

rowspan

The rowspan keyword is used to define how many rows the control spans.

colspan

The colspan keyword is used to define how many columns the control spans (default is four; one column for the label and three columns for the data).

valign

The valign keyword is used to define the vertical alignment of text within the control (top, middle or bottom).

halign

The halign keyword is used to define the horizontal alignment of text within the control (left, center or right).

fontfamily

The fontfamily keyword is used to specify the name of a font family used within a control with a CSS conformant string, i.e.: fontfamily = "verdana, sans-serif".

Note: Some controls override the used font, so that this element is ignored.

fontcolor

The fontcolor keyword is used to define the color of text within the control (hexadecimal value).

fontsize

The fontsize keyword is used to define the size of text within the control (pt, px, em).

labeltext

The labeltext keyword is used to reference a string object that will provide the text of the label.

labelvisible

The labelvisible keyword is used to define whether the label is visible (true or false).

labelrowspan

The labelrowspan keyword is used to define how many rows the label spans.

labelcolspan

The labelcolspan keyword is used to define how many columns the label spans.

labelposition

The labelposition keyword is used to define the position of the label (top, bottom, left or right).

labelvalign

The labelvalign keyword is used to define the vertical alignment of a label (top, middle or bottom).

labelhalign

The labelhalign keyword is used to define the horizontal alignment of a label (left, center or right).

labelfontfamily

The labelfontfamily keyword is used to specify the name of a font family used for the label text of a control with a CSS conformant string, i.e.: labelfontfamily = "verdana, sans-serif".

labelfontcolor

The labelfontcolor keyword is used to define the color of the label text (hexadecimal value).

labelfontsize

The labelfontsize keyword is used to define the size of the label text (pt, px, em).

detail

The detail keyword is used to define the columns of an aggregate or object pointer list. This can be either a layout block:

detail = layout {...}

or a reference to form page:

detail = PageDetails;

simple

The simple keyword is used to define the columns of an aggregate that should be displayed in the simple view for in-place editing. With object pointer lists the columns in the overview are specified.  This can be either a layout block:

simple = layout {...} (this block can specify a filter to be used in the simple view)

or a reference to form page:

simple = PageSimple;

empty

The empty keyword is used to define a cell in the grid layout without content.
Usage: empty; or empty { colspan = ...; }

filter

The filter property is used to apply a filter function to an object list property. A filter is an instance of COOSYSTEM@1.1:FilterExpression.

aggregation

The aggregation property is used to apply a function on a column. Predefined values are MenuSum, MenuAverage or MenuCount.

sort

The sort property sorts values in a column of a list. Available modes are up and down. When specifying such a value, a unique index should be set, too.

group

The group property allows to group values in a column of a list. Available modes are unique, alpha, year, quarter, month, week, day and hour. When specifying such a value, a unique index should be set, too.

index

The order of grouped and sorted columns is defined by index. This value should always be set when sort or group are specified.

fixed

The fixed property allows to make a column not horizontal scrollable. There are at least three columns necessary and it will not work on the last two columns. The column index starts with 1.

width

The width property is used to define the width of a column. There is no measure used. app.ducx removes added measures automatically.

height

The height property is used to define the height of a column. There is no measure used. app.ducx removes added measures automatically. The height of a row in a detail layout cannot be changed.

Behavior influence the appearance of a property when displayed in a form page. Behaviors defined in the layout overwrite behaviors defined at the property level (see chapter 5.1.3 Defining Miscellaneous Object Class Aspects”). If the behavior is defined at property level and in the layout, an information is generated. To suppress this information, the keyword override can be used.

Behavior always are expressions which are evaluated to get the desired value. If there are only constants used in the expression, the syntax allows to omit the expression block, resulting in a simple assignment.

Keyword

Description

visible

The property is only visible in the user interface, if the expression returns true. If the expression returns null or throws an error, the default visibility applies (i.e. invisible defined for the attribute). If a row in the layout does not contain any visible property, the whole row is removed.
If the visible expression is used to hide a column of an object list or aggregate list (possible in simple or detail layout), the grouping and sorting of this column is still considered.
Usage: visible = expression {...}

changeable

The property is changeable in the user interface, if the expression returns true. If the expression returns null or throws an error, the default behavior applies (i.e. readonly or readonly(ui) defined for the attribute).
Usage: changeable = expression {...}

mustbedef

The property must contain a value, if the expression returns true. If the expression returns null or throws an error, the default behavior applies (i.e. not null defined for the attribute).
Usage: mustbedef = expression {...}

validate

The expression is used to check whether the value entered in the property is valid. If an error occurs when evaluating the expression, this error is shown. If the expression returns false, a standard error is displayed.
Usage: validate = expression {...}

change

If the value of the property gets changed, the expression is executed. If an error occurs when evaluating the expression, this error is shown. The result of the expression is not relevant.
Usage: change = expression {...}

searchchange

If the value of the property gets changed in context of a search form, the expression is executed. If an error occurs when evaluating the expression, this error is shown. The result of the expression is not relevant.
Usage: searchchange = expression {...}

accset

The accset property is an expression which returns a list of access types (COOSYSTEM@1.1:AccessType). The current user must have access to the current object via at least one of these access types (based on the ACL evaluation of the kernel) in order to change the value of this property.
Usage: accset = expression {...}

accsetline

The accsetline property is an expression which returns a list of access types (COOSYSTEM@1.1:AccessType). This expression is evaluated for each line in an aggregate list, so that special access rights can be applied for each line in the list. The current user must have access to the current object via at least one of these access types (based on the ACL evaluation of the kernel) in order to change the value of the line.
Usage: accsetline = expression {...}

weight

The value of the weight property is an expression which has to return one of the enumeration values defined in COOATTREDIT@1.1:HighlightType. The weight of a form page element is used to draw the user’s attention to this particular element.
Usage: weight = expression {...}

controlstyle

The value of the controlstyle property is an expression which returns either a list of control styles (enumeration type COOATTREDIT@1.1:ControlStyle) or a control style definition (object of object class COOATTREDIT@1.1:ControlStyleDefinition). If the expression returns null or throws an error, the default behavior applies.

A control style definition references specific control styles.

The following control styles are supported:

  • CTRLSTYLE_DISPLAYREFERENCE
    display reference of languages, software components, software products and component objects in an object pointer property
  • CTRLSTYLE_DISABLECONTEXTMENU
    disable context menu on objects in object pointer property
  • CTRLSTYLE_DISABLECREATE
    disable create button for single object pointer property
  • CTRLSTYLE_DISABLESEARCH
    disable search button for single object pointer property
  • CTRLSTYLE_DISABLEQUICKSEARCH
    disable quick search field for object list property
  • CTRLSTYLE_DISABLEINPLACECHANGE
    disable F2 inplace editing in an aggregate property
  • CTRLSTYLE_DISABLEDRAGTARGET
  • CTRLSTYLE_AUTONUMERATE
  • CTRLSTYLE_IGNOREDBYTREE

Usage: controlstyle = expression {...}

controloptions

The value of the controloptions property is an expression, which returns additional options for a control as a dictionary. Please refer to the reference documentation (https://help.developer.fabasoft.com/index.php?topic=doc/Reference-Documentation/controls-overview.htm) for a description of possible options for specific controls. If the expression returns null or throws an error, the default behavior applies (i.e. control arguments specified as parameters to the control or the control arguments specified at the attribute using COOATTREDIT@1.1:attrrepresentation).
Usage: controloptions = expression {...}

When one of the above behavior expressions is evaluated, the local scope this contains the vApp state dictionary. The global scope ::this contains a dictionary holding the keys listed in the following table.

Key

Description

root

The root key stores the current object.

attribute

The attribute key stores the object representing the property or field.

value

The value key stores the current value of the property or field.

isedit

The isedit key is true if the property or field is evaluated on an editable form page.

isvalue

The isvalue key is true if the property or field is evaluated on a standard form page, not a form page for a search.

isdashboard

The isdashboard key is true if the property or field is evaluated in a dashboard view.

In a row block, the reference of a property or field can be preceded by the reference of a control. The control determines the behavior as well as the look and feel of this property or field.

The following table provides a list of important controls. For detailed information on controls and the associated parameters, please refer to the reference documentation:

https://help.developer.fabasoft.com/index.php?topic=doc/Reference-Documentation/controls-overview.htm

Control

Description

COOATTREDIT@1.1:CTRLAcl

This control is used to display and edit access control lists.

COOATTREDIT@1.1:CTRLAttrpath

This control is used to display a property path.

COOATTREDIT@1.1:CTRLBase

This control is used for simple data types like integer, float, string and object pointers.

COOATTREDIT@1.1:CTRLCont

This control is used to upload content.

COOATTREDIT@1.1:CTRLCurr

This control is used to display and edit currency properties.

COOATTREDIT@1.1:CTRLDateTime

This control is used to display date and datetime properties.

COOATTREDIT@1.1:CTRLMLName

This control is used to display and edit multilingual strings (using the compound type COOSYSTEM@1.1:LanguageStringList).

COOATTREDIT@1.1:CTRLObjNav

This control is used to display and edit an object pointer describing a hierarchical relationship.

COOATTREDIT@1.1:CTRLPassword

This control is used for entering passwords.

COOATTREDIT@1.1:CTRLPhone

This control is used to display and edit telephone numbers.

COOATTREDIT@1.1:CTRLPick

This control is used to display a list of enumeration entries or a list of objects as a group of radio buttons or checkboxes.

FSCVENV@1.1001:CTRLRating

This control is used to display a star rating.

COOATTREDIT@1.1:CTRLResearch

This control is used to display the input field for a research term.

COOATTREDIT@1.1:CTRLStrList

This control is used to display a list of strings in a combo box.

COOATTREDIT@1.1:CTRLText

This control is used to enable multiline text input for string lists.

COOATTREDIT@1.1:CTRLTimespan

This control is used to display and edit a time span in days, hours, minutes and seconds.

COOATTREDIT@1.1:CTRLTimestamp

This control is used to display and edit a time stamp in hours, minutes and seconds.

COOATTREDIT@1.1:CTRLTree

This control is used to display the tree.

COOATTREDIT@1.1:CTRLViewCont

This control is used to display content.

COOATTREDIT@1.1:CTRLXMLAttr

This control is used to display attributes of an XML document.

FSCDOX@1.1001:CTRLHtmlEditor

This control is used to attach an HTML editor to a string, string list, content or content aggregate.

FSCSIMLIST@1.1001:CTRLSimList

This control is used to display a simple object list, comparable to the Microsoft Outlook mail-add field.

FSCVENV@1.1001:CTRLDictionary

This control is used to display dictionaries.

FSCVENV@1.1001:CTRLInstantiate

This control is used to display the creatable objects and templates in the dialog box displayed when creating a new object.

FSCVENV@1.1001:CTRLPict

This control is used to display and upload pictures.

FSCVENV@1.1001:CTRLProgress

This control is used to display a progress bar.

FSCVENV@1.1001:CTRLRawText

This control is used to transfer the contents of script component objects to the web browser and can be used for injecting HTML code into the current page.

FSCVENV@1.1001:CTRLURLNav

This control is used to display and edit a URL and can be attached to a string property.

The following example demonstrates how to use the form page layout elements discussed in this chapter.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  form OrderForm {
    audience = enduser;
    inherit = true;
    formpage OrderGeneralPage {
      audience = enduser;
      symbol = SymbolOrder;
      dataset {
        orderstate;
        orderinvoice;
        orderdate;
        orderapproved;
        field orderagent {
          get = expression {
            coouser;
          }
        }
        field ordertotal;
      }
      layout {
        // APPDUCXSAMPLE@200.200:orderstate and APPDUCXSAMPLE@200.200:ordertotal
        // should be displayed side-by-side

        row {
          APPDUCXSAMPLE@200.200:orderdate {
            colspan = 4;
            labelposition = left;
            labeltext = StrOrderdateLabel;
          }
          APPDUCXSAMPLE@200.200:ordertotal {
            colspan = 4;
            labelposition = left;
          }
        }
        // APPDUCXSAMPLE@200.200:orderdate spans two rows, uses as many
        // columns as orderstate and ordertotal together and no label

        // is displayed

        row {
          APPDUCXSAMPLE@200.200:orderdate {
            rowspan = 2;
            colspan = 8;
            labelvisible = false;
          }
        }
        row {
        }
        // APPDUCXSAMPLE@200.200:orderapproved uses the control
        // COOATTREDIT@1.1:CTRLBase in order to be displayed as a group

        // of radio buttons

        row {
          COOATTREDIT@1.1:CTRLBase("UseRadio=true") orderapproved {
            colspan = 8;
            labelposition = left;
          }
        }
        row {
          orderagent {
            colspan = 8;
            labelposition = left;
          }
        }
      }
    }
    formpage OrderPositionsPage {
      audience = enduser;
      symbol = SymbolOrderPositions;
      dataset {
        user;
        orderpositions;
      }
    }
  }
}

The following example demonstrates how to define a form page and apply the COOATTREDIT@1.1:CTRLObjNav control to the FSCFOLIO@1.1001:orgindustry property of an organization to allow the user to select an industry from a hierarchical list of industries.

Note: Industries are represented as instances of object class FSCFOLIO@1.1001:FunctionTerm. The root object for the available industries is FSCFOLIO@1.1001:TermIndustry, where the top-level industries must be referenced in the FSCTERM@1.1001:narrowercompterms property. Subordinated industries must be referenced in the FSCTERM@1.1001:narrowercompterms property of the FSCFOLIO@1.1001:FunctionTerm object describing an industry.

The control parameters Root and Lists of the COOATTREDIT@1.1:CTRLObjNav control must be initialized with the addresses of the corresponding expression objects responsible for determining the root object of the hierarchy and the lists describing the hierarchy. To find out the address of the expression objects, refer to the “Address Assignment” list in the Eclipse Project Explorer.

For detailed information on the control parameters of the COOATTREDIT@1.1:CTRLObjNav control refer to:

https://help.developer.fabasoft.com/index.php?topic=doc/Reference-Documentation/control-cooattredit-CTRLObjNav.htm

Example

app.ducx Object Model Language

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import FSCTERM@1.1001;

  // Assuming that APPDUCXSAMPLE@200.200:ExprTermRoot is assigned the address
  // COO.200.200.1.100 in the address assignment list

  instance Expression ExprTermRoot {
    exprtext = expression {
      #TermIndustry;
    }
  }

  // Assuming that APPDUCXSAMPLE@200.200:ExprTermList is assigned the address
  // COO.200.200.1.101 in the address assignment list

  instance Expression ExprTermList {
    exprtext = expression {
      dictionary @list = {
        cls = #TermComponentObject,
        attrs = #narrowercompterms
      };

      return dictionary @treelist = {
        destattr = #orgindustry,
        lists = @list
      };
    }
  }
}

app.ducx User Interface Language

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;

  form FormOrgIndustry {
    audience = enduser;
    inherit = false;

    formpage PageOrgIndustry {
      audience = enduser;
      dataset {
        orgindustry;
      }
      layout {
        row {
          // Assuming that APPDUCXSAMPLE@200.200:ExprTermRoot is assigned the
          //
address COO.200.200.1.100 and APPDUCXSAMPLE@200.200:ExprTermList
          // is assigned the address COO.200.200.1.101 in the address

          //
assignment list
          COOATTREDIT@1.1:CTRLObjNav("Root=COO.200.200.1.100 Lists=COO.200.200.1.101
            IgnoreCompoundFlag=true") FSCFOLIO@1.1001:orgindustry {
            colspan = 4;
            labelposition = left;
          }
        }
      }
    }
  }
}

Special Layout Elements on a Form PagePermanent link for this heading

Besides properties there are other elements available as row elements:

  • empty is just a place holder for one or more empty cells.
  • hrule is a shortcut for a property displayed with CtrlStatic with the mode parameter set to “hr”, resulting in a horizontal line over all specified cells.
  • static is a shortcut for a property displayed with CtrlStatic with the mode parameter set to “text”, resulting in the display of a static string over all specified cells.

Example

app.ducx User Interface Language

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;

  form FormOrgIndustry {
    audience = enduser;
    inherit = false;
    formpage PageOrgIndustry {
      audience = enduser;
      dataset {
        orgindustry;
      }
      layout {
        row {
          empty;
          hrule {
            colspan = 2;
          }
          static StrTxt;
        }
        row {
          // Assuming that APPDUCXSAMPLE@200.200:ExprTermRoot is assigned the
          //
address COO.200.200.1.100 and APPDUCXSAMPLE@200.200:ExprTermList
          // is assigned the address COO.200.200.1.101 in the address

          //
assignment list
          COOATTREDIT@1.1:CTRLObjNav("Root=COO.200.200.1.100 Lists=COO.200.200.1.101
            IgnoreCompoundFlag=true") FSCFOLIO@1.1001:orgindustry {
            colspan = 4;
            labelposition = left;
          }
        }
      }
    }
  }
}

Using the Form DesignerPermanent link for this heading

The layout can be defined using the provided graphical form designer. You can switch from the “Code“ pane to the “Form Pages“ pane. The “Palette“ contains all properties that are defined in the dataset.

The form designer provides following features:

  • The properties can be adjusted within the form page by drag-and-drop.
  • Labels and fields can be spanned horizontally or vertically over multiple columns or lines.
  • Pressing the Alt key allows to select the label and to adjust it within the field. A label can be positioned left, right, at the top or at the bottom of a field.
  • A horizontal rule can be inserted by selecting it from the “Static Controls”.
  • To filter the available component objects, use the Filter field. Clicking “x” deletes the filter.
  • Use the context menu to define a specific control for a property.

Defining a Desk FormPermanent link for this heading

Syntax

deskform reference {
  audience = audience;
  dataset {
    property;
    ...
  }
}

Desk forms are special types of forms, used for displaying object list properties of compound objects in the so called explore view.

For instance, a desk form is used for displaying the object list properties shown in the list view on the right-hand side when you select an instance of object class Person in the tree view of the desk.

The deskform keyword is used to define a desk form. It must be followed by a reference and curly braces.

Defining the Audience for a Desk Form

Inside a deskform block, the audience keyword can be used for defining the audience for a desk form. For further information concerning the audience keyword please refer to chapter “Defining the Audience for a Form Page”.

Adding Properties to a Desk Form

All object list properties displayed on a desk form must be listed in a dataset block nested within the deskform block. Semicolons must be used to separate multiple entries.

The order of the properties in the dataset block also determines their order on the desk form.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  deskform CustomerDeskForm {
    audience = enduser;
    dataset {
      customerorders;
    }
  }
}

Extending Existing Desk Forms, Forms, and Form PagesPermanent link for this heading

Fabasoft app.ducx allows you to extend existing forms with new form pages as well as to add properties to existing desk forms and form pages belonging to other software components.

The extension of desk forms, forms and form pages that belong to another non-friend software component is discouraged.

Extending an Existing Desk FormPermanent link for this heading

Syntax

extend deskform reference {
  dataset {
    property;
    ...
  }
}

With the extend deskform keywords, you can add properties to a desk form that is part of another software component.

Extending an Existing FormPermanent link for this heading

Syntax

extend form reference {
  // New form pages can be defined inline
  formpage reference {
    audience = audience;
    dataset {
      property;
      ...
    }
  }
  // Existing form pages can be reused
  reference;
}

A form of another software component may be extended with form pages belonging to your software component.

To extend a form that is part of another software component, you can use the extend form keywords followed by the reference of the form you want to extend, and curly braces. You may either define new form pages inside the extension block or reference existing form pages of your software component.

New form pages added in an extension block are appended to the form after the existing form pages.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIOGUI@1.1001;

  // Extend form FSCFOLIOGUI@1.1001:FormPersonUV with a new form page
  // APPDUCXSAMPLE@200.200:PagePersonOrders

  extend form FormPersonUV {
    formpage PagePersonOrders {
      audience = enduser;
      symbol = SymbolOrder;
      dataset {
        customerorders;
      }
    }
  }
}

Extending an Existing Form PagePermanent link for this heading

Syntax

extend formpage reference {
  dataset {
    property;
    ...
  }
}

With the extend formpage keywords, you can add properties to a form page that is part of another software component.

Note: Properties added to a form page must also be part of the corresponding object class in order to be displayed on the form page.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIOGUI@1.1001;

  // Extend form page FSCFOLIOGUI@1.1001:PagePerson with a new
  // property APPDUCXSAMPLE@200.200:customertype

  extend formpage PagePerson {
    dataset {
      customertype;
    }
  }
}

Defining Menus, Button Bars, and Task PanesPermanent link for this heading

With the Fabasoft app.ducx user interface language of Fabasoft app.ducx, you can define the following user interface elements in addition to forms and form pages:

  • menu items and menu bars
  • button bars and buttons
  • task panes

Defining a MenuPermanent link for this heading

There are two types of menus:

  • Menu items are mainly used for invoking use cases, but can also contain one or more menu items in order to allow the definition of menu hierarchies with sub-menus.
  • A menu root is required as the outermost container holding one or more menu items.

Defining a New Menu ItemPermanent link for this heading

Usually, menu items are simply referred to as menus. A menu can either reference a use case that is invoked when the user selects the menu item in the user interface, or it can contain one or more sub-menus to create a menu hierarchy.

The menu keyword is used to define a menu. It must be followed by the reference and curly braces.

Using the accel keyword, an accelerator object can be assigned to the menu to allow the user to use a shortcut for accessing the menu.

The alias group is used to insert a separator before the menu entry.

Defining a Menu for Invoking a Use Case

Syntax

menu reference {
  group = booleanvalue;
  accel = accelerator;
  usecase = usecase;
}

The use case that should be invoked when the menu is selected by the user must be referenced using the usecase keyword.

Please note that the app.ducx compiler automatically generates a menu item for use cases that are defined using the menu usecase keywords in the app.ducx use case language. Thus, there usually is no need to define a custom menu when using the menu usecase keywords to define use cases that should be invoked from a menu.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  menu MenuMarkAsShipped {
    group = true;
    accel = AccelCtrlO;
    usecase = MarkOrderAsShipped;
  }
}

Defining Sub-Menus

Syntax

menu reference {
  accel = accelerator;
  entries = {
    menu,
    ...
  }
}

The entries keyword is used to create a hierarchical menu containing one or more sub-menus, which must be menu objects themselves. Multiple entries must be separated by commas.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  menu MenuSetOrderState {
    entries = {
      MarkOrderAsShipped,
      MarkOrderAsCompleted
    }
  }
}

Defining a New Menu RootPermanent link for this heading

Syntax

menuroot reference {
  entries = {
    menu,
    ...
  }
}

A menu root is required as the starting point for context menus and menu bars.

The menuroot keyword is used to define a menu root. It must be followed by the reference and curly braces. In the menuroot block, the entries keyword is used for referencing the menu items.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  menuroot MenuRootOrderContext {
    entries = {
      MenuObjectUnshare,
      MenuSeparator,
      MenuObjectRead,
      MenuObjectEdit,
      MenuSeparator2,
      MenuSetOrderState
    }
  }
}

Extending an Existing MenuPermanent link for this heading

Syntax

extend menu reference {
  entries = {
    menu,
    ...
  }
}

The extend menu keywords are used to add menu items to an existing menu or menu root belonging to another software component.

Note: Menus belonging to another software component can only be extended with menu items belonging to your software component.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  // Add menu APPDUCXSAMPLE@200.200:CreateOrderWizard to the context menu
  // of contact persons

  extend menuroot MenuRootContext {
    entries = {
      CreateOrderWizard
    }
  }
}

Weighted MenuPermanent link for this heading

Syntax

extend menu reference {
  weighted<..> = {
    ...
  }
}

Menu entries may be declared to be shown as buttons. In the menu extension block, weighted is used to assign menu entries.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;
  import COOATTREDIT@1.1;

  // Add menu MenuObjectEdit to the buttons
  // of MenuRoot

  extend menu MenuRoot {
    weighted<weightedmenuentry, COOATTREDIT@1.1:component> = {
      { MenuObjectEdit, APPDUCXSAMPLE@200.200 }
    }
  }
}

Defining a Task PanePermanent link for this heading

Syntax

taskpane reference {
  entries = {
    menu,
    ...
  }
}

A task pane is comprised of a list of menu items displayed in the left part of the quick view.

The taskpane keyword is used to define a task pane. It must be followed by the reference and curly braces.

Nested within the taskpane block, the entries keyword is used to reference the menu items displayed on the task pane. Multiple entries must be separated by commas.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  taskpane TaskPaneCustomer {
    entries = {
      MenuObjectEdit,
      MenuMarkOrderAsShipped,
      MenuCreateInvoice
    }
  }
}

Extending an Existing Task PanePermanent link for this heading

Syntax

extend taskpane reference {
  entries = {
    menu,
    ...
  }
}

The extend taskpane keywords are used to add menu items to an existing task pane belonging to another software component.

Note: Task panes belonging to another software component can only be extended with menu items belonging to your software component.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COOWF@1.1;

  // Add menu APPDUCXSAMPLE@200.200:MenuRerouteActivity to task pane
  // COOWF@1.1:TaskPaneActivity

  extend taskpane TaskPaneActivity {
    entries = {
      MenuRerouteActivity
    }
  }
}

Assigning User Interface Elements to an Object ClassPermanent link for this heading

Fabasoft app.ducx allows you to assign forms, symbols, context menus, menu bars, button bars, and task panes to object classes. These assignments are referred to as user interface element bindings.

Additionally, you can specify default column settings for each object pointer property assigned to these object classes.

It is recommended that you create a separate .ducx-ui file for defining your user interface element bindings such as bindings.ducx-ui although you can define all user interface model-related elements within a single .ducx-ui file.

For all user interface element bindings, the extend class keywords can be used, followed by the reference of the object class to extend and curly braces. This way, all user interface element extensions for an object class can be combined into a single extension block.

Menus, forms and column bindings can also be defined using the respective constructs:

  • menus for class {}
  • forms for class{}
  • columns for class {}

These constructs provide the possibility to specify more than one target class and reduce the complexity of the code by removing some indentation levels.

Assigning a Symbol to an Object ClassPermanent link for this heading

Syntax

symbol = symbol;

Object classes should have default symbols for objects of these classes. This can be achieved by using the symbol keyword either in the object model or in the user interface model.

Example

objmodel APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  class Order {
    symbol = SymbolOrder;
  }
}

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;

  extend class Order {
    symbol = SymbolOrder;
  }
}

Assigning Menus and Task Panes to an Object ClassPermanent link for this heading

Each object class has a default menu binding, defining main menu, context menu, background menu, container independent menu, task bar, and selection dependent task bar. These should be sufficient for most cases.

To add a few menus at predefined positions, there is no need to change these standard menus.

Should the need arise to do so, this can be done with the menus block, for one or more object classes.

Syntax

menus for references {
  mainmenu = menuroot;
  contextmenu = menuroot;
  windowmenu = menuroot;
  independentmenu = menuroot;
  tasks = taskpane;
  selectedtasks = taskpane;
  scope MyCloudApp {
    mainmenu = menuroot;
    contextmenu = menuroot;
    windowmenu = menuroot;
    independentmenu = menuroot;
    tasks = taskpane;
    selectedtasks = taskpane;
  }
}

There can be scope-specific menu bindings. Any valid component object can be used as scope.

When the menu bindings are evaluated by the kernel, the currently active scope is determined by the expression defined in the User Interface Scoping Rule (COODESK@1.1:UIScopingRule) referenced in the Current Domain (COOSYSTEM@1.1:CurrentDomain) object of your domain. The object returned by the expression is used as the current scope.

By default, FSCTEAMROOM@1.1001:ScopingRuleRoom is used (see also https://help.developer.fabasoft.com/index.php?topic=doc/Reference-Documentation/compobjs-fscteamroom.htm#FSCTEAMROOM_1_1001_ScopingRuleRoom). The scoping rule retrieves the scope object (used for menus, task panes, and forms) based on the room of the current object. The room of the current object is determined by FSCTEAMROOM@1.1001:GetContextRoom.

If the current scope determined by the User Interface Scoping Rule matches the scope object referenced in a menu binding, the corresponding menu is displayed. If there is no scope-specific menu available in an object class for the current scope, the default menu is displayed instead.

It is also possible to specify a menus block in the extend class block, using a slightly different syntax.

Syntax

extend class reference {
  menus {
    default = {
      mainmenu = menuroot;
      contextmenu = menuroot;
      windowmenu = menuroot;
      independentmenu = menuroot;
      expansions {
        expansion point {
          target = property;
          condition = expression {...}
          priority = priority;
          entries = {
            menu
          }
        }
      }
    }
    scope = {
      mainmenu = menuroot;
      contextmenu = menuroot;
      windowmenu = menuroot;
      independentmenu = menuroot;
      }
    }
  }
}

The keywords listed in the following table can be used within a menu binding block for assigning the different types of menus.

Note: Task panes are just menus with a different appearance.

Keyword

Description

mainmenu

With the mainmenu keyword, a menu root can be assigned to an object class that  is used as its main menu.

contextmenu

With the contextmenu keyword, a menu root can be assigned to an object class that is used as its context menu.

windowmenu

With the windowmenu keyword, a menu root can be assigned to an object class that is used as its background menu.

independentmenu

With the independentmenu keyword, a menu root can be assigned to an object class that is used as its container-independent menu.

tasks

With the tasks keyword a taskpane can be assigned to an object class.

selectedtasks

With the selectedtasks keyword a taskpane can be assigned to an object class that contains menu entries of the selected objects.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  extend class Order {
    menus {
      default = {
        mainmenu = MenuRootOrder;
        contextmenu = MenuRootOrderContext;
        windowmenu = MenuRootWinContext;
        independentmenu = MenuRootOLEContext;
      }
    }
  }
}

Assigning Menu Items to Object Classes (Expansion Points)Permanent link for this heading

To ensure a consistent look and feel of the user interface, new menu items should appear at predefined positions in the default menus, including task panes and context menus.

Default menus are prepared for extension by using so called expansion points.  Expansions points are named after the positions where they are used as placeholder.

The listed menu items or menu usecases are inserted at the predefined position.

Menu items can be restricted to UI scopes, this is achieved by surrounding the menu definitions with a scope block.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;
  import FSCTEAMROOM@1.1001;

  menus for Package {
    TaskpaneSelectedExpansion, MenuContextExpansion.objchildren {
      priority = 100;
      MenuEncryptObject {
        condition = expression { !cooobj.isencrypted }
      }
      MenuDecryptObject {
        condition = expression { cooobj.isencrypted }
      }
    }
    scope MyCloudApp {
      MenuContextExpansion.trchildren {
        priority = 100;
        MenuEncryptObject {
          condition = expression { !cooobj.isencrypted }
        }
        MenuDecryptObject {
          condition = expression { cooobj.isencrypted }
        }
      }
    }
  }
}

Additional restrictions for using the menu items can be specified:

  • Specific views can be addressed by adding them to the expansion point or by using the keyword target.
  • For optional menu items use the keyword  condition. Conditions must evaluate to true in order to make the menu item visible. The condition clause can be specified for the whole expansion block or inside a menu item block.
  • Generic assignments can be used to specify other values, for example priority.

When collecting menu items from the affected objects, the algorithm takes the object class hierarchy into account. The first object class referencing a menu item defines its appearance in the menu.

The priority property of expansions is used to define the order of the menu items. Expansions with a higher priority value are displayed before those with a lower priority.

Some well-known expansion points are listed in the following table.

Expansions point

Description

COODESK@1.1:MenuBackgroundExpansion

This expansion point inserts a menu entry in the background area. A symbol is required for empty object lists.

COODESK@1.1:MenuRootSimpleExpansion

This is used to add a menu entry to the simple menu view. This menu contains only symbols. The menu entry requires a selection in the tree.

COODESK@1.1:MenuObjectDirectExpansion

This expansion point adds a menu entry in the Object menu. The menu items are retrieved from the object class of the container object.

COODESK@1.1:MenuObjectExpansion

This expansion point is used to insert a menu entry in the Object menu. The menu items are retrieved from the object classes of the currently selected objects.

COODESK@1.1:MenuToolsDirectExpansion

This expansion point adds a menu entry in the Tools menu. The menu items are retrieved from the object class of the container object.

COODESK@1.1:MenuToolsExpansion

This expansion point is needed to add a menu entry in the “Tools” menu. The menu items are retrieved from the object classes of the currently selected objects.

COODESK@1.1:MenuContextDirectExpansion

This expansion point is used to extend the context menu. The menu items are retrieved from the object class of the container object, which is also the current object if the context menu is displayed in the tree.

COODESK@1.1:MenuContextExpansion

This expansion point is used to extend the context menu. The menu items are retrieved from the object classes of the currently selected objects.

COODESK@1.1:TaskPaneSelectedExpansion

This expansion point is used to insert a task pane entry. The entry is only activated if an object is selected.

COODESK@1.1:TaskPaneExpansion

This expansion point is used to insert a task pane entry. The menu items are retrieved from the object class of the container object.

<any>Expansion

Other expansion points defined by various software components.

When using the expansions which are targeting the container object (TaskPaneExpansion, *DirectExpansion) the current selection can be retrieved by using the current selection context.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;

  menus for Order {
    ToolsMenuDirectExpansion.myattachments {
      MenuSendAllObjects {
        condition = expression { #TV.TV_SELECTIONCONTEXT.selobjects!= null }
      }
    }
  }
}

Expansion points can be specified in extend object class also, but with a slightly different syntax. It is recommended to format these old-style menu assignments to the new form.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;
  import FSCTEAMROOM@1.1001;

  extend class Package {
    menus {
      default = {
        expansions {
          TaskPaneSelectedExpansion, MenuContextExpansion {
            target = {
              objchildren,
              trchildren
            }
            condition = expression { !cooobj.isencrypted }
            priority = 100;
            entries = {
              MenuEncryptObject
            }
          }
          TaskPaneSelectedExpansion, MenuContextExpansion {
            target = {
              objchildren,
              trchildren
            }
            condition = expression { cooobj.isencrypted }
            priority = 50;
            entries = {
              MenuDecryptObject
            }
          }
        }
      }
    }
  }
}

Expert note: Expansion points are just dynamic menus which collect their menu items from the object class of the current container resp. the object classes of the currently selected objects, thus removing the need of directly extending the menus. They are defined as group so that the calculated menu items are surrounded with separator lines.

Assigning Forms to Object ClassesPermanent link for this heading

Use cases and forms are associated in the context of object classes. When a use case involving a user interface is invoked, a matching form for this use case is located in the list of form bindings in the object class of the current object.

The most common use cases involving a user interface are listed in the following table. When creating a new object class, it is recommended to define form bindings for at least the first four use cases listed in the table.

Use case

Description

COOSYSTEM@1.1:ObjectConstructor

If there is a form assigned to the use case COOSYSTEM@1.1:ObjectConstructor, the property editor is started after creation of objects of this class.

COODESK@1.1:ObjectInfo

The form assigned to this use case is used for showing the tool tip of an object. All form pages of the form are displayed one below the other. The colspan of each property has to be the same to ensure a proper layout.

COODESK@1.1:CreateObject

This use case is invoked in the “Create” dialog when an object class is selected. The form assigned to this use case is embedded in the “Create” dialog. By default, a form with the properties Name and Subject is displayed. If no property should be displayed, you can use the COODESK@1.1:FormCreateObjectEmpty form.

COOATTREDIT@1.1:ReadObjectAttributes

This use case is invoked when the properties of an object are read.

COOATTREDIT@1.1:EditObjectAttributes

This use case is invoked when the properties of an object are edited.

COOSEARCH@1.1:SearchObjects

This use case is invoked when the search dialog box is opened.

COODESK@1.1:DisplayOptions

The form assigned to this use case is used for allowing users to select columns when changing the column settings of an object list.

COODESK@1.1:ExploreObject

This use case is invoked when an object is opened in the explore view by selecting the Explore menu.

COODESK@1.1:ExploreTree

The form assigned to this use case is used when a compound object is displayed in the tree view.

Note: COOSYSTEM@1.1:ObjectConstructor replaces the mapping of COOTC@1.1001:InitGUI.

The following example illustrates different scenarios for object creation. The default implementations used in the example show the form that is mapped to COOSYSTEM@1.1:ObjectConstructor.

Example

// Application executed when an object is created via menu or
// button in an object list

override FSCVENV@1.1001:InitializeCreatedObject {
  variant objectclass {
    impl = FSCVENV@1.1001:InitializeCreatedObjectApp;
  }
}

// Application executed when an object is created inside of
// an object pointer property

override FSCVENV@1.1001:InitializeCreatedObjectDoDefault {
  variant objectclass {
    impl = FSCVENV@1.1001:InitializeCreatedObjectApp;
  }
}

// Application executed when an object is created from
// a template

override FSCVENV@1.1001:InitializeTemplateCreatedObject {
  variant objectclass {
    impl = FSCVENV@1.1001:InitializeCreatedObjectApp;
  }
}

Form bindings for an object class are defined in a forms block for one or more object classes.

Syntax

forms for references {
  usecase {
    form;
    ...
  }
}

The form block can contain one or more form bindings. Each binding consists of the reference of one or more use cases, and a block denoting the forms that should be bound to these. In each binding, you can reference one or more forms. The reason for referencing more than one form in a binding is that you might want to provide different forms for administrators and end-users. As a rule of thumb, remember that the administrator form must be listed before the end-user form in a form binding.

Instead of specifying the reference of a use case in the binding, the keyword default can be used to bind forms to the use cases COOATTREDIT@1.1:EditObjectAttributes, COOATTREDIT@1.1:ReadObjectAttributes and COOSEARCH@1.1:SearchObjects at once.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;
  import COOATTREDIT@1.1;
  import COOSEARCH@1.1;
  import COOTC@1.1001;

  forms for Order {
    OpenObject, ReadObjectAttributes, EditObjectAttributes {
      OrderAdminForm;
      OrderUserForm;
    }
    SearchObjects {
      OrderSearchForm;
    }
    ObjectConstructor {
      OrderCreateForm;
    }
  }

  forms for Folder {
    default {
      FolderUserForm;
    }
  }
}

Moreover, the use case COODESK@1.1:OpenObject is used for both the form binding for objects that are opened by double clicking and the explore view binding. In this case, the order of the forms in the COODESK@1.1:OpenObject block is not relevant.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;
  import COOATTREDIT@1.1;
  import COOTC@1.1001;
  import FSCTEAMROOM@1.1001;

  extend class ContactPerson {
    forms {
      OpenObject {
        // The following form is used when a contact person is double-
        // clicked by the user (i.e. the "Open" menu is invoked)

        FormCustomer;
        // The desk form is used when a contact person is opened in
        // "Explore" mode (e.g. it is selected in the tree view)

        DeskFormCustomer;
      }
      ReadObjectAttributes {
        FormCustomer;
      }
      EditObjectAttributes {
        FormCustomer {
          priority = 100;
          // The condition to determine whether the form should be displayed
          condition = expression { objteamroom != null }
        }
      }
      SearchObjects {
        SearchFormCustomer;
      }
      InitGUI {
        CtorFormCustomer;
      }
    }
  }
}

The property priority is a priority value from 0 to n, used to rank the lines of the aggregate COOSYSTEM@1.1:classviews. The highest value determines the used view.

The expression condition is evaluated to check if the form should be used.

The viewscope defines a scoping context in which that mapping should be used.

Assigning Default Column Settings to an Object ClassPermanent link for this heading

When displaying object lists in the web client, default columns can be specified in the object class. This can be accomplished by using the keyword columns. columns can either be used standalone as columns for object classes or inside extend class.

Syntax

columns for reference {
  attrdef1 {
    column1;
    column2;
  }
  attrdef2 {
    freeze {
      column1;
      column2;
    }
    column3;
    column4;
     ...
    groupby {
      column1 asc;
    }
    sortby {
      column2 desc;
      ...
    }
    displaymodes {
      LISTVIEW_DETAILS;
    }
  }
  ...
}

Syntax

extend class reference {
  columns attrdef1 {
    freeze {
      column1;
      column2;
    }
    Column3;
    column4;
    ...
    groupby {
      column1;
    }
    sortby {
      column2 desc;
      ...
    }
  }
  columns attrdef2 {
    freeze {
      column1;
      column2;
    }
    column3;
    column4;
  }
  ...
}

This element can be repeated multiple times to specify distinct column settings for different object pointer properties.

Each column is represented by a property path, consisting of one or more properties. The width enclosed in parenthesis and the keyword readonly are optional.

The first columns can be marked as fixed by surrounding them with a block named freeze.

These columns can contain generic assignments. One of these assignments can be the property COOSYSTEM@1.1:dispmlname.  The values for this property are taken from the mlnames.lang file as usual, but the key to the distinct entries is the property path.

The next part could be a set of these columns to be displayed as group. This is specified with the keyword groupby.

Then a set of sorted columns can be listed, using the keyword sortby.

The next part can be a list of valid display modes. If one of these display modes is marked by default, this display mode is used at first display.

After that, generic assignments to properties of the aggregate COODESK@1.1:DisplayViewList can be specified, just like with any other aggregate.

Here is an example of some more complex column settings.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import COODESK@1.1;
  import COOATTREDIT@1.1;
  import COOTC@1.1001;
  import FSCTEAMROOM@1.1001;

  columns for ContactPerson {
    // configure the display of the property objsecread
    objsecread {
      /*
       * usertitle, userfirstname and userlastname are not scrollable

       */

      freeze {
        usertitle(20) {
          /*
           * rename the column to a new name

           */

          dispmlname = {}
        }
        /*
         * userfirstname and userlastname can not be changed in the list view

         */

        userfirstname readonly;
        userlastname readonly;
      }
      /*
       * display the name of the groups

       */

      usermemberof.grshortname;
      active;
      /*
       * group the list by organizations

       */
     groupby {
        usermemberof.grshortname;
      }
      /*
       * sort the list by lastname/firstname

       */

      sortby {
        userlastname asc;
        userfirstname;
      }
      displaymodes {
        /*
  
       * display view in detail mode by default
    
     */
        LISTVIEW_DETAILS default;
        /*
         * configure thumbnail size as 300 pixel

         */

        LISTVIEW_THUMB {
          dispviewthumbsize = 300;
        }
      }
    }
    /*
     * specifiy a custom filter for the list

     */

    dispviewfilter = #MyUserFilter;
  }
}

The corresponding language files have entries for the column title with the property names as keys. Please note, that the property name will be fully qualified.

Example

ContactPerson.dispviews[objsecread].dispcolumns[usertitle].dispmlname = "The Title"

Assigning Drag and Drop Actions to an Object ClassPermanent link for this heading

To provide drag and drop functionality in the object pointer properties of an object, the system needs to know how to perform the drag and drop operation. By default, nothing has to be done by the developer, as the app.ducx compiler automatically sets the default actions for the desired behavior.

To change this default behavior, the actions COODESK@1.1:classcopyaction, COODESK@1.1:classlinkaction and COODESK@1.1:classmoveaction can be set to null or changed in the extend class section.

Example

userinterface APPDUCXSAMPLE@200.200
{
  import COOSYSTEM@1.1;
  import COODESK@1.1;
  import COOTC@1.1001;

  extend class ContactPerson {
    classcopyaction = null;
    classlinkaction = COOTC@1.1001:DragIntoCopy;
    classmoveaction = COOTC@1.1001:DragIntoCopy;
  }
}

Expert note: It is also possible to change the drag and drop behavior for single object properties by specifying the actions for COODESK@1.1:attrcopyaction, COODESK@1.1:attrlinkaction and COODESK@1.1:attrmoveaction when defining the object pointer property.

Defining Default Display ViewsPermanent link for this heading

Syntax

displayview reference {
  columns ref {
  ...
  }
}

Column settings can be stored in dedicated objects of the class COOSYSTEM@1.1:DefaultDisplayView. These can be created by using the keyword displayview.