Software Customisation Guide
AVEVA Solutions Ltd
Disclaimer
Information of a technical nature, and particulars of the product and its use, is given by AVEVA Solutions Ltd and its subsidiaries without warranty. AVEVA Solutions Ltd and its subsidiaries disclaim any and all warranties and conditions, expressed or implied, to the fullest extent permitted by law. Neither the author nor AVEVA Solutions Ltd, or any of its subsidiaries, shall be liable to any person or entity for any actions, claims, loss or damage arising from the use or possession of any information, particulars, or errors in this publication, or any incorrect use of the product, whatsoever.
Copyright
Copyright and all other intellectual property rights in this manual and the associated software, and every part of it (including source code, object code, any data contained in it, the manual and any other documentation supplied with it) belongs to AVEVA Solutions Ltd or its subsidiaries. All other rights are reserved to AVEVA Solutions Ltd and its subsidiaries. The information contained in this document is commercially sensitive, and shall not be copied, reproduced, stored in a retrieval system, or transmitted without the prior written permission of AVEVA Solutions Ltd. Where such permission is granted, it expressly requires that this Disclaimer and Copyright notice is prominently displayed at the beginning of every copy that is made. The manual and associated documentation may not be adapted, reproduced, or copied, in any material or electronic form, without the prior written permission of AVEVA Solutions Ltd. The user may also not reverse engineer, decompile, copy, or adapt the associated software. Neither the whole, nor part of the product described in this publication may be incorporated into any third-party software, product, machine, or system without the prior written permission of AVEVA Solutions Ltd, save as permitted by law. Any such unauthorised action is strictly prohibited, and may give rise to civil liabilities and criminal prosecution. The AVEVA products described in this guide are to be installed and operated strictly in accordance with the terms and conditions of the respective license agreements, and in accordance with the relevant User Documentation. Unauthorised or unlicensed use of the product is strictly prohibited. First published September 2007 AVEVA Solutions Ltd, and its subsidiaries AVEVA Solutions Ltd, High Cross, Madingley Road, Cambridge, CB3 0HB, United Kingdom
Trademarks
AVEVA and Tribon are registered trademarks of AVEVA Solutions Ltd or its subsidiaries. Unauthorised use of the AVEVA or Tribon trademarks is strictly forbidden. AVEVA product names are trademarks or registered trademarks of AVEVA Solutions Ltd or its subsidiaries, registered in the UK, Europe and other countries (worldwide). The copyright, trade mark rights, or other intellectual property rights in any other product, its name or logo belongs to its respective owner.
Software Customisation Guide
Software Customisation Guide
Contents
Page
Customisation Guide
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:1
Customising a Graphical User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:1 Serious Warning About Software Customisation . . . . . . . . . . . . . . . . . . . . . . . . 1:1 How to Use this Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:2
Hints on the Trying the Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:2
Minimising Problems for Future Upgrades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:2 Note for Users Familiar with OO Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1:4
Variables, Objects, Functions and Methods. . . . . . . . . . . . . . . . . . . 2:1
PML Variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:1 Object Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:1 Members and Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:2 User-defined Object Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:2
Storing Object Type Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:3
Creating Variables (Objects) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:3
Local and Global Variable Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Notes on Naming Conventions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Variable with a Built-in Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating Other Types of Variable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Member Values of an Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:3 2:3 2:4 2:5 2:5
PML Functions and Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:5
Storing and Loading PML Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:7
12.0
Software Customisation Guide
PML Procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:7
Arguments of type ANY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:8 Using the Methods of an Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:9
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:9 2:11 2:11 2:11 2:12 2:12
Methods on User-Defined Object Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:10
Method Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constructor Methods with Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overloading with ANY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Invoking a Method from Another Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Developing a PML Object with Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Unset Variable Representations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:12 UNSET Values and UNDEFINED Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:13 Deleting PML Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:13 Forms as Global Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2:13
General Features of PML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:1
Functions, Macros and Object Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:1
Comments in PML Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:1 Leaving a PML File with the RETURN Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:2
Case Independence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:2 Abbreviations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:2 Special Character $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:2 Text Delimiters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:3 Filename Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:3 Storing and Loading PML Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:3
Rebuilding All PML File Indexes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:4 Querying the Location of PML Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3:4
PML Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:1
Format of Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:1 Operator Precedence. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:2 Boolean Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:2 Concatenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:3 Nesting Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:3 PML 1 and PML 2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:3 PML 2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4:3
ii
12.0
Software Customisation Guide
Control Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:1
IF Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:1
Nesting if-constructs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:2 BOOLEAN Expressions and if Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:2 IF TRUE Expression. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:4
DO Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:4
Stopping a DO loop: break and breakif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:5 Skipping Commands in a DO Loop using Skip or Skip if . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:6 Nested DO Loops. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:6
Jumping to a Labelled Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:6
Conditional Jumping to a Labelled Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:7 Illegal Jumping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5:7
Arrays
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:1
Creating Array Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:1 Arrays of Arrays (Multi-dimensional Arrays). . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:2 Array Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:2
Appending a New Element to an Existing Array. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting an Array Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Splitting a Text String into Array Elements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Length of String Array Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:3 6:3 6:3 6:3 6:4
Sorting Arrays Using Array Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:4 Sorting Arrays using the VAR Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:6 Subtotalling Arrays with the VAR Command . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:9 Arrays of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:10
DO Values with Arrays of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Block Evaluation And Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Block Evaluate to Sort an Array of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DO VALUES and DO INDICES with Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6:10 6:10 6:11 6:11
Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:1
PML Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:1
Naming and Running Macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:1 Macros with Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:1
Using Macros and Functions Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:3 Synonyms in PML Macros and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7:4
iii
12.0
Software Customisation Guide
Using PML in AVEVA Products . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8:1
Composing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8:1 Defining Variables for Late Evaluation (Rules) . . . . . . . . . . . . . . . . . . . . . . . . . . 8:2 Using PML in PDMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8:2
Accessing DB Elements As Objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Assigning Values to Element Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Accessing Information About a Session. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Evaluating Selected DB Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RAW keyword When setting Variables with VAR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Undo and Redo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8:2 8:3 8:4 8:4 8:5 8:5
Copies and References (for Advanced Users) . . . . . . . . . . . . . . . . . 9:1
Assignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:1 Form and Gadget References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:1 DB References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:1
Deep Copy involving References: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:2
Function Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:2
Constants as Function Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:2 Form and Gadget Properties Passed as Function Arguments. . . . . . . . . . . . . . . . . . . . . . . 9:3
Database Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9:3
Errors and Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10:1
Error Conditions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10:1 Handling Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10:1 Setting the ONERROR Behaviour. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10:2 Other Responses to an Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10:3
Handling Files and Directories. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:1
Creating a File Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:1
Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:1
Reading from Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:2 Writing to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:2 Reading and Writing ARRAYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:2 Error Handling When Using a File Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11:3
Developing PML Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:1
PML Tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:1
iv
12.0
Software Customisation Guide
Diagnostic Messages From Within PML Files . . . . . . . . . . . . . . . . . . . . . . . . . . 12:1 Alpha Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:2 Alpha Log and PML Tracing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:2 Suspending a Running PML Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:2 Querying PML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:2
Querying the Currently Running PML File Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:3 Querying the Values of PML Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:3 Querying What Can Be Typed Next . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12:3
Form Concepts: Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:1
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:1 Naming Forms and their Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:1 Simple Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:2
Adding a Gadget Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:3
Form Definition File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:4 How Forms are Loaded and Displayed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:4 PML Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:5 Revisiting our Simple Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13:6
Form and Gadget Callbacks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:1
Callbacks: Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:1 Callbacks: Form Methods / PML Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:1 PML Open Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:3
Events ............................................................. Open Callbacks at Meta-events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using a PML Function in an Open Callback. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Objects That Can Have Open Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:3 14:3 14:5 14:6
Undo/Redo Support for Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:6
Form Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:8 Gadget Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:9 Menu and Menufield Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:9
Core Managed Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14:9
Forms
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:1
Modules and Applications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:1
Application Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:1 Current Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:2
12.0
Software Customisation Guide
Defining a Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:2
Form Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Minimum Size and Resizability. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intelligent Resizable Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gadget Alignment Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Title and Icon Title. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Initialisation Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form OK and CANCEL Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Quit/Close Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . FIRSTSHOWN callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . KILLING callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Variables: PML Variables within a Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Querying Form Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Free Forms and Form Families . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Loading and Showing Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Position of Forms on the Screen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hiding Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Killing Forms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NOQUIT Form Status. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:3 15:3 15:4 15:4 15:5 15:5 15:5 15:6 15:7 15:8 15:8 15:9 15:9
Form Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:5
Loading, Showing, and Hiding Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:10
15:10 15:10 15:11 15:12 15:12 15:12
CORE Managed Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15:12
Menus
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:1
Menu Types and Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:1
Hints and Tips for Using Menu Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:1 Core-Code Based Menus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:2
Defining a Bar Menu Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:2
Defining a Menu Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Window Menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Online Help Menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Popup Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Finding Who Popped up a Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toggle Menus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:3 16:4 16:4 16:5 16:6 16:6
Editing Bars and Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:7
Inserting Menus into a Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:7 Inserting New Menu Fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:8 Changing the State of Menufields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:9
vi
12.0
Software Customisation Guide
Implied Menu-field Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:10 Creating Menus Dynamically . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16:11
Form Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:1
Form Coordinate System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:1
Form Setup NOALIGN Property. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:2 Gadget Box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:2
Positioning Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:2 Auto-placement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:3
Positioning Gadgets on a Defined Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting the Distance Between Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gadget Alignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How It All Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Positioning Gadgets and Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:3 17:3 17:4 17:4 17:6
Relative Placement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:6
Positioning Relative to the Last Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:6 Positioning Relative to the Form Extremities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:7
Mixing Auto and Relative Placement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:8 Absolute Gadget Positioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:8 AT Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:9 Intelligent Positioning and Resizing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:11
The ANCHOR Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:12 The DOCK Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17:12
Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18:1
Types of Frame. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18:1
Normal Frames. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tabset Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toolbar Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PANEL Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fold Up Panel Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18:1 18:1 18:2 18:2 18:2
Gadgets and their Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:1
Gadget Definition Commands. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:2 Some Generic Gadget Members and Methods . . . . . . . . . . . . . . . . . . . . . . . . . 19:3 Gadget Size Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:3
The Effect of the Tag on Gadget Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:3 User Specifiable Tagwidth for TEXT, TOGGLE and OPTION Gadgets. . . . . . . . . . . . . . . 19:3
vii
12.0
Software Customisation Guide
Specifying Gadget Size Relative to Other Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:4 An Example Form. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:4 The Meaning of Size for the PML Gadget Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:6
Gadgets that Support Pixmaps. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:7
Selected and Unselected States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:7 AddPixmap Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:7
De-activating gadgets: Greying Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:8
Greying Out Gadgets on Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:8
Making Gadgets Visible and Invisible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:9
Making Gadgets Visible and Invisible in Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:9
Setting Keyboard Focus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:9 Refreshing Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:10 Gadget Background Colour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19:10
Gadget Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:1
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:1
Simple Form Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:1 Complex Form Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:3
Frame Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:10
Defining a Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Frame Radio Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Managing Pages in Tabset Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Managing the Fold Up Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:10 20:11 20:14 20:14
CONTAINER Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:15
Example of Container Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:16
Paragraph Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:19
Textual Paragraph Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:19 Pixmap Paragraph Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:19 Textual Paragraph Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:20
Button Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:20
Buttons of Type Toggle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Buttons of type LINKLABEL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Form Control Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining a Dismiss Button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:20 20:21 20:21 20:22
Toggle Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:22 RToggle Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:23 Option and Combobox Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:25
viii
12.0
Software Customisation Guide
Textual Option Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combobox Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pixmap Option Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting and Getting the Current Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20:25 20:26 20:26 20:27
Slider Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:27
Event Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:28
Line Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:28 Numeric Input Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:28 List Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:29
Single Choice List Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:30 Multiple Choice List Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:31 Multi-Column List Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:33
Database Selector Gadgets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:34 Text Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:35
Controlling Text Gadgets Editing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Copying and Pasting into Text Fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatting in Text Input Gadgets: Imperial Units. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unset Text Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Validating Input to Text Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting the Value of a Text Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:36 20:38 20:38 20:40 20:40 20:43
TextPane Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:43
Cut and Paste in Textpanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:44
Fast Access to Lists, Selectors and Textpanes using DO Loops . . . . . . . . . 20:44 View Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:45
Defining a View Gadget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Resizable View Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pop-up Menus in Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining Alpha Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Graphical Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining PLOT Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining DRAFTs Area (2D) Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining DESIGNs Volume (3D) Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20:45 20:45 20:46 20:46 20:48 20:50 20:50 20:52
Alert Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21:1
Position of Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21:2 Input Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21:2
FMSYS Object and its Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:1
ix
12.0
Software Customisation Guide
Setting the Default Format of Text Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:1 Querying Forms & Menus System Information . . . . . . . . . . . . . . . . . . . . . . . . . 22:1 Swapping Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:2 Progress and Interrupt Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:2 Refreshing View Gadgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:3 Checking References to Other Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:3 Splash Screen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:4 Default Form Positioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:4 CurrentDocument() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:4 LoadForm() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:4 Cursor Function Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22:4
PML Add-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:1
Application Switching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:1
Main Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining an Add-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Add-in Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initialisation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:2 23:2 23:2 23:4 23:4 23:5 23:5 23:6 23:6
Menus
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:5
APPMENU Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Addition of Menu Items. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Removing Menu Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifying the Bar Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Toolbars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:7
Toolbar Control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:7 Removing Gadgets from a Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:8 Deactivating Gadgets on a Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:8
Forms
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:8
Registering a Form. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:8 Hiding Forms when Exiting Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:9 Storing Data Between Sessions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:9
Converting Existing User-defined Applications . . . . . . . . . . . . . . . . . . . . . . . 23:10
Replacement of the DBAR File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:10 Menu Name Clashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:11 Converting the DBAR File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:11
12.0
Software Customisation Guide
Example Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:11
Adding a Menu Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:11 Creating a Custom Delete Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23:12
Core Managed Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .A:1
Form Core Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:1
FORM Core Code Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:2
Gadget Core Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:2
GADGET Core Code Interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:3
Menufield Core Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:4
MENUFIELD core code interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A:4 PML Defined Menufields Managed by Application Framework Addins . . . . . . . . . . . . . . . . A:5
Manipulating VIEWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .B:1
Manipulating 2D Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B:1 Manipulating 3D Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B:3
xi
12.0
Software Customisation Guide
xii
12.0
Software Customisation Guide
Introduction
Introduction
This manual describes how to use PML, the AVEVA Programmable Macro Language. You should use it together with the Software Customisation Reference Manual. You do not have to be a professional programmer to start to learn PML, although you may find this manual difficult to follow unless you have some understanding of programming concepts such as if statements and do loops. If you have no programming experience, you should consider attending a PML Training Course. For details, contact your local support office, whose address is given on the copyright page of this manual. The current version of PML, sometimes referred to as PML2, may simply be seen as an extension to the original PML1 facilities. However, the more powerful techniques that are available mean that many programming tasks are carried out in different ways. There are some tasks which are carried out more efficiently using PML 1 facilities. These are described in this manual where necessary, you should also refer to the Database Management Reference Manual.
1.1
Customising a Graphical User Interface
Most AVEVA products make use of a Graphical User Interface (GUI) to drive the software. The interfaces provided with your AVEVA software are designed to apply to a wide range of situations and business needs. However, as you become more experienced with AVEVA products you may wish to design an interface that is more closely related to your requirements. PML 2 has been specifically designed for writing and customising the Forms and Menus for AVEVA products. Almost all the facilities available in PML 1 and the older Forms and Menus facilities continue to function as before even if they are not documented here. Before you begin customising a GUI, you must have a good working knowledge of the command syntax for the AVEVA product you are working with. The commands are described in detail in the reference manuals for the products.
1.2
Serious Warning About Software Customisation
The ability to customise individual Applications to suit your own specific needs gives you great flexibility in the ways in which you use your system. But it also introduces the risk that your modified macros may not be compatible with future versions of the software, since they are no longer under AVEVAs control. Your own Applications may diverge from future standard versions and may not take advantage of product enhancements incorporated into the standard product.
1:1
12.0
Software Customisation Guide
Introduction
To minimise this risk, it is most important that your in-house customisation policies constrain any changes which you make to the Applications so that they retain maximum compatibility with the standard product at all times. Remember that AVEVA Ltd can give you full technical support only for products over which it has control. We cannot guarantee to solve problems caused by software which you have written yourself.
1.3
How to Use this Manual
Chapters 2 to 12 describe the facilities available in PML2, with reference to the differences between PML1 and PML2. Chapters 13 onwards describe how to use PML2 to customise a GUI. Appendix A contains detailed information for AVEVA developers on how to use core-code managed objects. Appendix B contains details of how to manipulate the interactive 2D and 3D views.
1.3.1
Hints on the Trying the Examples
This manual is not really designed as a self-teach tutorial, although users who are already familiar with PML 1 programming may be able to use it as such. Because PML 2 is specifically designed to be used to create Forms and Menus, the best way of experimenting is to start up an AVEVA product and display the command line. You can then create a new form definition file, or edit an existing one, display the form, and use it to call the PML Functions which you have defined in separate files. The source files for some of the larger examples are available from the AVEVA web site, so you can download them rather than having to type them in. You can find them here under PDMS/Macro Library. http://support.aveva.com/support/United_Kingdom/index.htm
1.4
Minimising Problems for Future Upgrades
When future versions are released, the product documentation will identify which macro files and which parts of the directory hierarchy have been modified. You must then decide on one of three courses of action for dealing with any customised macros which you may have been using: Run your existing macros, thereby ignoring any enhanced features which may have been incorporated into the standard versions. Revert to using standard macros instead of your customised versions. Update your customised macros to take advantage of any enhanced features now available.
In order to minimise any problems resulting from updating your customised macros, you should adopt the following key principles as part of your customisation policy: The directory which holds the macros associated with your Applications is divided into two main areas: a standard product area and a user area. You should make changes only in the User area using only copies of the standard Application macros.
1:2
12.0
Software Customisation Guide
Introduction
Warning: You should never modify the original files, so that you can always revert to using these if things go wrong. The environment variable PMLLIB is a search path which must be set to the directory or list of directories under which user-defined PML Functions, objects and forms are stored. The directory specified can contain sub-directories which will automatically be scanned by PML. When writing your own PML Application macros or functions, follow the styles and conventions used in the AVEVA standard AppWare. Ensure that the names of any new forms which you create cannot conflict with the names of any standard forms which may be used in the AVEVA Applications. You should prefix the names of your forms and global variables with a suitable code to distinguish them from AVEVA names. For example, a company XYZ could choose to start all form and global variables names with the characters XYZ.
Current PML2 Naming Convention The majority of the existing PML2 code has been given a three or four letter prefix to the full name. Application Accommodation Administration Prefix ACC ADM Comments
Access platform, Stairs & ASL Ladders Area Based ADP Assembly Associations Common Design Draft Final Designer Global Hull Design Hull Drafting Integrator Isodraft Isometric ADP Diagrams Monitor Paragon Review Interface ABA ASSY ASSOC COMM DES DRA DRA GLB HULL HDRA INT ISO ISO DIAG MON CAT REVI None - Single file Add-in application No appware except main form None None apparent Mixed Mixed Plus ADP, DGN, DXF Add-in application
1:3
12.0
Software Customisation Guide
Introduction
Application Router Spooler Training Icon naming
Prefix RTR SPL TRA
Comments
Icons are named without regard to any rules, except on odd occasions.
Folder Actions Applications Access platform, Stairs & Ladders Assembly ADP Constructs Design Draft Profile Schematic Model Viewer Shapes Splash Styles
Prefix
Comments Various Various
ASL AD Various DES DRAFT PRFL SMV Various Various No existing icons Various STY Plus FSTY Various
1.5
Note for Users Familiar with OO Concepts
PML2 is almost an object-oriented language. Its main deficiency is that it lacks inheritance. However, it does provide for classes of built-in, system-defined and user-defined object types. Objects have members (their own variables) and methods (their own functions). All PML Variables are an instance of a built-in, system-defined or user-defined object type. Operators and methods are polymorphic what they do (their behaviour) depends on the type of the variable. Overloading of functions and operators is supported for all variable types. There is no concept of private members or methods, everything is public. There are only two levels of scope for variables: Global and Local. Arguments to PML Functions are passed-by-reference with Read/Write access so any argument can potentially be used as an output argument.
1:4
12.0
Software Customisation Guide
Introduction
Warning: Changing the value of an argument inside a PML Functions or method will change the value in the calling function or method.
1:5
12.0
Software Customisation Guide
Introduction
1:6
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
2
2.1
Variables, Objects, Functions and Methods
PML Variables
Variables are used to store values. Variables have names. The value that is stored can be changed but the name is fixed. You choose the names and decide what is stored by each variable. The variables used in PML 2 are objects: Every object (variable) has a unique name. An object has a set of functions associated with it, which can be called to manipulate this data. These functions are called methods. Some methods change the data held by the object, some return a result derived from the data, and some methods do both. The data that an object can hold and the functions that are available are fixed by the object type (sometimes called the objects class). Before you can create an object, the object type must have been defined. The object type definition specifies what the members and methods are for that type of object.
2.2
Object Types
Every PML2 variable has an object type which is set when the variable is created and remains fixed as long as the variable exists. Attempting to store a value of the wrong type in an existing variable will cause an error. The object type must exist before you can create a variable of that type. PML 2 is supplied with built-in object types, system-defined object types, and you can also define your own user-defined object types. The built-in object types include the following: Object STRING Description This holds any text, including newline and multi-byte characters such as Kanji. In macros written with PML1 where variables are created with the VAR command, all variables are of type STRING, even when they are storing numbers This is used for all numeric values including do loop counters. There is no separate integer type
REAL
2:1
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
Object BOOLEAN
Description This is used for the result of logical expressions and holds the value TRUE or FALSE Note: These are not the same as the STRING values TRUE and FALSE.
ARRAY
This holds many values of any type and is described in Chapter 6.
There are also system-defined variable types, such as POSITION and ORIENTATION in PDMS. User-defined variable types are explained in User-defined Object Types.
2.3
Members and Attributes
An object can contain one or more items of data referred to as its members or attributes. Each member has a name. STRING, REAL and BOOLEAN variables just have a value - no members. ARRAY variables have numbered elements, not members.
2.4
User-defined Object Types
You may find that the object types supplied with PML 2 are enough. However, you can define new object types if you need to. In any case, the following example may help you understand objects, their members and how they are used. The following commands define an object type FACTORY with two REAL members and a STRING member:
define object FACTORY member .Name is STRING member .Workers is REAL member .Output is REAL endobject
Here is another example where the object type FACTORY is itself used for one of the data members of another object type:
define object PRODUCT member .Code is STRING member .Total is REAL member .Site is FACTORY endobject
2:2
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
It is a good idea to use upper case for object-type names, and mixed upper and lower case for variable names, the objects themselves. For example, a type might be WORKERS, and a variable name might be NumberOfWorkers.
2.4.1
Storing Object Type Definitions
Object type definitions should normally be stored in a file with a lowercase name matching the name of the object type and a .pmlobj suffix in a directory specified in the PMLLIB search-path, which can include the current directory. PML will load a definition automatically when it is needed.
2.5
Creating Variables (Objects)
Note: There is no limit to the number of objects you can create of each type.
2.5.1
Local and Global Variable Names
PML variables are of two kinds: global and local. Global variables last for a whole session (or until you delete them). A local variable can be used only from within one PML Function or macro. These two kinds of variable are distinguished by their names. Names beginning !! are global; names beginning ! are local:
!SurfaceArea !!Area
PML Variable names may be any combination of letters and digits, starting with a letter, up to a maximum of 16 characters (plus the !! or !). Names are allowed to contain a dot (.) but this is now strongly discouraged as a dot has a special meaning in PML2 as a separator between an object and its methods (see Using the Methods of an Object), and between the components of form and gadget names. Rather than using a dot as part of a name we recommend that you use a mixture of upper and lower case to make variable names more meaningful, for example:
!!StartInUpperCase
2.5.2
Notes on Naming Conventions
Use a naming convention to avoid 'polluting the namespace of global variables. All global names beginning with the letters CD are reserved for AVEVA system use. Note that the most recent AVEVA Applicationware (AppWare) does not use a prefix. When creating new PML Macros you are responsible for avoiding name-clashes, for example, by using your own prefix. Here are some guidelines on naming variables: Use each variable for one purpose only and give it a meaningful name. Limit your use of global variables. Where possible use PML Functions rather than macros (macros are described in Macros) so as to make use of function return values and output arguments to return results.
2:3
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
Remember that within the methods of PML Objects and Forms you generally need only local variables. Any values which are to be exported should be made available as members or as method values or returned arguments. Only use PML Functions (necessarily global) for tasks which are genuinely globally accessible, i.e. independent of a specific object or form, or which need to be shared by several objects or forms.
Current Global Variables Application Area Based ADP Administration Application Switching Batch Handling CADCentre Draft Draft Icon Location Defaults General Specialised Various Others Prefix !!ABA !!ADM !!APP !!BAT !!CADC !!CDR !!CD2D !!DFLTS !!CDC !!CE Plus !!CDD, E, F, G, H, I, L, M, N, P, S, U, V, W Plus !!ERROR, !!FMSYS Icon pathnames Comments Add-in application Plus !!CDA
2.5.3
Creating a Variable with a Built-in Type
You can create variables of any of the built-in types (REAL, STRING, BOOLEAN or ARRAY), as in the following example, which creates a REAL variable and sets it value to 99:
!MyNumber = 99
Because the variable is set to a real, PML knows that its type is real. Similarly, you can create a STRING variable and set it like this:
!MyString = Hello World
The PML Variable !MyString and the constant Hello World are both objects of type STRING. A STRING is a very simple object and the only data it contains is its text value. In this simple expression we are creating a new object, a variable of STRING type, by making a copy of the original object, the STRING constant Hello World. Other examples: !!Answer = 42 \!Name = 'Fred' !Grid = TRUE $* creates !!Answer as a GLOBAL REAL variable $* creates !Name as a LOCAL STRING variable $* creates !Grid as a LOCAL BOOLEAN variable
2:4
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
A variable may also be given a type without giving it an initial value, in which case it will have the value UNSET:
!!Answer = REAL() !Name = STRING() !Grid = BOOLEAN() !Lengths = ARRAY()
For more about unset variables, see UNSET Values and UNDEFINED Variables.
2.5.4
Creating Other Types of Variable
You create variables of types that are system-defined or user-defined, using the OBJECT keyword. For example, to create a variable of type FACTORY:
!NewPlant = object FACTORY()
2.5.5
Using the Member Values of an Object
The way to set individual members of an object is to use the dot notation as follows:
!NewPlant = object FACTORY() !NewPlant.Name = ProcessA !NewPlant.Workers = 451 !NewPlant.Output = 2001
The dot notation is used in a similar way to access the value of a member of an object:
!People = !NewPlant.Workers
sets the variable !People to 451.
2.6
PML Functions and Methods
Functions and Methods may optionally have arguments that can be used to return values. Arguments have a data type which is specified in the function or method definition and they are checked when the Function or Method is called. An argument may be one of the built-in types REAL, STRING or BOOLEAN; an ARRAY; a built-in object or a user-defined object or specified as ANY. Functions and methods can optionally return values as their results. Functions that do not return values are known as PML Procedures (see PML Procedures). Here is a definition of a PML Function that has two REAL arguments. It also has a REAL return value, as shown by the final is REAL:
define function !!Area( !Length is REAL, !Width is REAL ) is REAL
Inside a function, the arguments are referenced just as if they were local PML Variables. The RETURN keyword is used to specify the variable that stores the return value:
2:5
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
define function !!Area( !Length is REAL, !Width is REAL ) is REAL !Area = !Length * !Width return !Area endfunction
When a PML Function is called, all the PML Variables passed as arguments must already exist. In addition, arguments used for input must have a value, which could be a constant, when the function is called:
define function !!LengthOfName(!Name is STRING) is REAL !TidyName = !Name.trim() return !TidyName.Length() endfunction
The function is called to set the value of a variable !Length as follows:
!Length = !!LengthOfName( '
FRED
')
Here ' FRED ' is a string constant passed as an argument. We could rewrite this function so that it returns its results by changing its arguments. The output argument, !Length, will be set to the value required when the function is called:
define function !!LengthAndTrim(!Name is STRING, !Length is REAL) !Name = !Name.Trim() !Length = !Name.Length() endfunction
Arguments used for output must exist prior to the call and one that is also used as an input argument must also have a value:
!Name = ' FRED ' !Length = REAL()
The function is called to set the value of a variable !Length as follows:
!!LengthAndTrim(' FRED ', !Length)
When an argument value is changed within a PML Function its value outside the function is also changed. The following call is incorrect, as the function cannot modify a constant:
!!LengthAndTrim('
FRED
' ,4 )
$* WRONG
A PML Function returning a value may be used wherever an expression or PML Variable can be used, for example, this call to the !Area function defined above:
!PartLength = 7 !PartWidth = 6
2:6
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
!SurfaceArea = !!Area(!PartLength, !PartWidth)
Note: You cannot switch to a different PDMS module if a PML Function is running. Use EXIT to exit from the function if it has failed to complete.
2.6.1
Storing and Loading PML Functions
When a PML Function is called it is loaded automatically from its source file in a directory located via the environment variable PMLLIB. The name of the external file must be lowercase and must have the .pmlfnc suffix. The source of a PML Function invoked as !!AREA or !!Area or !!area all correspond to the file named area.pmlfnc. Note: The!! signifies that the function is user-defined and that it is global - but !! does not form part of the external filename. All user-defined functions are global and only one may be defined per file. Note: The define function must be the first line in the file and that its name and the file name must correspond.
2.6.2
PML Procedures
A PML Procedure is a PML Function that does not return a result. A function is defined as a procedure by omitting the data type at the end of the define function statement:
define function !!Area( !Length is REAL, !Width is REAL, !Result is REAL) !Result = !Length * !Width endfunction
Here we are using an output argument, !Result, to return the result rather than using a function return value. The arguments to the !!Area procedure can be set as follows, and then the procedure invoked with the call command.
!SurfaceArea = REAL() !Partlength = 7 !PartWidth = 6 call !!Area(!PartLength, !PartWidth, !SurfaceArea)
There will be an error if you attempt to assign the result of a PML Procedure because there is no return value to assign. So, for example you can say:
call !!Area(!PartLength, !PartWidth, !SurfaceArea) !Answer = !SurfaceArea
But you cannot say:
!Answer = !!Area(!PartLength, !PartWidth, !SurfaceArea)
$* WRONG
2:7
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
The ( ) parentheses after the name of a procedure or function must always be present even for procedures that do not need arguments:
define function !!Initialise() !TotalWeight = 0 !!MaxWeight = 0 endfunction call !!Initialise()
Although the call keyword is strictly speaking optional, its use is recommended with procedures. Note: As well as procedures, you can invoke a PML Function that has a return value using call, in which case the function result value is discarded.
2.7
Arguments of type ANY
You may specify ANY as the type of an argument (and even as the type of the function return value). Note: The use of ANY should be the exception rather than the rule as it switches off argument type checking - an important feature of PML Functions to help ensure correct functioning of your PML. In the case an argument of type ANY, a value of any type may be passed as the argument to the function:
define function !!Print(!Argument is ANY) $P $!Argument endfunction
Where an argument of type ANY is used, you may need to find out its actual type before you can do anything with it. The ObjectType() method can be used for this purpose:
define function !!AnyType(!Argument is ANY) Type = !Argument.pmlobjectType() if ( !Type EQ 'STRING' ) then - - do something with a STRING elseif ( !Type EQ 'REAL' ) then - - do something with a REAL elseif ( !Type EQ 'DBREF' ) then - - do something with a DB Reference else - - do something with all other types or give an error endif endfunction
2:8
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
2.8
Using the Methods of an Object
Note: A method is a function that is specific to an object. The Software Customisation Reference Manual contains a table of the object types supplied as part of PML 2. For each object type, there is a list of the associated methods and members. For each object type, the table shows:
Name
The name of the method or member. For example, a REAL object has a method named Cosine. If there are any arguments, they are indicated in the brackets () after the name. For example, the REAL object has a method named BETWEEN which takes two REAL arguments.
Result or Type
For members, we use the heading Type; for methods, we use the heading Result. The type of the member or the result describes what kind of object we are expecting to see as a member or result of the method. For example, the result of the method Cosine is a REAL value. Some methods do not return a value: these are shown as NO RESULT.
Status
This column is used to give other information about the method or member. For methods, this column tells you whether the method modifies the state of the object. For members, this column tells you whether the member is Mutable (by the user) or Read Only. Note that for the system-defined PDMS object types, members correspond to PDMS attributes
Purpose
This column tells you what the member or method does.
2.8.1
Example
This section explains how to use methods, using a STRING variable as an example. Although the STRING is a simple object type, it has a large number of methods which can be called. For example, if you are interested in the length of the string value, look under the list in the Software Customisation Reference Manual for STRING objects, and you will find a method named Length.
2:9
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
This method returns a REAL value (the number of characters in the string), but has no effect on the variable itself. You can extract the number of characters in the string and store it in a new variable, !Nchars, by calling the method as follows:
!Nchars = !MyString.length()
$* A method call
Notice the dot separator between the name of the variable and the name of the method. Also note the ( ) brackets following the name of the method. The brackets are used to enclose the arguments of the method, but they must be present even if there are no arguments.
2.9
Methods on User-Defined Object Types
When you define a new object type, you can also define methods which can be used to handle all objects created with the new type. PML Method definitions are stored in the same file as the object definition, after the endobject command. Here is an example of an object which defines three methods to illustrate the main ideas. Note that within a method, !This represents the object which invoked the method and !This.Answer is the way to refer to member Answer of this object. The Code What it Does Defines the object, with a single member, Answer.
define object LIFE member .Answer is REAL endobject define method .Life() !This.Answer = 42 endmethod
Defines a method with no arguments but the same name as the type of the object is called the default constructor method. If the default constructor method is present, PML will call it automatically to initialise the object whenever an object of that type is created. A method may return a result in just the same way as a PML Function using the return command. Set a member of the object using !This.membername.
define method .Answer() IS REAL return !This.Answer endmethod define method .Answer( !Value Is REAL) !This.Answer = !Value endmethod
These methods might be used in the following way:
!Marvin = object LIFE() -- The method .Life() was called automatically !Number = !Marvin.Answer()
2:10
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
-- !Number is set to the value 42 !Marvin.Answer(40) !Number = !Marvin.Answer() -- !Number now has the value 40
Warning: When you create a new object type, or change an existing definition, you must load the definition by giving the command: pml reload object _name_
2.9.1
Method Overloading
Two or more methods on an object may share the same name providing they have different arguments. This is called method overloading. PML will invoke the method with the arguments which match the method call. It is common practice: To use a method with the same name as a member and one argument of the same type to set the members value. For example:
!Marvin.Answer(65)
To use a method of the same name as a member returning a value of the same type but with no arguments to get the members value. For example:
!Number = !Marvin.Answer()
2.9.2
Constructor Methods with Arguments
When an object is created, it is possible to supply arguments that are passed by PML to a constructor method with matching arguments instead of the default constructor method:
!Marvin = object LIFE(40)
This would invoke a method:
define method .Life(!Value IS REAL)
2.9.3
Overloading with ANY
As with PML Functions, the type of a method argument may be specified as ANY. If method overloading is being used, PML will invoke the method with a matching set of explicitlytyped arguments in preference to calling a method with arguments of type ANY, irrespective of the order the methods appeared in the object definition file:
define method .SetValue( !Argument Is ANY) define method .SetValue( !Argument Is REAL)
Then:
!SomeObject.SetValue(100)
will invoke the method with the REAL argument, but
!SomeObject.SetValue(Priceless )
will invoke the method with the ANY argument.
2:11
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
2.9.4
Invoking a Method from Another Method
Within a method !This.Methodname() refers to another method on the same object. So our second LIFE constructor method, the one with an argument, could be defined as:
define method .Life(!Value IS REAL) !This.Answer(!Value) endmethod
2.9.5
Developing a PML Object with Methods
Whenever you add a new method to an object, you need to tell PML to re-read the object definition, by giving the command:
pml reload object life
It is not necessary to use this command if you are simply editing an existing method (although you will have to use it if you edit a form definition file, and change the default constructor method, described in Form Definition File.)
2.10
Unset Variable Representations
Each new data type supports a String() method that returns a string representing the value of the variable. For example: !X = 2.5 !S = !X.String() $* defines a variable X of type REAL with 2.5 as its numeric value $* will be a variable of type STRING, with the value 2.5
UNSET variables of all built-in data types have an unset representation: !X = REAL()! S = !X.String() !X = BOOLEAN() !S = !X.String() !X = STRING() !S = !X.String() !X = ARRAY() !S = !X.String() Other variable types are system-defined variables. Most of these have adopted the unset string Unset. For example: !X = DIRECTION() !S = !X.String() $* yields the string Unset $* yields the string ARRAY $* yields the string Unset $* yields the string (the empty string) $* yields the string (the empty string)
2:12
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
User-defined data types can also provide a String() method. These also support an UNSET representation, and usually adopt the UNSET representation Unset.
2.11
UNSET Values and UNDEFINED Variables
All data types can have the value UNSET which indicates that a variable does not have a value. A variable created without giving it an initial value in fact has the value UNSET:
!X = REAL()
Variables with an UNSET value can be passed around and assigned, but use of an UNSET value where a valid item of data is required will always result in a PML error. The presence of an UNSET value may be tested either with functions or methods: Functions if ( Unset(!X) ) then if ( Set(!X) ) then Methods if ( !X.Unset() ) then if ( !X.Set() ) then
An UNDEFINED variable is one that does not exist. The existence of a variable may be tested with these functions:
if ( Undefined(!!Y) ) then . . . if ( Defined(!!Y) ) then
There is no equivalent method call. If the variable does not exist, attempting to call a method would result in an error.
2.12
Deleting PML Variables
A variable that exists can be explicitly made UNDEFINED with the Delete()method:
!!Y.Delete()
Warning: You must not attempt to delete members of objects or forms.
2.13
Forms as Global Variables
In PML 2, forms are a type of global variable. This means that a form cannot have the same name as any other global variable or any other form. Note that a form definition is also the definition of an object, so a form cannot have the same name as any other object type.
2:13
12.0
Software Customisation Guide
Variables, Objects, Functions and Methods
2:14
12.0
Software Customisation Guide
General Features of PML
3
3.1
General Features of PML
Functions, Macros and Object Definitions
Functions and Macros are PML Files that contain stored sequences of commands. The PML File is invoked whenever this sequence of commands is required. The PML File may also include control logic which alters the order in which the commands are carried out and special commands for handling errors. PML Files are normally created using a text editor. PML Functions and methods on objects (including forms) are the recommended way of storing command sequences because: There is a check that they have been called with the right type of arguments. Arguments can return values. A PML Function or method can return a result of any type. Most new AppWare code is written as methods on objects. PML Macros are explained in Macros as they are the basis of the older AppWare code. PML Macros are normally stored in a directory under the PDMSUI search-path. PML Functions are automatically loaded from a directory under the PMLLIB search-path.
3.1.1
Comments in PML Files
Comments are additional text included in a PML File for the benefit of someone reading the PML code. The PML processor ignores comments and so they do not affect the way the code executes. For a simple one line comment, begin the line with - - (two dashes) or $* (dollar and asterisk).
- - This is a new-style PML comment - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $* The following lines calculate the new angle
You can also use $* to add an inline comment to any line of PML:
!Z = !X + !Y
$* We are assuming both !X and !Y are REAL
A comment may extend over several lines provided it is enclosed in the escape sequences $( and $) .
$( A comment containing
3:1
12.0
Software Customisation Guide
General Features of PML
more than one line $)
A comment of this kind can be used temporarily to comment-out lines of PML to prevent them from being executed, but without deleting them from the file:
$( skip if (!X EQ !Y) $)
3.1.2
Leaving a PML File with the RETURN Command
At any point within a PML File a return command will stop further execution of the file and return to the calling PML File, if there is one:
if ( count EQ 0 ) then return endif
For clarity, return can be used as the final line of a PML Macro. However, the use of this command is not essential and there will be no error if it is not used. Note: This is a different use of return from the command used to set return values of variables.
3.2
Case Independence
Everything written in PML, including keywords such as if, do and else means the same thing in upper or lower case. The exception is text enclosed between quotes or vertical bars, which is used exactly as it is typed. Throughout this document you will see examples of PML code using a mixture of upper and lower case for readability.
3.3
Abbreviations
Many commands have a minimum abbreviation which can be used in place of the full command. For readability it is recommended that you use the full form of the command note that it is not less efficient than using the abbreviation. PML keywords such as if, else and do have no abbreviations.
3.4
Special Character $
The $ character has a special meaning in PML. It is an escape character, which means that together with the character which follows it are treated as a special instruction to PML. The pair of characters beginning with $ is known as an escape sequence. $P is a commonly encountered example, which is used to output a message to the screen:
$P This text will be output to the screen
3:2
12.0
Software Customisation Guide
General Features of PML
A number of other escape sequences will be described later in this manual. The important point to note here that if you need the dollar character itself as part of a command, you will need to double it:
$$
As the last character on a line, $ means that the next line is a continuation line. For example:
$P This is an example of a much longer message that will be $ output to the screen
3.5
Text Delimiters
Text strings must be enclosed in either single quotes, or apostrophes, or vertical bars: 'apostrophes' or vertical bars. The apostrophes and vertical bars are known as delimiters. Take great care to avoid unmatched delimiters as this can lead to many lines of PML code being included as part of the text string, and so lost.
3.6
Filename Extensions
The naming conventions are as follows: Extension .pmlfnc .pmlobj .pmlfrm Use for PML Function definition files PML object type definition files PML Form definition files
Note: All filename extensions must be entered in lower case.
3.7
Storing and Loading PML Files
PML Files must be stored in directories pointed to by the PMLLIB environment variable. When an AVEVA product is started up, PML scans each directory in the PMLLIB search path and creates a file named pml.index in each directory. This index file contains a list of all the PML Files in all the directories under the directory given in the PMLLIB search path. All the PML Files listed in the pml.index files are loaded automatically when the product is started up. When you are working on PML Files, you should store them in your own PML working directory, and add the path of your PML working directory as the first entry in your PMLLIB search path. Then, when you add a new PML File (after you have started up an AVEVA product), you will need to tell PML to rebuild its file index by giving the command:
pml rehash
3:3
12.0
Software Customisation Guide
General Features of PML
This command scans all the files under the first directory in your PMLLIB path, and updates the pml.index file. If other users have added PML Files and updated the appropriate pml.index files, you can access the new files by giving the command:
pml index
This command re-reads all the pml.index files in your search path without rebuilding them. When you are not running an AVEVA product, you can update the pml.index file in a given directory by giving the command:
pmlscan directory_name
This command runs a utility supplied with AVEVA products. Note: The commands pml rehash and pml index are a type of command known as PML directives: they are used outside PML Files to direct PML itself to take certain actions. More information about using PML directives with form definitions is given in PML Directives
3.7.1
Rebuilding All PML File Indexes
Note: This process can take some time, and it is possible that if another user gives the command at the same time, the index files may not be re-built properly. Hence it is recommended that this command should only be used when necessary. System Administrators are advised to maintain firm control over the directories in the PMLLIB search path by removing write access for most users. The following command scans all the files in all the directories in your PMLLIB path, and updates the pml.index files.
pml rehash all
3.7.2
Querying the Location of PML Files
If you are not sure where a given file is stored, you can query the path by giving the following command, using the appropriate file suffix:
q var !!PML.getpathname( 'filename.pmlobj' )
3:4
12.0
Software Customisation Guide
PML Expressions
PML Expressions
An expression consists of operators and operands. For example:
2 + 3
is an expression, where 2 and 3 are the operands, and + is the operator. The result of this expression is 5. Expressions can (and normally do) contain variables and, in PDMS, expressions will often contain names of PDMS element types, attributes and pseudo-attributes. Expressions can also contain arithmetic and trigonometric functions, such as the SIN trigonometric function. Often, expressions will contain logical operators:
!height GT !width
Here the logical operator GT is being be used to test if !height is greater than !width. Each expression has a type such as REAL, STRING or BOOLEAN. All the elements in an expression must be of the correct type. For example:
!X + 'text'
$* wrong, Wrong, WRONG!
is meaningless if !X is REAL and will result in an error. (But see Concatenation for using the concatenation operator to convert different types to STRING.)
4.1
Format of Expressions
The use of brackets, spaces and quotes in an expression is important. If you do not follow the rules given below you will get error messages: Text must be enclosed in quotes, either ' apostrophes or | vertical bars:
This is text |and this is text|
There must be a space before and after an operator. For example:
!X + !Y
In general, you do not need spaces before or after brackets, except when a name is followed by a bracket. If there is no space, the bracket will be read as part of the name. For example:
(Name EQ /VESS1 )
4:1
12.0
Software Customisation Guide
PML Expressions
4.2
Operator Precedence
Operators are evaluated in the order of the following list: the ones at the top of the list are evaluated first. Operator BRACKETS Comments Brackets can be used to control the order in which operators are evaluated, in the same way as in normal arithmetic. For example (!A +!B) * 2.
FUNCTIONS */ +NE NEQ GT LT GE GEQ LE LEQ NOT AND OR
4.3
Boolean Operators
The Boolean, sometimes called Logical, operators have the following meanings: The logical operators available are: Operator EQ NE LT GT LE OR LEQ GE OR GEQ NOT AND OR Comments TRUE if two expressions have the same value. TRUE if two expressions have different values. TRUE if the first expression is less than the second. TRUE if the first expression is greater than the second. TRUE if the first expression is less than or equal to the second. TRUE if the first expression is greater then or equal to the second. TRUE if the expression is FALSE. TRUE if both expressions are TRUE TRUE if either or both expressions are TRUE.
Note: The operators EQ, NE, LT, GT, LE and GE are sometimes referred to as comparator or relational operators; NOT, AND, and OR are sometimes referred to as Boolean
4:2
12.0
Software Customisation Guide
PML Expressions
operators. See also Section C.11, Precisions of Comparisons for tolerances in comparing numbers.
4.4
Concatenation
The & operator concatenates two STRING values (joins them end-to-end) to make a result of type STRING. Values of any type are automatically converted to a STRING first:
!X = 64 !Y = 32! Z = !X & !Y
$* !Z is the STRING 6432
4.5
Nesting Expressions
Expressions can be nested using brackets. For example:
( (SIN(!angleA) * 2) / SIN(!angleB) )
4.6
PML 1 and PML 2 Expressions
There are now two styles of expressions available: PML 2 expressions are used in if and do commands and when giving a PML Variable a value using the = (assignment) operator. PML 1 expressions must be used in all other situations, in particular when using an expression as an argument to a command. For more information regarding PML 1 refer to Database Management Reference Manual.
4.7
PML 2 Expressions
PML2 introduces enhanced facilities for expressions in if and do commands and when giving a PML Variable a value using = assignment. For example, the value of a PML Variable can be used by giving the variable name as the expression to the right of =:
!SavedValue = !Number
Users familiar with PML1 should note the absence of $ preceding the variable name. These new expressions do not need to be enclosed in ( ) parentheses:
!NewValue = !OldValue + 1
PML 2 expressions: May be of any complexity. May contain calls to PML Functions and Methods. May include form gadget values (described later), and object members and methods. For example:
!NewValue = !!MyFunction(!OldValue) * !!Form.Gadget.Val / !MyArray.Method()
4:3
12.0
Software Customisation Guide
PML Expressions
4:4
12.0
Software Customisation Guide
Control Logic
Control Logic
There are four types of construct for implementing control logic within a PML Function or Macro. These are: The if construct for conditional execution of commands. The do command for looping and the associated break and skip. The golabel for jumping to a line with a label. The handle construct for dealing with errors.
5.1
IF Construct
The full form of an if-construct is as follows:
if (!Word EQ 'Peanuts' OR !Word EQ 'Crisps') then!Snacks = !Snacks + 1 !Meal = FALSE elseif ( !Word EQ 'Soup') then !Starters = !Starters + 1 !Meal = TRUE elseif (!Word EQ 'Fruit' Or !Word EQ 'IceCream' ) then !Puddings = !Puddings + 1 !Meal = TRUE else !MainCourse = !MainCourse + 1 !Meal = TRUE endif
Each BOOLEAN expression, such as (!Word EQ 'Soup'), is examined in turn to see whether it is TRUE or FALSE. As soon as an expression that is TRUE is encountered, the following block of commands is executed. Once a block of commands has been executed, everything else up to the endif is ignored. The else command is optional. If it is included, you can be sure that exactly one command block within the if-construct will be executed. The elseif commands are also optional. Once one of the elseif expressions has been found to be TRUE, any remaining elseif commands are ignored. Thus the simplest form of the if-construct is:
5:1
12.0
Software Customisation Guide
Control Logic
if ( !Number LT 0 ) then !Negative = TRUE endif
You may not concatenate the commands into one line, so the following are not allowed:
if ( !Number LT 0 ) then if ( !Number LT 0 )
!Negative = TRUE endif
$* WRONG $* WRONG
!Negative = TRUE
Note: That expressions such as:
if ( !TrueValue OR !UnsetValue) if ( !FalseValue AND !UnsetValue)
ignore !UnsetValue if the value is not required to determine the outcome of the expression. The same is true for PML Functions which have returned an error.
5.1.1
Nesting if-constructs
Any if-construct may contain further if ... elseif endif constructs:
if (!Number LT 0) then !Negative = TRUE if (!Number EQ -1 ) then !OnlyJustNegative = TRUE endif endif
It is particularly helpful with nested if constructs to indent the code so that the logic is clear.
5.1.2
BOOLEAN Expressions and if Statements
New expressions based on the operators such as EQ and GT give a BOOLEAN result that can be used directly in a PML2 if test:
if (!NewValue - 1 GT 0) then
The expression can be a simple variable provided it is a BOOLEAN type variable:
!Success = !NewValue GT 0 if (!Success) then
The expression could be a user-defined PML Function provided it returns a BOOLEAN result:
if (!!MyFunction() ) then
Note: The BOOLEAN constants TRUE, FALSE, YES and NO and their single-letter abbreviations not enclosed in quotes return BOOLEAN results and so can be used directly in expressions. For example: Code if ( TRUE ) if ( FALSE ) Result Type BOOLEAN
5:2
12.0
Software Customisation Guide
Control Logic
if ( T ) if ( F ) if ( YES ) if ( NO ) if ( Y )
BOOLEAN
BOOLEAN
BOOLEAN
The following do not return BOOLEAN values and are therefore invalid: Code if ( 1 ) if ( 0 ) if ( TRUE ) if ( FALSE ) if ( T ) if ( F ) Variable = 1 if ($Variable) For upward compatibility with PML1, STRING variables set to TRUE, FALSE, YES or NO or their single-letter abbreviations can be used in an if-test as long as they are evaluated with a preceding $. For example: Code Variable = TRUE if ($Variable) There is a built-in PML Method and a function for converting a value to BOOLEAN: Result Type STRING REAL STRING STRING Result Type REAL
!MyString = TRUE if (!MyString.Boolean() ) then . . .
The Boolean conversion is as follows: Code REAL zero $* All other positive and negative REAL values STRING FALSE, F, NO and N STRING false, f, no and n STRING TRUE, T, YES AND Y STRING true, t, yes and y Result FALSE TRUE FALSE FALSE TRUE TRUE
5:3
12.0
Software Customisation Guide
Control Logic
5.1.3
IF TRUE Expression
IFT/RUE will return a value of the type defined by the second and third arguments. If the initial Boolean expression is true, the result of the first expression is returned. If false, the result of the second expression is returned. Both the second and third arguments are fully evaluated regardless of the value of the Boolean. This is because the function is evaluated using reverse polish procedure (as is the case of the expression design). This allows the IF statement to be nestable with any of the arguments to IF capable of including other IF functions. If logical1 expression is set to true, then value of typeX1expression is returned If logical1 expression is set to false, then value of typeX1 expression is returned typeX1 and typeX2 are two arguments of the same type which may be: Logical Logical Array Real Real Array ID ID Array Text Position Direction
5.2
DO Loops
A do-loop enables a series of commands to be repeated more than once. The number of times the series is repeated is controlled by a counter. Control is passed to the line following the enddo command after executing the commands within the loop with the counter variable at its final value. The full format of the do-loop is as follows:
do !x from 10 to 100 by 10 !Total = !Total + !X enddo
The enddo must be present at the end of the loop. The !X , from, to and by are optional, therefore in its simplest form you may use:
do commands block enddo
This will loop forever unless something in the commands block stops the loop (see break and golabel below)
5:4
12.0
Software Customisation Guide
Control Logic
The elements of the loop are as follows: Element !X Purpose A PML local (or global) variable that is automatically updated with the value of the loop-counter every time round the loop. If you do not supply a loop variable, a hidden unnamed variable will be used for the counter. Note that the loop variable is REAL. PML will delete any pre-existing variable of the same name. After the loop has finished, the counter variable will retain the value it had last time through the loop. from Defines the value of the counter for the first time round the loop. If you do not give a value, it will default to 1. to Defines the value of the counter for the final time round the loop. The default is infinity. by Defines the step size (positive or negative) by which the counter value is changed each time round the loop. The default value is +1.
5.2.1
Stopping a DO loop: break and breakif
If the to option is not given, the command block within the loop will be repeated indefinitely. To stop looping, use either the break or break if command:
do !Number if (!Number GT 100) then break endif !Result = !Result + !Number enddo do !Number break if (!Number GT 100) !Result = !Result + !Number enddo
Any expression may be used with the breakif command, even a PML Function, provided the result is BOOLEAN (i.e. TRUE or FALSE). The ( ) parentheses are optional but recommended. The loop counter variable retains the value it had when the break from the loop occurred.
5:5
12.0
Software Customisation Guide
Control Logic
5.2.2
Skipping Commands in a DO Loop using Skip or Skip if
A skip command is used to go back to the beginning of the do loop, to repeat the loop with the next value of the do loop counter, omitting any commands following the skip command. The following example skips odd numbers:
do !X !Number = !Sample[!X] if ((INT(!Number/2) NE (!Number/2)) then skip endif !Result = !Result + !Number enddo
The skip if command can sometimes be more convenient:
do !X !Number = !Sample[!X] skip if (INT(!Number/2) NE (!Number/2)) !Result = !Result + !Number enddo
5.2.3
Nested DO Loops
You can nest do-loops one inside the other. The counter for each loop must have a different name.
do !X to 10 do !Y !Z = !X + !Y break if (!Y GT 5) enddo enddo
The inner-most loop goes through all the values of !Y before the outer loop moves on to the second value of !X. Note that the break (or skip) command acts just on the loop containing it - in this case the inner-most loop.
5.3
Jumping to a Labelled Line
The golabel command in PML allow you to jump to a line with a matching label name
LABEL /FRED : :
5:6
12.0
Software Customisation Guide
Control Logic
GOLABEL /FRED
The label name /FRED has a maximum length of 16 characters, excluding the / slash which must be present. The next line to be executed will be the line following LABEL /FRED, which could be before or after the GOLABEL command.
5.3.1
Conditional Jumping to a Labelled Line
do !A do !B to 3 !C = !A * !B golabel /finished if (!C GT 100) !Total = !Total + !C enddo enddo label /finished $P Total is $!Total
If the expression !C GT 100 is TRUE there will be a jump to LABEL /FINISHED and PML execution will continue with the line
$P Total is $!Total
If the expression is FALSE, PML execution will continue with the line:
!Total = !Total + !C
5.3.2
Illegal Jumping
The following is an illegal jump into a nested do block. It is however permitted to jump out of a nested block to a line in an enclosing block.
golabel /illegaL do !Count to 5
$* WRONG
!Total = !Total + !Count label /illegal enddo
5:7
12.0
Software Customisation Guide
Control Logic
5:8
12.0
Software Customisation Guide
Arrays
6
6.1
Arrays
Creating Array Variables
An ARRAY variable can contain many values, each of which is called an array element. An Array is created automatically by creating one of its array elements. For example to create element one of a new array named NewArray:
!NewArray[1] = !NewValue
This will create an array variable named !NewArray if it does not already exist and will set element 1 of that array to the value of !NewValue. If !NewArray already exists as a simple variable, you will get an error message and the command will be ignored. Note: How array elements are referred to by means of a subscript expression in [ ] square brackets and that there must be no space between the end of the array name and the subscript. Array elements are accessed in the same way when using the value in an expression:
!Average =
( !Sample[1] + !Sample[2] + !Sample[3] ) / 3
It is also possible to create an empty array which has no elements:
!X = ARRAY()
The array subscript may be any expression which evaluates to a number. One of the simplest expressions is the value of a variable:
!MyArray[!Next] = 15
The individual elements of an array variable can be set independently and in any order. Thus you can set !X[1] and !X[10] without setting any of the intervening elements !X[2] to !X[9]. In other words PML arrays are allowed to be sparse and to have gaps between the subscript numbers which have values set. Note: Negative subscripts are no longer permitted. An array subscript of zero is allowed but you are advised against using it as many of the array facilities ignore array element zero. An array subscript may be an expression of any complexity provided it evaluates to a positive REAL result and may even include a call to a PML Function:
!Value = !MyArray[!A + (!B * !!MyFunction() ) + !C ]
PML Arrays may be heterogeneous. That is to say the elements of a PML array do not have to be all of the same type. Array elements may even be user-defined objects.
6:1
12.0
Software Customisation Guide
Arrays
Non-existent array elements after the last set element of the array and the non-existent elements in the gaps of a sparse array are all UNDEFINED: the function Undefined() will return TRUE and the function Defined() will return FALSE for all these subscripts.
6.2
Arrays of Arrays (Multi-dimensional Arrays)
An array element may itself be an array:
!Surname = 1 !Forname = 2 !Employee[1][!Surname] = 'Smith' !Employee[1][!Forname] = 'Samuel' !Employee[2][!Surname] = 'Bull' !Employee[2][!Forname] = 'John' !FullName = !Employee[1][!Forname] & ' ' & !Employee[1][!Surname]
The value !FullName will be 'Samuel Smith'. It is also possible to assign an entire array to an array element:
!TempName[!Surname] = 'Truman' !TempName[!Forname] = 'Harry' !Employee[3] = !TempName !FullName = !Employee[3][!Forname] & ' ' & !Employee[3][!Surname]
The value !FullName will now be 'Harry Truman'.
6.3
Array Methods
Note: The Software Customisation Reference Manual contains a list of all PML Methods. Array methods are built-in functions for performing a variety of operations on the array. These methods are invoked with a dot following the array name. The method name must be followed by ( ) parentheses - even if the function has no arguments:
!Nelements = !MyArray.Size()
This method sets !Nelements to the number of elements currently in the array. This is an example of a no-effect method which does not alter the array but returns a REAL result which can be assigned to another variable. Here is method which does change the array:
!MyArray.Clear()
This is an example of a method which modifies the array by deleting all the array elements but produces no-result value, so there is nothing to assign to another variable. There is a third kind of method which both changes the array and returns a result value. Here the result is assigned to a variable:
6:2
12.0
Software Customisation Guide
Arrays
!NewArray = !OldArray.RemoveFrom(5,10)
This is an example of a method result which modifies the array by removing 10 elements, starting at element 5. NewArray value is a new array containing the 10 removed elements. If not required, the result can be simply discarded by invoking the method as a command and not assigning the result to a variable:
!OldArray.RemoveFrom(5,10)
Note: Always use an array method, if one is available, in preference to constructing a doloop as it is far more efficient.
6.3.1
Appending a New Element to an Existing Array
To set a new element at the end of an existing array without needing to know which elements are already set, use the Append() method thus:
!Result.Append(!NewValue)
The new array element to be created is determined automatically by adding 1 to the highest existing index for the array !Result. The data are stored in !Result[1] if the array does not yet contain any elements. The array !Result must exist before you can call this method. If necessary you can create an empty array (with no elements) beforehand:
!Result = ARRAY()
If !Result exists already as a simple variable, you will get an error and the command is ignored.
6.3.2
Deleting an Array Element
To destroy an array element use the Delete() method.
!MyArray[N].Delete()
The deleted array element would test as UNDEFINED. Note that the array continues to exist even when you have deleted all its elements.
6.3.3
Deleting an Array
To delete the entire array, together with any existing array elements, use the Delete method on the array itself:
!MyArray.Delete()
6.3.4
Splitting a Text String into Array Elements
You can split a text string into its component fields and store each field in a separate array element using a text strings Split() method. This can be useful after reading a record from a file into a variable. By default, the delimiter is any white-space character (tab, space or newline):
!Line = '123 456 789' !ArrayOfFields = !Line.split()
6:3
12.0
Software Customisation Guide
Arrays
The white-space is treated as a special case since consecutive white-spaces are treated as a single delimiter and white-spaces at the start or finish of the string are ignored. The result is to create the array-variable !ArrayOfFields (if it does not already exist) with the element !FIELDS[1] set to '123', !FIELDS[2] set to '456', and !FIELDS[3] set to '789'. To specify a different delimiter, specify the required (single) character as the argument to the Split() method:
!Line = '123 ,456 ,,789' !ArrayOfFields = !Line.split(',')
In this example, comma is used as the delimiter. !ArrayOfFields is created if it does not already exist with the element !FIELDS[1] set to '123', !FIELDS[2] set to '456', !FIELDS[3] created but set to zero length, and !FIELDS[4] set to '789'. Note that in this case, unlike the white-space delimiter, consecutive occurrences of the comma define empty elements. Note: The only way to set the special white-space delimiter is by default; that is, by not specifying any delimiter as an argument to the Split() method. If a space is specified explicitly as the delimiter (as ' '), it will behave in the same way as comma in this example. You can combine an array-append method with a text-string Split() method in a single command to append the fields of a text string to the end of an existing array variable, thus:
!ArrayOfFields.AppendArray(!Line.Split())
6.3.5
Length of String Array Elements
The length of the longest element in an array can be a useful thing to know, for example when you are outputting the values in table form. You can do this using the Width() method. For example, in the array !LIST:
!LIST[1]'One' !LIST[2]'Two' !LIST[3]'Three'
The command:
!Width = !List.width()
would set to !Width to the value 5, the length of the longest element in !LIST, which is Three'. Note: If the array contained elements that were not strings, these are ignored when calculating the maximum width.
6.4
Sorting Arrays Using Array Methods
The simplest way of sorting an array is to use the Sort() method:
!MyArray.Sort()
This is a no-result method that modifies the array by performing a sort in-situ.
6:4
12.0
Software Customisation Guide
Arrays
The sort is into ascending order and will be an ASCII sort on an array of STRING elements and a NUMERIC sort on an array of REAL values. The Sort() method returns the array itself as a list result, so it is possible to follow the call to the Sort() method immediately with a call to the Invert() method, which will return a descending sort:
!MyArray.Sort().Invert()
An alternative approach is an indirect sort using the method SortedIndices() which returns a REAL array representing new index positions for the array elements in their sorted positions:
!NewPositions = !MyArray.SortedIndices()
The array can be sorted by applying the new index values using the ReIndex() method:
!MyArray.ReIndex(!NewPositions)
More important, the index values in !NewPositions can be used to sort other arrays as well. To use some simple examples, imagine we had the array !Animals that contained: Index [1] [2] [3] [4] [5] The command: Animal Wombat Kangaroo Gnu Aardvark Antelope
!Animals.Sort ()
Would move the array elements so that they now appeared in the following order: Index [1] [2] [3] [4] [5] Animal Aardvark Antelope Gnu Kangaroo Wombat
On the other hand, the command:
!Index = !Animals.SortedIndices()
6:5
12.0
Software Customisation Guide
Arrays
Would create a new array !index representing the subscript values of the array elements in !Animals then sort these index values (without altering the array !Animals). After the sort, !index would look like this: Index [1] [2] [3] [4] [5] The command: Subscript 4 5 3 2 1
!Index.Invert()
Would result in !index now looking like:
Index [1] [2] [3] [4] [5]
Subscript 1 2 3 5 4
6.5
Sorting Arrays using the VAR Command
These facilities were designed to work with arrays of STRINGS. Where a multi-level sort is required it is still necessary to use the older facilities of the VAR command to perform the sort. Using a different example, look at the arrays !Car, !Colour and !Year: !Car [1] [2] [3] [4] [5] [6] CHARIOT FORD VAUXHALL FORD FORD (Unset) !Colour MUD RED YELLOW YELLOW (Unset) BLUE !Year 26 1978 1990 1993 1986 1993
6:6
12.0
Software Customisation Guide
Arrays
[7] [8] [9] [10
Ford (Unset) vauxhall FORD
GREEN (Unset) YELLOW YELLOW
(Unset) (Unset) 1994 1993
If you want to sort the arrays by car model, then on colour, and then on year, you would give the command:
VAR
!Index
SORT
!Car
CIASCII
!Colour
!Year
NUMERIC
The sorted index values are put into the array !Index, (for clarity shown here with the rows of the original arrays they are pointing to), !Index [1] [2] [3] [4] [5] [6] [7] [8] [9] [10 1 7 2 4 10 5 3 9 6 8 !Car !Colour MUD GREEN RED YELLOW YELLOW (Unset) YELLOW YELLOW BLUE (Unset) !Year 2 (Unset) 1978 1993 1993 1986 1990 1994 1993 (Unset)