The Configuration Folder Module

The configuration folder module is responsible for drawing the contents of the tabbed dialog box used to edit a tag instance's properties. It must perform three tasks:

  • Define the tab labels
  • Respond to users requests to change from one tab to another
  • Display the correct fields in each tab

Each configuration module must contain the following states:

  • An initialization state.
    Used to initialize variables and pass control to the Switch state.
  • A Switch state.
    Used to switch from one tab's state to another, thereby allowing the user to switch tabs in the panel.
  • One state for each tab.
    These states contain the GUI functions to display the parameter fields.

The Parameters Section

Every configuration module will have exactly the same parameters section. To begin a new configuration module, copy the following:

(
  Parms                { Pointer to array of parameters                };
  Current              { Currently selected tab (starts at 0)          };
  PtrWaitClose         { Pointer to FLAG - TRUE when wait to close     };
  OKPressed            { OK Pressed from Properties Dialog             };
  CancelPressed        { Cancel Pressed from the properties Dialog     };
  ParmsData            { Parameter data                                };
  OldParms             { Old parameters                                };
  OldParmsData         { Old parameters                                };
  ParmsReady           { Pointer to the array of parameter ready flags };
) 
  • The parameters array, Parms, is used by VTScada to link your tag parameters to this module.
  • VTScada sets the value of Current when a user clicks on a tab in the configuration panel. You will need to watch Current to know when to switch tabs.
  • PtrWaitClose is used by the VTScada code that handles the dialog box's Close button. It enables the code to finish all work before the dialog closes.
  • OKPressed is similar, but ensures that the values are written to the parameter array.
  • CancelPressed is set if the user cancels the configuration session. This allows you the chance to reset any values that may have been changed before cancel was pressed. Often useful, but not found in every configuration panel module.
  • ParmsData, OldParms and OldParmsData are arrays used by the tools that display values within the config folder. As a rule, you should include these even if you write no code for them.
  • ParmsReady is used in types derived from Context tags and tracks if each parameter is ready (TRUE) or in the process of being edited (FALSE).

The Variables Declaration Section

[
  Constant WIDTH = 500;
  Trigger                     { Edit field trigger                     };
  EditOK                      { OK to edit tag parameters              };
  [(1)
    IDTabLabel       = "ID";
    ConfigTabLabel   = "Settings";
  ]
] 

The following are standard variables in a configuration folder.

  • Width - Normally declared as a constant, VTScada programmers set this value for their convenience when placing objects on the dialog. The height is set automatically by VTScada to accommodate all of the fields in the tallest tab of the dialog.
  • Trigger - Used by VTScada. Will be required in the code for each input field.
  • EditOK - Should be set according to whether the current user has tag modification privileges, then used in the FocusID field of every input control. (A value of 0 for FocusID disables a p-control.)
  • Tab label names - The text to display at the top of each tab.

The tab labels are declared in a Class 1 block. Each entry should be the phrase key for the label. The text you provide for each label name will be used as the default if not otherwise specified in the application's default language file. You are advised to create an entry for each label name using the Languages tab of the Application Properties dialog, then use the phrase key generated for that label.

The order in which the labels are provided will match the order of the tabs from left to right. For example, the following is copied from the Analog Status tag:

  [(1){ class declaration }
    IDTabLabel        = "ID";
    IOTabLabel        = "I/O";
    ScalingTabLabel   = "Scaling";
    AlarmTabLabel     = "Alarms";
    ExtAlmTabLabel    = "External Alarms";
    QualityTabLabel   = "Quality";
    OrderTabLabel     = "Order";
    HistorianTabLabel = "Historian";
  ]

For each tab, you must provide a state containing the graphics statements to be shown in that tab. See, Configuration Tab Contents.

The first tab in every dialog box must be the ID tab.

Initialization State

The initial state of the configuration module (commonly named, "Init") will set initial values for variables where required and pass control to the Switch state. If no initialization is required for your parameters, the state will always be written as follows:

Init [
  If 1 Switch;
  [
    {***** Initialize the wait close flag to not wait *****}
    *PtrWaitClose = 0;
  ]
]

Switch State

This is a crucial part of every configuration folder. The state for each of your tabs must monitor the parameter Current for change, which indicates that the user has chosen to view another tab. Control is passed to the Switch state, which checks the value of Current and activates the state matching the user's selection of tab. VTScada looks after updating the value of Current in response to the user's click on a tab. Tabs are numbered from left to right, staring at 0.

The content of this state is a set of IF statements, one for each tab in your config panel.

Switch [
  If Current == 0 ID;
  If Current == 1 Settings;
]

The ID State

Every tag must have a state named ID where the Name, Area, Description parameters are configured. VTScada tags include a HelpKey parameter, which is also configured in this tab, but this is optional for your custom tag.

Copy the following for your custom tag, optionally deleting the HelpKey entry if not in use. Note the first statement, watching the value of Current.

ID [
  If Current != 0 && ! *PtrWaitClose Switch;

   { Let the caller know when it's ok to close }
  *PtrWaitClose = PickValid(Trigger, 1) == 0;

    { Tag Name }
  GUITransform(30, 90, Width - 30, 45   { Boundaries of transform        },
               1, 1, 1, 1, 1            { No scaling                     },
               0, 0, 1, 0               { No movement; visible; reserved },
               0, 0, 0                  { Not selectable                 },
               \DialogLibrary.PEditName(Trigger));

    { Tag Area }
  GUITransform(30, 200, Width - 30, 100 { Boundaries of transform        },
               1, 1, 1, 1, 1            { No scaling                     },
               0, 0, 1, 0               { No movement; visible; reserved },
               0, 0, 0                  { Not selectable                 },
               \DialogLibrary.PAreaSelect(1 { can edit }, 2 { ID }, Parms[1] { Init },
                                          1 { Bevel }, 0 { VertAlign },
                                          1 { AlignTitle }, 1 { ParmNum },
                                          Trigger { Trigger }, OKPressed));

    { Tag Description }
  GUITransform(30, 200, Width - 30, 155 { Boundaries of transform        },
               1, 1, 1, 1, 1            { No scaling                     },
               0, 0, 1, 0               { No movement; visible; reserved },
               0, 0, 0                  { Not selectable                 },
                \PPhraseEdit(\#Description, \GetPhrase("DescriptionLabel"), 
                            1 { ID }, Trigger, 2, FALSE));

    { Help Key }
  GUITransform(30, 255, Width - 30, 210,
               1, 1, 1, 1, 1            { No scaling                     },
               0, 0, 1, 0               { No movement; visible; reserved },
               0, 0, 0                  { Not selectable                 },
               \DialogLibrary.PEditField(\#HelpKey, \GetPhrase("HelpSearchKeyLabel"),
                                         \#VTypeText, 4 {FID}, Trigger, 2, FALSE));
]

P-Tools for Parameter Entry

The P-tools are a set of graphics statements designed expressly for parameter editing. Use these, and only these, in the tabs of your custom configuration panel. A full list is provided in the VTScada function reference. See: Graphics P-Tools.

The first parameter of each P-tool is a numeric value matching the defined constant of one of your tag parameters. (See: Parameter Constants.) This creates the link between each field in your configuration dialog and the parameters in your tag. For clarity, you are advised to use the name assigned to each constant rather than its numeric value.

The P-tools are not placed directly on a page, but are instead wrapped within a GUITransform statement that sets their location. The recommended size for each can be obtained from the example provided in the function reference for each.

It can be challenging to place the transforms evenly within a tab. The following guidelines may help, but expect to spend adjusting the layout. The coordinates of a GUITransform are defined in the order (left, bottom, right, top) and the 0, 0 coordinate of a VTScada window is at the upper left.

  • Define a width constant for the dialog and place transforms relative to that value.
  • Leave a border of 15 pixels to the left and to the right of the collection of transforms.
  • VTScada sets the height of the dialog automatically, allowing space for everything you place within it. Set the top of the first transform at 45 pixels to leave room for the title and a margin, then work down from there.
  • Leave at least 10 pixels between the bottom of one transform and the top of the next.
Settings [
  If Current != 1 && !*PtrWaitClose Switch;
  *PtrWaitClose = False(Trigger);
  
     { Parameter 1 as text }
  GUITransform(30, 90, ((Width - 60) / 2) - 5  , 45,
               1, 1, 1, 1, 1            { No scaling                     },
               0, 0, 1, 0               { No movement; visible; reserved },
               0, 0, 0                  { Not selectable                 },
               \DialogLibrary.PEditField(\#Property1, \GetPhrase("Property1Label"), 
                                         4 { text }, 1 { ID }, 
                                         Trigger { trigger }));
   
     { Parameter 2 as numeric selection }
  GUITransform(((Width - 60) / 2) + 5, 90, Width - 30, 55,
               1, 1, 1, 1, 1,
               0, 0, 1, 0,
               0, 0, 0,
               \DialogLibrary.PSpinbox(\#Property2, \GetPhrase("Property2Label"),
                                       1,
                                       0, 25 { Limits },
                                       3, 0, 1, 2, 
                                       Invalid, Invalid, Trigger));

]