SlideShare a Scribd company logo
TTRRAAIINNIINNGGGGUUIIDDEE
www.aveva.com
AVEVA Plant
(12 Series)
Programmable Macro
Language (Basic)
TM-1401
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
2
www.aveva.com
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
3
www.aveva.com
Revision Log
Date Revision Description of Revision Author Reviewed Approved
16/01/2009 0.1 Issued for Review BT
26/01/2009 0.2 Reviewed BT EW
29/01/2009 1.0 Approved for Training 12.0.SP3 BT EW RP
Updates
All headings containing updated or new material will be highlighted.
Suggestion / Problems
If you have a suggestion about this manual or the system to which it refers please report it to the AVEVA
Group Solutions Centre at gsc@aveva.com
This manual provides documentation relating to products to which you may not have access or which may
not be licensed to you. For further information on which products are licensed to you please refer to your
licence conditions.
Visit our website at http://www.aveva.com
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.
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, trademark rights or other intellectual property rights in any other product, its name or logo
belongs to its respective owner.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
4
www.aveva.com
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 Limited. 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 Limited or 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 licence agreements, and in accordance with the relevant User
Documentation. Unauthorised or unlicensed use of the product is strictly prohibited.
Printed by AVEVA Solutions on 28 January 2009
© AVEVA Solutions and its subsidiaries 2001 – 2007
AVEVA Solutions Ltd, High Cross, Madingley Road, Cambridge, CB3 0HB, United Kingdom.
5
Contents
www.aveva.com
1 Introduction.............................................................................................................................................. 9
1.1 Aim .................................................................................................................................................... 9
1.2 Objectives......................................................................................................................................... 9
1.3 Prerequisites .................................................................................................................................... 9
1.4 Course Structure.............................................................................................................................. 9
1.5 Using this guide ............................................................................................................................... 9
2 PML Overview ........................................................................................................................................ 11
2.1 PML Programmable Macro Language.......................................................................................... 11
2.2 PML2 - A More Powerful Language.............................................................................................. 11
2.3 PML 2 Jargon.................................................................................................................................. 12
2.4 Features of PML2 ........................................................................................................................... 12
3 Macros and Synonyms.......................................................................................................................... 13
3.1 A simple Macro............................................................................................................................... 13
3.2 The OUTPUT Command ................................................................................................................ 13
3.3 Communicating with AVEVA Products in PML........................................................................... 14
3.4 Parameterised Macros................................................................................................................... 14
3.5 Synonyms....................................................................................................................................... 14
3.6 Recursive Synonyms..................................................................................................................... 15
3.7 Deleting Synonyms........................................................................................................................ 15
Exercise 1 - The Centre of a Handwheel ..................................................................................................... 16
4 Variables................................................................................................................................................. 17
4.1 Numbered Variable types.............................................................................................................. 17
4.2 Named Variable types.................................................................................................................... 17
4.2.1 Setting named variables........................................................................................................... 17
4.3 PML 2 Variable types ..................................................................................................................... 18
4.3.1 Creating Variables.................................................................................................................... 18
4.3.2 Expanding Variables ................................................................................................................ 18
4.3.3 Expressions.............................................................................................................................. 19
4.3.4 Expression operators ............................................................................................................... 19
4.3.5 Operator Precedence............................................................................................................... 19
4.3.6 PML 2 expressions................................................................................................................... 20
4.3.7 Using Variables In Expressions ............................................................................................... 20
4.3.8 Arrays....................................................................................................................................... 20
4.3.9 Concatenation Operator........................................................................................................... 20
Exercise 2 - The variable Centre of a Handwheel....................................................................................... 21
5 PML Control............................................................................................................................................ 23
5.1 DO loop ........................................................................................................................................... 23
5.1.1 DO loops with BREAK.............................................................................................................. 23
5.1.2 DO loops with SKIP.................................................................................................................. 24
5.1.3 DO Index and DO Values......................................................................................................... 24
5.1.4 DO Loops Examples ................................................................................................................ 24
5.2 IF Statements.................................................................................................................................. 25
5.2.1 Simple IF construct. ................................................................................................................. 25
5.2.2 IF, THEN, ELSEIF and ELSE Statements ............................................................................... 25
5.3 Branching ....................................................................................................................................... 25
5.4 Conditional Jumping ..................................................................................................................... 26
Exercise 3 - The Full Handwheel.................................................................................................................. 26
6 Boolean Expressions and IF Statements ............................................................................................ 27
6.1 Simple Boolean Expressions........................................................................................................ 27
6.2 Converting a value to BOOLEAN ................................................................................................. 27
6.3 Valid Boolean expressions ........................................................................................................... 27
6.4 Invalid Boolean expressions ........................................................................................................ 28
6.5 Boolean expressions PML1 upward compatibility.................................................................... 28
7 Errors & Error Handling ........................................................................................................................ 29
7.1 Example of Errors .......................................................................................................................... 29
7.2 Error Handling................................................................................................................................ 29
7.3 Alert Objects................................................................................................................................... 29
7.3.1 Alert Objects with no return value ............................................................................................ 29
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
6
www.aveva.com
7.4 Alert Objects that return value ..................................................................................................... 30
7.4.1 Confirm Alerts........................................................................................................................... 30
7.4.2 Question Alerts......................................................................................................................... 30
7.4.3 Input Alerts ............................................................................................................................... 30
Exercise 4 – Error Handling.......................................................................................................................... 31
8 PML 1 Hierarchy..................................................................................................................................... 33
8.1 Modifications to PDMSUI .............................................................................................................. 33
9 PML2 Functions and Objects ............................................................................................................... 35
9.1 The pmllib environment variable.................................................................................................. 35
9.2 Modifications to pmllib.................................................................................................................. 35
9.3 Updating PDMSUI and PMLLIB..................................................................................................... 36
9.4 PML2 Objects ................................................................................................................................. 36
9.5 PML2 Methods................................................................................................................................ 36
9.6 Method Concatenation .................................................................................................................. 37
9.7 The !!CE Object .............................................................................................................................. 38
9.8 PML2 Functions ............................................................................................................................. 38
Exercise 5(a) – Convert the Hose reel macro into a function ................................................................... 39
Exercise 5(b) – Adding arguments to the function .................................................................................... 40
10 Forms .................................................................................................................................................. 41
10.1 Forms Are Global Objects............................................................................................................. 41
10.2 Dynamic loading of Objects, Forms and Functions................................................................... 41
10.3 Form Definition............................................................................................................................... 42
10.3.1 Using the .net framework ......................................................................................................... 42
10.3.2 Showing and hiding Forms....................................................................................................... 42
10.3.3 Built-in methods for Forms....................................................................................................... 43
10.4 Callbacks ........................................................................................................................................ 43
10.5 Form Gadgets................................................................................................................................. 44
10.5.1 Built-in members and methods for Gadgets ............................................................................ 44
10.5.2 Gadget positioning ................................................................................................................... 45
10.5.3 Docking and Anchoring Gadgets ............................................................................................. 46
10.6 Paragraph Gadgets........................................................................................................................ 47
10.7 Button Gadgets .............................................................................................................................. 47
10.7.1 Linklabel ................................................................................................................................... 48
10.8 Text Entry Gadgets ........................................................................................................................ 48
10.9 Format Object................................................................................................................................. 49
10.10 List Gadgets ............................................................................................................................... 50
10.11 Frame Gadgets........................................................................................................................... 52
10.11.1 Fold Up Panel Frames ......................................................................................................... 53
10.12 Textpane Gadgets...................................................................................................................... 53
10.13 Option Gadgets .......................................................................................................................... 54
10.14 Toggle Gadgets.......................................................................................................................... 54
10.15 Radio Gadgets............................................................................................................................ 55
10.16 Form Member Variables ............................................................................................................ 56
10.17 Tooltips ....................................................................................................................................... 56
10.18 Progress Bar............................................................................................................................... 57
Exercise 6(a) - Calculation methods........................................................................................................... 58
Exercise 6(b) - Loops .................................................................................................................................... 59
Exercise 6(c) – Concatenation ..................................................................................................................... 60
Exercise 6(d) – String manipulation ............................................................................................................ 61
Exercise 7 – Storing and resetting defaults................................................................................................ 62
10.19 Open Callbacks .......................................................................................................................... 63
Exercise 8 – Tabsets and Open Callbacks.................................................................................................. 64
10.20 Bar Menus................................................................................................................................... 65
10.20.1 Defining a Menu Object........................................................................................................ 65
11 PML Objects ....................................................................................................................................... 67
11.1 Built in PML OBJECT Types ......................................................................................................... 67
11.2 Forms and Menus Objects............................................................................................................ 68
11.3 3D Geometry Objects .................................................................................................................... 68
11.4 Methods Available to All Objects ................................................................................................. 69
11.5 The File Object ............................................................................................................................... 70
11.5.1 Using file objects ...................................................................................................................... 70
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
7
www.aveva.com
11.5.2 Use Notepad to open file.......................................................................................................... 71
Exercise 9 – Menubar.................................................................................................................................... 71
12 User-Defined Objects ........................................................................................................................ 73
13 Collections.......................................................................................................................................... 75
13.1 The Collection Syntax (PML 1) ..................................................................................................... 75
13.2 The Object Collection Syntax (PML 2) ......................................................................................... 75
Exercise 10 – Equipment Collections.......................................................................................................... 76
14 Pop-Up Menus.................................................................................................................................... 77
Exercise 11(a) – Pop-up menu ..................................................................................................................... 78
Exercise 11(b) – Equipment Checking ........................................................................................................ 79
Exercise 11(c) – Setting Equipment attributes........................................................................................... 80
15 View Gadgets ..................................................................................................................................... 81
15.1 Alpha Views.................................................................................................................................... 81
15.2 Plot View Example ......................................................................................................................... 81
15.3 Volume View example ................................................................................................................... 82
Exercise 12(a) – Adding a Volume View...................................................................................................... 83
Exercise 12(b) – Adding a Clipbox to the view........................................................................................... 84
Exercise 12(c) – Dynamically modify a clipbox.......................................................................................... 85
Exercise 12(d) – Add Nozzle tagging........................................................................................................... 86
Exercise 12(e) – Add Highlighting ............................................................................................................... 87
16 Event Driven Graphics (EDG) ........................................................................................................... 89
16.1 Simple EDG..................................................................................................................................... 89
16.2 Using EDG ...................................................................................................................................... 90
Exercise 13 – Using EDG .............................................................................................................................. 91
Exercise 13(a) – Add EDG to !!ex10............................................................................................................. 91
Exercise 13(b) – Add EDG to !!ex11b .......................................................................................................... 92
Exercise 13(c) – Add EDG to !!ex12b........................................................................................................... 93
17 Miscellaneous .................................................................................................................................... 95
17.1 Recursive Pml2 Functions............................................................................................................ 95
17.2 Undo and Redo............................................................................................................................... 95
17.2.1 Marking the database............................................................................................................... 95
17.2.2 Undo and Redo Database Commands .................................................................................... 95
17.3 Error tracing ................................................................................................................................... 96
18 Menu Additions .................................................................................................................................. 97
18.1 Miscellaneous Notes ..................................................................................................................... 97
18.2 Modules that use the new Addins functionality ......................................................................... 97
18.3 Adding a Menu/Toolbar................................................................................................................. 97
18.4 Application Design ........................................................................................................................ 97
18.5 Form and Toolbar Control............................................................................................................. 98
18.6 Converting Existing Applications ................................................................................................ 98
18.6.1 DBAR and Add-in Object ......................................................................................................... 99
18.6.2 Bar Menu and Toolbar ............................................................................................................. 99
18.6.3 Define toolbar........................................................................................................................... 99
18.6.4 Adding to Menus ...................................................................................................................... 99
18.6.5 Adding new menus to form .................................................................................................... 100
18.7 Example object including toolbars, bar menus and menus.................................................... 101
Exercise 14 – Add a Utility and Toolbar menu ......................................................................................... 103
19 Upgrading from PML1 to PML2 ...................................................................................................... 105
19.1 Points to watch out for................................................................................................................ 105
Appendix A – PDMS Primitives.................................................................................................................. 107
Appendix B – Example code ...................................................................................................................... 111
Appendix B1 - Example ex1.mac ........................................................................................................... 111
Appendix B2 - Example ex2.mac ........................................................................................................... 112
Appendix B3 - Example ex3.mac ........................................................................................................... 113
Appendix B4 - Example ex4.mac ........................................................................................................... 114
Appendix B5 - Example ex5a.pmlfnc..................................................................................................... 115
Appendix B6 - Example ex5b.pmlfnc..................................................................................................... 116
Appendix B7 - Example ex6a.pmlfrm .................................................................................................... 118
Appendix B8 - Example ex6b.pmlfrm .................................................................................................... 119
Appendix B9 - Example ex6c.pmlfrm .................................................................................................... 121
Appendix B10 - Example ex6d.pmlfrm .................................................................................................. 124
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
8
www.aveva.com
Appendix B11 - Example ex7.pmlfrm .................................................................................................... 127
Appendix B12 - Example ex8.pmlfrm .................................................................................................... 131
Appendix B13 - Example ex9.pmlfrm .................................................................................................... 135
Appendix B14 - Example ex10.pmlfrm .................................................................................................. 139
Appendix B15 - Example ex11a.pmlfrm ................................................................................................ 140
Appendix B16 - Example ex11b.pmlfrm ................................................................................................ 141
Appendix B17 - Example ex11c.pmlfrm ................................................................................................ 143
Appendix B18 - Example ex12a.pmlfrm ................................................................................................ 146
Appendix B19 - Example ex12b.pmlfrm ................................................................................................ 150
Appendix B20 - Example ex12c.pmlfrm ................................................................................................ 154
Appendix B21 - Example ex12d.pmlfrm ................................................................................................ 159
Appendix B22 - Example ex12e.pmlfrm ................................................................................................ 165
Appendix B23 - Example ex13a.pmlfrm ................................................................................................ 172
Appendix B24 - Example ex13b.pmlfrm ................................................................................................ 174
Appendix B25 - Example ex13c.pmlfrm ................................................................................................ 177
Appendix B26 - Example ex14................................................................................................................ 182
9
www.aveva.com
CHAPTER 1
1 Introduction
This manual is designed to give an introduction to the AVEVA Plant Programming Macro Language, There
is no intention to teach software programming but just how the customisation using PML can be done in
AVEVA Plant.
Appendix B contains example code that answers each exercise. The exercises have been deliberately
written to be open to interpretation. This means that the code you produce maybe different.
1.1 Aim
The following points need to be understood by the trainees:
Understand how PML can be used to customise Vantage Plant Design (PDMS)
Understand how to create Functions, Forms and Objects.
Understand how to use the built-in features of Vantage Plant Design (PDMS)
Understand the use of Addins to customise the environment.
1.2 Objectives
At the end of this training, you will have a:
Broad overview of Programmable Macro Language
Basic coding practices and conventions
How PML can interact with the Design model
How Forms and Menus can be defined with PML
1.3 Prerequisites
The participants must have completed an AVEVA Basic Design Course and have some basic progremmin
knowledge.
1.4 Course Structure
Training will consist of oral and visual presentations, demonstrations and set exercises. Each workstation
will have a training project, populated with model objects. This will be used by the trainees to practice their
methods, and complete the set exercises.
1.5 Using this guide
Certain text styles are used to indicate special situations throughout this document, here is a summary;
Menu pull downs and button press actions are indicated by bold dark turquoise text.
Information the user has to Key-in 'will be red and BOLD'
Annotation for trainees benefit:
Additional information
Refer to other documentation
System prompts should be bold and italic in inverted commas i.e. 'Choose function'
Example files or inputs will be in the courier new font, colours and styles used as before.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
10
www.aveva.com
11
www.aveva.com
CHAPTER 2
2 PML Overview
Macros A macro is a group of PDMS commands written to a file
PML Programmable Macro Language (two parts)
PML1 First version of PML including loops, IF statements, string handling, labels etc.
PML2 Object orientated language builds on PML1 and extends the facilities to be like other object
based languages (C++, Smalltalk)
Forms Most applications are driven by forms and menus. Most PML will be based on a form.
2.1 PML Programmable Macro Language
Macros are ASCII files containing PDMS commands in sequence. By asking PDMS to run a macro, you are
really asking PDMS to run a series of commands in a set order (as defined in the macro file)
Programmable macros are macros that contain program constructs such as IF statements, DO loops and
variables
Macros are run in PDMS by typing $m/FILENAME on to the command line (Display>Command Line).
Any extra information added to a macro line is treated as input parameters and are passed to the macro.
i.e. $M/BUILDBOX 100 200 300
This means that the extra 3 values after the macro name are treated as parameters 1, 2 and 3. When
entered in this way, these parameters are then available for use in the macro instead of fixed values.
2.2 PML2 - A More Powerful Language
PML2 is an enhanced version of PML and is more like other modern languages that you may be familiar
with.
PML2 is almost an object oriented language. It provides most features of other Object Orientated
Programming (OOP) languages except for inheritance. It provides 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.
Typically, fewer lines of code needed with PML2 when compared to traditional PML (PML1) and it has been
designed to be easier to read/write. While most PML1 macros will still run within PDMS, PML2 bring many
new features that were previously unavailable.
Built in methods for different variable types remove several multi line procedures used in old style macros.
Use of $ characters is dramatically reduced with a more readable format for expressions
$-style macros will still work provided the syntax has been followed correctly. It is possible to convert
traditional PML code to include newer PML2 features, but it is important that users maintain compatibility at
all times.
Many new features have been added to improve speed and ease of use. These features will be discussed
and demonstrated through this course.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
12
www.aveva.com
2.3 PML 2 Jargon
2.4 Features of PML2
The main features of PML2 are:
• Available Variable Types - STRING, REAL, BOOLEAN, ARRAY
• Built in Methods for commonly used actions
• Global Functions supersede old style macros
• User Defined Object Types
• PML Search Path (PMLLIB)
• Dynamic Loading of Forms, Functions and Objects
• Aid objects for geometric modelling
PML is now more consistent with other programming languages and more structured in form. The new data
types are now OBJECTS which can be operated by running METHODS.
The old $ based variables are still valid, but are always treated as strings.
Global functions are macros which can be called more like subroutines than traditional macros. e.g. a
function can be called between the brackets of an IF statement and return a BOOLEAN result
User-defined object types enable a group of mixed variables to be combined into packages. The resulting
object can then be used as a simple variable and the separate parts set or used as attributes of the variable.
e.g. !fred.position !fred.name
Search paths and dynamic loading mean that it is no longer necessary to pre load forms or have synonyms
for calling macros.
A large number of new aid objects have been created so that users can do more graphical construction.
13
www.aveva.com
CHAPTER 3
3 Macros and Synonyms
A macro is a group of PDMS commands written to a file (in sequence) that can be run together. This
removes the need for user to have to enter every line of code separately. This means that repetitive
processes can be run as a macro.
3.1 A simple Macro
Below is an example of a macro to produce a BOX and CYLINDER and connect to two together, all within
an EQUI.
Type the following into a suitable text editor and save it as c:pmltrainingSimpleMac.mac
NEW EQUIP /ABCD
NEW BOX
XLEN 300 YLEN 400 ZLEN 600
NEW CYL DIA 400 HEI 600
CONN P1 TO P2 OF PREV
You have created your first macro. To run the macro into PDMS, type $M/ onto the command file, followed
by the full file path of the saved macro.
e.g. $M/c:pmltrainingSimpleMac.mac
When running this macro in, ensure the Current Element (CE) is a ZONE or below
Alternatively the macro can be run by Dragging and Dropping it onto the Command Window.
3.2 The OUTPUT Command
While developing a macro there are two main methods within PDMS to find the information it needs:
OUTPUT command
DB listing utility
Both provide the information needed, so the choice on which will be personal. An example of using the
OUTPUT command is as follows:
Type file /c:pmltrainingaa.txt onto the command line, then press enter
(typing file /c:pmltrainingaa.txt over or FFile /c: pmltrainingaa.txt is also acceptable).
PDMS will open the specified file ready to write to. If the file does not exist, this process will create it.
Choose the require element of interest and ensure it is the CE. After it is chosen, type OUTPUT CE onto
the command line. This will print the information PDMS has about the CE to the file.
Last step, type TERM onto the command line. This will close the form, allowing it to be opened by another
program. This file will hold the information (e.g. attributes) PDMS needs to define the elements.
Try the OUTPUT command on the equipment created by SimpleMac.mac. Notice the additional
information PDMS saves about the elements (information not specified in the macro).
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
14
www.aveva.com
3.3 Communicating with AVEVA Products in PML
All commands need to be supplied to the command processor as STRINGS. This is important when
working with element creation (using the NEW syntax)
To expand the contents of a PML variable into a string - put a $ in front of it!
!CompType = |ELBO|
!dist = 5600
NEW $!CompType
DIST $!dist
3.4 Parameterised Macros
Macros can be parameterised. This means instead of hard coding the values through the macro, the values
can be referenced, allowing them to be varied. Simplemac.mac can be parameterised as follows:
NEW EQUIP /$1
NEW BOX
XLEN $2 YLEN $3 ZLEN $4
NEW CYL DIA $3 HEI $4
CONN P1 TO P2 OF PREV
Save the Macro as c:pmltrainingParameterMac.mac
To run this Macro, parameters need to be passed to it. This appending the parameter values to the macro:
e.g. $M/c:pmltrainingParameterMac.mac ABCDE 300 400 600
If no parameters are specified, the macro will fail. To avoid this, default values can be put inside the macro.
This is done by specified $d1= at the top of the macro. For example:
$d1=ABCDEF
$d2=300
$d3=400
$d4=600
Default values will only be used if no parameters are specified.
Macros may have up to 9 parameters separated by space. In the below example, ABC, DEF & GHK are
seen as separate strings and therefore different parameters:
e.g. $M/c:pmltrainingNinePara.mac ABC DEF GHK 55 66 77 88 99 00
If a text string is required as a single parameter, it can be entered by placing a $< before and a $> after the
string.
e.g. $M/c:pmltrainingSevenPara.mac $<ABC DEF GHK$> 55 66 77 88 99 00
$< $> act as delimiters and anything in between is interpreted as a single parameter.
3.5 Synonyms
Synonyms are abbreviations of longer commands. They are created by assigning the command to a
synonym variable:
e.g. $SNewBox=NEW BOX XLEN 100 YLEN 200 ZLEN 300
A synonym can also be parameterised:
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
15
www.aveva.com
e.g. $SNewBox=NEW BOX XLEN $S1 YLEN $S2 ZLEN $S3
To call the first version, type NewBox.
For the second version, type NewBox 100 200 300
3.6 Recursive Synonyms
It is possible for a synonym to call itself, effectively looping through the same command. The following
example shows how the XLEN attribute of a group of boxes (owned by the same element) can be updated:
e.g. $SXChange=XLEN 1000 $/ NEXT $/ XChange
This method will end with an error as it runs until it runs out of boxes to change. $/ acts as a return
character
3.7 Deleting Synonyms
To kill a synonym, type $SXXX= & all synonyms $sk
To switch synonyms off and on $S- and $S+
If all synonyms are killed, the synonyms needed to run PDMS will be removed. This means PDMS will
no longer work properly and will require restarting. If synonyms are turned off, some PDMS
functionality will also be removed. The return this functionality, the synonyms should be turned back
on.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
16
www.aveva.com
Exercise 1 - The Centre of a Handwheel
Write a macro to build the centre of a handwheel (shown right)
It shall be constructed from 4 primitives: 2 boxes, a cylinder and a dish
Create the primitives within a PDMS Design session using the available
appware. Once this is done, use the OUTPUT command to see the
information PDMS needs to create them.
Based on the output, use the CONN command to connect the Ppoints of
primitives together
i.e. CONN P1 TO P1 OF PREV
This will connect PPoint 1 (P1) of the current primitive to P1 of the primitive created previously.
The hierarchy created should look similar to the following:
The dimensions of the primitives are:
BOX1 - Xlength = 100mm
Ylength = 100mm
Zlength = 100mm
CYLI - Diameter = 80mm
Height = 5mm
BOX2 - Xlength = 50mm
Ylength = 50mm
Zlength = 15mm
DISH1 - Diameter = 50mm
Height = 15mm
To aid with connecting the primitives, refer to the adjacent
diagram showing an exploded version of the equipment,
with the PPoints identified.
At the end of the macro add the following line:
ADD /HandWheel AUTO /HandWheel
This line will add the created equipment to the drawlist and
scale the view so it can be seen. You could also add the
following line before it.
REM ALL
This will clear the drawlist first, ensuring that only the new piece of equipment is seen in the main 3D
window.
Save the file as c:pmltrainingex1.mac and run it on the command line by typing
$m/c:pmltrainingex1.mac
An example of the completed macro can be found in Appendix B
17
www.aveva.com
CHAPTER 4
4 Variables
Variables set using the VAR syntax are PML1 style variables and are stored in AVEVA products as strings.
Otherwise, they are PML2 style variables.
4.1 Numbered Variable types
Numbered variables are set by typing a number then value after the command VAR. Examples of this are
below:
var 1 name
var 2 ‘hello’
var 3 (99)
var 4 (99 * 3 / 6 + 0.5)
var 117 pos in site
var 118 (name of owner of owner)
var 119 ‘hello ’ + ‘world ‘ + ‘how are you’
To obtain the value of variable 1, enter q var 1, q var 117 etc.
The available variable numbers only go to 119 (there is no 120) and they are module dependant. For these
reasons, this technique is no longer commonly used.
4.2 Named Variable types
To give a variable a name, the required name must be preceded with either a single or double exclamation
mark (!), !variablename or !!variablename
single ! - a local variable (can only be seen in the current macro)
double!! - a global variable
Variable names may be up to 64 characters long and the names can contain alpha and numeric
characters.
Variable names must not start with a number or contain a . (full stop)
4.2.1 Setting named variables
The following are some examples of setting variables:
VAR !FRED NAME
Takes the current element’s (ce) name attribute
VAR !POS POS IN WORLD
Takes ce position attribute relative to world coordinates
VAR !x ‘NAME’
Sets the variable to the text string ‘NAME’
VAR !temp (23 * 1.8 + 32)
Calculate a value using the expression
VAR !list COLL ALL ELBO FOR CE
Makes a string array of database references
Quotes ‘ ‘ or vertical bars | | may be used as text Delimiters
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
18
www.aveva.com
4.3 PML 2 Variable types
There are four basic variable types: STRING ‘any alpha numeric characters’
REAL any numeric value
BOOLEAN true/false t/f (but not 0/1)
ARRAY any combination of the above
Note: PML1 style variables using the VAR syntax are only stored as strings.
4.3.1 Creating Variables
The following are some examples of setting PML2 variables types:
!Name = ‘Fred’
To create a LOCAL, STRING variable
!!Answer = 42
To create a GLOBAL, REAL variable:
!!Flag = TRUE
To create a GLOBAL, BOOLEAN variable:
!newarray = ARRAY()
To create a LOCAL empty ARRAY
!newarray[1] = |xxx| or !newarray[1] = ‘xxx’
To add to first value to the empty ARRAY (locally)
The type of variable is automatically implied by its content
!!answer = 42 becomes a REAL
!name = ‘fred’ becomes STRING
!flag = TRUE becomes BOOLEAN
Variables can be initialised to ensure only correct results can be set. All variable types can be set up the
following way:
!!number = real()
!!text = string()
4.3.2 Expanding Variables
To expand variables in AVEVA products on the command line use a $. When the line is read, the values of
the variables will be used.
VAR !XLEN (1000)
VAR !YLEN (1000)
VAR !ZLEN (1000)
NEW BOX XLEN $!XLEN YLEN $!YLEN ZLEN $!ZLEN
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
19
www.aveva.com
4.3.3 Expressions
Expressions are calculations using PML variables. This can be done is a PML1 or PML2 style:
PML1: VAR !Z ( |$!X| + |$!Y| )
PML2: !Z = !X + !Y
In the PML1 example, !Z is set as a STRING variable. In the PML2 example, !Z is returned as a REAL,
if !X and !Y are REAL
Setting variables using the PML2 method is neater and more readable when compared to PML1.
Any variable can be forced to be a STRING by putting a dollar in front of it.
!x = 64 this returns a REAL.
VAR !y (64) this returns a STRING
IF(!x eq !y)THEN is invalid syntax because the comparison is mixing variable types.
IF($!x eq !y)THEN valid because the dollar in front of !x forces it to be a STRING.
4.3.4 Expression operators
There are a number of expression operators which are available for use. The actual syntax will depend on
whether a PML1 or PML2 style has been adopted.
Numeric operators: + - / *
Comparison operators: LT GT EQ NE LE GE
Logic operators: NOT AND OR
Numeric functions: SIN COS TAN SQR POW NEGATE ASIN ACOS ATAN LOG ALOG ABS INT NINT
For further examples, refer to PDMS Software Customisation Reference Manual:
Some examples of expressions in use:
!s = 30 * sin(45)
!t = pow(20,2) (raise 20 to the power 2 (=400))
!f = (match(name of owner,|LPX|)gt 0)
4.3.5 Operator Precedence
When PDMS reads an expression, there is a precedence that applied to it. This should be considered when
writing one. The order is as follows:
()
* /
+ -
EQ NE GT LT GE LE
NOT
AND
OR
e.g. (60 * 2 / 3 + 5) = 45
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
20
www.aveva.com
4.3.6 PML 2 expressions
PML 2 expressions may be of any complexity, they may contain calls to PML Functions and Methods and
include Form gadget values ,object members and methods.
For example:
!NewVal = !!MyFunc(!OldVal) * !!Form.Gadget.Val / !MyArray.Method()
4.3.7 Using Variables In Expressions
$ and quotes are not necessary when using the value of a variable in a PML2 expression:
!X = 64 (instead of VAR !X (64))
!Y = 32
!Z = !X + !Y
The same expression PML1 is still valid ( VAR !Z (|$!X| + |$!Y|) ), but in this case !Z is a STRING
variable
4.3.8 Arrays
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 or it can be initialised as an empty
ARRAY. If an ARRAY ELEMENT is itself an ARRAY, this will create a Multi-dimensional ARRAY.
For example an example of an array, type out the following onto the command line:
!x[1] = |ABCD|
!x[2] = |DEFG|
!y[1] = |1234|
!y[2] = |5678|
!z[1] = !x
!z[2] = !y
To query the information about !z, type q var !z. This will return the following information:
<ARRAY>
[1] <ARRAY> 2 Elements
[2] <ARRAY> 2 Elements
To find out more information about the elements within the Multi-dimensional array, type q var !z[1] or q var
!z[2][1]
4.3.9 Concatenation Operator
Values to be concatenated are automatically converted to STRING by the ‘&’ operator. Type the following
onto the command line:
!a = 64
!b = 32
!m = ‘mm’
!c = !a & !b & !m
q var !c
Compare this against the results of typing
!d = !a + !b
q var !d
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
21
www.aveva.com
Exercise 2 - The variable Centre of a Handwheel
Write a parameterised macro to build the centre of a handwheel. ex1.mac will be the basis for the new
macro. Also, add two extra primitives to represent an arm (a cylinder) and part of the wheel (a circular
torus).
Use the $d1=XXX syntax to replace the values used in ex1.mac with parameters
$d1 should be used for the name of the equipment and the rest should be set as the required dimensions
Give BOX1 a name so that it can be referred to. This will be useful when positioning the new cylinder and
circular torus. As $1 is a string, a unique name can be created by using the variable with some additional
characters e.g. /$1-XXX
The new cylinder shall have a height of 500mm and should not overlap the original BOX1. Both the cylinder
and circular torus shall have a diameter of 50mm. The centre line of the circular torus shall intercept the end
of the new cylinder.
The CONN method from exercise 1 can still be used, but instead of using PREV, we can reference other
named elements. Think about the available PPoints when positioning the new primitives (Refer to Appendix
A)
The hierarchy created should look similar to the following:
Save the file as c:pmltrainingex2.mac and run it on the command line by typing
$m/c:pmltrainingex2.mac
An example of the completed macro can be found in Appendix B
Try running the macro again with a different equipment name variable to check it works
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
22
www.aveva.com
23
www.aveva.com
CHAPTER 5
5 PML Control
5.1 DO loop
A DO loop is a way of looping within the PML macro allowing pieces of code to be run more than once. This
is useful as it allows code to be reused and reduces the length of code.
As an example, type out the following and save it a c:pmltrainingDoLoop.mac:
DO !loopCounter FROM 1 TO 10
!value = !loopCounter * 2
q var !loopCounter !value
ENDDO
If the above example is run into PDMS, values of !loopCounter and !value with be printed to the command
line for the full range of the defined loop. The step of the loop can be altered by adding BY to the loop
definition:
eg: DO !loopCounter FROM 1 TO 10 BY 2
5.1.1 DO loops with BREAK
If you need a loop to run until a certain condition is reached, a BREAK command will exit the current loop:
Type out the following example and save it a c:pmltrainingDoBreak.mac:
!n = 0
DO
!n = !n + 1
!value = POW(!n, 2)
q var !value
BREAK IF (!value GT 1000)
ENDDO
The BREAK command can also be called from within a normal IF construct. This is typically done if multiple
break conditions need to be considered.
e.g. IF (!value GT 1000)
BREAK
ENDIF
The loop in the example will run until the BREAK condition is met. If the condition is never reached, then the
code will run indefinitely! A DO loop of 1 to 100000 could be used instead, as it has an end.
An open DO loop that never meets the break condition will run indefinitely
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
24
www.aveva.com
5.1.2 DO loops with SKIP
It is possible to skip part of the DO loop using the SKIP command. This could be useful if parts of a number
sequence needs to be missed:
Type out the following example and save it a c:pmltrainingDoSkip.mac:
DO !n FROM 1 TO 25
SKIP IF (!n LE 5) OR (!n GT 15)
q var !n
ENDDO
The SKIP command can also be called within a normal IF construct (as the BREAK command)
5.1.3 DO Index and DO Values
DO Index and DO Values are ways of looping through arrays. This is an effective method for controlling the
values used for the loops. Typically values are collected into an ARRAY variable then looped through using
the following:
DO !X VALUES !ARRAY
!X takes each ARRAY element
ENDDO
DO !X INDEX !ARRAY
!X takes a number from 1 to !ARRAY size
ENDDO
5.1.4 DO Loops Examples
Type out the following as an example of looping through an ARRAY of values. Save the following as
c:pmltrainingDoArray.mac.
VAR !Zones COLL ALL ZONES FOR SITE
VAR !Names EVAL NAME FOR ALL FROM !Zones
q var !Names
DO !x VALUES !Names
q var !x
ENDDO
DO !x INDEX !Names
q var !Names[!x]
ENDDO
The example uses the COLL syntax as a method of defining an array. This syntax will be explained later in
the manual. It shows how the two methods can extract the same information from the source array.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
25
www.aveva.com
5.2 IF Statements
An IF statement is a construct for the conditional execution of commands. The commands will only be run if
the conditions of the IF statement are met.
5.2.1 Simple IF construct.
A simple example of an IF construct is shown below. The code within the IF construct is only run if the
expression is TRUE. An example is as follows:
IF ( !Number LT 0 ) THEN
!Negative = TRUE
ENDIF
5.2.2 IF, THEN, ELSEIF and ELSE Statements
An IF construct can be extended by adding additional conditions. This is done by adding either ELSEIF or
ELSE to it. When an IF construct is encountered, PML will evaluate its condition. If the condition is FALSE,
PDMS will look to the next ELSEIF condition.
Once a condition is found to be TRUE, that code will be run that proportional of the code and the IF
construct is complete. If an ELSE condition is added, this portion of code will only be run if the other
conditions are never met. This is a way of ensuring some code is always run.
Type out the following example, and save it as c:pmltrainingNumCheck.mac. Run it with one real
parameter.
IF ($1 EQ 0) THEN
$p Your value is zero
ELSEIF ($1 LT 0) THEN
$p Your value is less than zero
ELSE
$p Your value is Greater than zero
ENDIF
The ELSEIF and ELSE commands are optional, but there can only be one ELSE command in an IF
construct.
5.3 Branching
PML provides a way of jumping from one part of a macro to another using GOLABEL.
LABEL /FRED Max length 16 characters, excluding (/)
...
Some PML code
...
GOLABEL /FRED
The next line to be executed will be the line following LABEL /FRED, which could be before or after the
GOLABEL command.
The use of this method should be limited. It can make code hard to read and debug.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
26
www.aveva.com
5.4 Conditional Jumping
Type out the following as an example of conditional jumping. Save it as c:pmltrainingConditional.mac.
DO !A
$P Processing $!A
DO !B TO 10
!C = !A * !B
GOLABEL /finished if (!C GT 100)
$P Product $!C
ENDDO
ENDDO
LABEL /finished
$P Finished with processing = $!A Product = $!C
If the expression !C GT 100 is TRUE there will be a jump to label /finished and PML execution will continue
with the $P command. If the expression is FALSE, PML execution will continue with the command: $P
Product $!C and go back through the DO loop.
Exercise 3 - The Full Handwheel
Introduce variables and calculations to reduce the number of parameters needed to build a handwheel. Use
ex2.mac as a basis for the new macro and use a loop to complete the outer wheel.
Create two SUBE elements. One will contain the
primitives that make up the centre of the handwheel
and the other the arm of the handwheel.
Use a loop to copy the arm SUBE element to
complete the outer wheel. When building the loop,
consider how many copies are needed.
When creating a copy, create the element as usual
but append COPY /XXXX to the line. This will create
a new element, but copy it from /XXXX
e.g. NEW BOX COPY /XXXX
As each arm will need to be rotated 90° from the previous, the ROTATE command can be used
e.g. ROTATE BY AAA ABOUT BBB
where AAA is the angle of rotation and BBB a direction to rotate around i.e. U. Think about how the loop
can be used to change the angle of rotation and the name of the copied elements.
The hierarchy created should look similar to the
following
Save the file as c:pmltrainingex3.mac and run it on the command line by typing $m
c:pmltrainingex3.mac
An example of the completed macro can be found in Appendix B
27
www.aveva.com
CHAPTER 6
6 Boolean Expressions and IF Statements
6.1 Simple Boolean Expressions
Expressions based on the operators such as EQ (equal to) and GT (greater than) give a BOOLEAN result
which can be used directly in an IF construct.
An example is as follows. Type out the example and save it as c:pmltrainingBoolean.mac. Run it as a
single parameter macro.
!value = int($1)
IF ( !value NE 1 ) THEN
!Test = FALSE
ELSEIF ( !value.eq(1) ) THEN
!Test = TRUE
ENDIF
q var !Test
The expression can be a simple variable provided it is a BOOLEAN type variable:
!Success = !Value GT 0
IF ( !Success ) THEN
The expression could be a user-defined PML function or method that returns a BOOLEAN result:
IF ( !!MyFunction() ) THEN
6.2 Converting a value to BOOLEAN
There is a built-in PML method and a function for converting a value to BOOLEAN:
!MyString = |TRUE|
IF ( !MyString.Boolean() ) THEN ...
The Boolean conversion is as follows:
REAL zero becomes FALSE
All other positive and negative REAL values become TRUE
STRING ‘FALSE, ‘F’, ‘NO’ and ‘N’ become FALSE
STRING ‘false, ‘f’, ‘no’ and ‘n’ become FALSE
STRING ‘TRUE’, ‘T’, ‘YES’ AND ‘Y’ become TRUE
STRING ‘true’, ‘t’, ‘yes’ and ‘y’ become TRUE
6.3 Valid Boolean expressions
BOOLEAN constants are 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:
if ( TRUE ) and if ( FALSE ) BOOLEAN OK
if ( T ) and if ( F ) BOOLEAN OK
if ( YES ) and if ( NO ) BOOLEAN OK
if ( Y ) and if ( N ) BOOLEAN OK
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
28
www.aveva.com
6.4 Invalid Boolean expressions
The following do not return BOOLEAN values and are therefore invalid:
if ( 1 ) and if ( 0 ) REAL invalid
if ( |TRUE| ) and if ( |FALSE| ) STRING invalid
if ( |T| ) and if ( |F| ) STRING invalid
if ($Variable) where Variable = 1 REAL invalid
6.5 Boolean expressions PML1 upward compatibility
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:
if ($Variable) where Variable = ‘TRUE’ STRING OK
29
www.aveva.com
CHAPTER 7
7 Errors & Error Handling
An error condition can occur when a command could not complete successfully. This is because of a
mistake in the
macro or function (either input or execution). An error normally has three effects:
• An Alert box appears which the user must acknowledge.
• An error message is outputted to the command line together with a trace back to the error source.
• Any current running PML macros and functions are abandoned.
7.1 Example of Errors
This example of an error is caused by an attempt to create an Equipment when in the wrong part of the
hierarchy.
(41,8) ERROR – Cannot create an EQUI at this level.
The 41 is the program section which identified the error and 8 is the error code itself.
7.2 Error Handling
If the input line was part of a PML macro or function, the error may optionally be HANDLED. This allows the
designer of the macro to limit the errors the user will experience.
Type out the following example and save it as c:pmltrainingErrorTest.mac. First run the macro at a SITE
element, then at a ZONE element and then again at the same ZONE. Compare the return printed lines in
the command window.
NEW EQUI /ABCD
HANDLE (41, 8)
$p Need to be at a ZONE or below
ELSEHANDLE (41, 12)
$p That name has already been used. Names must be unique
ELSEHANDLE ANY
$p Another error has occurred
ELSEHANDLE NONE
$p Everything OK. EQUI created
ENDHANDLE
7.3 Alert Objects
Alert objects allow user-controlled pop-up forms to be used.
7.3.1 Alert Objects with no return value
There are 3 types of alert with no return value:
!!Alert.Error( |You cannot do this!| )
!!Alert.Message( |Saving your data now| )
!!Alert.Warning( |Incorrect value!| )
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
30
www.aveva.com
By default, all alert forms appear with the relevant button as near to the cursor as possible. To position an
alert specifically, X and Y values can be specified as a proportion of the screen size.
!!Alert.Error( |You cannot do this!| , 0.25, 0.1)
7.4 Alert Objects that return value
There are three types of alert which return a value, confirm, question and input alerts.
7.4.1 Confirm Alerts
Confirm alerts return ‘YES’ or ‘NO’ as strings
e.g. !Answer = !!Alert.Confirm( |Are you sure!| )
After typing the above onto the command line, type q var !Answer
7.4.2 Question Alerts
Answer alerts return ‘YES’ or ‘NO’ or ‘CANCEL’ as strings
e.g. !Answer = !!Alert.Question( |OK to delete Site| )
After typing the above onto the command line,
type q var !Answer
7.4.3 Input Alerts
The first value is the prompt and the second is the default value. Input alerts return a value as a string.
e.g. !Answer = !!Alert.Input( |Enter Width of Floor|,|10| )
After typing the above onto the
command line, type q var !Answer
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
31
www.aveva.com
Exercise 4 – Error Handling
Add some error handling to control any errors generated while running ex3.mac.
Although you will not be able to handle every error, think about likely errors and how to handle them
What would be a suitable response to an error? Should it be ignored? Or maybe some user-feedback
provided? Maybe PDMS should do something automatically to correct it?
An example of user-feedback could be to print a warning to the command line. To do this, start a line with
$p followed by a space. Whatever is written after this shall be printed to the command line.
e.g. $p Error Found
To get you started, the following are examples of some errors which may occur:
• At the wrong level in the hierarchy (i.e. at a PIPE element rather than a ZONE)
• A suitable hierarchy level for equipment creation does not exist (or cannot be found)
• An element called ‘HandWheel’ already exists
Save the file as c:pmltrainingex4.mac and run it on the command line by typing $m/c:pmltraining
ex4.mac
An example of the completed macro can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
32
www.aveva.com
33
www.aveva.com
CHAPTER 8
8 PML 1 Hierarchy
All PML1 Macros are in a directory structure pointed at by the variable PDMSUI.
The PDMSUI environment variable
Set PDMSUI=C:AVEVAplantPDMS12.0.2pdmsui
Standard AVEVA environment variable are set in a bat files called EVAR.bat in the executable directory.
All PML1 macros and forms are called using synonyms
For example the macros and forms associated with piping are called using the synonym CALLP
$S CALLP=$M/%PDMSUI%/DES/PIPE/$s1
CALLP MPIPE
This is why if all synonyms are killed that PDMS will no longer work properly
8.1 Modifications to PDMSUI
It is normal practice to create a parallel hierarchy to contain any new or modified PML.
Changes to AVEVA standard product may cause PDMS to function inappropriately
These modifications can then be called by modifying the PDMSUI variable to point at a multi path. This can
be done by putting a new file path in front of the %PDMSUI% definition. This will update the PDMSUI
environment variable to include the specified file path.
Set PDMSUI=c:pmltrainingPDMSUI %pdmsui%
The new file path should go in front of %PDMSUI% so this area is checked first for content. Once content is
found, other locations will not be searched.
This modification should be done after the PDMSUI environment variable has been defined. This can be
done at the bottom of the EVAR.bat file or in the PDMS.bat file (after the line which calls evar.bat).
The environment variables can be checked with PDMS by using the q evar syntax
q evar PDMSUI or q evar ‘SAM000’
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
34
www.aveva.com
35
www.aveva.com
CHAPTER 8
9 PML2 Functions and Objects
9.1 The pmllib environment variable
The PMLLIB environment variable points to a PML2 directory structure
Set PMLLIB= C:AVEVAplantPDMS12.0.2pmllib
There are 3 new file extensions .pmlfnc for Functions, .pmlfrm for Forms and .pmlobj for Objects, with these
extensions the files will be loaded by PDMS automatically when the program is started.
Functions are loaded by PDMS and are run by typing the following !!mymac(). This runs file
mymac.pmlfnc
Forms are displayed by typing Show !!Myform or !!Myform.show()
Objects have to be assigned to a variable before they can be used i.e. !x = object MyObject()
9.2 Modifications to pmllib
It is normal practice to create a parallel hierarchy to contain any new or modified PML.
Changes to AVEVA standard product may cause PDMS to function inappropriately
These modifications can then be called by modifying the PMLLIB variable to point at a multi path. This can
be done by putting a new file path in front of the %PMLLIB% definition. This will update the PMLLIB
environment variable to include the specified file path.
Set pmllib=c:pmltrainingPMLLIB %pmllib%
The new file path should go in front of %PMLLIB% so this area is checked first for content. Once content is
found, other locations will not be searched.
This modification should be done after the PMLLIB environment variable has been defined. This can be
done at the bottom of the EVAR.bat file or in the PDMS.bat file (after the line which calls evar.bat).
In AVEVA products environment variables can be checked using the q evar syntax i.e. q evar pmllib
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
36
www.aveva.com
9.3 Updating PDMSUI and PMLLIB
Edit the Evar.bat file to include multi paths for PDMSUI and PMLLIB
These settings should be made at the bottom of the evar.bat file
Set pdmsui=c:pmltrainingpdmsui %pdmsui%
Set pmllib=c:pmltrainingpmllib %pmllib%
The setting of the variable can be checked in AVEVA Plant Design (PDMS) using the following commands:
q evar pdmsui and q evar pmllib
If a pmllib file is c once items have been loaded by PDMS, it needs to be reloaded. This can be done by
typing either pml reload form !!NAME or pml reload object NAME
If a new file is to pmllib, the files can be remapped so PDMS knows where it is located. This is done by
typing pml rehash onto the command line. This will update the first file location in the search path. To
update all search paths, type pml rehash all.
9.4 PML2 Objects
An object is a PML grouping of information. It may have MEMBERS (used to hold data) ands METHODS
(used to complete an action). Once assigned to a variable, that variable becomes an instance of that object.
This means that variable will behave as the object definition.
While it is possible to create user-defined objects (discussed later), PDMS is supplied with a large number of
built-in objects. A full list of these can be found in the PDMS Software Customisation Reference Manual.
For example, type !pos = object position() onto the command line. Query the variable and check the results
against the members of a position object listed in the reference manual.
Although a FORM is an object, it is a subject in its own and will be discussed later.
9.5 PML2 Methods
When working with built-in objects, there may also be BUILT-IN METHODS (object dependant). These
methods have been defined to complete certain actions applicable to object. For example, type the
following into the command line:
!value = |56|
!result = !value * 2
This example will have caused an error as a string cannot be used in an expression like this. To avoid the
error, refer to the STRING object in the Reference Manual and find the .real() method. This method
translates the variable from a STRING to a REAL so that it can be used in the expression. The !value
remains a string, but !results now becomes a REAL e.g.
!value = |56|
!result = !value.real() * 2
Within PML2, there are built-in methods for all the standard objects (ARRAY, TABLE, FORM, and STRING).
Refer to PDMS Software Customisation Reference Manual for the available methods and information
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
37
www.aveva.com
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 The type of value returned by 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 members.
For methods, this column tells you whether the method MODIFIES the value of the object.
For members, this column tells you whether the member is SETTABLE (by the user) or
UNSETTABLE.
Note that for the system-defined PDMS object types, members correspond to PDMS attributes
ACTION This column tells you what the member or method does.
A large number of methods have been provided for the built-in PML data types: For example, for STRING
objects, you will find a method named Length.
!Name = ‘Tony Blair’
!NumberOfLetters = !Name.Length()
q var !NumberOfLetters
This method returns a REAL value (the number of characters in the string), but has NO EFFECT on the
variable itself.
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.
The following method creates an ARRAY of STRINGS:
e.g. !NameStrings = !Name.Split()
9.6 Method Concatenation
It is possible to apply multiple methods to the same variable within the same line of code. This process will
work providing the data passed at each stage is valid. Try the following on the command line:
!line = 'hello world how are you'
!newline = !line.upcase().split().sort()
q var !line !newline
<STRING> 'hello world how are you'
<ARRAY>
[1] <STRING> 'ARE'
[2] <STRING> 'HELLO'
[3] <STRING> 'HOW'
[4] <STRING> 'WORLD'
[5] <STRING> 'YOU'
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
38
www.aveva.com
9.7 The !!CE Object
A special GLOBAL PML variable !!CE always points to the current PDMS element and its attributes. Type q
var !!CE onto the command line and compare it against typing q att. You will notice the returned attribute
information is the same of the members list of the !!CE object.
This means that the !!CE object can be used to assign the values of attributes to !variables
For example, !BranchHeadBore = !!CE.Hbore assigns the HBORE attribute (taken from the current BRAN
element) to the variable !BranchHeadBore making it real.
If the !!CE object member is an object itself, that object will also have members so further information be
obtained e.g.
!HeadPosition = !!CE.Hpos.East East member from a POSITION object
!Easting = !!CE.Href.Cpar[1] Cata parameter member (attribute) of a DBREF object
If the !!CE object member is an object with built-in methods, these methods can also be called:
!PosWRTValve = !!CE.Hpos.WRT(ZONE) POSITION object w.r.t the owning ZONE
This process can also be reversed allowing the setting of attributes for the CE. This means that it is possible
to record the current value of an attribute, modify and reassign back to the CE. For example, type out the
following onto the command line:
!Pos = !!CE.Pos
q POS
!Pos.Up = 2000
!!CE.Pos = !Pos
q POS
These lines will have moved the CE up by 2000. Try this example again with some other attributes.
9.8 PML2 Functions
Functions are new style macros which are pre-loaded by PDMS and can be called directly. For example, to
call the function called FuncName.pmlfnc, type !!FuncName() onto the command line.
A function is defined within a .pmlfnc file stored within the PMLLIB file path. For an example of a function,
type the following into a new file and save it as c:pmltrainingpmllibfunctionsNameCE.pmlfnc.
define function !!NameCE()
!ce = !!CE.fullname
$p $!ce
endfunction
To run this function, type !!NameCE() onto the command line. You will notice the fullname is printed below
it. This is an example of a NON-RETURN function with NO ARGUMENTS.
If the function can be given arguments which are then assigned to variables with the function. If a variable is
returned, this means that the function can be assigned to another variable or as part of a calculation. Type
out the following, and save it as c:pmltrainingpmllibfunctionsArea.pmlfnc:
define function !!Area(!Radius is REAL) is REAL
!CircleArea = !Radius.Power(2) * 3.142
return !CircleArea
endfunction
As this function is an example of a RETURN function with an ARGUEMENT, it can be used as part of an
expression. The returned value is based the functions argument and its type (REAL in this case):
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
39
www.aveva.com
!Height = 64
!CylinderVolume = !!Area(2.3) * !Height
q var !CylinderVolume
As indicated by the !!, functions are global. This means that once defined, they can be called by any form or
method within PDMS minimising repetitive code.
Synonyms are disabled inside functions
Exercise 5(a) – Convert the Hose reel macro into a function
This exercise will cover how to update existing macros to make use of updated functionality.
The macro that will be updated is c:pmltrainingmacrosex5.mac. Have a look at the file. It uses the
READ method and this technique is no longer valid. How can the required values be passed to the macro?
A function can be used to allow input values. Save the updated macro as a function called ex5a.pmlfnc in
the directory c:pmltrainingpmllibfunctions
To begin with, define a function with one argument: The name of the equipment. Apply suitable error
handling to the function and check it works. After typing PML REHASH ALL, type !!ex5a(‘HoseWheel’) and
a new hose wheel will be created.
Look at the macro and you will see it uses the same hand wheel we have defined so far.
The function uses the variable !WheelDia to alter the diameter of the hand wheel. Update the function by
adding another argument, the diameter of the hand wheel. Test your function and see the impact of altering
this variable.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
40
www.aveva.com
Exercise 5(b) – Adding arguments to the function
Extend the function written in exercise 5a to accept two more arguments:
• the width of the hosewheel
• the diameter of the hose wheel.
Rewrite parts of the functions so that hosewheel will change size based on these inputted numbers. How do
the primitives in the hosewheel relate to these dimensions.
Reduce the lines of code by introducing DO loops and PML2 syntax
Save the updated function as a function called ex5b.pmlfnc in the directory
c:pmltrainingpmllibfunctions
Type show !!ex5plt to see an dimensioned plot file
!!ex5b(|Hose-Reel-001|, 1000, 2000)
41
www.aveva.com
CHAPTER 10
10 Forms
10.1 Forms Are Global Objects
Forms now look like GLOBAL OBJECTS, with Gadgets as their MEMBERS. Once loaded, the information
held within a form can be accessed at anytime.
To find out information about the form, it can be queried as if it was an object. For example, lets use the
Graphics Settings form (Settings>Graphics…)
Type Show !!gphsettings onto the command line to see the form in question or choose it from the menu
Type q var !!gphsettings onto the command line. The information is a list of the members of the form.
Compare this list against some of the gadget s on the form. As gadgets are members of forms, we can find
information about these.
The first gadget listed is called OK (representing the OK button on the form). Type q var !!gphsettings.ok.
The information returned is information about the button. Specific information about the gadget can be
queried directly e.g.:
q var !!gphsettings.ok.tag
q var !!gphsettings.ok.val
q var !!gphsettings.ok.active
To get the name of a shown form, type show !!pmlforms. This form can list shown forms
10.2 Dynamic loading of Objects, Forms and Functions
When a PML object is used for the first time, it is loaded automatically. This applies to both FORMS and
OBJECTS e.g.:
!Person = object PRIMEMINISTER()
show !!MyInputForm
Once an object is loaded by PDMS, the definition is held by PDMS. This means that if the object is changed
whilst it is loaded, the form will need to be reloaded. To reload a form type pml reload form or object
followed by the object name e.g.:
pml reload form !!MyInputForm
pml reload object PRIMEMINISTER
If a new file is created whilst PDMS is open, the file will not be mapped (even if it is saved in an appropriate
file path). The remap files type pml rehash. This will remap all the files within the first file path in the
PMLLIB variable.
The remap all files in all the file paths, type pml rehash all
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
42
www.aveva.com
10.3 Form Definition...
Forms are defined within .pmlfrm files and should be defined in the following way. A .pmlfrm file can contain
the form setup definition and any methods created in association:
setup form !!fname
...
exit
define method .init()
...
Endmethod
10.3.1 Using the .net framework
Form objects can now make use of the .net framework. This allows new features to be included on forms:
• Docking forms (automatic resizing)
• Anchoring gadgets (useful when resizing)
• Multicolumn lists
• Tabs on Forms
• Menu Additions to existing applications:
• Toolbar Additions to existing applications
• DBAR Conversions
Although it is now possible to dock forms, it does not apply to every form. There are some rules to consider
when deciding if a form should dock:
• Does the form need to remain open?
• Is the form used heavily
• If a form has an OK/Cancel button, it should not need docking
• If a form has a menubar, it CANNOT be docked
To declare a form as dockable, this has to be done on the top of the definition. By including dialog dock left,
we are stating that the form is displayed, it shall already be docked to the left:
setup form !!fnam dialog dock left
To define a floating, dockable form, use the following line:
setup form !!fnam dialog resizeable
To define a form of a certain size in the centre of the screen, use the following line:
setup form !!fnam document at xr 0.5 yr 0.5 size 100 100
If no additional details are included, the default form creation is a Dialog, non-resizeable, size adjusted
automatically to fit contents form.
For more examples, refer to the FORM object in the PDMS Software Customisation Reference Manual
10.3.2 Showing and hiding Forms
Now forms can be found through the PMLLIB search path, there is no longer the need to load them
individually. To show a form use show !!formname. This will load the form definition and show it in one go!
Sometimes it is useful to have the form loaded with seeing it (e.g. to refer to stored information). A form can
be loaded (but not shown) by typing loadform !!formname
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
43
www.aveva.com
10.3.3 Built-in methods for Forms
Although is possible to define user-defined methods within user-defined forms (discussed later), all FORM
objects have built-in methods available. Try on the following on the command line:
!!gphsettings.show()
q var !!gphsettings.shown()
!!gphsettings.hide()
q var !!gphsettings.shown()
In this example, the .show() method is used to show the form, the .shown() method returns whether the form
is shown and the .hide() method hides the form.
For more examples, refer to the FORM object in the PDMS Software Customisation Reference Manual
10.4 Callbacks
If an object has a CALLBACK member, it can be given a callback string. This means that if the user
interacts with the object, an action can be performed. The callback can do one of three things:
• show a form
• execute a command directly
• run a function or method
A FORM object has some special callbacks which are used when the form completes certain actions (e.g.
Shown, closed)
Copy out the following into a new file and save it as Callback.pmlfrm. Put the file into the appropriate file
path c:pmltrainingpmllibforms and remap the files. To see the form, type show !!Callback. Press the
buttons look at the command line.
setup form !!Callback
!this.formTitle = |Callback Example|
!this.initcall = |!this.init()|
!this.okcall = |!this.okCall()|
!this.cancelcall = |!this.cancelCall()|
!this.quitcall = |!this.quitcall()|
button .ok ' OK ' OK
button .can 'Cancel' at x30 CANCEL
exit
define method .Callback()
$p --Constructor Method--
endmethod
define method .init()
$p --Initialise Method--
endmethod
define method .okcall()
$p --OK Method--
endmethod
define method .cancelcall()
$p --Cancel Method--
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
44
www.aveva.com
define method .quitcall()
$p --Quit Method--
endmethod
At the top of the form, the callback members of the form where set user-defined methods within the form.
• The CONSTRUCTOR method was called when the form loaded (notice, it has the same name as
the form).
• The INITCALL method is called everytime the form is shown (perfect for setting default values
• The OKCALL method is called by any button gadget with the OK in its definition
• The CANCELCALL method is called by any button gadget with CANCEL in its definition
• The QUITCALL method is called by clicking the close button on the form.
If no callbacks are defined for OKCALL, CANCELCALL and QUITCALL the default is to hide the form
only
10.5 Form Gadgets
There are many kinds of form gadgets, each an object that will have its own members and methods. When
you are defining gadgets on a form, there are two common aims:
• Define the area to be taken up on the form
• Define the action to be taken if the gadget is selected
It is the position and size of the gadget that determines the area taken up and its action is defined by its
CALLBACK member.
10.5.1 Built-in members and methods for Gadgets
As Gadgets are objects, there are a variety of useful members and built-in methods that can be used. Using
the previous example (!!Callback), type the following onto the command line:
To grey-out the OK button
!!Callback.ok.Active = FALSE
To hide the CANCEL button
!!Callback.can.Visible = FALSE
Apply a tooltip to the OK button
!!Myform.ok.setToolTip(|This is an OK button|)
For further information, PDMS Software Customisation Reference Manual
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
45
www.aveva.com
10.5.2 Gadget positioning
Gadgets are positioned on a form from top left using the AT syntax. The AT syntax defines the origin of the
gadget in relationing to the owning object (i.e. FORM or FRAME). .
Gadgets can be positioned explicity or in relation to other gadgets. When referring to other gadgets, there 6
known positions on a gadget: XMIN, XCEN, XMAX, YMIN, YCEN and YMAX. These refer to fixed position
in the x and y directions on the referenced gadget. A gadget can be thought of as an enclosing box that will
enclose the geometry of the gadget (including its name tag if specified).
To position a gadget at a known position use:
at x 0 y 0
To position the above CANCEL button use Xmax and Ymin of OK use:
at xmax.ok + 10 ymin.ok
To position a DISMISS button in the bottom corner of a form use:
at xmax form – size ymax form
For more positioning syntax, refer page 2-59 in the PDMS Software Customisation Reference Manual
The available syntax and its order can be derived by referring to the SYNTAX GRAPHS in the reference
manual. These diagrams are available for most Gadgets and can be used when initially defining them. The
picture below is an example of the Syntax Graph for gadget positioning (<fgprl> refers to another graph):
Refer PDMS Software Customisation Reference Manual for more guidance on these graphs
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
46
www.aveva.com
10.5.2.1 Position Gadgets using the path command
The path command can be used to define the logical position of subsequent gadgets. This method has
been superseded by the previous method and has been included for information.
After a gadget has been defined, the next gadget is positioned based on a PATH, HDIST or VDIST and
HALIGN or VALIGN. As an example, see the picture below:
Button .But1 $* default placement
PATH down
HALIGN centre
VDIST 2
paragraph .Par2 width 3 height 2 $* auto-placed
toggle .Tog3 $* auto-placed
PATH right
HDIST 3
VALIGN bottom
List .Lis4 width 2 height 3 $* auto-placed
PATH up
HALIGN right
Paragraph .Par5 width 3 height 3 $* auto-placed
10.5.3 Docking and Anchoring Gadgets
After a gadget has been loaded its size and position are locked. To modify the position or size manually, the
alterations have to be made in the file and the form reloaded. As forms can be resized, it is necessary for
gadgets to move/resize so the layout of the form remains.
There are two available syntax definitions that can help DOCK or ANCHOR. This syntax should be included
when defining a gadget and can be included if <fgdock> or <fganch> are included in the gadgets syntax
graph.
The DOCK and ANCHOR are mutually exclusive so only one is defined per gadget
ANCHOR controls the position of an edge of the gadget relative to the corresponding edge of its container.
For example, if a DISMISS button is anchored to the Right + Bottom, it will remain in the bottom, right of the
form if it is resized.
DOCK forces gadget fill the available space in a certain direction. For example, if a list is docked to the left,
it will maintain its width, but its height will change it fill its container. DOCK FILL is very useful for ensuring a
gadget is the full size of its container.
Copy out the following into a new file and save it as DockExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files.
setup form !!DockExample dialog resizeable
!this.formTitle = |Dock and Anchor|
!buttpos = |xmax.f1 - size ymax.f1 - size|
frame .f1 anchor ALL width 30 height 5
button .butt1 |Dock TOP| dock TOP
button .butt2 |Anchor B+R| at $!buttpos anchor R+B
exit
exit
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
47
www.aveva.com
Resize the form and observe the results.
Once a gadget is declared as Anchored or Docking it will remain so. If a change is required, the form
definition should be updated and the form reloaded.
Refer PDMS Software Customisation Reference Manual for the Syntax Graphs.
10.6 Paragraph Gadgets
Paragraph gadgets are simple named gadgets which allow a piece of TEXT or a PIXMAP to be displayed on
a form. It is a passive gadget that cannot be selected by the user so has no callback. Paragraph gadgets
are used display either instructions or pictures.
Copy out the following into a new file and save it as ParaExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files.
setup form !!ParaExample
!this.formTitle = |Paragraphs|
para .para1 text |Normal paragraph gadget| width 20
para .para2 at x 0 ymax.para1 backg 6 text |A cyan paragraph gadget| width 20
para .para3 at x 0 ymax.para2 pixmap width 154 height 50
para .para4 at x 0 ymax.para3 + 0.5 text || wid 20 hei 2
exit
define method .ParaExample()
-- Update the displayed text using CONSTRUCTOR method
!this.para4.val = |Above was a PIXMAP, this is on two lines|
-- Use built-in method to apply picture
!this.para3.AddPixmap(|c:pmltrainingpmllibimagesaveva.png|)
Endmethod
Refer to the Reference Manual and Guide for more examples
The last value of the last gadget was set during the CONSTRUCTOR method. empty paragraph gadgets
can be created to reserve space with values set after creation..
10.7 Button Gadgets
Button gadgets are typically used to invoke an action or to display a child form. Its CALLBACK can call a
LOCAL METHOD, GLOBAL FUNCTION or OBJECT METHOD. If a callback and a child form are both
specified, the callback command will be run before the child form is displayed.
Copy out the following into a new file and save it as ButtonExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files.
setup form !!ButtonExample dialog resizeable
!this.formTitle = |Buttons|
button .butt1 |Normal|
button .butt2 |Green| backg 5
button .butt3 |Deactive|
button .butt4 |form| form !!ParaExample
button .butt5 toggle backg 4 call |!this.check()| pixmap wid 31 hei 21
exit
define method .ButtonExample()
-- Deactivate butt3 in CONSTRUCTOR method
!this.butt3.active = FALSE
-- Use built in method to apply pictures
!this.butt5.AddPixmap(|c:pmltrainingpmllibimagesoff.png|, |c:pmltrainingpmllibimageson.png|)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
48
www.aveva.com
endmethod
define method .check()
-- Return the toggle button value to the command line
!check = !this.butt5.val
$p $!check
endmethod
Refer to the Reference Manual and Guide for more examples
As .butt5 was set as a toggle button, it has either a TRUE or FALSE state. This means that a toggle button
holds a .val member which can be set or queried.
10.7.1 Linklabel
The Linklabel, provides a purely textual button presentation, i.e. it has no enclosing box. It is often used to
indicate a link to some application item, e.g. a hyperlink to a file, a link to an associated form. They do cause
validation of any modified text fields of the form whenever they are pressed.
The tag text is shown in a different colour to all other gadget's tag text. The link label gadget highlights by
underlining when the mouse cursor passes over it. Pressing it causes a SELECT event to be raised and
runs any associated call back.
Linklabels have the following restrictions:
• They don't support change of background colour.
• They don't support 'pressed' and 'not pressed' value.
• They can have popup menus, though this is not recommended.
• They don't have Control Types e.g. OK, CANCEL etc.
Copy out the following into a new file and save it as LinkLabelExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!LinkLabelExample dialog resizeable
!this.formTitle = |LinkLabel|
button .butt1 |Paragraph Form| linklabel form !!ParaExample
exit
10.8 Text Entry Gadgets
A text input gadget provides the user a way of entering a single value into PDMS. A TEXT gadget is defined
by:
WIDTH – determines the displayed number of characters. An optional scroll width can also be specified
TYPE – determines the type of the variable created when inputting a value. This is important when PML
uses the variable. You may also supply a FORMAT object (explained below) to format the value entered
(e.g. whole number)
Copy out the following into a new file and save it as TextExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
49
www.aveva.com
setup form !!TextExample
!this.formTitle = |Text|
path down
text .txt1 |Val as String | width 10 is STRING
text .txt2 |Only numbers | width 10 is REAL format
!!REALFMT
text .txt3 |Round numbers | width 10 is REAL format
!!INTEGERFMT
text .txt4 |For passwords | width 10 NOE is STRING
text .txt5 |Limited scroll| width 10 scroll 1 is STRING
text .txt6 |Not editable | width 10 is STRING
exit
define method .TextExample()
-- Make Text 6 uneditable
!this.txt6.val = |Cannot change!|
!this.txt6.setEditable(FALSE)
endmethod
The benefit of making a text gadget uneditable (rather than deactivated) is so the user can select its
contents. A deactive text box will be full greyed out and unselectable.
Refer to the Reference Manual and Guide for more examples
10.9 Format Object
A FORMAT object manages the information needed to convert a number (always in mm) to a STRING. It
can also be used apply a format to a text gadget. A format objects are usually defined as global variables so
that they are available across PDMS. For example, type the following onto the command line:
!!OneDP = object FORMAT()
!!OneDP.dp = 1
q var !!OneDp
There are four standard FORMAT objects which are already defined in standard PDMS:
!!DistanceFmt For distance units
!!BoreFmt For Bore Units
!!RealFmt To give a consistent level of decimal places on real numbers
!!IntegerFmt To force real numbers to be integers(0 dp Rounded)
To find out more information about these FORMAT object, query them as global variables on the command
line q var !!BoreFmt
For example the number of decimal places displayed using !!RealFmt could be set !!RealFmt.dp = 6 the
default value is 2.
These standard format objects are used within the forms of PDMS. Changing the definition of these objects
will change the way standard product behaves.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
50
www.aveva.com
10.10List Gadgets
A LIST gadget presents and ARRAY of values to the user. This can be a SINGLE or MULTI-
DIMENSIONAL ARRAY
All the values in the gadget are set by assigning an ARRAY. ARRAY variables can be applied to a LIST at
any time. The choice between MULTIPLE, COLUMN and SINGLE has to be made when the gadget is
defined. The values within a COLUMN list (headings and values) are set by using built-in gadget methods.
Copy out the following into a new file and save it as ListExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files
setup form !!ListExample
!this.formTitle = |Lists|
!vshap = |width 15 height 6|
list .lst1 |Single Array List| call |!this.value()| SINGLE ZEROSEL $!vshap
list .lst2 |Multi-Select List| MULTI $!vshap
list .lst3 |Appending List| call |!this.append()| $!vshap
list .lst4 |Multi-column List| COLUMNS $!vshap
exit
define method .ListExample()
-- Define values contained within the lists
do !I from 1 to 5
!Dvalue[!I] = |Number| & !I
!Rvalue[!I] = |<| & !I & |>|
do !J from 1 to 2
!multi[!I][!J] = |col | & !J & |(| & !I & |)|
enddo
enddo
!this.lst1.dtext = !Dvalue
!this.lst1.rtext = !Rvalue
!this.lst2.dtext = !Dvalue
!single[1] = |Click to append values|
!this.lst3.dtext = !single
!this.lst4.setRows(!multi)
!heading[1] = |One|
!heading[2] = |Two|
!this.lst4.setHeadings(!heading)
endmethod
define method .value()
--Print the Dtext and Rtext values to the command line
!dtext = !this.lst1.selection('Dtext')
!rtext = !this.lst1.selection('Rtext')
$p Selected Dtext is $!<dtext> (Rtext is $!<rtext> - hidden!)
endmethod
define method .append()
-- Append value to List 3
!nextLine = !this.lst3.dtext.size() + 1
!val = |Appended | & !nextLine
!this.lst3.add(!val)
Endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
51
www.aveva.com
Refer to the Reference Manual and Guide for more examples
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
52
www.aveva.com
10.11Frame Gadgets
A FRAME is a cosmetic gadget which is used to surround a group of similar gadgets. This helps with
organisation, positioning and user experience. A frame can also be declared as a TABSET or a RGROUP
(explained later) and even a TOOLBAR (when defined for the main PDMS window).
Copy out the following into a new file and save it as FrameExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!FrameExample dialog resizeable
!this.formTitle = |Frames|
frame .tabset TABSET anchor ALL wid 15 hei 5
frame .f1 |Docked| at 0 0 dock FILL
frame .fA |Dock All| dock FILL
frame .fB |Dock Right| dock RIGHT wid 10
frame .fC |Dock Bottom| dock B hei 4
exit
exit
exit
exit
frame .f3 |Other| at 0 0 dock FILL
!pos = |at xcen.fG - 0.5 * size ymax|
frame .fG |Deactive| wid 15 hei 4
button .but1 |Try and click!| at 1 1
exit
button .but |Show Frame| $!pos backg 8 call |!this.showF()|
frame .fH |Hidden Frame| at xmin.fG ymax.but2 width.fG hei.fG
exit
exit
exit
exit
define method .FrameExample()
!this.fG.active = FALSE
!this.fH.visible = FALSE
endmethod
define method .showF()
if !this.but.val.eq(TRUE) then
!this.fH.visible = TRUE
!this.but.tag = |Hide Frame|
else
!this.fH.visible = FALSE
!this.but.tag = |Show Frame|
endif
endmethod
When creating a FRAME gadget, for every FRAME there must be an associated EXIT.
If insufficient exits are provided, this will cause an error and the form will NOT LOAD. As the error occurred
in side the FORM DEFINITION, the command line will still be in form definition mode and will not function as
usual.
To exit this mode, type EXIT on the command line until and ERROR is received. This will mean that form
definition mode has been exited and normal commands will work again.
It is good practise to provide 2 spaces when working inside a code block. This provides an easy way to spot
missing exits.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
53
www.aveva.com
10.11.1 Fold Up Panel Frames
This is like a Panel but has a formal title bar, which displays the tag text and provides an icon which can be
clicked to fold-up and hide, or unfold and show the contained gadgets.
Copy out the following into a new file and save it as FoldUPFrameExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!FoldUPFrameExample dialog resizeable
!this.formTitle = |Fold Up Frames|
path down
frame .tabset1 foldup 'Frame Active' anchor ALL wid 25 hei 5
text .text1 'Text 1' width 10 is STRING
text .text2 'Text 2' width 10 is STRING
text .text3 'Text 3' width 10 is STRING
text .text4 'Text 4' width 10 is STRING
exit
frame .tabset2 foldup 'Frame Not Active' anchor ALL wid 25 hei 3
button .butt1 |Normal|
button .butt2 |Green| backg 5
exit
exit
define method .FoldUPFrameExample()
!this.tabset1.expanded = true
!this.tabset2.expanded = false
endmethod
10.12Textpane Gadgets
A TEXTPANE gadget provides an area on a form into which a user may edit multiple lines of text and
cut/paste from elsewhere on the PML screen. The inputted value is stored as an ARRAY of STRINGS and
can be set and read from the gadget.
Copy out the following into a new file and save it as TextpaneExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!TextpaneExample
!this.formTitle = |Textpane|
!this.initCall = |!this.init()|
text .txt1 call |!this.append()| width 30 is STRING
textpane .txtp |Compiled text| at x 0 ymax wid 40 hei 5
button .but1 |Swop Line| at xmax - size y 0 call |!this.swop()|
exit
define method .init()
!this.txt1.val = |Enter a STRING to swop|
do !I from 1 to 10
!val[!I] = |Text on Line Number | & !I
enddo
!this.txtp.val = !val
endmethod
define method .swop()
!lineNO = !this.txtp.curPos()
!line = !this.txtp.line(!lineNo[1])
!this.txtp.setLine(!lineNo[1], !this.txt1.val)
!this.txt1.val = !line
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
54
www.aveva.com
This example will demonstrate that the TEXTPANE has some useful built-in methods for extracting
information. A TEXTPANE cannot be assigned a callback, but cursor position can be derived (or set).
Select a line on the TEXTPANE and press the button to set the value of the line.
10.13Option Gadgets
An OPTION gadget offers a single choice from a list of items. It may contain either PIXMAPS or STRINGS,
but not a mixture. The gadget displays the CURRENT choice in the list. When the user presses the option
gadget, the entire set of items is shown as a drop-down list and the user can then select a new item by
dragging cursor to the option required.
The width of a text option gadget must be specified. A tag name is optional and is displayed to the left of the
gadget. The available options is stored as an ARRAY of STRINGs as the gadgets DTEXT or RTEXT and
can be updated by altering this array.
Copy out the following into a new file and save it as OptionExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!OptionExample
!this.formTitle = |Options|
option .opt1 |Normal| at 0 0 width 7
option .opt2 |Pixmap| at xmax.opt1 y 0 pixmap width 16 height 16
exit
define method .OptionExample()
!dtext[1] = |Red|
!dtext[2] = |Yellow|
!dtext[3] = |Green|
!dtext[4] = |Cyan|
!this.opt1.dtext = !dtext
do !I from 1 to 4
!files[!I] = |/c:temppmllibimages| & !I & |.gif|
enddo
!this.opt2.dtext = !files
!this.opt2.rtext = !dtext
endmethod
Try querying the Rtext of the pixmap gadget by using a built-in gadget method:
q var !!OptionExample.opt1.selection()
q var !!OptionExample.opt2.selection()
10.14Toggle Gadgets
TOGGLE gadgets are used for independent on/off settings. This means they are used in situations where
the user has two choices i.e. is it bold or not? Is it on or off? A toggle will return a BOOLEAN state under is
val member, but can also store different descriptions for selected and unselected.
Copy out the following into a new file and save it as ToggleExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!ToggleExample
!this.formTitle = |Toggles|
path right
toggle .tog1 |Normal| call |!this.state(!this.tog1)|
toggle .tog2 |Changed States| call |!this.state(!this.tog2)| states |NO| |YES|
exit
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
55
www.aveva.com
define method .state(!gad is GADGET)
if (!gad.val) then
q var !gad.onvalue
else
q var !gad.offvalue
endif
endmethod
10.15Radio Gadgets
A RADIO GROUP is used to give a user a single choice between a small fixed number of choices. Two
objects can be used to define a radio group: RGROUP or RTOGGLE. An RGROUP element defines the
entire object and the tags contained; an RTOGGLE is contained within a normal FRAME object. An
RGROUP object has been superseded by the RTOGGLE, but both methods are still valid
RGROUP objects can be displayed vertically or horizontally. RTOGGLE objects can be arranged within a
FRAME as required and can be placed alongside other gadgets.
Copy out the following into a new file and save it as RGroupExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!RGroupExample
!this.formTitle = |Radio Groups|
rgroup .vert |RGroup| FRAME vertical callback |!this.rg(!this.vert)|
add tag |Left| select |L|
add tag |Centre| select |C|
add tag |Right| select |R|
exit
frame .rtog |RToggle| at xmax + 1 y 0
path down
rToggle .left |Left| states || |L|
rToggle .cen |Centre| at ymax – 0.5 states || |C|
rToggle .righ |Right| at ymax – 0.5 states || |R|
exit
exit
define method .RGroupExample()
!this.rtog.callback = |!this.rt(!this.rtog)|
endmethod
define method .rg(!gad is GADGET)
q var !gad.val
q var !gad.selection()
endmethod
define method .rt(!gad is GADGET)
q var !gad.val
!rtog = !gad.rtoggle(!gad.val)
q var !rtog.onvalue
endmethod
Notice the appearance of the two gadgets are very similar
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
56
www.aveva.com
10.16Form Member Variables
As a FORM is an OBJECT, it may be given MEMBERS. These will be used to store data, effectively created
global variables. The benefit of this method is that data is global without having large numbers of individual
variables.
Form members replaces the previous method of USERDATA (PML1 style data storage), and are given a
PML data type. These variables have the same lifetime as the form and are deleted when the form itself is
unloaded.
The below example shows how the concept of a CE button is implemented (used on AVEVA standard
forms). The CE is set when the form is shown, and does not update until the CE button is pressed.
Copy out the following into a new file and save it as FmemExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files
setup form !!FmemExample
!this.formTitle = |Form Members|
!this.initcall = |!this.init()|
button .ce |CE| callback '!this.init()'
para .ceName width 30 hei 1
member .ceRef is DBREF
member .Storage is ARRAY
exit
define method .init()
!this.ceRef = !!CE
!this.ceName.val = !!CE.FLNN
!this.Storage.append(!this.ceRef)
endmethod
Test the members by typing q var !!FmemExample.ceRef or q var !!FmemExample.Storage
10.17Tooltips
Tooltips are small help boxes which pop up when you move the mouse over an active gadget.
The following gadgets can have a tooltip defined:
Button
Text
Toggle
Option
An example of creating a tooltip: BUTTON .B1 |SAVE| PIXMAP TOOLTIP |Save Work|
Refer to the correct Syntax Graph from the PDMS Software Customisation Reference Manual for more
info.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
57
www.aveva.com
10.18Progress Bar
The application main window now has an inbuilt progress indicator in the status bar along its base. This can
be accessed from PML via methods on the FMSYS object.
Method Name Result Purpose
Progress( ) real Get the current Integer value in percent shown by the progress bar, in the range 0 to 100.
Zero means the bars is invisible.
SetProgress( !percent ) no result Set the Integer value in percent to be displayed in the progress bar. Values
will be forced into the range 0 to 100.
Resultant value of 0 will cause the bar to become invisible.
setup form !!ProgressBar
!!ProgressBar.formtitle = |Progress Bar|
button .DoIt ' Show Progress ' Call |!this.doit()|
exit
define method .DoIt()
!!FMSYS.setProgress(0)
do !cou from 1 to 100
!!FMSYS.setProgress(!cou)
enddo
!!FMSYS.setProgress(0)
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
58
www.aveva.com
Exercise 6(a) - Calculation methods
Create a basic calculation form that will performance a temperature conversion. The form will allow the user
to enter a temperature value and specify a type, then the form shall convert it. The converted temperature
should then be displayed to the user.
Supply a TEXT and RADIO GROUP gadget for the user to enter the input values and a TEXT gadget for the
results.
Also provide a PARAGRAPH gadget to provide the user with the type of the converted temperature. The
displayed text of this paragraph gadget will change depending on the input temperature type.
You should organise the input and output gadgets into FRAME gadgets and given them the same width and
height.
Write a method that will convert the inputted value into the required output. The CALLBACK on both input
gadgets shall call this method. By doing this, the output value will be calculated if either input gadget is
used. The equations you will need are as follows
°C = ( °F x 1.8 ) + 32
°F = ( °C – 32 ) / 1.8
The required method needs to know the unit of the input value so the correct equation can be used.
Only one equation needs to be used at a time.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex6a.pmlfrm and show it on the command line by typing
show !!ex6a (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
59
www.aveva.com
Exercise 6(b) - Loops
This exercise will expand the form created in exercise 6a by adding another calculation. The new
calculation will take a RANGE of temperature values (in °C) as an input and fill in a TABLE with the
equivalent °F values.
Three TEXT gadgets (min value, max value and step size) shall be provided for user input. The output
should be a LIST gadget with the headings No., Centigrade, Fahrenheit.
You may wish to add a fourth column (between the two temperature values) that will contain an ‘=’ symbol
Create another two FRAME gadgets to contain the new gadgets and ensure that they are the same width as
the previous frames and that new ones are the same height. Check that the gadgets are aligned.
When defining the LIST gadget, we need it to fill the FRAME that contains it. What method is available to
do this that saves us having to define its size?
Write a CONSTRUCTOR method that will set the headings of the LIST gadget and will set some default
values in the other gadgets.
Add a method to take the input values and fill in the list. This method should loop through the range of input
values to compile an ARRAY. Once the ARRAY OF STRINGS has been defined, use the .setRows()
method to add it to the list. Add a BUTTON that will call this method and fill in the table
A FORMAT object could be used to round any calculated value. It can be referred to when setting the
type of the TEXT gadget, or when converting a REAL to a STRING
You could also add a method to check the input values to ensure they are valid:
e.g. Should the min value be greater than the max value?
Should a value be less than -273?
Should the step size be equal to zero?
These checks could be carried out when the user enters the values. If the values are incorrect, what would
be a suitable response (i.e. error message, auto correction)?
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex6b.pmlfrm and show it on the command line by typing
show !!ex6b (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
60
www.aveva.com
Exercise 6(c) – Concatenation
This exercise will use a TEXTPANE gadget to store information entered by the user and append it to the
data already collected.
Add two new FRAME gadgets to the bottom of the form created in exercise 6b. The input FRAME should
hold three TEXT gadgets allowing the user to enter a value for Input Temp., Safe Temp, and Range. The
output frame should be filled with a TEXTPANE gadget.
Write a method which reads the inputted values, collects them into a single string and appends them to the
textpane gadget. The form of the collected string shall be:
1. 100°C is 212°F - 15°C/59°F - ABOVE safe range
Where 1. is the line number, 100 is the Input Temp, 15 is the amount the input temp is outside the safe
temperature range and ABOVE safe range is a statement about the number. The Fahrenheit numbers are
converted from the centigrade values.
Modify the existing temperature conversion method so that it can be used for the above calculation. The
modified method should still work for exercise 6a.
Inputted values and calculated values are to be compiled into a single string. The format of any calculated
value may need to be set before adding to the string. After creating this string, append it to the current
TEXTPANE value. Add a BUTTON gadget to carry out this method.
A method is needed to empty the TEXTPANE so that new information can be inserted. This does not
necessarily need a new user-defined method. Most gadgets have a default .clear() method which can be
called. Add a BUTTON that clears the TEXTPANE.
A TEXTPANE gadget can be selected, copied, edited on the form by the user. This means that
individual lines or whole gadget can be manually cleared. Try selecting the contents of the gadget and
pressing delete!
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex6c.pmlfrm and show it on the command line by typing
show !!ex6c (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
61
www.aveva.com
Exercise 6(d) – String manipulation
This exercise will look at string manipulation and how available methods can be used together to carry out a
number of steps in a single line of code. The form will continue from the form created in exercise 9.
Add another two FRAME gadgets, both with two TEXT gadgets. In the input frame the user will be asked to
enter an input string and a delimiting character. The output boxes will return a modified string value and the
number of delimiters encountered.
The input string shall be a number of centigrade values, separated by a single character e.g.
10°C/30°C/20°C/5°C
The method shall modify the string in the following steps:
• Split the string based on the delimiter
• Count how many temperature values are being converted
• Remove the °C characters
• Convert the remaining number to Fahrenheit
• Compile all the converted values in order, including °F and separated by a space.
Add a BUTTON to the form that carries out this method
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex6d.pmlfrm and show it on the command line by typing show
!!ex6d (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
62
www.aveva.com
Exercise 7 – Storing and resetting defaults
This exercise shall use a form member to store default values so that the user of the form can reset any
values entered. The user should also be able to update the values.
Add two new BUTTON gadgets to the form: an APPLY and a RESET
Add a MEMBER to the form that will store the values for the INPUT TEXT gadgets as an ARRAY.
Write a method that if the user presses the RESET button, the values from the member will be transferred to
the input text gadgets. The APPLY button should overwrite the values in the member with the values from
the text gadgets.
Methods can accept input arguments. This can be used to identify which gadget called the method,
meaning that one user-defined method could be produced for the above
ARRAYs of information can be of one variable type (e.g. STRING). Values may need to be converted
before being stored.
Consider how the user would use this method. Add some appropriate checks/error handling to ensure that
the desired results are achieved.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex7.pmlfrm and show it on the command line by typing show
!!ex7 (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
63
www.aveva.com
10.19Open Callbacks
An OPEN CALLBACK is a means of providing change information about the gadget the user is interacting
with. It means that for every change, the callback will be called.
Two pieces of information are passed during an open callback (1) the name of the gadget being altered and
(2) a keyword (as a STRING). These keywords indicate the event which caused the callback. Different
keywords will be generated by different gadgets, under different circumstances e.g. a multi – selection
gadget may have a ‘SELECT’ ‘UNSELECT’, as well as the more standard ‘START’ ‘STOP’
PDMS recognises an open callback if a method only has one bracket e.g. call |!this.opencall(|
For an open callback to work, there must be an appropriate method defined. An open callback method must
be able to accept two arguments (1) the gadget and (2) the keyword
e.g. define method .opencall(!a is GADGET, !b is STRING)
As the method is called at every significant event, the open callback method should be written to recognise
keywords.
The following example shows how an open callback can be used on a SLIDER gadget to update a TEXT
gadget. It shows how an open callback can change its method based on a different event keyword. In this
case, the MOVE events are counted then written to the text gadget once a STOP event is encountered.
Copy out the following into a new file and save it as OpenCallExample.pmlfrm. Put the file into the
appropriate file path c:pmltrainingpmllibforms and remap the files
setup form !!OpenCallExample
!this.formTitle = |Open Callback|
slider .slide anchor L+R horizontal range 0 100 step 5 val 50 wid 30
text .text |Value of slider| at xmax - size ymax + 1 anchor B+R wid 5 is REAL
text .moves |Number of moves| at xmax.text - size ymax anchor B+L wid 5 is REAL
member .store is REAL
exit
define method .OpenCallExample()
!this.slide.callback = |!this.slideMove(|
!this.moves.val = 0
!this.store = 0
!this.text.val = !this.slide.val
endmethod
define method .slideMove(!gad is GADGET, !val is STRING)
!this.text.val = !gad.val
!this.text.refresh()
if !val eq |MOVE| then
!this.store = !this.store + 1
elseif !val eq |STOP| then
!this.moves.val = !this.store
!this.store = 0
endif
endmethod
The .refresh() method has been applied to the .text gadget to ensure its value updates as the slider is
moved. The number of moves is stored as a member of the form. This saves a new global variable from
being defined and means the increasing value can be shared between the open callbacks.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
64
www.aveva.com
An open callback can be given to any gadget that accepts a callback. Different gadgets may generate
different event keywords
Exercise 8 – Tabsets and Open Callbacks
This exercise will take the form from exercise 7 and add tabs to it. The input and output FRAME elements
from the previous form should now be converted to tabs.
Remove all the form buttons from within the frames. These methods shall now be called when the
RESULTS tab is SHOWN. To do this there should be an OPEN CALLBACK on the RESULTS tab. The
open callback will report the status of the tab and when it is ‘Shown’, a method will call all the conversions so
that the RESULTS tab is filled in.
Remember: Callbacks can only be applies to a frame during the constructor method
Instead of a CLEAR LIST button, why not modify the Temperature Check method so that if the user leaves
the Input Temp. value UNSET, the list is cleared.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex8.pmlfrm and show it on the command line by typing show
!!ex8 (after typing pml rehash)
An example of the completed form can be found in Appendix B
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
65
www.aveva.com
10.20Bar Menus
Forms may have a bar menu gadget which appears as a row of options across the top of the form. A bar
menu is defined within form definition and specifies the options the user has to choose from. There are
three types that can be added:
Choose – displays a user-defined menu object
Window – displays a list of the open forms
Help – displays the standard help options
After the bar command, use the built-in method .add() to add extra options to the bar menu. E.g.
bar
!this.bar.add(|Choose|,|Menu1|)
!this.bar.add(|Window|,|Window|)
!this.bar.add(|Help|,|Help|)
Bar menus can only be added to forms which are not dockable
Menu1 is a menu object which has been created by adding it to the bar object. Other references to MENU
objects will require the MENU object to have been defined.
10.20.1 Defining a Menu Object
Within the form definition the menu sub-command creates a named menu object. You can then use the
menu’s .add() method to add named menu fields. A menu field can do one of three things:
Execute a callback
Display a form
Display a sub-menu
You can also add a visual separator between fields.
!menu = !this.newmenu(|Menu1|, |MAIN|)
!menu1.add(|CALLBACK|,|Query|,|q ban|)
!menu1.add(|FORM|,|Hello…|, |hello|)
!menu1.add(|SEPARATOR|)
!menu1.add(|MENU|,|Pull-right1|,|Pull1|)
This creates a menu called menu1 with 3 fields - Query, Hello… and Pull-right1 with a separator between
the last two fields
The Query field when picked will execute the callback command ‘q ban’
The Hello... field when picked will load and display the form !!hello. By convention, the text on a menu field
leading to a form ends with three dots, which you must include with the text displayed for the field.
The SEPARATOR, usually a line, will appear after the previous field.
The Pull-right1 field when picked will display the sub-menu !this.Pull1 to its right. A menu field leading to a
sub-menu ends with a > symbol: this is added automatically.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
66
www.aveva.com
67
www.aveva.com
CHAPTER 11
11 PML Objects
11.1 Built in PML OBJECT Types
There are a large number of standard objects within PML2.
These are All Variable types, BORE, DIRECTION, DBREF, FORMAT, MDB, ORIENTATION, POSITION,
FILE, PROJECT, SESSION, TEAM, USER, ALERT, FORM, all form Gadgets and various graphical aid
objects.
Each object has a set of built in methods for setting or formatting the object contents.
ARRAY - Arrays can contain any data types including other arrays and can be sparse
BLOCK - Blocks are used to store commands for a special form of working on arrays. The
block contains a list of commands and “block Evaluation” is used to perform the
actions on an array
BOOLEAN - Boolean is true or false 0 and 1 will not do!
FILE - File is in principle a file name, but the file object contains built in methods for
working on the file.
OBJECT -
REAL - Real is a number. There is no integer!
STRING - String is a text string in quotes’ ‘ or vertical bars | |
DATETIME - returns current Date and Time information
BANNER
BORE - a bore object is a single variable which only accepts bore input. The purpose of a
bore only object is to allow bore units to be dealt with implicitly. Setting a bore unit
!bore = 80 does not work
DB - a DB object is an object representing a database. Can be used to interrogate
information about type, team, access, claim type
DBREF - a dbref object a ref to a database it has members(access, file, name, number,
foreign, type, description, claim(string) and team(team))
DBSESS
DIRECTION - a Direction object has members (direction, origin(dbref), up, east, north(real))
MACRO
MDB - MDB object has members (name and description, both string)
ORIENTATION - an orientation object has members(alpha(real), origin(dbref), Gamma and
beta(reals))
POSITION - a position object has members(origin(dbref) up, east, north(reals)
POSTUNDO
PROJECT - a project object has one member (evar(string))
SESSION
TEAM - a team object has members (name and description(reals))
UNDOABLE
USER - a user object has members(access, name, description(strings))
FORMAT - Format is a way of formatting data for example metric or imperial]
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
68
www.aveva.com
11.2 Forms and Menus Objects
ALERT
BAR
BUTTON
COMBOBOX
CONTAINER
FMSYS
FORM
FRAME
LINE
LIST
MENU
NUMERIC
OPTION
PARAGRAPH
RTOGGLE
SELECTOR
SLIDER
TEXT
TEXTPANE
TOGGLE
VIEW ALPHA
AREA
PLOT
VOLUME
11.3 3D Geometry Objects
ARC
LINE
LINEARGRID
LOCATION
PLANE
PLANTGRID
POINTVECTOR
POSTEVENTS
POSTUNDO
PROFILE
RADIAL GRID
XYPOSITION
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
69
www.aveva.com
11.4 Methods Available to All Objects
The table following lists the methods available to all objects. The table gives the name of each method and
the type of result you get back from it.
The third column of the table describes what the method does.
Name Result Purpose
Attribute( 'Name') ANY To set or get a member of an
object, providing the member
name as a STRING.
Attributes() ARRAY OF
STRINGS
To get a list of the names of
the members of an object as
an array of STRING.
Delete() NO RESULT Destroy the object - make it
undefined
EQ(any) BOOLEAN Type-dependent comparison
LT(any) BOOLEAN Type-dependent comparison
(converting first to STRING if
all else fails)
Max(any) ANY Return maximum of object and
second object
Min(any) ANY Return minimum of object and
second object
NEQ(any) BOOLEAN TRUE if objects do not have the
same value(s)
ObjectType() STRING Return the type of the object as a
string
Set() BOOLEAN TRUE if the object has been given
a value(s)
String() STRING Convert the object to a STRING
Unset() BOOLEAN TRUE if the object does not have
a value
Refer to the Software Customisation Reference Manual for further details.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
70
www.aveva.com
11.5 The File Object
The FILE object is an example of how older functionality has been replaced with a PML2 style object. This
object replaces the old ‘openfile’ ‘readfile’ ‘writefile’ ‘closefile’ syntax and provides increased functionality (file
path, if the file is open etc). it is now possible to Read or Write to a file in a single operation.
To create a file object:
!input = object file(’C:FileName’)
!output = object file(’C:FileName.out’)
To Open a file:
!output.open(’WRITE’) Avaiable options = READ, WRITE, OVERWRITE, APPEND
11.5.1 Using file objects
To read a line from file:
!line = !input.ReadRecord() File must be open
To write a line to file:
!output.WriteRecord(!line) File must be open
To read all the input file:
!filearray = !input.ReadFile() Files are opened and Closed automatically
To write all of the data to file
!output.WriteFile(‘WRITE’,!filearray) Files are opened and Closed automatically
The .ReadFile() method has a default maximum file size which it can read. This can be increased by
passing the method a REAL argument (representing the number of lines in the file)
Copy out the following into a new file and save it as FileExample.pmlfrm. Put the file into the appropriate
file path c:pmltrainingpmllibforms and remap the files
setup form !!FileExample
!this.formTitle = |File Object|
text .txt1 |File Path| call |!this.read()| width 25 is string
para .par1 at x 0 ymax text || width 35
para .par2 at x 0 ymax text || width 35
exit
define method .read()
!file = object file(!this.txt1.val)
!file.open('READ')
!n = 0
do
!line = !file.ReadRecord()
if !line.unset() then
BREAK
else
!n = !n + 1
endif
enddo
!file.close()
!date = !file.DTM()
!this.par1.val = |Number of Lines in file = | & !n & |; File size = | & !file.size()
!this.par2.val = |Date modified = | & !date
Endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
71
www.aveva.com
11.5.2 Use Notepad to open file.
You could use the “syscom” command to open an external program like Notepad, by adding an & to the end
of the line will opens a new process. If you do not use then & PDMS will be suspended until the program is
closed.
!file = object file(|C:temppmllibformsex6a.pmlfrm|)
syscom |c:/WINDOWS/notepad.exe $!file&|
Exercise 9 – Menubar
This exercise will add a menu bar to the form to replace the remaining buttons on the form !!ex8.
Add a MENU BAR to the form. The bar should contain the following:
Control > Close, Seperator, Load Defaults…
Defaults> Update Defaults, Reset to Defaults
Help> (standard help menu)
To close the form, the user will click on Control>Close (replacing the Dismiss button)
To load default values from an external file, the user shall choose Control>Load default files
Defaults>Update Defaults should replace the Apply button and Defaults>Reset to Defaults should replace
the Reset button
Make Control>Load Defaults… call a standard AVEVA function - !!FILEBROWSER. This built in function
can be used to set up the standard AVEVA file browser form and this form can be used to navigate to the
required file. The function call should be in the following form:
call !!fileBrowser(''AAA'', ''BBB'', ''CCC'', DDD, ''EEE'')
Where AAA is the starting file path for the form to open at (e.g. c:); BBB is the required file type (e.g. *.txt);
CCC is a string that will feature at the top of the file browser form; DDD is a BOOLEAN value stating if the
file has to exist; EEE is the callback string for the file browsers OK button. This callback string should call a
method from our form (explicitly referenced) that will read the chosen file.
For example
call !!fileBrowser('c:pmltraining', '.txt', 'Load Defaults', false, '!!ex9.loadFile()')
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
72
www.aveva.com
73
www.aveva.com
CHAPTER 12
12 User-Defined Objects
User Defined Objects can contain any variable or object type as members. Information is grouped with an
object for ease of reference and standard reference.
User-defined objects can also contain user-defined methods that will use the information stored within the
object. These methods may represent a calculation, or information retrieval.
After an object has been declared as a variable, the methods can be applied to the variable. For example:
define object ELEMENT
member .Type is STRING
member .Material is STRING
endobject
define method .FullDesc() is STRING
return !this.Type & ‘ ‘ & !this.Material
endmethod
Once a variable is declared as an ELEMENT object then the method can be applied.
!item = object ELEMENT()
!Item.Type = |Flange|
!Item.Material = |Carbon Steel|
!name = !item.FullDesc()
A method with no arguments but the same name as the type of the object is called the default constructor
method.
More than one method can be given the same name as the object, provide only one has no arguments
Copy out the following into a new file and save it as UserBox.pmlobj. Put the file into the appropriate file
path c:pmltrainingpmllibobjects and remap the files
------------------------------------------------------------------
-- object to hold information about a USERBOX.
------------------------------------------------------------------
define object USERBOX
member .xlen is REAL
member .ylen is REAL
member .zlen is REAL
endobject
define method .USERBOX()
!this.xlen = 0
!this.ylen = 0
!this.zlen = 0
endmethod
define method .USERBOX(!x is REAL, !y is REAL, !z is REAL)
!this.xlen = !x
!this.ylen = !y
!this.zlen = !z
endmethod
define method .volume() is REAL
return !this.xlen * !this.ylen * !this.zlen
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
74
www.aveva.com
endmethod
define method .surfaceArea() is REAL
return !this.xlen * !this.zlen * 2 + !this.ylen * !this.zlen * 2 + !this.xlen * !this.ylen * 2
endmethod
To test this object works, type out the following onto the command line.
!aaa = object USERBOX()
q var !aaa.volume()
<REAL> 0
q var !aaa.surfacearea()
<REAL> 0
!aaa.userbox(10,20,30)
q var !aaa.volume()
<REAL> 6000
q var !aaa.surfacearea()
<REAL> 2200
75
www.aveva.com
CHAPTER 14
13 Collections
A very powerful feature of the PDMS database is the ability to collect and evaluate data according to rules.
There are two available methods for collection (1) PML1 syntax (2) PML2 objects. Both methods are still
valid
13.1 The Collection Syntax (PML 1)
Before typing out the following onto the command line, ensure the STABILISER plant is the CE
var !zone collect all zones for site
var !name eval name for all from !zone
q var !zone !name
var !equi coll all equi with owner eq /EQUIP
q var !equi
!!CE = !equi[1].dbref()
var !box coll all box for ce
var !volume eval (xlen * ylen * zlen) for all from !box
q var !volume
These examples show that elements can be collected, but also evaluated to extract further information
Because this uses the var command, all collected items are STRINGs not DBREFs
13.2 The Object Collection Syntax (PML 2)
Before typing out the following onto the command line, ensure the STABILISER plant is the CE
!equiColl = object COLLECTION()
!equiColl.type(‘EQUI‘)
!equiColl.scope(!!ce)
!expr = object EXPRESSION(|PURP eq ‘PUMP’|)
!equiColl.filter(!expr)
!results = !equiColl.results()
q var !results
For this method to work, a collection object must be declared and used. For the COLLECTION’s .filter()
method to be used, it must be given an EXPRESSION object as an argument.
Using a collection object makes its built-in methods available for users.
Because this uses the collection object, all collected items are DBREFs not STRINGs.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
76
www.aveva.com
Exercise 10 – Equipment Collections
This exercise will create a new form that will act as an Equipment Checker. It will allow user to see
information about the chosen piece of equipment.
Start a blank form and add to it an OPTION gadget (to hold the available pieces of equipment) and a LIST
gadget (to hold the nozzles for the selected piece of equipment). You may wish to put these gadgets inside
a FRAME gadget.
When the user chooses a piece of equipment from the option gadget, the nozzle list shall update showing
the equipment’s nozzles.
Write a method that collects all the EQUI elements for the ZONE of the CE. Try and write the collection part
of the method in a PML 1 style. What happens if no pieces of equipment are found in the ZONE? Call this
method from within the initcall method.
Write a method that runs after the piece of equipment has been chosen. This method should collect all the
NOZZ elements for that EQUI element. Try writing the collection part of the method in a PML 2 style. After
the method has run, set the full names of the collected NOZZ elements to the LIST.
Add a button to the form which updates the available EQUI elements in the option gadget. This will ensure
the form can be updated without having to be reloaded. Make sure that if the OPTION gadget is updated
by the user, the LIST gadget is also updated.
PML 2 collections return DBREF numbers of the collected elements. Do not forget to convert these
values into the full name values before updating the LIST gadget. Use Query>Attributes in Design to
find a suitable attribute.
It is recommended that although the user will wish to see the fullname, it is worth storing the collected
elements. This will allow easier navigation between elements. This could be an opportunity to user the
Dtext/Rtext members.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex10.pmlfrm and show it on the command line by typing
show !!ex10 (after typing pml rehash)
77
www.aveva.com
CHAPTER 14
14 Pop-Up Menus
Pop-up Menu is an MENU objects that are displayed within a gadget by right-clicking on it. This is a useful
method of providing the user with relevant functionality relating to the gadget selected
!menu = !this.newMenu('listPopup')
!menu.add(|callback|, |Find|, |!this.init()|)
!menu.add(|separator|)
!menu.add(|callback|, |Modify...|, |!this.listPopupCallback()|)
!this.eqpl.setPopup(!this.listPopup)
In this above example, a MENU object is defined that contains two callbacks. Find calls the .init() method
(refreshing the form) and Modify calls a specific method.
The MENU object is applied to the LIST gadget (called eqpl) by using the .setPopup() method. This method
can be used whenever it is a valid method of the gadget
Refer to the PDMS Customisation Reference Manual for the available methods for different gadgets
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
78
www.aveva.com
Exercise 11(a) – Pop-up menu
This exercise will develop the form created in exercise 10 by adding a POP-UP menu that will allow the user
to navigate to a selected nozzle.
Define a MENU object for the popup and assign it to the LIST gadget. This menu should call a user-
defined method that will assign the !!CE object with the dbref of the chosen nozzle.
If the collected DBREF() information was stored within the RTEXT member of the LIST gadget it will be
easier to obtain the selected nozzle’s dbref.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex11a.pmlfrm and show it on the command line by typing
show !!ex11a (after typing pml rehash)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
79
www.aveva.com
Exercise 11(b) – Equipment Checking
Extend the form by adding a NOZZLE CHECKING method. This method should look at each of the
collected nozzles and check that various conditions are met. This will provide the user with the information
about the nozzles, quickly highlighting which require further checking.
Write a method that looks at each collected NOZZ element and checks the following:
Is it connected? This can be decided by checking the NOZZ element’s CREF attribute. If the
attribute is unset or the reference is invalid, then the user will have to check that
nozzle
Is it attached? Check the positions of the NOZZ and PIPE elements and if they are different, then
the NOZZ should be checked
Is it aligned? Check the directions of the NOZZ and PIPE elements. If they are different, then
they should be checked
Is it sized correctly? Compare the diameter of the PIPE to the size of NOZZ. If they are different, then
they should be checked.
If the NOZZ is not connected, does the user need to be informed about its alignment? Use the
Query>Attributes form in design to identify the attributes available for use.
Add a BUTTON to refresh the LIST gadget. This button will re-run the nozzle check method after the user
has updated the NOZZ elements.
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex11b.pmlfrm and show it on the command line by typing
show !!ex11b (after typing pml rehash)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
80
www.aveva.com
Exercise 11(c) – Setting Equipment attributes
This exercise will develop the form created in exercise 11b by giving the user the chance to edit some of the
EQUI elements attributes.
Add a TEXTPANE to the form and set the three default attributes as Description, Function and Purpose.
Write a method that reads these attributes from the EQUI element and displays the correct values. This
method should be run every time a new piece of equipment is chosen.
As it is a TEXTPANE gadget, it is possible for users to add additional information to it. We shall use this
feature as part of the method. Extend the method so that values from the TEXTPANE are read and the
EQUIs attributes are updated. The method should also include any additional attributes which the user may
have entered. Add a BUTTON to update the EQUI attributes
This method will have to read each line of the gadget, split it and use the split values to set the
attributes. When a new EQUI element is chosen, attributes values should be read and gadgets text
updated accordingly.
Add error handling methods to cover unknown attributes, or incorrect attribute values. If the user enters an
incorrect attribute, advise the user of this.
Ensure the title of LIST gadget always includes the name of the chosen EQUI
An example of a form which completes the exercise is shown below:
Save the file as c:pmltrainingpmllibformsex11c.pmlfrm and show it on the command line by typing
show !!ex11c (after typing pml rehash)
81
www.aveva.com
CHAPTER 15
15 View Gadgets
VIEW gadgets are named gadgets which are used to display the information from available databases. The
way the information is displayed depends on the VIEW gadget type.
General View Types:
ALPHA views for displaying text output and / or allowing command input.
PLOT views for displaying non-interactive 2D plotfiles.
Application-specific View Types
AREA views for displaying interactive 2D graphical views.
VOLUME views for displaying interactive 3D graphical views.
Refer to the correct VIEW element type in the PDMS Customisation Reference Manual for more
information
15.1 Alpha Views
Save the file as c:pmltrainingpmllibformsAlphaView.pmlfrm and show it on the command line by
typing show !!AlphaView (after typing pml rehash)
setup form !!alphaView
!this.formTitle = |Alpha View|
view .Input AT X 0 Y 0 ALPHA
height 20 width 40
channel REQUESTS
channel COMMANDS
exit
path down
button .Button1 'Apply'
path right
button .Button2 'Dismiss' at xmax form -size
exit
This gadget is the same as is used for the standard command line. It provides information direct from the
current database in text format.
15.2 Plot View Example
Save the file as c:pmltrainingpmllibformsPlotView.pmlfrm and show it on the command line by typing
show !! PlotView (after typing pml rehash)
setup form !!plotView
!this.formTitle = |Plot View|
view .view1 plot width 41 hei 15
exit
exit
define method .plotView ()
!this.view1.borders = FALSE
!this.view1.add(|/C:pmltrainingpmllibformshosewheel.plt|)
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
82
www.aveva.com
A PLOT view can be used to provide the user with extra information. The extra information would be
contained in a .plt file and is applied to the view during the constructor method.
A PLOT view is used within standard PDMS is describe design parameters
15.3 Volume View example
Save the file as c:pmltrainingpmllibformsVolumeView.pmlfrm and show it on the command line by
typing show !!VolumeView (after typing pml rehash)
setup form !!volumeView
!this.formTitle = |Volume View|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Focus on CE', '!this.init()')
view .view3D volume
width 41 height 15
limits auto
isometric 3
exit
button .but |Focus on CE| at xmax form - size ymax call |!this.init()|
exit
define method .volumeView()
!this.view3D.borders = FALSE
!this.view3D.background = |darkslate|
!this.view3D.shaded = TRUE
!this.view3D.projection = |PARALLEL|
!this.view3D.radius = 100
!this.view3D.range = 500.0
!this.view3D.eyemode = FALSE
!this.view3D.step = 25
!this.view3D.setpopup(!this.pop1)
endmethod
define method .init()
!limits[1] = !!CE.wvol[1]
!limits[2] = !!CE.wvol[4]
!limits[3] = !!CE.wvol[2]
!limits[4] = !!CE.wvol[5]
!limits[5] = !!CE.wvol[3]
!limits[6] = !!CE.wvol[6]
!this.view3D.limits = !limits
endmethod
The above example makes use of an attribute WVOL. This is a pseudo-attribute (available for most
elements) that returns the world coordinates for an enclosing box (at world orientation). The value of this
attribute was used to set the limits of the volume view.
Notice: the WVOL array is arranged differently to that required by the Volume Views limits member
The limits of the view are reset everytime the form is shown, or when the button/pop menu are used.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
83
www.aveva.com
Exercise 12(a) – Adding a Volume View
Add a VOLUME VIEW to the form so that users can see the chosen piece of equipment
Add a VIEW gadget to the form and set its type to VOLUME. This view gadget will now act like the main
PDMS 3D window. This means that the drawlist items which are seen in the main window will also be seen
in this gadget. To make the gadget more useful, we want to focus on the piece of equipment chosen on the
form.
Write a method to update the limits of the view to focus on the chosen piece of equipment. This method
should be called everytime a new piece of equipment is chosen.
Refer to the PDMS Software Customisation Reference Manual for the VIEW commands that can be
used.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
84
www.aveva.com
Exercise 12(b) – Adding a Clipbox to the view
Add a CLIPBOX to the volume view created in exercise 12(a). This clipbox shall be sized to the chosen
piece of equipment ensuring the extra elements outside the equipments volume will not be seen.
The key to solving this exercise is to investigate how clipboxes are created. The process is not
documented, but we can investigate how standard PDMS implements clipboxes.
Add a GPHCLIPBOX MEMBER to the form which will store the clipbox definition. This object type was
identified by using the show !!pmlforms form to look at the main PDMS window.
After adding a GPHCLIPBOX as a member to the form, type show !!pmlforms onto the command line.
Check the “only shown forms” toggle and select your form from the top list. At the bottom of the form the
members will be listed. By selecting the GPHCLIPBOX member, its properties are listed. It is these
properties which will hold the clipbox definition (e.g. VIEW is the view gadget the clipbox is linked to;
ACTIVE sets whether it is turned on; BOX holds the dimension information).
Write a method that will calculate the size, position and limits of the clipbox (to ensure it is displayed
correctly). The calculated limits and clipbox should then be applied to the 3D view gadget. The method
should use the chosen equipment as the basis for this calculation and be run every time a new piece of
equipment is chosen.
Add this line to your code CLIP XLENGTH AA YLENGTH BB ZLENGTH CC POSITION DD ORIENTATION
EE, where AA, BB, CC, DD and EE are values the macro shall derived. After this line edit the VIEW gadget
and type clipbox enable
To derive the occupied volume, is there a suitable attribute (or pseudo-attribute) that can be
referenced?
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
85
www.aveva.com
Exercise 12(c) – Dynamically modify a clipbox
The clipbox that was created in exercise 12b was fixed to the dimension of the piece of equipment. What if
the user needs to see nearby items, such as flanges connecting to the nozzles.
Add a SLIDER gadget to the form to allow users to expand/ contract the clipbox as required.
Add an open callback method to the SLIDER to change the values of XLEN, YLEN and ZLEN of the clipbox.
After changing these values the macro should update the VIEW gadget dynamically. Gadgets have a
.refresh() method. Use this method to refresh the VIEW gadget whenever the SLIDER is moved.
Add two TEXT gadgets that will contain the minimum and maximum values for the SLIDER. Add a method
that will allow users to type in new values and update the range of the slider. This is important as EQUI
elements can vary in scale. The step of slider should be calculated from the min and max values
Add a TOGGLE gadget to allow the users to decide whether the VIEW limits are changed by the slider.
Update the slider method to check the status of this toggle.
If the clipbox set larger than the view limits then you will notice that parts of the model will not be displayed
correctly
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
86
www.aveva.com
Exercise 12(d) – Add Nozzle tagging
Add a method for users to tag the nozzles in the VIEW gadget
Add two TOGGLE BUTTONs to the form. One will tag a single nozzle and the other will tag all nozzles.
When a button is selected, items will be tagged and tags will be removed when the buttons are unselected.
Pictures have been provided to make pixmap buttons. Add the following line to the forms constructor
method:
gadget.AddPixmap(!!PML.GetPathName('AAAA’), !!PML.GetPathName(‘BBBB’))
where AAAA is the reference picture for the unselected button and BBBB is for when it is selected. The
!!PML.GetPathName function is a built-in function to derive the file path of the picture. This is useful as it
means the file path does not need to be hard coded.
Write a method that will tag a single nozzle. The nozzle that will be tagged should be the one selected in the
nozzle list. The command to tag an item is as follows:
AID TEXT NUMBER $!NO '$!TAG' AT $!POS
where !NO is a reference number used to identify the tag, !TAG is the text that will be displayed in the tag
and !POS is the position of the tag (bottom left corner).
To remove a tag, we can use a built-in PDMS method. As it is a PML 1 method, we can call it in the
following way:
$m/%PDMSUI%desgraphicsGAIDCLEAR $<AAAA>
where AAAA is the tag reference number. To remove all tags, do not include $<AAAA>.
To remove a single tag, it will need to have a unique reference number
Add a member to the form to keep track of which nozzles are tagged. Add a method to the callback from the
nozzle list to check whether a nozzle is tagged. If the chosen nozzle is already tagged, the method should
make the tag button selected (to allow users to untag).
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
87
www.aveva.com
Exercise 12(e) – Add Highlighting
Provide a way of the user seeing the results of the nozzle check graphically.
Elements in the 3D view can be assigned a colour that will override its auto-colour. Colours are expressed
as numbers.
enhance AAAA col 1
where AAAA is the name of the element to be highlighted and the number after col is a PDMS index colour.
The colours which are able to be used are shown on the AVEVA standard form !!colourselect.
Add a new FRAME gadget to the form and within it create four new BUTTONs. These buttons will display
the highlight colours that will be used to colour the EQUI. The four colours will highlight (1) the piece of
equipment (2) connected nozzles (3) unconnected nozzles and (4) nozzles which the user needs to check
Also add another FRAME within the new one that will hold 50 small coloured buttons. These buttons will
display the colours available to the user. Instead of manually creating these buttons, why not use a DO
loop? Set the visibility of this FRAME to FALSE.
When setting the background colour of these buttons what values should be used. Is there a source that
can be referenced? Perhaps another form?
Add a method to the 4 buttons that will make the colour picker FRAME visible. Add methods to the colour
picker buttons that will apply the colour of the picked button to the button which displayed the colour picker
frame. After the colour has been chosen, hide the colour picker frame again.
Add a PIXMAP TOGGLE BUTTON to the form that will highlight the elements in the view using the specified
colours
To remove the highlight colours, use the following code:
unenhance all
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
88
www.aveva.com
89
www.aveva.com
CHAPTER 16
16 Event Driven Graphics (EDG)
The EDG has been developed to allow a common interface for the AppWare developer to use when setting
up the graphic canvas for graphical selection. This method is relatively simple and easily extendible. This
will allow the developer to concentrate on the development of their own application without the need to know
the underlying mechanism (core implementation) of the EDG interaction handlers and system.
The system handles all the underlying maintenance of the current events stacked e.g. associated forms,
initialisation sequences, close sequences, etc.
The current implementation of the system has mainly been developed for interaction with the 3D graphic
views in the Design module. However, the interface can be used with any of the modules that use the same
executable and the standard 3D graphic views.
EDG supersedes the old ID@ syntax
16.1 Simple EDG
Save the file as c:pmltrainingpmllibformsEDGExample.pmlfrm and show it on the command line by
typing show !!EDGExample (after typing pml rehash)
setup form !!EDGexample
!this.formtitle = |EDG Example|
button .but1 |Pick Element| call |!this.pick()|
exit
define method .pick()
-- define event packet
!packet = object EDGPACKET()
-- define standard element pick
!packet.elementPick(|Pick Element <esc> to finish|)
-- return information about picked item
!packet.action = |q var !this.return[1].item|
-- when finished, doing following
!packet.close = |$p Finished|
-- add the event packet to the EDG object
!!EDGCntrl.add(!packet)
endmethod
The above example shows how information is returned from for the elements picked. The form of the
returned information is dependant on the type of pick that has been used.
Refer to the EDG Interface manual for further explanation
EDG is based around a number of objects with built-in methods. These examples only cover the basic
implementation of EDG. For more in depth information and examples, refer the EDG interface manual.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
90
www.aveva.com
16.2 Using EDG
Copy out the following into a new file and save it as PickEquip.pmlfrm. Put the file into the appropriate file
path c:pmltrainingpmllibforms and remap the files
setup form !!pickEquip
!this.formTitle = |Pick Equipment|
!this.initcall = |!this.init()|
!this.quitcall = |!this.clear()|
button .pick |Start Pick| call |!this.init()|
textpane .txt1 |Picked Equipments| at x 0 ymax width 25 height 10
member .storage is array
exit
define method .init()
!this.clear()
!packet = object EDGPACKET()
!packet.elementPick(|Pick Equipments <esc> to add to list|)
!packet.description = |Identify Equipment|
!packet.action = |!!pickEquip.identify(!this.return[1].item)|
!packet.close = |!!pickEquip.setInfo()|
!!EDGCntrl.add(!packet)
endmethod
define method .identify(!pick is DBREF)
do
if !pick.type.eq(|EQUI|) or !pick.type.eq(|WORL|) then
break
else
!pick = !pick.owner
endif
enddo
if !pick.type.eq(|EQUI|) then
!name = !pick.name
if !this.storage.findfirst(!pick.flnn).unset() then
enhance $!name col 215
!this.storage.append(!pick.flnn)
else
!this.storage.remove(!this.storage.findfirst(!pick.flnn))
unenhance $!name
endif
endif
endmethod
define method .setInfo()
!this.txt1.val = !this.storage
endmethod
define method .clear()
do !i values !this.storage
unenhance /$!i
enddo
!!edgCntrl.remove(|Identify Equipment|)
!this.txt1.clear()
!this.storage.clear()
endmethod
This example shows how a method can take the returned information and use it. In this case, the picked
element type is checked whether it is a piece of equipment. If it is not, the method loops up the hierarchy
until one is found (or the world is reached).
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
91
www.aveva.com
There is a different method for the pick action to the close action. For this reason, the picked elements are
collected a form member. The close method applies the form member to the textpane gadget.
Exercise 13 – Using EDG
This exercise will add Event Driven Graphics to some of the forms created.
Exercise 13(a) – Add EDG to !!ex10
Add a BUTTON to the form that will allow users to identify pieces of equipment in the main PDMS 3D
window. Once they have picked a piece of equipment, that piece of equipment is automatically chosen in
the option gadget and the nozzle list should update.
Add a PIXMAP BUTTON to the form that will run a method initialising the EDG.
Add another method that will be run by the EDG method. This method should do the following steps:
• Turn the EDG event off after something has been chosen
• Identify the type of element chosen
• If an EQUI has been chosen, OK
• Otherwise, loop up the hierarchy to find an EQUI.
• If an EQUI cannot be found, report to the user and re-initialise the EDG
• Find the chosen EQUI in the OPTION gadget and set it to the correct equipment
• Run the nozzle collection method
To remove an EDG instance, use !!edgCntrl.remove(|AAA|), where AAA is the description of the EDG
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
92
www.aveva.com
Exercise 13(b) – Add EDG to !!ex11b
Extend the previous exercise by allowing users to identify either a nozzle or a piece of equipment.
If a piece of equipment is chosen, update the option gadget to that EQUI.
If a nozzle is chosen, make that nozzle selected in the nozzle list.
What happens if the user chooses a nozzle on another piece of equipment?
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
93
www.aveva.com
Exercise 13(c) – Add EDG to !!ex12b
Extend the previous method by allowing users to pick inside the 3D VIEW gadget on the form.
Add a TEXT gadget at the top of 3D view (called .prompt). This will act as the user feedback for the view.
Update the VIEW gadget to make it compatible with EDG. Using !!pmlforms, look at the properties of the
main PDMS 3D window and compare it with the 3D view on the form. The differences should show how the
form’s 3D view should be updated.
Add the VIEW gadget to the EDG event.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
94
www.aveva.com
95
www.aveva.com
CHAPTER 17
17 Miscellaneous
The following sections described some other useful PML actions.
17.1 Recursive Pml2 Functions
PML2 functions may be called recursively. This can be used to produce iterative solvers:
define function !!Fibonacci(!Last is REAL, !Previous is REAL)
!Next = !Last + !Previous
!!ResultArray.Append(!Next)
if (!!ResultArray.Size() LT 100 ) then
-- Here the function calls itself
!!Fibonacci(!Next, !Last)
endif
endfunction
This iterative solver can be used to compile an array of Fibonacci numbers (an increasing series of
numbers, where the next number is the sum of the previous two). These can be used for such things as
Fibonacci rectangles, golden ratio and the value of Phi.
17.2 Undo and Redo
If you build an application that creates or deletes items from the PDMS Database it is good practice to
handle the ability to undo the modifications. Undo is a useful feature that users expect to be able to use.
17.2.1 Marking the database
The undo button goes back to the last database mark or savework so your application should mark the
database before modification.
MarkDB ‘Comment’
The text string is output if the Undodb command is used
17.2.2 Undo and Redo Database Commands
UndoDB - Undo the database back to the last database mark
RedoDB - Redo the last Undo
These actions can be performed by including the above lines within your code. There is also an
UNDOABLE object with built-in methods which can extend this functionality further.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
96
www.aveva.com
17.3 Error tracing
It is possible to list all the commands that PDMS runs when a PML operation is carried out. This list can
either be printed to the command window, or written to an external file.
Type $r109 /c:log.log onto the command line
where c:log.log is the output file name (it shall be created if it does not exist)
Now every PML action will be written to the external file. The file will list every line of code and action
carried out. Lines read will be indicated by a line number in square brackets. Lines not read will be
indicated by a line number between round brackets. Entry and exit points between methods, functions and
objects are indicated as well as any errors.
Type $r110 onto the command line to print the same lines to the command window.
Printing to the screen should only be done when a small number of lines are to be printed. A large
number of lines will take a long time to print to the screen and there is also a limit to the number of lines
which can be contained by the command window. For large operations, print to a file
Once you are finished with error tracing, type $r to the command line.
This will need to be typed before the output file can be opened
97
www.aveva.com
CHAPTER 18
18 Menu Additions
Previous to 11.6, if you required additions to the menus, you copied the FSYSTEM/DBAR files and manually
edited them to add new menus.
Every time a new version of PDMS is released, you have to update any files you have copied.
As part of the .net work, this process has been removed so that no update will be needed in subsequent
versions of PDMS. This process has been replaced with the new ADDIN File syntax.
To add new menus and toolbars to PDMS 11.6 or later, the ADDIN file syntax (FSYSTEM/DBAR) is no
longer valid.
18.1 Miscellaneous Notes
To find out the menus currently contained within a model, use q var !!appcatmain for Paragon and q var
!!appdesmain for Design.
More examples can be found in directory pmllib/design/objects. All the add-in application objects begin with
the letters app****.pmlobj e.g. appaccess.pmlobj.
Forms with menus cannot be docked.
18.2 Modules that use the new Addins functionality
Addins are available in modules that have a form named appxxxmain.pmlfrm where xxx is the module such
as des, cat, dra etc. These modules are Design (des), Draft (dra), Paragon (cat) and Spooler.
The spooler form is named spooler.pmlfrm but still uses addins.
Isodraft currently uses the old FSYSTEM and cannot use addins.
Admin and Monitor use separate forms named adminapplic.pmlfrm and monitormain.pmlfrm and also cannot
use addins.
18.3 Adding a Menu/Toolbar
For a file created in %PDMSUI%DESADDINS directory, the name doesn’t matter, except for identification.
The file will contain similar information to the old applications file in %PDMSUI%
This file is used for menu additions, new toolbars and standard application switching
18.4 Application Design
Below is an example of an ADDIN file which is used to load the Equipment application within design. Notice
how the file only contains a number of file references. The addin file is automatically run by PDMS, so
whatever this file references will also be run.
name: EQUI
directory: EQUI
showOnMenu: TRUE
object: appEqui
title: Equipment
callback: CALLE XEQUIAPP
synonym: CALLE
startup: $M /%PDMSUI%DESEQUIINIT
Macro to call when the menu is selected
Synonym to call equipment macros
Macro to run on startup of the EQUI
application (for the first time)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
98
www.aveva.com
18.5 Form and Toolbar Control
Forms are controlled using the APPFORMCNTRL object. Forms can be registered to:
Appear only in certain applications
Be reshown when PDMS restarts (serialisation)
!!appFormCntrl.registerForm(!form is FORM)
Toolbars are controlled using the APPTBARCNTRL object: to avoid having too many toolbars on screen,
each is enabled only when the user is in the right application.
Users can add more forms/toolbars to these control objects, and those items will be shown to the user.
18.6 Converting Existing Applications
For users upgrading from the FSYSTEM/DBAR method, it is possible to transfer your existing files to the
ADDIN syntax:
Existing application has an entry in the PDMSUI%DESDFLTSAPPLICATIONS file
New application has an add-in definition file in %PDMSUI%DESADDINS
OLD
# Equipment Application
ApplicationDirectory: EQUI
Title: Equipment
Form: _CDEQUIAPP
Callback: CALLE XEQUIAPP
Synonym: CALLE
NEW
Name: EQUI
ShowOnMenu: TRUE
Directory: EQUI
Title: Equipment
Object: APPEQUI
Callback: CALLE XEQUIAPP
Synonym: CALLE
Startup: $M /%PDMSUI%DESEQUIINIT
Previously, the main form was swapped when changing application. Existing applications defined menus
and toolbars in the DBAR macro, which was called from the FSYSTEM macro. Now the main form stays the
same and menus are shown and hidden as needed. Menus and toolbars are defined in an add-in object.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
99
www.aveva.com
18.6.1 DBAR and Add-in Object
The contents of the ADD-IN object and the DBAR macro are very similar. The difference is the syntax used.
18.6.2 Bar Menu and Toolbar
Add to bar menu
OLD
label /BAR
add |Position| _POSITION
add |Orientate| _ORI
add |Connect| _CONN
return
NEW
define method .barMenu()
!bmenu = object APPBARMENU()
!bmenu.add('Position', 'POSITION')
!bmenu.add('Orientate', 'ORI')
!bmenu.add('Connect', 'CONN')
!!appMenuCntrl.addBarMenu(!bmenu, 'EQUI')
endmethod
18.6.3 Define toolbar
OLD
label /DATA
-- define buttons
-- for toolbar
return
NEW
define method .toolbars()
frame .equiToolbar toolbar 'Equipment Toolbar'
-- define buttons for toolbar
exit
!!appTbarCntrl.addToolbar('equiToolbar', 'EQUI')
endmethod
18.6.4 Adding to Menus
OLD
label /CREATE
add sep
add |Equipment...| FORM _CDEQUI
add |Sub-Equipment...| FORM _CDSUBEQ
add |Primitives...| FORM _CDPRIM
add |Standard...| form !!equCreateStd
NEW
define method .createMenu()
!menu = object APPMENU('sysCrt')
!menu.add('SEPARATOR')
!menu.add('FORM', 'Equipment...', 'CDEQUI',
'equiEquipment')
!menu.add('FORM', 'Sub-Equipment...', 'CDSUBEQ',
Add to bar menu
Add to Create menu
Define toolbars
Add new menus to
form
DBAR macro ADD-IN object
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
100
www.aveva.com
return 'equiSubEquipment')
!menu.add('FORM', 'Primitives... ', 'CDPRIM',
'equiPrimitives')
!menu.add('FORM', 'Standard... ', 'equCreateStd',
'equiStandard')
!!appMenuCntrl.addMenu(!menu, 'EQUI')
endmethod
18.6.5 Adding new menus to form
OLD
label /MENU
menu _POSITION
add |Explicitly (AT)...| |!!pos3DExplicit()|
add |Relatively (BY)...| |CALLIBD
X3DPOSR|
add |Move| MENU _MOVE
add |Drag| MENU _DRAG
add |Plane Move| MENU _PLMOVE
add SEPARATOR
add |Equipment Point| MENU _PPEAT
exit
…
return
NEW
define method .menus()
!menu = object APPMENU('POSITION')
!menu.add('CALLBACK', |Explicitly (AT)...|,
|!!pos3DExplicit()|, 'Explicitly')
!menu.add('CALLBACK', |Relatively (BY)...|, |CALLIBD
X3DPOSR|, 'Relatively')
!menu.add('MENU', |Move|, 'MOVE', 'Move')
!menu.add('MENU', |Drag|, 'DRAG', 'Drag')
!menu.add('MENU', |Plane Move|, 'PLMOVE',
'PlaneMove')
!menu.add('SEPARATOR')
!menu.add('MENU', |Equipment Point|, 'PPEAT',
'EquipmentPoint')
!!appMenuCntrl.addMenu(!menu, 'EQUI')
…
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
101
www.aveva.com
18.7 Example object including toolbars, bar menus and menus
This is only an example showing adding toolbars, bar menus and menus. The effect of this object will be to
add a new toolbar and main menu. It will also add some extra menu options to the EQUI application,
including some under the Utilities menu. It will demonstrate how user-defined forms/functions/callbacks can
be added to the PDMS menu system.
The methods .modifyForm() and .modifyMenus() run automatically, so can be used to call the objects
methods.
Type out the following and save it as appcompa.pmlobj
define object APPCOMPA
endobject
------------------------------------------------------------------
-- Method: .modifyForm()
-- Description: Standard method
-- Makes modifications to the main form
------------------------------------------------------------------
define method .modifyForm()
!this.toolbars()
endmethod
-----------------------------------------------------------------
-- Method: .modifyMenus()
-- Description: Standard Method
-- Runs all other menu creation methods
-----------------------------------------------------------------
define method .modifyMenus()
!this.barMenu()
!this.menus()
!this.specificMenus()
!this.UtilsMenu()
endmethod
------------------------------------------------------------------
-- Method: .UtilsMenu()
-- Description: Adds to the Utilities menu in the EQUI application
------------------------------------------------------------------
define method .UtilsMenu()
!menu = object APPMENU('SYSUTIL')
!menu.add('SEPARATOR')
!menu.add('CALLBACK', |EQUI Form A...|, |$p Form A|)
!menu.add('CALLBACK', |EQUI Form B...|, |$p Form B|)
!!appMenuCntrl.addMenu(!menu, 'EQUI')
endmethod
-------------------------------------------------------------------
-- Method: .toolbars()
-- Description: Creates toolbar for all applications
-------------------------------------------------------------------
define method .toolbars()
frame .MyFormToolbar toolbar 'CompanyA Toolbar'
!iconSize = !!comSysOpt.iconSize()
!Pixmap1 = !!pml.getPathName('createpipe-' & !iconSize & '.png')
!Pixmap2 = !!pml.getPathName('exclamation-' & !iconSize & '.png')
button .but1 'Show Form A' tooltip 'Show Company Form A' $
pixmap /$!<Pixmap1> width $!iconSize height $!iconSize callback |$p Form A|
button .but2 'Show Form B' tooltip 'Show Company Form B' $
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
102
www.aveva.com
pixmap /$!<Pixmap2> width $!iconSize height $!iconSize callback |$p Form B|
exit
!!appTbarCntrl.addToolbar('CompAToolbar', 'ALL')
endmethod
------------------------------------------------------------------
-- Method: .barMenu()
-- Description: Adds options to the bar menu for all applications
------------------------------------------------------------------
define method .barMenu()
!bmenu = object APPBARMENU()
!bmenu.add(|Company A|, 'CompAMenu')
!!appMenuCntrl.addBarMenu(!bmenu, 'ALL')
endmethod
------------------------------------------------------------------
-- Method: .menus()
-- Description: Creates menus to the bar for all applications
------------------------------------------------------------------
define method .menus()
!menu = object APPMENU('CompAMenu')
!menu.add('CALLBACK', |Company Form A...|, |$p Form A|)
!menu.add('CALLBACK', |Company Form B...|, |$p Form B|)
!!appMenuCntrl.addMenu(!menu, 'ALL')
endmethod
------------------------------------------------------------------
-- Method: .menus()
-- Description: Creates menus to the bar for specific applications
------------------------------------------------------------------
define method .specificMenus()
!menu = object APPMENU('CompAMenu')
!menu.add('SEPARATOR')
!menu.add('CALLBACK', |EQUI specific form...|, |$p EQUI specific|)
!!appMenuCntrl.addMenu(!menu, 'EQUI')
endmethod
To call the above object, copy out the following into a new file called COMPA (no file extension) and save it
into %PDMSUI%desaddins. Update %PDMSUI% in PDMS.bat if not done already.
name: COMPA
title: Company A app
showOnMenu: FALSE
object: APPCOMPA
Where Name is the unique id for user and addin code
Title is the text description of the add-in
ShowOnMenu determines whether the add-in has an entry on the Applications menu, i.e. whether the add-in
defines an application (false by default). If it were an application addin like MDS this would be TRUE.
Object is the object file that is used to define the menu/toolbar additions.
These are some optional lines that can be included. Callback (typically CALLE XEQUI Macro to call when
the menu is selected) Startup (typically $m/%pdmsui%/des/equi/init Macro to run on startup of the equi app
(for first time)) ModuleStartup ( the callback run when the PDMS module first starts) StartupModify (Name
of application to modify and the callback run when an application is first started, separated by a colon.e.g.
EQUI:!!equiAppStartupCall()) SwitchModify (Name of application to modify and the callback to run when the
application is switched to, separated by a colon. e.g. PIPE:!!pipeAppSwitchCall() )
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
103
www.aveva.com
To add a startup macro to more than one application, add more entries into the add-in file typically:-
SwitchModify:EQUI:!!equiAppStartupCall()
SwitchModify:PIPE:!!equiAppStartupCall()
SwitchModify:GEN:!!equiAppStartupCall()
The following keys are only used for applications, i.e. add-ins that have a menu option on the Applications
menu and can be switched to.
Menu Entry for application on the applications menu (the title is used if this isn’t specified)
Directory Name of the application directory under %PDMSUI%module
Synonym Synonym created for the directory (only used if the directory is specified)
Group Group number (applications with the same group number are put into a submenu together)
GroupName Description of submenu to appear on main menu
Exercise 14 – Add a Utility and Toolbar menu
Create some additional menus that will sit within the Equipment application and allow you access to your
forms.
Create an addin file that will point to the definition of the new menus. Call your file PML (with no file
extension) and save it to %pdmsui%/des/addins.
Create a file named apppml.pmlobj containing four methods:
.UtilsMenu()
.toolbars()
.modifyMenus() - calling .UtilsMenu()
.modifyForm() - calling .toolbars()
Add two new menus (Calculator and Equipment Checker) to the Utilities drop down menu in the Equipment
application (see the above picture). To each of these menus add a further sub-menu that lists the forms you
have created. Define these menus in the .UtilsMenu() method
Add a toolbar to the .toolbar() method. This toolbar should be titled ‘PML’ and contain two
buttons that will open two of your forms. You may wish to use pixmap buttons (with the images
provided)
When you have completed and saved apppml.pmlobj, type PML REHASH ALL into the command line, then
type Design. This will reload the design session and you should see the additions you have made.
Please note that even a simply spelling mistake in the above exercise can prevent design from loading
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
104
www.aveva.com
If Design fails to load, do the following:
Read the error message in the command window and action appropriately
If objects are “not found”, check the file paths and type PML REHASH ALL
Once the error has been fixed, type DESIGN onto the command line and Design should load.
If typing DESIGN generates an error, the command line is still in setup mode and needs exiting – type EXIT
To close the command line, type FINISH
105
www.aveva.com
CHAPTER 19
19 Upgrading from PML1 to PML2
19.1 Points to watch out for
Only Algebraic expressions are allowed, (No reverse-polish notations after “=“ sign)
Creating numeric variable with “=“ creates a REAL
Some PML1 macros using the “=“ will now create variables of the wrong type.
VAR !name value will now create a STRING value.
DO variables are now REAL rather than STRING
If “=“ has been used in existing PML code and problems are found, re-write the code using PML2
technology, or revert to PML1 VAR technology.
Conversion utility “eq2var” (Currently runs through an “awk” script)
DO variables in PML2 are automatically deleted to ensure that they can be created, This can upset other
variables if of the same name.
On exit DO variables remain REAL; previously they would have been STRING
+1 if loop ran to completion.
Variable in “do values” is deleted on exit.
DO from to are required to be REAL, Existing macros are unaffected by this ($)
Change variable names to avoid DO variables
Check DO expressions, re-write as necessary
Results of an expression in IF must be TRUE or FALSE.
An error will occur where ZERO=FALSE
e.g. if ($value) then - - (PML1)
will have to be either if ($value EQ 1) then
or if ( BOOLEAN($value)) then
Most common occurrence
PML1 if ( match ($!String1,$!String2)) then
PML2 if ( match ($!String1,$!String2) GT 0 ) then
Check Form and Global Variable Names
Forms are now GLOBAL variables, and cannot have the same names as a Global Variable.
Form and Gadget Names Must be Unique and Start with a Letter
Forms & Menus enforces the rule that gadget names must start with a letter, and must be unique, (Gadget
names can be re-used in different forms).
New Forms & Menus Error Messages.
No longer possible to use setup form from within .INIT macro.
Gadgets that are outside the form are now ERRORS.
More than one OK,CANCEL or HELP will generate an error.
Var list & do list are restricted to LIST gadgets, for TEXTPANES & SELECTOR gadgets use var
pane,selector & do selector
DOT in variable, Form and Gadget Names
Is now used as separator between a Form or Object name and the name of one of its members or functions.
i.e. !Array.size()
var !String ‘comment’
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
106
www.aveva.com
!Old.Name = ‘!String’
could now use:-
!Size = $!<Old.name>.length()
or
!Size = $!Old.name$N.length()
Negative Array Subscript is now an Error.
Array subscripts MUST now be positive or zero, Zero is permitted but many of the array methods ignore the
zero’th element.
Macros which make use of negative array subscripts will need to be revised.
$MKn & $MK-n Withdrawn.
These commands may have had a role when macros were run directly from a terminal, but are incompatible
with form-driven software.
Macros will have to be re-written.
Synonyms are NOT Available in PML Functions but are still available in Macros.
= in PDMS10 is not compatible with = in PDMS11
Components in Function to the Right of “=“
Existing “var” code is not affected.
Add brackets if PML1 code has none.
To convert to “text” add “$”
!X = 32 , !Y = 52
!Z = !X + !Y Result = REAL …..84
!Z = ‘$!X’ + ‘$!Y’ Result = STRING …..3252
Notes for PML1 users
$Wn Will Break the GUI Software.
Numbered Variables Are no longer available.
Macros Avoid Mixing with PML Functions.
Global Variables for results Use Function “Return”.
$M- $M+ $MK Only for debugging, not LIVE code.
$R+ $R- Withdrawn, (PML TRACE ON/OFF)
Synonyms Not permitted in PML Functions.
VAR Syntax Use “=“ Where possible.
VAR Name READ Use ALERT object or Form.
Expressions in ( ) Brackets not needed after “=“
!VALUE = NAME Use !VALUE = !!CE
$ Use variables without $
Don’t Quote variables With no $, quotes not needed.
@ cursor functions Use Event Driven Graphics
!ARRAY[-ve] Not allowed in PML2
!ARRAY[0] Not advised to use at PML2
Dots “.” in Names New meaning at PML2
Form EDIT syntax Use direct setting.
107
www.aveva.com
APPENDIX A
Appendix A – PDMS Primitives
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
108
www.aveva.com
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
109
www.aveva.com
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
110
www.aveva.com
111
www.aveva.com
APPENDIX B
Appendix B – Example code
This appendix contains examples of code that provide solutions to each of the exercises. As some
exercises required existing forms to be updated, new code or code which has been changed is show in Red
for completion all code is included.
Appendix B1 - Example ex1.mac
------------------------------------------------------------------
-- Programming Macro Language Training Course
-- Exercise 1 - PML1 Macro to build centre of a Handwheel
------------------------------------------------------------------
-- 1. Create a new piece of equipment
-- 2. Create primitives, positioning them relative to each other
NEW EQUIPMENT /HandWheel
NEW BOX XLEN 100 YLEN 100 ZLEN 100
NEW CYLINDER DIAM 80 HEIG 5
CONN P1 TO P3 OF PREV
NEW BOX XLEN 50 YLEN 50 ZLEN 15
CONN P6 TO P2 OF PREV
NEW DISH DIAM 50 HEIG 15
CONN P2 TO P3 OF PREV
ADD /HandWheel AUTO /HandWheel
-- Note: to run this macro type into the command line:
-- $m/c:/pmltraining/ex1.mac
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
112
www.aveva.com
Appendix B2 - Example ex2.mac
------------------------------------------------------------------
-- Programming Macro Language Training Course
-- Exercise 2 - Parameterised Macro to build centre of a Handwheel
-- and single part of outer wheel
------------------------------------------------------------------
-- 1. Convert ex1 to include parameters
-- 2. Add extra primitives to represent the outer wheel
$d1=HandWheel
$d2=100
$d3=80
$d4=5
$d5=50
$d6=15
$d7=500
$d8=525
$d9=575
NEW EQUIPMENT /$1
NEW BOX /$1-Centre
XLEN $2 YLEN $2 ZLEN $2
NEW CYLINDER DIAM $3 HEIG $4
CONN P1 TO P3 OF PREV
NEW BOX XLEN $5 YLEN $5 ZLEN $6
CONN P6 TO P2 OF PREV
NEW DISH DIAM $5 HEIG $6
CONN P2 TO P3 OF PREV
NEW CYLINDER DIAM $5 HEIG $7
CONN P1 TO P2 OF /$1-Centre
NEW CTORUS RINS $8 ROUT $9
CONN P0 TO P0 OF /$1-Centre
ADD /$1 AUTO /$1
-- Note: to run this macro type into the command line:
-- $m/c:/pmltraining/ex2.mac HANDWHEEL 100 80 5 50 10 500 525 575
New primitives
reference the newly
named BOX1
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
113
www.aveva.com
Appendix B3 - Example ex3.mac
------------------------------------------------------------------
-- Programming Macro Language Training Course
-- Exercise 3 - Parameterised Macro to build centre of a Handwheel
-- and outer wheel using a loop
------------------------------------------------------------------
-- 1. Convert ex2 to include less parameters (include calculations)
-- 2. Introduce sub-equipments to organise primitives
-- 3. Add a loop to copy and rotate the arm sub-equipment
$d1=HandWheel
$d2=100
$d3=50
$d4=500
!WashDia = $2 - 20
!WashThk = $2 / 20
!BoltSize = $2 / 2
!BoltThk = $2 / 10
!Dia1 = $4 + ( $2 / 4 )
!Dia2 = !Dia1 + $3
NEW EQUIPMENT /$1
NEW SUBE /$1-Centre
NEW BOX /$1-Centre-Box XLEN $2 YLEN $2 ZLEN $2
NEW CYLINDER DIAM $!WashDia HEIG $!WashThk
CONN P1 TO P3 OF PREV
NEW BOX XLEN $!BoltSize YLEN $!BoltSize ZLEN $!BoltThk
CONN P6 TO P2 OF PREV
NEW DISH DIAM $!BoltSize HEIG $!BoltThk
CONN P2 TO P3 OF PREV
NEW SUBE /$1-Arm-1
NEW CYLINDER DIAM $3 HEIG $4
CONN P1 TO P2 OF /$1-Centre-Box
NEW CTORUS RINS $!Dia1 ROUT $!Dia2
CONN P0 TO P0 OF /$1-Centre-Box
do !p from 2 to 4
NEW SUBE /$1-Arm-$!p COPY PREV
ROTATE BY 90 ABOUT U
enddo
ADD /$1 AUTO /$1
-- Note: to run this macro type into the command line:
-- $m/c:/pmltraining/ex3.mac HANDWHEEL 100 50 500
Loop to create copies
6 variables created
from the 4
parameters
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
114
www.aveva.com
Appendix B4 - Example ex4.mac
------------------------------------------------------------------
-- Programming Macro Language Training Course
-- Exercise 4 - Add error handling
------------------------------------------------------------------
-- 1. Add error handling
-- 2. Handle error if try to create at wrong part of hierarchy
-- 3. Handle error if equipment already exists
ZONE
handle ANY
!!Alert.Error(|Need to be at a ZONE element, or below|)
elsehandle NONE
$d1=HandWheel
$d2=100
$d3=50
$d4=500
!WashDia = $2 - 20
!WashThk = $2 / 20
!BoltSize = $2 / 2
!BoltThk = $2 / 10
!Dia1 = $4 + ( $2 / 4 )
!Dia2 = !Dia1 + $3
!n = REAL()
NEW EQUIPMENT /$1$!n
handle ANY
!n = 0
LABEL /NameRepeat
!n = !n + 1
name /$1$!n
handle ANY
GOLABEL /NameRepeat
endhandle
endhandle
NEW SUBE /$1$!n-Centre
NEW BOX /$1$!n-Centre-Box XLEN $2 YLEN $2 ZLEN $2
NEW CYLINDER DIAM $!WashDia HEIG $!WashThk
CONN P1 TO P3 OF PREV
NEW BOX XLEN $!BoltSize YLEN $!BoltSize ZLEN $!BoltThk
CONN P6 TO P2 OF PREV
NEW DISH DIAM $!BoltSize HEIG $!BoltThk
CONN P2 TO P3 OF PREV
NEW SUBE /$1$!n-Arm-1
NEW CYLINDER DIAM $3 HEIG $4
CONN P1 TO P2 OF /$1$!n-Centre-Box
NEW CTORUS RINS $!Dia1 ROUT $!Dia2
CONN P0 TO P0 OF /$1$!n-Centre-Box
do !p from 2 to 4
NEW SUBE /$1$!n-Arm-$!p COPY PREV
ROTATE BY 90 ABOUT U
enddo
EQUI
REM ALL
ADD /$1$!n AUTO /$1$!n
endhandle
-- Note: to run this macro type into the command line:
-- $m/c:/pmltraining/ex4.mac HANDWHEEL 100 50 500
First error handle: error
generated if PDMS
cannot navigate to a
ZONE element
Second error handle:
Error generated when
new element is given the
name of an existing one.
Variable !aa updated to
the number of members
in the zone. This
provides a unique
number to append to the
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
115
www.aveva.com
Appendix B5 - Example ex5a.pmlfnc
define function !!ex5a(!name is STRING)
VAR !CENTRE (100)
VAR !WHEELDIA (500)
VAR !TUBEDIA ($!CENTRE / 2)
NEW EQUIP /$!NAME
NEW SUBE /$!NAME-BASE
REM ALL
ADD /$!NAME AUTO /$!NAME
EQUIP
$P
$P DONE!
$P
endfunction
Middle code as ex5.mac
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
116
www.aveva.com
Appendix B6 - Example ex5b.pmlfnc
define function !!ex5b(!name is STRING, !wheelDia is REAL, !wheelWidth is REAL)
NEW EQUIP /$!name
-- Admin controlled parameters
!centre = 100
!axleDia = 100
!baseThk = 50
!wheelThk = 10
!hoseDia = 150
-- Calculations based on parameters
!axleHeight = (!wheelDia / 2) + 250
!TwheelWidth = !wheelWidth + (2 * !wheelThk) + !baseThk
!tubeDia = !centre / 2
!HwheelDia = !wheelDia / 3
!BwheelDia = !wheelDia / 2
!No = !wheelWidth / !hoseDia
!loops = !No.int()
NEW SUBE /$!NAME-Base
NEW BOX XLEN ($!TwheelWidth + 200) YLEN ($!TwheelWidth + 200) ZLEN $!baseThk
POS E 0 N 0 U ($!baseThk / 2)
do !I from 0 to 1
NEW EXTRUSION HEIG ($!baseThk / 2)
!mod = !TwheelWidth - ($!baseThk / 2)
POS W 0 S (($!TwheelWidth / 2) - ($!mod * $!I)) U 0
ORI Y is E and Z is N
NEW LOOP
NEW VERTEX
POS E $!baseThk S ($!TwheelWidth / 2) U 0
NEW VERTEX
POS E $!baseThk N ($!Twheelwidth / 2) U 0
NEW VERTEX
POS E $!axleHeight N ($!BwheelDia / 2) U 0
NEW VERTEX
POS E ($!axleHeight + ($!BwheelDia / 2)) N ($!BwheelDia / 2) U 0
FRAD ($!BwheelDia / 2)
NEW VERTEX
POS E ($!axleHeight + ($!BwheelDia / 2)) S ($!BwheelDia / 2) U 0
FRAD ($!BwheelDia / 2)
NEW VERTEX
POS E $!axleHeight S ($!BwheelDia / 2) U 0
enddo
NEW CYLINDER /$!NAME-Base-Axle DIAM $!axleDia HEIG ($!Twheelwidth + 50)
POS E 0 N 0 U $!axleHeight
ORI Y is E and Z is N
NEW SUBE /$!NAME-Hose
POS E 0 N 0 U $!axleHeight
ORI Y is D and Z is S
do !I from -1 to 1 by 2
NEW CYLINDER DIAM $!wheelDia HEIG $!wheelThk
POS E 0 N 0 U ((($!hoseDia * ($!loops / 2)) + ($!wheelThk / 2)) * $!I)
enddo
do !I from 0 to (!loops - 1)
do !J from 0 to 1
NEW CTORUS RINS (($!wheelDia / 2) - 50 - $!hoseDia) ROUT (($!wheelDia / 2) - 50) ANGL 180
POS E 0 N 0 U ((($!hoseDia * ($!loops / 2))) - ($!hoseDia / 2) - ($!hoseDia * $!I))
ROTATE BY ($!J * 180) ABOUT S wrt /*
enddo
enddo
NEW CYLINDER DIAM $!hoseDia HEIG ($!wheelDia / 3)
CONN P1 TO P2 OF PREV
NEW CYLINDER DIAM ($!hoseDia + 40) HEIG 25
Increase the number of
variables controlled by
the owner of the function
Whole number of hose
loops calculated
Loop to create the two
extrusions. Position
controlled by the loop
value
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
117
www.aveva.com
CONN P1 TO P2 OF PREV
NEW CYLINDER DIAM ($!hoseDia + 10) HEIG 50
CONN P1 TO P2 OF PREV
NEW CYLINDER DIAM ($!hoseDia + 40) HEIG 25
CONN P1 TO P2 OF PREV
NEW CONE DTOP ($!hoseDia + 10) DBOT 100 HEIG ($!hoseDia * 1.5)
CONN P1 TO P2 OF PREV
NEW REVOLUTION ANGL 360
NEW LOOP
NEW VERTEX
NEW VERTEX
POS W 10 N 0 U 0
NEW VERTEX
POS W 10 N 60 U 0
FRAD 5
NEW VERTEX
POS W 0 N 60 U 0
FRAD 5
REVO
CONN P1 TO P2 OF PREV
ROTATE BY 90 ABOUT D
NEW SUBE /$!NAME-Centre
NEW BOX /$!NAME-Centre-Box XLEN $!centre YLEN $!centre ZLEN $!centre
CONN P6 TO P2 OF /$!NAME-Base-Axle
NEW CYLINDER DIAM ($!centre - 20) HEIG ($!centre / 20)
CONN P1 TO P3 OF PREV
NEW BOX XLEN ($!centre / 2) YLEN ($!centre / 2) ZLEN ($!centre / 10)
CONN P6 TO P2 OF PREV
NEW DISH DIAM ($!centre / 2) HEIG ($!centre / 10)
CONN P2 TO P3 OF PREV
NEW SUBE /$!NAME-Arm-1
!box = /$!NAME-Centre-Box
!!CE.pos = !box.worpos
NEW CYLINDER DIAM $!tubeDia HEIG ($!HwheelDia - ($!tubeDia / 2) - ($!centre / 2))
CONN P1 TO P2 OF /$!NAME-Centre-Box
NEW CTORUS RINS ($!HwheelDia - $!tubeDia) ROUT $!HwheelDia
CONN P0 TO P0 OF /$!NAME-Centre-Box
do !p from 2 to 4
!angle = (!p - 1) * 90
NEW SUBE /$!NAME-Arm-$!P COPY /$!NAME-Arm-1
ROTATE BY $!angle ABOUT S
enddo
REM ALL
ADD /$!name AUTO /$!name
EQUIP
$P
$P DONE
$P
Endfunction
Navigate back to the
Revolution primitive so it
can be connected by
primitive
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
118
www.aveva.com
Appendix B7 - Example ex6a.pmlfrm
setup form !!ex6a dialog resizeable
!this.formTitle = |Exercise 6(a) Form|
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| call |!this.tempConv()| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at xmax.tempin + 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL
exit
define method .ex6a()
!this.tempin.callback = |!this.tempConv()|
!this.temp.val = 0
!this.tempIn.val = 1
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.temp.val * 1.8 + 32
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = (!this.temp.val - 32 ) / 1.8
!this.text2.val = |°C|
endif
endmethod
Depending whether C of
F is entered by the user,
the correct equation is
d
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
119
www.aveva.com
Appendix B8 - Example ex6b.pmlfrm
setup form !!ex6b dialog resizeable
!this.formTitle = |Exercise 6(b) Form|
path down
frame .input |Inputs| at x 0 anchor T+L+B
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| call |!this.tempConv()| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| anchor ALL at x1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY
exit
exit
frame .results |Results| at xmax + 1 y 0 anchor ALL
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor ALL at x1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
exit
button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL
exit
define method .ex6b()
!this.tempin.callback = |!this.tempConv()|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
!headings.append(| |)
!headings.append(|Fahrenheit|)
!this.table1.setHeadings(!headings)
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.temp.val * 1.8 + 32
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = (!this.temp.val - 32 ) / 1.8
!this.text2.val = |°C|
endif
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
As the step value
should be a whole
number, we shall
use a PDMS
standard format
Define default values as
part of the constructor
method
If the FILL button is
pressed, a loop collects
the required values in an
array and applies them
to the output table.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
120
www.aveva.com
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
endif
endmethod
Use !flag variable to
identify which gadget
initiates the method
Series of checks to
make sure the entered
values are correct
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
121
www.aveva.com
Appendix B9 - Example ex6c.pmlfrm
setup form !!ex6c dialog resizeable
!this.formTitle = |Exercise 6(c) Form|
path down
frame .input |Inputs| at x 0 anchor T+L+B
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| call |!this.tempConv()| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| at x 1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY
exit
frame .tempCheck |Temperatue Check| anchor ALL at x1 width.tempIn
text .inputTemp |Input Temp.| call || width 10 is REAL
text .safeTemp |Safe Temp. | call || width 10 is REAL
text .range |Range (±) | call || width 10 is REAL
button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range
button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY
exit
exit
frame .results |Results| at xmax + 1 y 0 anchor ALL
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor L+T+R at x1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x1 ymin.tempCheck
width.tempCheck height.tempCheck
textpane .table2 dock fill width 1 height 1
exit
exit
button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL
exit
define method .ex6c()
!this.tempin.callback = |!this.tempConv()|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
!headings.append(| |)
!headings.append(|Fahrenheit|)
!this.table1.setHeadings(!headings)
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
!this.inputTemp.val = 100
!this.safeTemp.val = 75
!this.range.val = 10
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
122
www.aveva.com
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.CtoF(!this.temp.val)
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = !this.FtoC(!this.temp.val)
!this.text2.val = |°C|
endif
endmethod
define method .CtoF(!val is REAL) is REAL
!fahren = !val * 1.8 + 32
return !fahren
endmethod
define method .FtoC(!val is REAL) is REAL
!centi = (!val - 32 ) / 1.8
return !centi
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
Method updated to use
conversion methods
which return converted
temperatures
Equations moved to
separate methods so
they can be used by
other methods.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
123
www.aveva.com
endif
endmethod
define method .compile()
!compile = ARRAY()
!compiled = !this.table2.val
!No = !compiled.size() + 1
if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then
!diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val)
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range|
elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then
!diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range|
else
!compareString = ||
endif
!newLine = !No & |. | & !this.inputTemp.val & |°C is | &
!this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString
!compiled.append(!newLine)
!this.table2.val = !compiled
endmethod
Calculate the differences
using the new
conversion methods.
Concatenate the new
values into a single
string and append to the
existing value
Read the existing table
value and the number
of the next line
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
124
www.aveva.com
Appendix B10 - Example ex6d.pmlfrm
setup form !!ex6d dialog resizeable
!this.formTitle = |Exercise 6(d) Form|
path down
frame .input |Inputs| at x 0 anchor T+L+B
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| call |!this.tempConv()| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| at x 1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY
exit
frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn
text .inputTemp |Input Temp.| call || width 10 is REAL
text .safeTemp |Safe Temp. | call || width 10 is REAL
text .range |Range (±) | call || width 10 is REAL
button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range
button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY
exit
frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn
text .stringIn |Input | width 24 is STRING
text .delim |Delimiter | width 10 is STRING
button .split | Split >> | call |!this.split()| at xmax.delim + 2 ymin.delim APPLY
exit
exit
frame .results |Results| anchor ALL at xmax + 1 y 0
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck
width.tempCheck height.tempCheck
textpane .table2 dock fill width 1 height 1
exit
frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn
text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT
text .result |Result | width.stringIn is STRING
exit
exit
button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL
exit
define method .ex6d()
!this.tempin.callback = |!this.tempConv()|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
!headings.append(| |)
!headings.append(|Fahrenheit|)
!this.table1.setHeadings(!headings)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
125
www.aveva.com
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
!this.inputTemp.val = 100
!this.safeTemp.val = 75
!this.range.val = 10
!this.stringIn.val = |10°C/30°C/20°C/5°C|
!this.delim.val = |/|
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.CtoF(!this.temp.val)
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = !this.FtoC(!this.temp.val)
!this.text2.val = |°C|
endif
endmethod
define method .CtoF(!val is REAL) is REAL
!fahren = !val * 1.8 + 32
return !fahren
endmethod
define method .FtoC(!val is REAL) is REAL
!centi = (!val - 32 ) / 1.8
return !centi
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
126
www.aveva.com
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
endif
endmethod
define method .compile()
!compile = ARRAY()
!compiled = !this.table2.val
!No = !compiled.size() + 1
if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then
!diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val)
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range|
elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then
!diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range|
else
!compareString = ||
endif
!newLine = !No & |. | & !this.inputTemp.val & |°C is | &
!this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString
!compiled.append(!newLine)
!this.table2.val = !compiled
endmethod
define method .split()
!split = !this.stringIn.val.trim().split(!this.delim.val)
!this.number.val = !split.size()
!result = ||
do !I index !split
!result = !this.CtoF(!split[!I].substring(1, !split[!I].length() – 2 ).real()).string(!!INTEGERFMT) & |°F |
& !result
enddo
!this.result.val = !result
endmethod
Loop through the split
values, convert them
and recompile as a
string
Read the input string
and split it on the input
delimiter
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
127
www.aveva.com
Appendix B11 - Example ex7.pmlfrm
setup form !!ex7 dialog resizeable
!this.formTitle = |Exercise 7 Form|
path down
frame .input |Inputs| at x 0 anchor T+L+B
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| call |!this.tempConv()| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| at x 1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY
exit
frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn
text .inputTemp |Input Temp.| call || width 10 is REAL
text .safeTemp |Safe Temp. | call || width 10 is REAL
text .range |Range (±) | call || width 10 is REAL
button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range
button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY
exit
frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn
text .stringIn |Input | width 24 is STRING
text .delim |Delimiter | width 10 is STRING
button .split | Split >> | call |!this.split()| at xmax.delim + 2 ymin.delim APPLY
exit
exit
frame .results |Results| anchor ALL at xmax + 1 y 0
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck
width.tempCheck height.tempCheck
textpane .table2 dock fill width 1 height 1
exit
frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn
text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT
text .result |Result | width.stringIn is STRING
exit
exit
button .apply | Apply | at x 0 ymax form anchor L+B call |!this.setData(1)|
button .reset | Reset | at xcen form - 0.5 * size ymin.apply anchor L+B call |!this.setData(2)|
button .dismiss | Dismiss | at xmax form-size ymin.apply anchor R+B CANCEL
member .data is ARRAY
exit
define method .ex7()
!this.tempin.callback = |!this.tempConv()|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
Form member to store data
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
128
www.aveva.com
!headings.append(| |)
!headings.append(|Fahrenheit|)
!this.table1.setHeadings(!headings)
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
!this.inputTemp.val = 100
!this.safeTemp.val = 75
!this.range.val = 10
!this.stringIn.val = |10°C/30°C/20°C/5°C|
!this.delim.val = |/|
!this.setData(1)
endmethod
define method .setData(!flag is REAL)
-- Either save the values, or bring them back (array of strings)
if !flag.eq(1) then
!this.data[1] = !this.temp.val
!this.data[2] = !this.tempIn.val
!this.data[3] = !this.mini.val
!this.data[4] = !this.maxi.val
!this.data[5] = !this.step.val
!this.data[6] = !this.inputTemp.val
!this.data[7] = !this.safeTemp.val
!this.data[8] = !this.range.val
!this.data[9] = !this.stringIn.val
!this.data[10]= !this.delim.val
else
!this.temp.val = !this.data[1]
!this.tempIn.val = !this.data[2]
!this.mini.val = !this.data[3]
!this.maxi.val = !this.data[4]
!this.step.val = !this.data[5]
!this.inputTemp.val= !this.data[6]
!this.safeTemp.val = !this.data[7]
!this.range.val = !this.data[8]
!this.stringIn.val = !this.data[9]
!this.delim.val = !this.data[10]
!this.tempConv()
!this.fill()
!this.split()
endif
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.CtoF(!this.temp.val)
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = !this.FtoC(!this.temp.val)
!this.text2.val = |°C|
endif
endmethod
define method .CtoF(!val is REAL) is REAL
!fahren = !val * 1.8 + 32
return !fahren
endmethod
Method created to
store/change appropriate
default values.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
129
www.aveva.com
define method .FtoC(!val is REAL) is REAL
!centi = (!val - 32 ) / 1.8
return !centi
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
endif
define method .compile()
!compile = ARRAY()
!compiled = !this.table2.val
!No = !compiled.size() + 1
if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then
!diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val)
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range|
elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then
!diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range|
else
!compareString = ||
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
130
www.aveva.com
endif
!newLine = !No & |. | & !this.inputTemp.val & |°C is | &
!this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString
!compiled.append(!newLine)
!this.table2.val = !compiled
endmethod
define method .split()
!split = !this.stringIn.val.trim().split(!this.delim.val)
!this.number.val = !split.size()
!result = ||
do !I index !split
!result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result
enddo
!this.result.val = !result
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
131
www.aveva.com
Appendix B12 - Example ex8.pmlfrm
setup form !!ex8 dialog resizeable
!this.formTitle = |Exercise 8 Form|
path down
frame .tabSet TABSET 'tabset' anchor all
frame .input |Inputs| at x 0 y 0 dock fill
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| at x 1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
exit
frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn
text .inputTemp |Input Temp.| call || width 10 is REAL
text .safeTemp |Safe Temp. | call || width 10 is REAL
text .range |Range (±) | call || width 10 is REAL
exit
frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn
text .stringIn |Input | width 24 is STRING
text .delim |Delimiter | width 10 is STRING
exit
exit
frame .results |Results| at x 0 y 0 dock fill
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck
width.tempCheck height.tempCheck
textpane .table2 dock fill width 1 height 1
exit
frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn
text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT
text .result |Result | width.stringIn is STRING
exit
exit
exit
button .apply | Apply | at x 0 ymax form anchor L+B call |!this.setData(1)|
button .reset | Reset | at xcen form - 0.5 * size ymin.apply anchor L+B call |!this.setData(2)|
button .dismiss | Dismiss | at xmax form-size ymin.apply anchor R+B CANCEL
member .data is ARRAY
exit
define method .ex8()
!this.results.callback = |!this.tabCall(|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
!headings.append(| |)
!headings.append(|Fahrenheit|)
Tabset added and buttons
removed
Callback applied to
results tab
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
132
www.aveva.com
!this.table1.setHeadings(!headings)
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
!this.inputTemp.val = 100
!this.safeTemp.val = 75
!this.range.val = 10
!this.stringIn.val = |10°C/30°C/20°C/5°C|
!this.delim.val = |/|
endmethod
define method .tabCall(!gad is GADGET, !type is STRING)
if !type eq |SHOWN| then
!this.tempConv()
!this.fill()
!this.compile()
!this.split()
endif
endmethod
define method .compile()
if !this.inputTemp.val.unset() then
!this.table2.clear()
else
!compile = ARRAY()
!compiled = !this.table2.val
!No = !compiled.size() + 1
if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then
!diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val)
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = !diff & |°C/| & !diffFahr & |°F - ABOVE safe range|
elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then
!diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = !diff & |°C/| & !diffFahr & |°F - BELOW safe range|
else
!compareString = ||
endif
!newLine = !No & |. | & !this.inputTemp.val & |°C is | &
!this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F - | & !compareString
!compiled.append(!newLine)
!this.table2.val = !compiled
endif
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.CtoF(!this.temp.val)
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = !this.FtoC(!this.temp.val)
!this.text2.val = |°C|
endif
endmethod
define method .CtoF(!val is REAL) is REAL
!fahren = !val * 1.8 + 32
return !fahren
Method updated to check
for an unset input
temperature
Open callback calls all
methods once the results tab
is SHOWN
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
133
www.aveva.com
endmethod
define method .FtoC(!val is REAL) is REAL
!centi = (!val - 32 ) / 1.8
return !centi
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
endif
endmethod
define method .split()
!split = !this.stringIn.val.trim().split(!this.delim.val)
!this.number.val = !split.size()
!result = ||
do !I index !split
!result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result
enddo
!this.result.val = !result
endmethod
define method .setData(!flag is REAL)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
134
www.aveva.com
-- Either save the values, or bring them back (array of strings)
if !flag.eq(1) then
!this.data[1] = !this.temp.val.string()
!this.data[2] = !this.tempIn.val.string()
!this.data[3] = !this.mini.val.string()
!this.data[4] = !this.maxi.val.string()
!this.data[5] = !this.step.val.string()
!this.data[6] = !this.inputTemp.val.string()
!this.data[7] = !this.safeTemp.val.string()
!this.data[8] = !this.range.val.string()
!this.data[9] = !this.stringIn.val
!this.data[10]= !this.delim.val
else
if !this.data.size().eq(10) then
!this.temp.val = !this.data[1].real()
!this.tempIn.val = !this.data[2].real()
!this.mini.val = !this.data[3].real()
!this.maxi.val = !this.data[4].real()
!this.step.val = !this.data[5].real()
!this.inputTemp.val= !this.data[6].real()
!this.safeTemp.val = !this.data[7].real()
!this.range.val = !this.data[8].real()
!this.stringIn.val = !this.data[9]
!this.delim.val = !this.data[10]
!this.tempConv()
!this.fill()
!this.split()
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
135
www.aveva.com
Appendix B13 - Example ex9.pmlfrm
setup form !!ex9 dialog resizeable
!this.formTitle = |Exercise 9 Form|
bar
!this.bar.add('Control', 'Menu1')
!this.bar.add('Defaults', 'Menu2')
!this.bar.add('Help', 'Help')
!menu1 = !this.newmenu( 'Menu1', 'MAIN')
!menu1.add('CALLBACK', 'Close', '!this.hide()', 'Close')
!menu1.add('SEPARATOR')
!menu1.add('CALLBACK', 'Load Defaults...', 'call !!fileBrowser(''c:'', ''*.txt'', ''Load Defaults'', false,
''!!ex9.loadFile()'')')
!menu2 = !this.newmenu( 'Menu2', 'MAIN')
!menu2.add('CALLBACK', 'Update Defaults', '!this.setData(1)')
!menu2.add('CALLBACK', 'Reset to Defaults', '!this.setData(2)')
path down
frame .tabSet TABSET 'tabset' anchor all
frame .input |Inputs| at x 0 y 0 dock fill
frame .tempIn |Temperature conversion (Input)| at x 1
text .temp |Temperature| width 10 is REAL
rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp
rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp
exit
frame .tempRange |Temperature Range| at x 1 width.tempIn
text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL
text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL
text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT
exit
frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn
text .inputTemp |Input Temp.| call || width 10 is REAL
text .safeTemp |Safe Temp. | call || width 10 is REAL
text .range |Range (±) | call || width 10 is REAL
exit
frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn
text .stringIn |Input | width 24 is STRING
text .delim |Delimiter | width 10 is STRING
exit
exit
frame .results |Results| at x 0 y 0 dock fill
frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn
height.tempIn
text .out |Temperature| call || width 10 is REAL
para .text2 at xmax.out ymin.temp text || width 5
exit
frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange
height.tempRange
list .table1 dock fill columns width 1 height 1
exit
frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck
width.tempCheck height.tempCheck
textpane .table2 dock fill width 1 height 1
exit
frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn
text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT
text .result |Result | width.stringIn is STRING
exit
exit
exit
member .data is ARRAY
Bar menu added to replace
buttons
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
136
www.aveva.com
exit
define method .loadFile()
!file = !!filebrowser.file
if !file.IsOpen() then
!file.close()
endif
!lines = !file.ReadFile()
!n = 0
do !I values !lines
if !I.substring(1, 2).eq(|--|) or !I.eq(||) then
else
!n = !n + 1
!collect[!n] = !I
endif
enddo
if !collect.size().eq(10) then
!this.data = !collect
!this.setData(2)
else
!!Alert.Warning(|Please check the chosen default file|)
endif
endmethod
define method .ex9()
!this.results.callback = |!this.tabCall(|
!headings = ARRAY()
!headings.append(|No.|)
!headings.append(|Centigrade|)
!headings.append(| |)
!headings.append(|Fahrenheit|)
!this.table1.setHeadings(!headings)
!this.temp.val = 0
!this.tempIn.val = 1
!this.mini.val = 0
!this.maxi.val = 100
!this.step.val = 25
!this.inputTemp.val = 100
!this.safeTemp.val = 75
!this.range.val = 10
!this.stringIn.val = |10°C/30°C/20°C/5°C|
!this.delim.val = |/|
endmethod
define method .tabCall(!gad is GADGET, !type is STRING)
if !type eq |SHOWN| then
!this.tempConv()
!this.fill()
!this.compile()
!this.split()
endif
endmethod
define method .tempConv()
if !this.tempIn.val.eq(1) then
!this.out.val = !this.CtoF(!this.temp.val)
!this.text2.val = |°F|
elseif !this.tempIn.val.eq(2) then
!this.out.val = !this.FtoC(!this.temp.val)
!this.text2.val = |°C|
endif
Method takes file name from
standard PDMS file browser
form
Loop through the read file,
collecting the lines of interest
Check the amount of the
collected information is as
expected
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
137
www.aveva.com
endmethod
define method .CtoF(!val is REAL) is REAL
!fahren = !val * 1.8 + 32
return !fahren
endmethod
define method .FtoC(!val is REAL) is REAL
!centi = (!val - 32 ) / 1.8
return !centi
endmethod
define method .fill()
!n = 0
do !temp from !this.mini.val to !this.maxi.val by !this.step.val
!n = !n + 1
!temps[!n][1] = !n.string()
!temps[!n][2] = !temp.string()
!temps[!n][3] = |=|
!fahren = !temp * 1.8 + 32
!temps[!n][4] = STRING(!fahren,!!RealFMT)
enddo
!this.table1.setRows( !temps )
endmethod
define method .check(!flag is REAL)
if !flag.eq(0) then
if !this.step.val.eq(0) then
!this.step.val = 1
endif
elseif !flag.eq(1) or !flag.eq(2) then
if !this.maxi.val.unset() then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !this.mini.val.unset() then
!this.mini.val = !this.maxi.val - !this.step.val
endif
if (!this.mini.val.lt(-273)) then
!this.mini.val = -273
if (!this.maxi.val.leq(!this.mini.val)) then
!this.maxi.val = -272
endif
elseif (!this.maxi.val.lt(-273)) then
!this.mini.val = -273
!this.maxi.val = -272
endif
if (!this.maxi.val.leq(!this.mini.val)) then
if !flag.eq(1) then
!this.maxi.val = !this.mini.val + !this.step.val
elseif !flag.eq(2) then
!this.mini.val = !this.maxi.val - !this.step.val
endif
endif
endif
endmethod
define method .compile()
if !this.inputTemp.val.unset() then
!this.table2.clear()
else
!compile = ARRAY()
!compiled = !this.table2.val
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
138
www.aveva.com
!No = !compiled.size() + 1
if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then
!diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val)
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = !diff & |°C/| & !diffFahr & |°F - ABOVE safe range|
elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then
!diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val
!diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT)
!compareString = !diff & |°C/| & !diffFahr & |°F - BELOW safe range|
else
!compareString = ||
endif
!newLine = !No & |. | & !this.inputTemp.val & |°C is | &
!this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F - | & !compareString
!compiled.append(!newLine)
!this.table2.val = !compiled
endif
endmethod
define method .split()
!split = !this.stringIn.val.trim().split(!this.delim.val)
!this.number.val = !split.size()
!result = ||
do !I index !split
!result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result
enddo
!this.result.val = !result
endmethod
define method .setData(!flag is REAL)
-- Either save the values, or bring them back (array of strings)
if !flag.eq(1) then
!this.data[1] = !this.temp.val.string()
!this.data[2] = !this.tempIn.val.string()
!this.data[3] = !this.mini.val.string()
!this.data[4] = !this.maxi.val.string()
!this.data[5] = !this.step.val.string()
!this.data[6] = !this.inputTemp.val.string()
!this.data[7] = !this.safeTemp.val.string()
!this.data[8] = !this.range.val.string()
!this.data[9] = !this.stringIn.val
!this.data[10]= !this.delim.val
else
if !this.data.size().eq(10) then
!this.temp.val = !this.data[1].real()
!this.tempIn.val = !this.data[2].real()
!this.mini.val = !this.data[3].real()
!this.maxi.val = !this.data[4].real()
!this.step.val = !this.data[5].real()
!this.inputTemp.val= !this.data[6].real()
!this.safeTemp.val = !this.data[7].real()
!this.range.val = !this.data[8].real()
!this.stringIn.val = !this.data[9]
!this.delim.val = !this.data[10]
!this.tempConv()
!this.fill()
!this.split()
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
139
www.aveva.com
Appendix B14 - Example ex10.pmlfrm
setup form !!ex10
!this.formTitle = |Exercise 10 form|
!this.initcall = |!this.init()|
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
exit
exit
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
140
www.aveva.com
Appendix B15 - Example ex11a.pmlfrm
setup form !!ex11a
!this.formTitle = |Exercise 11a form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
exit
exit
define method .ex11a()
!this.nozz.setpopup(!this.pop1)
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
endif
endif
endmethod
Constructor method add to
apply pop-up menu to
gadget.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
141
www.aveva.com
Appendix B16 - Example ex11b.pmlfrm
setup form !!ex11b
!this.formTitle = |Exercise 11b form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
exit
exit
define method .ex11b()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!this.nozz.setpopup(!this.pop1)
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
Method reads the nozzles in
the list gadget. This means
it could be run on its own.
Check method runs through
the attributes of the nozzles
and checks the attributes:
Cref: connection reference
Check to see if the nozzle is
attached. If an error occurs
when navigating to the cref
connection needs checking
Href or Tref: pipe head/tail
ref
A pointer on the pipe which
should point back at the
connected nozzle
Hpos, Hdir, Hbore, Tpos,
Tdir and Tbore: pipe
attributes
Check these attributes
against the nozzle to check
for problems.
If problems are found, a
value of “check” is used
Constructor method adds
headings to the list gadget
Method now calls
.checkNozz() method
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
142
www.aveva.com
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
.setrows() method overwrites
the Rtext, therefore rtext
remember then reset.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
143
www.aveva.com
Appendix B17 - Example ex11c.pmlfrm
setup form !!ex11c
!this.formTitle = |Exercise 11c form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
exit
exit
define method .ex11c()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
endif
endif
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
Method runs in a “read
attribute” mode or a “write
attribute” mode – decide by
!fl
Read the attributes already
typed into the text pane
Constructor method default
values to the textpane
Method now calls
.updateAtt() method –
passing 1 as an arguement
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
144
www.aveva.com
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I.eq(1) then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
Calculate new attribute
values for the chosen
equipment
Compile new strings for the
textpane and apply to the
gadget
Add a error array to record
errors
Handle any errors relating to
date type (Real, String etc)
Apply to attribuite values to
the chosen equipment
If handles don’t solve it,
record the !attrib variable to
the error array
If errors exist, report them to
the user. Loop through the
members of the array to
compile one string
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
145
www.aveva.com
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
146
www.aveva.com
Appendix B18 - Example ex12a.pmlfrm
setup form !!ex12a
!this.formTitle = |Exercise 12a form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
view .view3d at x 0.5 y0.5 VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
exit
exit
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
endif
endif
endmethod
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!limits[1] = !equip.wvol[1] - !add
!limits[2] = !equip.wvol[4] + !add
!limits[3] = !equip.wvol[2] - !add
!limits[4] = !equip.wvol[5] + !add
!limits[5] = !equip.wvol[3] - !add
!limits[6] = !equip.wvol[6] + !add
!this.view3d.limits = !limits
endmethod
define method .ex12a()
Volume View element added
(shaded, isometric 3)
Method now calls .limits ()
Set the limits of the view
based on the world volume
of the chosen equipment.
Notice that the limits array is
in a different order to wvol
array.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
147
www.aveva.com
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
148
www.aveva.com
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
149
www.aveva.com
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
150
www.aveva.com
Appendix B19 - Example ex12b.pmlfrm
setup form !!ex12b
!this.formTitle = |Exercise 12b form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
view .view3d at x 0.5 y0.5 VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
exit
member .clipbox is GPHCLIPBOX
member .limits is ARRAY
exit
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!limits[1] = !equip.wvol[1] - !add
!limits[2] = !equip.wvol[4] + !add
!limits[3] = !equip.wvol[2] - !add
!limits[4] = !equip.wvol[5] + !add
!limits[5] = !equip.wvol[3] - !add
!limits[6] = !equip.wvol[6] + !add
!this.limits = !limits
!this.view3d.limits = !limits
!pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2
!pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2
!pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2
!this.clipbox.box.position.east = !pos[1]
!this.clipbox.box.position.north = !pos[2]
!this.clipbox.box.position.up = !pos[3]
!this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add
!this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add
!this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add
!this.clipbox.view = !this.view3d
!this.clipbox.active = FALSE
!this.clipbox.view.owner().clipbox.set()
!this.view3d.clipping = TRUE
endmethod
define method .ex12b()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
Member added to store
clipbox definition
Method extended to
calculate clipbox information
Once clipbox is calculated,
the clipbox is applied to the
view
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
151
www.aveva.com
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
!this.view3d.refresh()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
152
www.aveva.com
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
153
www.aveva.com
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
154
www.aveva.com
Appendix B20 - Example ex12c.pmlfrm
setup form !!ex12c
!this.formTitle = |Exercise 12c form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
view .view3d at x 0.5 y0.5 VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46
slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5
text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL
text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is
REAL
toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5
exit
exit
member .clipbox is GPHCLIPBOX
member .limits is ARRAY
exit
define method .ex12c()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
!this.minslide.val = -1000
!this.maxslide.val = 5000
endmethod
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!this.limits[1] = !equip.wvol[1] - !add
!this.limits[2] = !equip.wvol[4] + !add
!this.limits[3] = !equip.wvol[2] - !add
!this.limits[4] = !equip.wvol[5] + !add
!this.limits[5] = !equip.wvol[3] - !add
!this.limits[6] = !equip.wvol[6] + !add
!this.limits = !limits
Slider gadget added
Constructor method default
values to the textpane
Method updated to point at
new form member
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
155
www.aveva.com
!this.view3d.limits = !this.limits
!pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2
!pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2
!pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2
!this.clipbox.box.position.east = !pos[1]
!this.clipbox.box.position.north = !pos[2]
!this.clipbox.box.position.up = !pos[3]
!this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add
!this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add
!this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add
!this.clipbox.view = !this.view3d
!this.clipbox.active = FALSE
!this.clipbox.view.owner().clipbox.set()
!this.view3d.clipping = TRUE
endmethod
define method .slide()
!value = !this.slide.val
if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or
(!this.clipbox.box.zlength + !value lt 0) then
else
if !this.incl.val.eq(TRUE) then
!modlimit = ARRAY()
!limits = !this.limits
!modlimit[1] = !limits[1] - !value
!modlimit[2] = !limits[2] + !value
!modlimit[3] = !limits[3] - !value
!modlimit[4] = !limits[4] + !value
!modlimit[5] = !limits[5] - !value
!modlimit[6] = !limits[6] + !value
!this.view3d.limits = !modlimit
endif
!this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value
!this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value
!this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value
!this.view3d.refresh()
endif
endmethod
define method .updateRange()
!range[1] = !this.minslide.val
!range[2] = !this.maxslide.val
!range[3] = 100
!this.slide.range = !range
!this.slide.refresh()
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
Limits modified based on the
value of the slider gadget
Method to modify range of
slider gadget
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
156
www.aveva.com
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
!this.view3d.refresh()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
157
www.aveva.com
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
158
www.aveva.com
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
159
www.aveva.com
Appendix B21 - Example ex12d.pmlfrm
setup form !!ex12d
!this.formTitle = |Exercise 12d form|
!this.initcall = |!this.init()|
!this.quitcall = |!this.clear()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
view .view3d at x 0.5 y0.5 VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip call |!this.check()| columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
button .tagNozzles toggle tooltip 'Tag All Nozzles' pixmap at xmin.refreshNozz - size ymax.nozz
call |!this.tag(2)| width 16 height 16
button .tagNozz toggle tooltip 'Tag Selected Nozzle' pixmap at xmin.tagNozzles - size
ymax.nozz call |!this.tag(1)| width 16 height 16
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46
slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5
text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL
text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is
REAL
toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5
exit
exit
member .clipbox is GPHCLIPBOX
member .limits is ARRAY
member .tagged is ARRAY
exit
define method .ex12d()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
!this.minslide.val = -1000
!this.maxslide.val = 5000
!this.tagNozz.AddPixmap(!!PML.GetPathName('single.png'), !!PML.GetPathName('single_x.png'))
!this.tagNozzles.AddPixmap(!!PML.GetPathName('multi.png'), !!PML.GetPathName('multi_x.png'))
endmethod
New member added to store
tagged information.
Constructor method adds
the pictures to the pixmap
buttons
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
160
www.aveva.com
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
!this.tagged.clear()
do !I from 1 to !this.nozz.dtext.size()
!this.tagged[!I] = FALSE
enddo
!this.clear()
endif
endif
endmethod
define method .tag(!type is REAL)
!nozz = !this.nozz.selection().dbref()
!no = !this.nozz.val
if !type.eq(1) then
if !this.tagNozz.val.eq(TRUE) then
!nozzname = !nozz.namn
!nozzpos = !nozz.pos
AID TEXT NUMBER 1500$!no '$!nozzname' AT $!nozzpos
!this.tagged[!no] = TRUE
else
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!no$>
!this.tagged[!no] = FALSE
endif
!testtagged = !this.tagged
!testtagged.unique()
if !testtagged.size().eq(1) and !testtagged[1].eq(TRUE) then
!this.tagNozzles.val = TRUE
endif
elseif !type.eq(2) then
if !this.tagNozzles.val.eq(TRUE) then
do !i index !this.nozz.rtext
!nozzname = !this.nozz.rtext[!i].dbref().namn
!nozzpos = !this.nozz.rtext[!i].dbref().pos
AID TEXT NUMBER 1500$!i '$!nozzname' AT $!nozzpos
!this.tagged[!i] = TRUE
enddo
!this.tagNozz.val = TRUE
else
do !i index !this.nozz.rtext
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$>
!this.tagged[!i] = FALSE
enddo
!this.tagNozz.val = FALSE
Depending which button is
pressed and its value,
nozzles are tagged or
t d
Unique tag numbers
needed. Created based on
the tags position in the
l li t
Extra check if nozzles
tagged individually. If they
are all tagged, or if there is
only one nozzle, the tag all
button is toggled
Part of the method to tag all
nozzles.
Method now resets the
stored tagged information
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
161
www.aveva.com
endif
endif
endmethod
define method .check()
!check = !this.tagged[!this.nozz.val]
if !check.eq(TRUE) then
!this.tagNozz.val = TRUE
else
!this.tagNozz.val = FALSE
endif
endmethod
define method .clear()
do !i index !this.nozz.rtext
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$>
enddo
!this.tagNozz.val = FALSE
!this.tagNozzles.val = FALSE
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
!this.view3d.refresh()
endhandle
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
New callback on nozzle list
runs this method. It checks
if the chosen nozzle is
already tagged and sets the
status of the tag button.
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
162
www.aveva.com
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
163
www.aveva.com
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!limits[1] = !equip.wvol[1] - !add
!limits[2] = !equip.wvol[4] + !add
!limits[3] = !equip.wvol[2] - !add
!limits[4] = !equip.wvol[5] + !add
!limits[5] = !equip.wvol[3] - !add
!limits[6] = !equip.wvol[6] + !add
!this.limits = !limits
!this.view3d.limits = !limits
!pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2
!pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2
!pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2
!this.clipbox.box.position.east = !pos[1]
!this.clipbox.box.position.north = !pos[2]
!this.clipbox.box.position.up = !pos[3]
!this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add
!this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add
!this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add
!this.clipbox.view = !this.view3d
!this.clipbox.active = FALSE
!this.clipbox.view.owner().clipbox.set()
!this.view3d.clipping = TRUE
endmethod
define method .slide()
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
164
www.aveva.com
!value = !this.slide.val
if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or
(!this.clipbox.box.zlength + !value lt 0) then
else
if !this.incl.val.eq(TRUE) then
!modlimit = ARRAY()
!limits = !this.limits
!modlimit[1] = !limits[1] - !value
!modlimit[2] = !limits[2] + !value
!modlimit[3] = !limits[3] - !value
!modlimit[4] = !limits[4] + !value
!modlimit[5] = !limits[5] - !value
!modlimit[6] = !limits[6] + !value
!this.view3d.limits = !modlimit
endif
!this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value
!this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value
!this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value
!this.view3d.refresh()
endif
endmethod
define method .updateRange()
!range[1] = !this.minslide.val
!range[2] = !this.maxslide.val
!range[3] = 100
!this.slide.range = !range
!this.slide.refresh()
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
165
www.aveva.com
Appendix B22 - Example ex12e.pmlfrm
setup form !!ex12e
!this.formTitle = |Exercise 12e form|
!this.initcall = |!this.init()|
!this.quitcall = |!this.clear()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
view .view3d at x 0.5 y0.5 VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip call |!this.check()| columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
button .tagNozzles toggle tooltip 'Tag All Nozzles' pixmap at xmin.refreshNozz - size
ymax.nozz call |!this.tag(2)| width 16 height 16
button .tagNozz toggle tooltip 'Tag Selected Nozzle' pixmap at xmin.tagNozzles - size
ymax.nozz call |!this.tag(1)| width 16 height 16
textpane .atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
button .hlNozz toggle tooltip 'Highlight Nozzles' pixmap at xmin.tagNozz - size ymax.nozz
call |!this.highlight()| width 16 height 16
frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46
slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5
text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is
REAL
text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is
REAL
toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5
exit
frame .colour |Edit Highlight Colour| at xmin.equipframe + 0.5 ymax.limitslide width.limitslide
para .para1 at xmin.colour + 0.5 ymin.colour + 0.75 text |Current equipment |
para .para2 at xmin.colour + 0.5 ymax.para1 text |Connected nozzles |
para .para3 at xmin.colour + 0.5 ymax.para2 text |Unconnected nozzles|
para .para4 at xmin.colour + 0.5 ymax.para3 text |Check nozzles |
button .butt1 | | at xmax.para1 - 3 ymin.para1 call |!this.colourpick('A' )|
button .butt2 | | at xmax.para2 - 3 ymax.para1 call |!this.colourpick('B' )|
button .butt3 | | at xmax.para3 - 3 ymax.para2 call |!this.colourpick('C' )|
button .butt4 | | at xmax.para3 - 3 ymax.para3 call |!this.colourpick('D' )|
frame .colourpick at xmax.butt1 + 4 ymin.colour + 0.5 width 10
!val = 0
do !I from 1 to 10
do !J from 0 to 4
!val = !val + 1
!no = !I & |000| & !J
!x = (!I * 2) - 1
!y = (!J * 0.75) + 0.5
button .butt$!no | | pixmap at x$!x ymin.colourpick + $!y call |!this.colourpick($!val)| backg
$!val width 10 aspect 1
enddo
enddo
exit
exit
exit
Loop to create 50 buttons
Each button applied unique
name, position and colour
(based on colours read from
!!colourselect). Pixmap
buttons used to esure small
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
166
www.aveva.com
member .clipbox is GPHCLIPBOX
member .limits is ARRAY
member .col is REAL
member .tagged is ARRAY
member .highlight is ARRAY
exit
define method .ex12e()
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
!this.minslide.val = -1000
!this.maxslide.val = 5000
!this.colourpick.visible = FALSE
!this.butt1.background = 1
!this.butt2.background = 20
!this.butt3.background = 18
!this.butt4.background = 23
!this.tagNozz.AddPixmap(!!PML.GetPathName('single.png'), !!PML.GetPathName('single_x.png'))
!this.tagNozzles.AddPixmap(!!PML.GetPathName('multi.png'), !!PML.GetPathName('multi_x.png'))
!this.hlNozz.AddPixmap(!!PML.GetPathName('highlight.png'),
!!PML.GetPathName('highlight_x.png'))
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
!this.view3d.refresh()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
New members added
highlight information
Constructor method adds
the pictures to the highlight
button, initial colours the pick
buttons and hides the
colourpick frame
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
167
www.aveva.com
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
!this.tagged.clear()
do !I from 1 to !this.nozz.dtext.size()
!this.tagged[!I] = FALSE
enddo
!this.clear()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
168
www.aveva.com
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!this.highlight = !nozzinfo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
Check information stored
ready for use with the
highlight method
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
169
www.aveva.com
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
$!err|)
endif
endif
endmethod
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!limits[1] = !equip.wvol[1] - !add
!limits[2] = !equip.wvol[4] + !add
!limits[3] = !equip.wvol[2] - !add
!limits[4] = !equip.wvol[5] + !add
!limits[5] = !equip.wvol[3] - !add
!limits[6] = !equip.wvol[6] + !add
!this.limits = !limits
!this.view3d.limits = !limits
!pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2
!pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2
!pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2
!this.clipbox.box.position.east = !pos[1]
!this.clipbox.box.position.north = !pos[2]
!this.clipbox.box.position.up = !pos[3]
!this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add
!this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add
!this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add
!this.clipbox.view = !this.view3d
!this.clipbox.active = FALSE
!this.clipbox.view.owner().clipbox.set()
!this.view3d.clipping = TRUE
!this.view3d.refresh()
endmethod
define method .slide()
!value = !this.slide.val
if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or (!this.clipbox.box.zlength +
!value lt 0) then
else
if !this.incl.val.eq(TRUE) then
!modlimit = ARRAY()
!limits = !this.limits
!modlimit[1] = !limits[1] - !value
!modlimit[2] = !limits[2] + !value
!modlimit[3] = !limits[3] - !value
!modlimit[4] = !limits[4] + !value
!modlimit[5] = !limits[5] - !value
!modlimit[6] = !limits[6] + !value
!this.view3d.limits = !modlimit
endif
!this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value
!this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value
!this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value
!this.view3d.refresh()
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
170
www.aveva.com
define method .updateRange()
!range[1] = !this.minslide.val
!range[2] = !this.maxslide.val
!range[3] = 100
!this.slide.range = !range
!this.slide.refresh()
endmethod
define method .tag(!type is REAL)
!nozz = !this.nozz.selection().dbref()
!no = !this.nozz.val
if !type.eq(1) then
if !this.tagNozz.val.eq(TRUE) then
!nozzname = !nozz.namn
!nozzpos = !nozz.pos
AID TEXT NUMBER 1500$!no '$!nozzname' AT $!nozzpos
!this.tagged[!no] = TRUE
else
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!no$>
!this.tagged[!no] = FALSE
endif
!testtagged = !this.tagged
!testtagged.unique()
if !testtagged.size().eq(1) and !testtagged[1].eq(TRUE) then
!this.tagNozzles.val = TRUE
endif
elseif !type.eq(2) then
if !this.tagNozzles.val.eq(TRUE) then
do !i index !this.nozz.rtext
!nozzname = !this.nozz.rtext[!i].dbref().namn
!nozzpos = !this.nozz.rtext[!i].dbref().pos
AID TEXT NUMBER 1500$!i '$!nozzname' AT $!nozzpos
!this.tagged[!i] = TRUE
enddo
!this.tagNozz.val = TRUE
else
do !i index !this.nozz.rtext
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$>
!this.tagged[!i] = FALSE
enddo
!this.tagNozz.val = FALSE
endif
endif
endmethod
define method .check()
!check = !this.tagged[!this.nozz.val]
if !check.eq(TRUE) then
!this.tagNozz.val = TRUE
else
!this.tagNozz.val = FALSE
endif
endmethod
define method .colourpick(!colour is ANY)
!col = !colour.string()
if !col.eq('A') then
!this.col = 1
!this.colourpick.visible = TRUE
elseif !col.eq('B') then
!this.col = 2
Method shows/hides the
colour pick frame
(depending on the
t)
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
171
www.aveva.com
!this.colourpick.visible = TRUE
elseif !col.eq('C') then
!this.col = 3
!this.colourpick.visible = TRUE
elseif !col.eq('D') then
!this.col = 4
!this.colourpick.visible = TRUE
else
if !this.col.eq(1) then
!this.butt1.background = !col.real()
elseif !this.col.eq(2) then
!this.butt2.background = !col.real()
elseif !this.col.eq(3) then
!this.butt3.background = !col.real()
elseif !this.col.eq(4) then
!this.butt4.background = !col.real()
endif
!this.colourpick.visible = FALSE
endif
endmethod
define method .highlight()
!ce = !this.equip.selection().dbref().flnn
!cecol = !this.butt1.background
enhance /$!ce col $!cecol
if !this.hlNozz.val.eq(TRUE) then
!nozz = !this.highlight
do !I index !nozz
!nozzle = !this.nozz.rtext[!I].dbref().flnn
if !nozz[!I][2].eq(|OK|) then
!col = !this.butt2.background
elseif !nozz[!I][2].eq(|Check|) then
!col = !this.butt3.background
endif
if !nozz[!I][3].eq(|Check|) or !nozz[!I][4].eq(|Check|) or !nozz[!I][5].eq(|Check|) then
!col = !this.butt4.background
endif
enhance /$!nozzle col $!col
enddo
else
unenhance /$!ce
do !i index !this.nozz.rtext
!nozzle = !this.nozz.rtext[!i].dbref().flnn
unenhance /$!nozzle
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$>
enddo
endif
endmethod
define method .clear()
!ce = !this.equip.selection().dbref().flnn
unenhance /$!ce
do !i index !this.nozz.rtext
!nozzle = !this.nozz.rtext[!i].dbref().flnn
unenhance /$!nozzle
$m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$>
enddo
!this.tagNozz.val = FALSE
!this.tagNozzles.val = FALSE
endmethod
Run through the stored
check information and apply
the colours as required
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
172
www.aveva.com
Appendix B23 - Example ex13a.pmlfrm
setup form !!ex13a
!this.formTitle = |Exercise 13a form|
!this.initcall = |!this.init()|
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
button .pick tooltip 'Identify Equipment' pixmap at xmin.equipframe + 0.5 ymax.title call
|!this.pick()| width 16 height 16
option .equip at xmax.pick ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
exit
exit
define method .ex13a()
!this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png'))
endmethod
define method .pick()
!packet = object EDGPACKET()
!packet.elementPick(|Identify Equipment|)
!packet.description = |Identify Equipment|
!packet.action = |!!ex13a.identify(!this.return)|
!!edgCntrl.add(!packet)
endmethod
define method .identify(!pickInfo is ANY)
!item = !pickInfo[1].item
!!edgCntrl.remove(|Identify Equipment|)
-- Loop to find the EQUI element
do
break if (!item.type eq |EQUI|) or (!item.type eq |WORL|)
!item = !item.owner
enddo
if !item.type eq |WORL| then
!!Alert.Warning(|Choose a piece of equipment|)
!this.pick()
else
-- Find the EQUI in the OPTION gadget
!this.equip.val = !this.equip.dtext.FindFirst(!item.flnn)
handle ANY
!!Alert.Warning(|The picked equipment is not avaiable in the current OPTION gadget|)
endhandle
!this.collNozz()
endif
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
Apply pixmap to pick button
Create an EDG packet
Set the packet action to run
a method on this form. As
EDG is separate for the
form, full name is required
This method processes the
EDG info
Loop up hierarchy till either
type equals EQUI or WORL
If WORL is found, need to
repick
Option gadget updated to
chosen equipment. Handle
any errors
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
173
www.aveva.com
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
endif
endif
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
174
www.aveva.com
Appendix B24 - Example ex13b.pmlfrm
setup form !!ex13b
!this.formTitle = |Exercise 13b form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
frame .equipframe at x 0 y 0
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
button .pick tooltip 'Identify Nozzle' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.pick()|
width 16 height 16
exit
exit
define method .ex13b()
!this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png'))
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!this.nozz.setpopup(!this.pop1)
endmethod
define method .pick()
!packet = object EDGPACKET()
!packet.elementPick(|Identify EQUI or NOZZ - Escape to cancel|)
!packet.description = |Identify Element|
!packet.action = |!!ex13b.identify(!this.return)|
!!edgCntrl.add(!packet)
endmethod
define method .identify(!pickInfo is ANY)
!item = !pickInfo[1].item
!!edgCntrl.remove(|Identify Element|)
-- Loop to find the EQUI element
!posNOZZ = 1
!pickedNozz = ||
do
if !item.type eq |NOZZ| then
!pickedNozz = !item.flnn
endif
break if (!item.type eq |EQUI|) or (!item.type eq |WORL|)
!item = !item.owner
enddo
if !item.type eq |WORL| then
!!Alert.Warning(|Choose either a nozzle or piece of equipment|)
!this.pick()
else
-- Find the EQUI in the OPTION gadget
!this.equip.val = !this.equip.dtext.FindFirst(!item.flnn)
!this.collNozz()
-- Pick the chosen NOZZ
if !pickedNozz.length() gt 0 then
Add pixmap to new button
Method as before, but now
advising user they can pick
either EQUI or NOZZ
Set initial variable values
Loop up through hierarchy to
find NOZZ or EQUI
(remember both)
Set the option gadget to the
chosen piece of equipment
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
175
www.aveva.com
do !I indices !this.nozz.dtext
!splitDTEXT = !this.nozz.dtext[!I].split()
if !pickedNozz eq !splitDTEXT[1] then
!posNozz = !I
endif
enddo
endif
!this.nozz.val = !posNozz
endif
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
Select the identified nozzle
in the nozzle list. If a piece
of EQUI was chosen, the
first nozzle in the list will be
highlighted
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
176
www.aveva.com
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
177
www.aveva.com
Appendix B25 - Example ex13c.pmlfrm
setup form !!ex13c
!this.formTitle = |Exercise 13c form|
!this.initcall = |!this.init()|
!this.newMenu(|pop1|)
!this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ')
para .prompt at x0 y0 text |Navigate : | width 46 lines 1
view .view3d at x 0.5 y0.5 call '!!edgCntrl.canvasPick(' prompt .prompt VOLUME
width 45 aspect 0.707
border off
shading on
isometric 3
inmode create _default type |DES_NAVIGATE|
inmode create _pick type |DES_PICK|
exit
frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d
para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment|
option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10
list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5
button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()|
button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()|
button .pick tooltip 'Identify Nozzle' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.pick()|
width 16 height 16
textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5
button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)|
exit
member .clipbox is GPHCLIPBOX
member .limits is ARRAY
exit
define method .ex13c()
!this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png'))
!nozz = ARRAY()
!nozz.append(|Name|)
!nozz.append(|Connected?|)
!nozz.append(|Attached?|)
!nozz.append(|Aligned?|)
!nozz.append(|Size check?|)
!this.nozz.setHeadings(!nozz)
!info[1] = 'Description - Unset'
!info[2] = 'Function - Unset'
!info[3] = 'Purpose - Unset'
!this.atta.val = !info
!this.nozz.setpopup(!this.pop1)
endmethod
define method .pick()
!packet = object EDGPACKET()
!packet.elementPick(|Identify EQUI or NOZZ - Escape to cancel|)
!packet.description = |Identify Element|
!packet.action = |!!ex13b.identify(!this.return)|
!!edgCntrl.addView(!!ex13c.view3d)
!!edgCntrl.add(!packet)
endmethod
define method .identify(!pickInfo is ANY)
!item = !pickInfo[1].item
!!edgCntrl.remove(|Identify Element|)
!!edgCntrl.RemoveView(!!ex13c.view3d)
Canvaspick open callback
applied to the VIEW
element. Prompt text gadget
added to feedback to user
Add another view to the
Once finished, remove view
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
178
www.aveva.com
-- Loop to find the EQUI element
!posNOZZ = 1
!pickedNozz = ||
do
if !item.type eq |NOZZ| then
!pickedNozz = !item.flnn
endif
break if (!item.type eq |EQUI|) or (!item.type eq |WORL|)
!item = !item.owner
enddo
if !item.type eq |WORL| then
!!Alert.Warning(|Choose either a nozzle or piece of equipment|)
!this.pick()
else
-- Find the EQUI in the OPTION gadget
!this.equip.val = !this.equip.dtext.FindFirst(!item.flnn)
!this.collNozz()
-- Pick the chosen NOZZ
if !pickedNozz.length() gt 0 then
do !I indices !this.nozz.dtext
!splitDTEXT = !this.nozz.dtext[!I].split()
if !pickedNozz eq !splitDTEXT[1] then
!posNozz = !I
endif
enddo
endif
!this.nozz.val = !posNozz
endif
endmethod
define method .init()
if !!CE.type.eq(|SITE|) then
!level = |SITE|
else
!level = |ZONE|
endif
VAR !coll COLL ALL EQUIP FOR $!level
handle ANY
!!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|)
elsehandle NONE
if !coll.size().eq(0) and !level.eq(|ZONE|) then
VAR !coll COLL ALL EQUIP FOR SITE
!!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|)
endif
VAR !name EVAL FLNN FOR ALL FROM !coll
!this.equip.dtext = !name
!this.equip.rtext = !coll
!this.collNozz()
endhandle
endmethod
define method .collNozz()
!equipRef = !this.equip.selection().dbref()
if !equipRef.unset() then
--!!Alert.(|Make sure you are at an EQUI or ZONE element|)
!this.nozz.clear()
else
!nozzColl = object COLLECTION()
!nozzColl.type('NOZZ')
!nozzColl.scope(!equipRef)
!results = !nozzColl.results()
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
179
www.aveva.com
if !nozzColl.size().geq(1) then
do !I from 1 to !nozzColl.size()
!dtext[!I] = !results[!I].flnn
!rtext[!I] = !results[!I].string()
enddo
!this.nozz.dtext = !dtext
!this.nozz.rtext = !rtext
!this.checkNozz()
!this.updateAtt(1)
!this.limits()
endif
endif
endmethod
define method .checkNozz()
do !I index !this.nozz.rtext
!nozz = !this.nozz.rtext[!I].dbref()
!nozzPos = !nozz.pos
!nozzDir = !nozz.pdir[1]
!nozzSize = !nozz.cpar[1]
!pipe = !nozz.cref
!piperef = !pipe.href
handle ANY
!connected = |Check|
!aligned = |N/A|
!size = |N/A|
!attached = |N/A|
elsehandle NONE
!connected = |OK|
if !pipe.href.eq(!nozz) then
!pipePos = !pipe.hpos
!pipeDir = !pipe.hdir
!pipeSize = !pipe.hbore
else
!pipePos = !pipe.tpos
!pipeDir = !pipe.tdir
!pipeSize = !pipe.tbore
endif
if !nozzPos.eq(!pipePos) then
!attached = |OK|
else
!attached = |Check|
endif
if !nozzDir.eq(!pipeDir) then
!aligned = |OK|
else
!aligned = |Check|
endif
if !nozzSize.eq(!pipeSize) then
!size = |OK|
else
!size= |Check|
endif
endhandle
!nozzInfo[!I][1] = !nozz.flnn
!nozzInfo[!I][2] = !connected
!nozzInfo[!I][3] = !attached
!nozzInfo[!I][4] = !aligned
!nozzInfo[!I][5] = !size
enddo
!rtext = !this.nozz.rtext
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
180
www.aveva.com
!this.nozz.setrows(!nozzInfo)
!this.nozz.rtext = !rtext
endmethod
define method .updateAtt(!flag is REAL)
!equip = !this.equip.selection().dbref()
!this.atta.tag = !equip.flnn & ' Attributes'
!contents = !this.atta.val
if !flag.eq(1) then
!n = 0
do !I index !contents
!n = !n + 1
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val[!I] = !equip.Attribute(!attrib)
handle ANY
!n = !n - 1
elsehandle NONE
if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then
!val[!I] = |Unset|
endif
!out[!n] = !attrib & | - | & !val[!I]
endhandle
enddo
!this.atta.val = !out
elseif !flag.eq(2) then
!errors = ARRAY()
do !I index !contents
!text = !contents[!I]
!split = !text.split('-')
!attrib = !split[1].trim()
!val = !split[2].trim()
if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then
!originalCE = !!CE
!!CE = !equip
$!attrib nul
!!CE = !originalCE
else
!equip.$!attrib = !val
handle ANY
!equip.$!attrib = '$!val'
handle ANY
!errors.append(!attrib)
endhandle
endhandle
endif
enddo
if !errors.unset() then
else
!err = ''
do !I from 1 to !errors.size()
if !I eq 1 then
!err = |(1) | & !errors[!I]
else
!err = !err & ', (' & !I & |) | & !errors[!I]
endif
enddo
!!Alert.Error(|The following attributes types or attribute values
are not valid for EQUI elements:
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
181
www.aveva.com
$!err|)
endif
endif
endmethod
define method .limits()
!equip = !this.equip.selection().dbref()
!add = 5
!limits[1] = !equip.wvol[1] - !add
!limits[2] = !equip.wvol[4] + !add
!limits[3] = !equip.wvol[2] - !add
!limits[4] = !equip.wvol[5] + !add
!limits[5] = !equip.wvol[3] - !add
!limits[6] = !equip.wvol[6] + !add
!this.limits = !limits
!this.view3d.limits = !limits
!pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2
!pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2
!pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2
!this.clipbox.box.position.east = !pos[1]
!this.clipbox.box.position.north = !pos[2]
!this.clipbox.box.position.up = !pos[3]
!this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add
!this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add
!this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add
!this.clipbox.view = !this.view3d
!this.clipbox.active = FALSE
!this.clipbox.view.owner().clipbox.set()
!this.view3d.clipping = TRUE
endmethod
AVEVA Plant (12 Series)
Programmable Macro Language - TM-1401
182
www.aveva.com
Appendix B26 - Example ex14
Addin – filename: PML
name: PMLTraining
title: PML Training
showOnMenu: FALSE
object: appPML
Object – filename: apppml.pmlobj
define object appPML
endobject
define method .UtilsMenu()
!menu = object APPMENU('SYSUTIL')
!menu.add('SEPARATOR')
!menu.add('MENU', |Calculator|, 'CalcForm')
!menu.add('MENU', |Equipment Checker|, 'EquipCheck')
!!appMenuCntrl.addMenu(!menu, 'EQUI')
!menu = object APPMENU('CalcForm')
!menu.add('FORM', |Exercise 6(a)...|, |ex6a|)
!menu.add('FORM', |Exercise 6(b)...|, |ex6b|)
!menu.add('FORM', |Exercise 6(c)...|, |ex6c|)
!menu.add('FORM', |Exercise 6(d)...|, |ex6d|)
!menu.add('FORM', |Exercise 7...|, |ex7|)
!menu.add('FORM', |Exercise 8...|, |ex8|)
!menu.add('FORM', |Exercise 9...|, |ex9|)
!!appMenuCntrl.addMenu(!menu, 'EQUI')
!menu= object APPMENU('EquipCheck')
!menu.add('FORM', |Exercise 10...|, |ex10|)
!menu.add('FORM', |Exercise 11(a)...|, |ex11a|)
!menu.add('FORM', |Exercise 11(b)...|, |ex11b|)
!menu.add('FORM', |Exercise 12(a)...|, |ex12a|)
!menu.add('FORM', |Exercise 13(a)...|, |ex13a|)
!!appMenuCntrl.addMenu(!menu, 'EQUI')
endmethod
define method .toolbars()
frame .PMLToolbar toolbar 'PMLToolbar'
!calcPixmap = !!pml.getPathName('calculator.png')
!equiPixmap = !!pml.getPathName('spanner.png')
button .calc 'Show Calculator' tooltip 'Show Calculator ' pixmap /$!<calcPixmap> width 16 height
16 callback |show !!ex9|
button .equi 'Show Equipment Checker' tooltip 'Show Equipment Checker ' pixmap
/$!<equiPixmap> width 16 height 16 callback |show !!ex12a|
exit
!!appTbarCntrl.addToolbar('PMLToolbar', 'EQUI')
endmethod
define method .modifyMenus()
!this.UtilsMenu()
endmethod
define method .modifyForm()
!this.toolbars()
endmethod
Define the menu names first
and add them to the Utilities
menu
Once defined, submenus
can be applied
Toolbar needs to be in a
frame (containing the
reference toolbar)
Pixmap buttons added
Standard modfy methods
run the methods above
methods

More Related Content

DOC
Pdms latest commands
PPTX
Process Drawings
PDF
ARMACO STANDARD
PDF
Aspen Capital Cost Estimator User s Guide.pdf
PPTX
Tag numbering system
PPT
Electrical and Instrumentation (E&I) Engineering for Oil and Gas Facilities
PDF
EPLAN-Function Overview
PDF
compressor alignment procedure -1.pdf
Pdms latest commands
Process Drawings
ARMACO STANDARD
Aspen Capital Cost Estimator User s Guide.pdf
Tag numbering system
Electrical and Instrumentation (E&I) Engineering for Oil and Gas Facilities
EPLAN-Function Overview
compressor alignment procedure -1.pdf

What's hot (20)

PDF
SCRM[1]
PDF
Toyota 6FD18 Forklift Service Repair Manual
PDF
Mechanical completion
PDF
Caterpillar cat 3054 c industrial engine (prefix 334) service repair manual (...
PPTX
PRESSURE VESSELS & STORAGE TANKS.pptx
PDF
Pipe hangers
PDF
Flange Bolt Chart
PDF
PERKINS 1100 SERIES 1106C INDUSTRIAL ENGINE (ELECTRONIC)(Model VK)Service Rep...
PDF
Perkins 2506 15
PDF
New holland lb115 b backhoe loader service repair manual
PDF
Piping Training course-How to be an Expert in Pipe & Fittings for Oil & Gas c...
PDF
Piping components, materials, codes and standards part 1- pipe
PDF
Perkins 2800 series 2806 c e18 tag3 diesel engine service repair manual
PDF
Saes w-011-welding on plot ( process ) piping
PPTX
Introduction to piping.......PLEASE give your valuable comments if you like t...
PDF
PERKINS 2200 SERIES 2206D-E13TA INDUSTRIAL ENGINE Service Repair Manual
PDF
Pressure piping thickness and flange rating calculation 2
PDF
Komatsu sk714 5 skid steer loader service repair manual (sn 37 af01876 and up)
PDF
Electronic modular control panel ii + paralleling emcp ii + p systems ope...
PDF
Jcb 540 170 load control (supplement) service repair manual
SCRM[1]
Toyota 6FD18 Forklift Service Repair Manual
Mechanical completion
Caterpillar cat 3054 c industrial engine (prefix 334) service repair manual (...
PRESSURE VESSELS & STORAGE TANKS.pptx
Pipe hangers
Flange Bolt Chart
PERKINS 1100 SERIES 1106C INDUSTRIAL ENGINE (ELECTRONIC)(Model VK)Service Rep...
Perkins 2506 15
New holland lb115 b backhoe loader service repair manual
Piping Training course-How to be an Expert in Pipe & Fittings for Oil & Gas c...
Piping components, materials, codes and standards part 1- pipe
Perkins 2800 series 2806 c e18 tag3 diesel engine service repair manual
Saes w-011-welding on plot ( process ) piping
Introduction to piping.......PLEASE give your valuable comments if you like t...
PERKINS 2200 SERIES 2206D-E13TA INDUSTRIAL ENGINE Service Repair Manual
Pressure piping thickness and flange rating calculation 2
Komatsu sk714 5 skid steer loader service repair manual (sn 37 af01876 and up)
Electronic modular control panel ii + paralleling emcp ii + p systems ope...
Jcb 540 170 load control (supplement) service repair manual
Ad

Similar to Programmable Macro Language (Basic) (20)

PDF
AVEVA Plant And AVEVA Marine (12.1) Diagrams Administration
POTX
Alarm Notifications with WIN-911 NOW Available for InduSoft Web Studio - Indu...
PDF
73299519-Avaya-Communication-Manager-Basic-Diagnostics-Quick-Reference.pdf
PDF
5410 User
PDF
S7 auto_install
PDF
Honeywell vista-10p-programming-guide
PDF
Manual ip1603
PDF
En 600stdprg fwmanual
PDF
Assembly Language for X86 Processors 8th Edition Kip R. Irvine
PDF
PDF
라벨뷰 Labelview 바코드라벨디자인프로그램 바코드라벨출력프로그램 바코드라벨인쇄프로그램 매뉴얼
PDF
Pendukung Printer APD4_T81_Devmode_E_RevE.pdf
PDF
Delta v emerson_getting_started
PDF
Man Avira Antivir Unix Server En
PDF
Atv32 programming manual
PDF
Logo e 97
PDF
데이타맥스프린터 DATAMAX A-Class 열전사 RFID 바코드프린터엔진 오토라벨러엔진 매뉴얼
PPTX
CoDeSys First Steps.pptx to programming for beginners
AVEVA Plant And AVEVA Marine (12.1) Diagrams Administration
Alarm Notifications with WIN-911 NOW Available for InduSoft Web Studio - Indu...
73299519-Avaya-Communication-Manager-Basic-Diagnostics-Quick-Reference.pdf
5410 User
S7 auto_install
Honeywell vista-10p-programming-guide
Manual ip1603
En 600stdprg fwmanual
Assembly Language for X86 Processors 8th Edition Kip R. Irvine
라벨뷰 Labelview 바코드라벨디자인프로그램 바코드라벨출력프로그램 바코드라벨인쇄프로그램 매뉴얼
Pendukung Printer APD4_T81_Devmode_E_RevE.pdf
Delta v emerson_getting_started
Man Avira Antivir Unix Server En
Atv32 programming manual
Logo e 97
데이타맥스프린터 DATAMAX A-Class 열전사 RFID 바코드프린터엔진 오토라벨러엔진 매뉴얼
CoDeSys First Steps.pptx to programming for beginners
Ad

More from Hadi Karimi (14)

PDF
Piping Farsi Manual
PPT
Visual Studio 2008 & .Net 3.5
PDF
AVEVA-Schematic-3D-Integrator
PDF
AVEVA Everything 3D
PDF
AVEVA Engineering
PDF
AVEVA Pipe Stress Interface
PDF
AVEVA Multi Discipline Supports
PDF
AVEVA Plant
PDF
AVEVA Review
PDF
AVEVA PID 12.0
PDF
AVEVA Diagrams 12.0
PDF
AVEVA Instrumentation
PDF
AVEVA Electrical
PDF
AVEVA PDMS 12.0
Piping Farsi Manual
Visual Studio 2008 & .Net 3.5
AVEVA-Schematic-3D-Integrator
AVEVA Everything 3D
AVEVA Engineering
AVEVA Pipe Stress Interface
AVEVA Multi Discipline Supports
AVEVA Plant
AVEVA Review
AVEVA PID 12.0
AVEVA Diagrams 12.0
AVEVA Instrumentation
AVEVA Electrical
AVEVA PDMS 12.0

Programmable Macro Language (Basic)

  • 2. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 2 www.aveva.com
  • 3. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 3 www.aveva.com Revision Log Date Revision Description of Revision Author Reviewed Approved 16/01/2009 0.1 Issued for Review BT 26/01/2009 0.2 Reviewed BT EW 29/01/2009 1.0 Approved for Training 12.0.SP3 BT EW RP Updates All headings containing updated or new material will be highlighted. Suggestion / Problems If you have a suggestion about this manual or the system to which it refers please report it to the AVEVA Group Solutions Centre at gsc@aveva.com This manual provides documentation relating to products to which you may not have access or which may not be licensed to you. For further information on which products are licensed to you please refer to your licence conditions. Visit our website at http://www.aveva.com 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. 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, trademark rights or other intellectual property rights in any other product, its name or logo belongs to its respective owner.
  • 4. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 4 www.aveva.com 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 Limited. 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 Limited or 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 licence agreements, and in accordance with the relevant User Documentation. Unauthorised or unlicensed use of the product is strictly prohibited. Printed by AVEVA Solutions on 28 January 2009 © AVEVA Solutions and its subsidiaries 2001 – 2007 AVEVA Solutions Ltd, High Cross, Madingley Road, Cambridge, CB3 0HB, United Kingdom.
  • 5. 5 Contents www.aveva.com 1 Introduction.............................................................................................................................................. 9 1.1 Aim .................................................................................................................................................... 9 1.2 Objectives......................................................................................................................................... 9 1.3 Prerequisites .................................................................................................................................... 9 1.4 Course Structure.............................................................................................................................. 9 1.5 Using this guide ............................................................................................................................... 9 2 PML Overview ........................................................................................................................................ 11 2.1 PML Programmable Macro Language.......................................................................................... 11 2.2 PML2 - A More Powerful Language.............................................................................................. 11 2.3 PML 2 Jargon.................................................................................................................................. 12 2.4 Features of PML2 ........................................................................................................................... 12 3 Macros and Synonyms.......................................................................................................................... 13 3.1 A simple Macro............................................................................................................................... 13 3.2 The OUTPUT Command ................................................................................................................ 13 3.3 Communicating with AVEVA Products in PML........................................................................... 14 3.4 Parameterised Macros................................................................................................................... 14 3.5 Synonyms....................................................................................................................................... 14 3.6 Recursive Synonyms..................................................................................................................... 15 3.7 Deleting Synonyms........................................................................................................................ 15 Exercise 1 - The Centre of a Handwheel ..................................................................................................... 16 4 Variables................................................................................................................................................. 17 4.1 Numbered Variable types.............................................................................................................. 17 4.2 Named Variable types.................................................................................................................... 17 4.2.1 Setting named variables........................................................................................................... 17 4.3 PML 2 Variable types ..................................................................................................................... 18 4.3.1 Creating Variables.................................................................................................................... 18 4.3.2 Expanding Variables ................................................................................................................ 18 4.3.3 Expressions.............................................................................................................................. 19 4.3.4 Expression operators ............................................................................................................... 19 4.3.5 Operator Precedence............................................................................................................... 19 4.3.6 PML 2 expressions................................................................................................................... 20 4.3.7 Using Variables In Expressions ............................................................................................... 20 4.3.8 Arrays....................................................................................................................................... 20 4.3.9 Concatenation Operator........................................................................................................... 20 Exercise 2 - The variable Centre of a Handwheel....................................................................................... 21 5 PML Control............................................................................................................................................ 23 5.1 DO loop ........................................................................................................................................... 23 5.1.1 DO loops with BREAK.............................................................................................................. 23 5.1.2 DO loops with SKIP.................................................................................................................. 24 5.1.3 DO Index and DO Values......................................................................................................... 24 5.1.4 DO Loops Examples ................................................................................................................ 24 5.2 IF Statements.................................................................................................................................. 25 5.2.1 Simple IF construct. ................................................................................................................. 25 5.2.2 IF, THEN, ELSEIF and ELSE Statements ............................................................................... 25 5.3 Branching ....................................................................................................................................... 25 5.4 Conditional Jumping ..................................................................................................................... 26 Exercise 3 - The Full Handwheel.................................................................................................................. 26 6 Boolean Expressions and IF Statements ............................................................................................ 27 6.1 Simple Boolean Expressions........................................................................................................ 27 6.2 Converting a value to BOOLEAN ................................................................................................. 27 6.3 Valid Boolean expressions ........................................................................................................... 27 6.4 Invalid Boolean expressions ........................................................................................................ 28 6.5 Boolean expressions PML1 upward compatibility.................................................................... 28 7 Errors & Error Handling ........................................................................................................................ 29 7.1 Example of Errors .......................................................................................................................... 29 7.2 Error Handling................................................................................................................................ 29 7.3 Alert Objects................................................................................................................................... 29 7.3.1 Alert Objects with no return value ............................................................................................ 29
  • 6. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 6 www.aveva.com 7.4 Alert Objects that return value ..................................................................................................... 30 7.4.1 Confirm Alerts........................................................................................................................... 30 7.4.2 Question Alerts......................................................................................................................... 30 7.4.3 Input Alerts ............................................................................................................................... 30 Exercise 4 – Error Handling.......................................................................................................................... 31 8 PML 1 Hierarchy..................................................................................................................................... 33 8.1 Modifications to PDMSUI .............................................................................................................. 33 9 PML2 Functions and Objects ............................................................................................................... 35 9.1 The pmllib environment variable.................................................................................................. 35 9.2 Modifications to pmllib.................................................................................................................. 35 9.3 Updating PDMSUI and PMLLIB..................................................................................................... 36 9.4 PML2 Objects ................................................................................................................................. 36 9.5 PML2 Methods................................................................................................................................ 36 9.6 Method Concatenation .................................................................................................................. 37 9.7 The !!CE Object .............................................................................................................................. 38 9.8 PML2 Functions ............................................................................................................................. 38 Exercise 5(a) – Convert the Hose reel macro into a function ................................................................... 39 Exercise 5(b) – Adding arguments to the function .................................................................................... 40 10 Forms .................................................................................................................................................. 41 10.1 Forms Are Global Objects............................................................................................................. 41 10.2 Dynamic loading of Objects, Forms and Functions................................................................... 41 10.3 Form Definition............................................................................................................................... 42 10.3.1 Using the .net framework ......................................................................................................... 42 10.3.2 Showing and hiding Forms....................................................................................................... 42 10.3.3 Built-in methods for Forms....................................................................................................... 43 10.4 Callbacks ........................................................................................................................................ 43 10.5 Form Gadgets................................................................................................................................. 44 10.5.1 Built-in members and methods for Gadgets ............................................................................ 44 10.5.2 Gadget positioning ................................................................................................................... 45 10.5.3 Docking and Anchoring Gadgets ............................................................................................. 46 10.6 Paragraph Gadgets........................................................................................................................ 47 10.7 Button Gadgets .............................................................................................................................. 47 10.7.1 Linklabel ................................................................................................................................... 48 10.8 Text Entry Gadgets ........................................................................................................................ 48 10.9 Format Object................................................................................................................................. 49 10.10 List Gadgets ............................................................................................................................... 50 10.11 Frame Gadgets........................................................................................................................... 52 10.11.1 Fold Up Panel Frames ......................................................................................................... 53 10.12 Textpane Gadgets...................................................................................................................... 53 10.13 Option Gadgets .......................................................................................................................... 54 10.14 Toggle Gadgets.......................................................................................................................... 54 10.15 Radio Gadgets............................................................................................................................ 55 10.16 Form Member Variables ............................................................................................................ 56 10.17 Tooltips ....................................................................................................................................... 56 10.18 Progress Bar............................................................................................................................... 57 Exercise 6(a) - Calculation methods........................................................................................................... 58 Exercise 6(b) - Loops .................................................................................................................................... 59 Exercise 6(c) – Concatenation ..................................................................................................................... 60 Exercise 6(d) – String manipulation ............................................................................................................ 61 Exercise 7 – Storing and resetting defaults................................................................................................ 62 10.19 Open Callbacks .......................................................................................................................... 63 Exercise 8 – Tabsets and Open Callbacks.................................................................................................. 64 10.20 Bar Menus................................................................................................................................... 65 10.20.1 Defining a Menu Object........................................................................................................ 65 11 PML Objects ....................................................................................................................................... 67 11.1 Built in PML OBJECT Types ......................................................................................................... 67 11.2 Forms and Menus Objects............................................................................................................ 68 11.3 3D Geometry Objects .................................................................................................................... 68 11.4 Methods Available to All Objects ................................................................................................. 69 11.5 The File Object ............................................................................................................................... 70 11.5.1 Using file objects ...................................................................................................................... 70
  • 7. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 7 www.aveva.com 11.5.2 Use Notepad to open file.......................................................................................................... 71 Exercise 9 – Menubar.................................................................................................................................... 71 12 User-Defined Objects ........................................................................................................................ 73 13 Collections.......................................................................................................................................... 75 13.1 The Collection Syntax (PML 1) ..................................................................................................... 75 13.2 The Object Collection Syntax (PML 2) ......................................................................................... 75 Exercise 10 – Equipment Collections.......................................................................................................... 76 14 Pop-Up Menus.................................................................................................................................... 77 Exercise 11(a) – Pop-up menu ..................................................................................................................... 78 Exercise 11(b) – Equipment Checking ........................................................................................................ 79 Exercise 11(c) – Setting Equipment attributes........................................................................................... 80 15 View Gadgets ..................................................................................................................................... 81 15.1 Alpha Views.................................................................................................................................... 81 15.2 Plot View Example ......................................................................................................................... 81 15.3 Volume View example ................................................................................................................... 82 Exercise 12(a) – Adding a Volume View...................................................................................................... 83 Exercise 12(b) – Adding a Clipbox to the view........................................................................................... 84 Exercise 12(c) – Dynamically modify a clipbox.......................................................................................... 85 Exercise 12(d) – Add Nozzle tagging........................................................................................................... 86 Exercise 12(e) – Add Highlighting ............................................................................................................... 87 16 Event Driven Graphics (EDG) ........................................................................................................... 89 16.1 Simple EDG..................................................................................................................................... 89 16.2 Using EDG ...................................................................................................................................... 90 Exercise 13 – Using EDG .............................................................................................................................. 91 Exercise 13(a) – Add EDG to !!ex10............................................................................................................. 91 Exercise 13(b) – Add EDG to !!ex11b .......................................................................................................... 92 Exercise 13(c) – Add EDG to !!ex12b........................................................................................................... 93 17 Miscellaneous .................................................................................................................................... 95 17.1 Recursive Pml2 Functions............................................................................................................ 95 17.2 Undo and Redo............................................................................................................................... 95 17.2.1 Marking the database............................................................................................................... 95 17.2.2 Undo and Redo Database Commands .................................................................................... 95 17.3 Error tracing ................................................................................................................................... 96 18 Menu Additions .................................................................................................................................. 97 18.1 Miscellaneous Notes ..................................................................................................................... 97 18.2 Modules that use the new Addins functionality ......................................................................... 97 18.3 Adding a Menu/Toolbar................................................................................................................. 97 18.4 Application Design ........................................................................................................................ 97 18.5 Form and Toolbar Control............................................................................................................. 98 18.6 Converting Existing Applications ................................................................................................ 98 18.6.1 DBAR and Add-in Object ......................................................................................................... 99 18.6.2 Bar Menu and Toolbar ............................................................................................................. 99 18.6.3 Define toolbar........................................................................................................................... 99 18.6.4 Adding to Menus ...................................................................................................................... 99 18.6.5 Adding new menus to form .................................................................................................... 100 18.7 Example object including toolbars, bar menus and menus.................................................... 101 Exercise 14 – Add a Utility and Toolbar menu ......................................................................................... 103 19 Upgrading from PML1 to PML2 ...................................................................................................... 105 19.1 Points to watch out for................................................................................................................ 105 Appendix A – PDMS Primitives.................................................................................................................. 107 Appendix B – Example code ...................................................................................................................... 111 Appendix B1 - Example ex1.mac ........................................................................................................... 111 Appendix B2 - Example ex2.mac ........................................................................................................... 112 Appendix B3 - Example ex3.mac ........................................................................................................... 113 Appendix B4 - Example ex4.mac ........................................................................................................... 114 Appendix B5 - Example ex5a.pmlfnc..................................................................................................... 115 Appendix B6 - Example ex5b.pmlfnc..................................................................................................... 116 Appendix B7 - Example ex6a.pmlfrm .................................................................................................... 118 Appendix B8 - Example ex6b.pmlfrm .................................................................................................... 119 Appendix B9 - Example ex6c.pmlfrm .................................................................................................... 121 Appendix B10 - Example ex6d.pmlfrm .................................................................................................. 124
  • 8. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 8 www.aveva.com Appendix B11 - Example ex7.pmlfrm .................................................................................................... 127 Appendix B12 - Example ex8.pmlfrm .................................................................................................... 131 Appendix B13 - Example ex9.pmlfrm .................................................................................................... 135 Appendix B14 - Example ex10.pmlfrm .................................................................................................. 139 Appendix B15 - Example ex11a.pmlfrm ................................................................................................ 140 Appendix B16 - Example ex11b.pmlfrm ................................................................................................ 141 Appendix B17 - Example ex11c.pmlfrm ................................................................................................ 143 Appendix B18 - Example ex12a.pmlfrm ................................................................................................ 146 Appendix B19 - Example ex12b.pmlfrm ................................................................................................ 150 Appendix B20 - Example ex12c.pmlfrm ................................................................................................ 154 Appendix B21 - Example ex12d.pmlfrm ................................................................................................ 159 Appendix B22 - Example ex12e.pmlfrm ................................................................................................ 165 Appendix B23 - Example ex13a.pmlfrm ................................................................................................ 172 Appendix B24 - Example ex13b.pmlfrm ................................................................................................ 174 Appendix B25 - Example ex13c.pmlfrm ................................................................................................ 177 Appendix B26 - Example ex14................................................................................................................ 182
  • 9. 9 www.aveva.com CHAPTER 1 1 Introduction This manual is designed to give an introduction to the AVEVA Plant Programming Macro Language, There is no intention to teach software programming but just how the customisation using PML can be done in AVEVA Plant. Appendix B contains example code that answers each exercise. The exercises have been deliberately written to be open to interpretation. This means that the code you produce maybe different. 1.1 Aim The following points need to be understood by the trainees: Understand how PML can be used to customise Vantage Plant Design (PDMS) Understand how to create Functions, Forms and Objects. Understand how to use the built-in features of Vantage Plant Design (PDMS) Understand the use of Addins to customise the environment. 1.2 Objectives At the end of this training, you will have a: Broad overview of Programmable Macro Language Basic coding practices and conventions How PML can interact with the Design model How Forms and Menus can be defined with PML 1.3 Prerequisites The participants must have completed an AVEVA Basic Design Course and have some basic progremmin knowledge. 1.4 Course Structure Training will consist of oral and visual presentations, demonstrations and set exercises. Each workstation will have a training project, populated with model objects. This will be used by the trainees to practice their methods, and complete the set exercises. 1.5 Using this guide Certain text styles are used to indicate special situations throughout this document, here is a summary; Menu pull downs and button press actions are indicated by bold dark turquoise text. Information the user has to Key-in 'will be red and BOLD' Annotation for trainees benefit: Additional information Refer to other documentation System prompts should be bold and italic in inverted commas i.e. 'Choose function' Example files or inputs will be in the courier new font, colours and styles used as before.
  • 10. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 10 www.aveva.com
  • 11. 11 www.aveva.com CHAPTER 2 2 PML Overview Macros A macro is a group of PDMS commands written to a file PML Programmable Macro Language (two parts) PML1 First version of PML including loops, IF statements, string handling, labels etc. PML2 Object orientated language builds on PML1 and extends the facilities to be like other object based languages (C++, Smalltalk) Forms Most applications are driven by forms and menus. Most PML will be based on a form. 2.1 PML Programmable Macro Language Macros are ASCII files containing PDMS commands in sequence. By asking PDMS to run a macro, you are really asking PDMS to run a series of commands in a set order (as defined in the macro file) Programmable macros are macros that contain program constructs such as IF statements, DO loops and variables Macros are run in PDMS by typing $m/FILENAME on to the command line (Display>Command Line). Any extra information added to a macro line is treated as input parameters and are passed to the macro. i.e. $M/BUILDBOX 100 200 300 This means that the extra 3 values after the macro name are treated as parameters 1, 2 and 3. When entered in this way, these parameters are then available for use in the macro instead of fixed values. 2.2 PML2 - A More Powerful Language PML2 is an enhanced version of PML and is more like other modern languages that you may be familiar with. PML2 is almost an object oriented language. It provides most features of other Object Orientated Programming (OOP) languages except for inheritance. It provides 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. Typically, fewer lines of code needed with PML2 when compared to traditional PML (PML1) and it has been designed to be easier to read/write. While most PML1 macros will still run within PDMS, PML2 bring many new features that were previously unavailable. Built in methods for different variable types remove several multi line procedures used in old style macros. Use of $ characters is dramatically reduced with a more readable format for expressions $-style macros will still work provided the syntax has been followed correctly. It is possible to convert traditional PML code to include newer PML2 features, but it is important that users maintain compatibility at all times. Many new features have been added to improve speed and ease of use. These features will be discussed and demonstrated through this course.
  • 12. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 12 www.aveva.com 2.3 PML 2 Jargon 2.4 Features of PML2 The main features of PML2 are: • Available Variable Types - STRING, REAL, BOOLEAN, ARRAY • Built in Methods for commonly used actions • Global Functions supersede old style macros • User Defined Object Types • PML Search Path (PMLLIB) • Dynamic Loading of Forms, Functions and Objects • Aid objects for geometric modelling PML is now more consistent with other programming languages and more structured in form. The new data types are now OBJECTS which can be operated by running METHODS. The old $ based variables are still valid, but are always treated as strings. Global functions are macros which can be called more like subroutines than traditional macros. e.g. a function can be called between the brackets of an IF statement and return a BOOLEAN result User-defined object types enable a group of mixed variables to be combined into packages. The resulting object can then be used as a simple variable and the separate parts set or used as attributes of the variable. e.g. !fred.position !fred.name Search paths and dynamic loading mean that it is no longer necessary to pre load forms or have synonyms for calling macros. A large number of new aid objects have been created so that users can do more graphical construction.
  • 13. 13 www.aveva.com CHAPTER 3 3 Macros and Synonyms A macro is a group of PDMS commands written to a file (in sequence) that can be run together. This removes the need for user to have to enter every line of code separately. This means that repetitive processes can be run as a macro. 3.1 A simple Macro Below is an example of a macro to produce a BOX and CYLINDER and connect to two together, all within an EQUI. Type the following into a suitable text editor and save it as c:pmltrainingSimpleMac.mac NEW EQUIP /ABCD NEW BOX XLEN 300 YLEN 400 ZLEN 600 NEW CYL DIA 400 HEI 600 CONN P1 TO P2 OF PREV You have created your first macro. To run the macro into PDMS, type $M/ onto the command file, followed by the full file path of the saved macro. e.g. $M/c:pmltrainingSimpleMac.mac When running this macro in, ensure the Current Element (CE) is a ZONE or below Alternatively the macro can be run by Dragging and Dropping it onto the Command Window. 3.2 The OUTPUT Command While developing a macro there are two main methods within PDMS to find the information it needs: OUTPUT command DB listing utility Both provide the information needed, so the choice on which will be personal. An example of using the OUTPUT command is as follows: Type file /c:pmltrainingaa.txt onto the command line, then press enter (typing file /c:pmltrainingaa.txt over or FFile /c: pmltrainingaa.txt is also acceptable). PDMS will open the specified file ready to write to. If the file does not exist, this process will create it. Choose the require element of interest and ensure it is the CE. After it is chosen, type OUTPUT CE onto the command line. This will print the information PDMS has about the CE to the file. Last step, type TERM onto the command line. This will close the form, allowing it to be opened by another program. This file will hold the information (e.g. attributes) PDMS needs to define the elements. Try the OUTPUT command on the equipment created by SimpleMac.mac. Notice the additional information PDMS saves about the elements (information not specified in the macro).
  • 14. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 14 www.aveva.com 3.3 Communicating with AVEVA Products in PML All commands need to be supplied to the command processor as STRINGS. This is important when working with element creation (using the NEW syntax) To expand the contents of a PML variable into a string - put a $ in front of it! !CompType = |ELBO| !dist = 5600 NEW $!CompType DIST $!dist 3.4 Parameterised Macros Macros can be parameterised. This means instead of hard coding the values through the macro, the values can be referenced, allowing them to be varied. Simplemac.mac can be parameterised as follows: NEW EQUIP /$1 NEW BOX XLEN $2 YLEN $3 ZLEN $4 NEW CYL DIA $3 HEI $4 CONN P1 TO P2 OF PREV Save the Macro as c:pmltrainingParameterMac.mac To run this Macro, parameters need to be passed to it. This appending the parameter values to the macro: e.g. $M/c:pmltrainingParameterMac.mac ABCDE 300 400 600 If no parameters are specified, the macro will fail. To avoid this, default values can be put inside the macro. This is done by specified $d1= at the top of the macro. For example: $d1=ABCDEF $d2=300 $d3=400 $d4=600 Default values will only be used if no parameters are specified. Macros may have up to 9 parameters separated by space. In the below example, ABC, DEF & GHK are seen as separate strings and therefore different parameters: e.g. $M/c:pmltrainingNinePara.mac ABC DEF GHK 55 66 77 88 99 00 If a text string is required as a single parameter, it can be entered by placing a $< before and a $> after the string. e.g. $M/c:pmltrainingSevenPara.mac $<ABC DEF GHK$> 55 66 77 88 99 00 $< $> act as delimiters and anything in between is interpreted as a single parameter. 3.5 Synonyms Synonyms are abbreviations of longer commands. They are created by assigning the command to a synonym variable: e.g. $SNewBox=NEW BOX XLEN 100 YLEN 200 ZLEN 300 A synonym can also be parameterised:
  • 15. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 15 www.aveva.com e.g. $SNewBox=NEW BOX XLEN $S1 YLEN $S2 ZLEN $S3 To call the first version, type NewBox. For the second version, type NewBox 100 200 300 3.6 Recursive Synonyms It is possible for a synonym to call itself, effectively looping through the same command. The following example shows how the XLEN attribute of a group of boxes (owned by the same element) can be updated: e.g. $SXChange=XLEN 1000 $/ NEXT $/ XChange This method will end with an error as it runs until it runs out of boxes to change. $/ acts as a return character 3.7 Deleting Synonyms To kill a synonym, type $SXXX= & all synonyms $sk To switch synonyms off and on $S- and $S+ If all synonyms are killed, the synonyms needed to run PDMS will be removed. This means PDMS will no longer work properly and will require restarting. If synonyms are turned off, some PDMS functionality will also be removed. The return this functionality, the synonyms should be turned back on.
  • 16. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 16 www.aveva.com Exercise 1 - The Centre of a Handwheel Write a macro to build the centre of a handwheel (shown right) It shall be constructed from 4 primitives: 2 boxes, a cylinder and a dish Create the primitives within a PDMS Design session using the available appware. Once this is done, use the OUTPUT command to see the information PDMS needs to create them. Based on the output, use the CONN command to connect the Ppoints of primitives together i.e. CONN P1 TO P1 OF PREV This will connect PPoint 1 (P1) of the current primitive to P1 of the primitive created previously. The hierarchy created should look similar to the following: The dimensions of the primitives are: BOX1 - Xlength = 100mm Ylength = 100mm Zlength = 100mm CYLI - Diameter = 80mm Height = 5mm BOX2 - Xlength = 50mm Ylength = 50mm Zlength = 15mm DISH1 - Diameter = 50mm Height = 15mm To aid with connecting the primitives, refer to the adjacent diagram showing an exploded version of the equipment, with the PPoints identified. At the end of the macro add the following line: ADD /HandWheel AUTO /HandWheel This line will add the created equipment to the drawlist and scale the view so it can be seen. You could also add the following line before it. REM ALL This will clear the drawlist first, ensuring that only the new piece of equipment is seen in the main 3D window. Save the file as c:pmltrainingex1.mac and run it on the command line by typing $m/c:pmltrainingex1.mac An example of the completed macro can be found in Appendix B
  • 17. 17 www.aveva.com CHAPTER 4 4 Variables Variables set using the VAR syntax are PML1 style variables and are stored in AVEVA products as strings. Otherwise, they are PML2 style variables. 4.1 Numbered Variable types Numbered variables are set by typing a number then value after the command VAR. Examples of this are below: var 1 name var 2 ‘hello’ var 3 (99) var 4 (99 * 3 / 6 + 0.5) var 117 pos in site var 118 (name of owner of owner) var 119 ‘hello ’ + ‘world ‘ + ‘how are you’ To obtain the value of variable 1, enter q var 1, q var 117 etc. The available variable numbers only go to 119 (there is no 120) and they are module dependant. For these reasons, this technique is no longer commonly used. 4.2 Named Variable types To give a variable a name, the required name must be preceded with either a single or double exclamation mark (!), !variablename or !!variablename single ! - a local variable (can only be seen in the current macro) double!! - a global variable Variable names may be up to 64 characters long and the names can contain alpha and numeric characters. Variable names must not start with a number or contain a . (full stop) 4.2.1 Setting named variables The following are some examples of setting variables: VAR !FRED NAME Takes the current element’s (ce) name attribute VAR !POS POS IN WORLD Takes ce position attribute relative to world coordinates VAR !x ‘NAME’ Sets the variable to the text string ‘NAME’ VAR !temp (23 * 1.8 + 32) Calculate a value using the expression VAR !list COLL ALL ELBO FOR CE Makes a string array of database references Quotes ‘ ‘ or vertical bars | | may be used as text Delimiters
  • 18. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 18 www.aveva.com 4.3 PML 2 Variable types There are four basic variable types: STRING ‘any alpha numeric characters’ REAL any numeric value BOOLEAN true/false t/f (but not 0/1) ARRAY any combination of the above Note: PML1 style variables using the VAR syntax are only stored as strings. 4.3.1 Creating Variables The following are some examples of setting PML2 variables types: !Name = ‘Fred’ To create a LOCAL, STRING variable !!Answer = 42 To create a GLOBAL, REAL variable: !!Flag = TRUE To create a GLOBAL, BOOLEAN variable: !newarray = ARRAY() To create a LOCAL empty ARRAY !newarray[1] = |xxx| or !newarray[1] = ‘xxx’ To add to first value to the empty ARRAY (locally) The type of variable is automatically implied by its content !!answer = 42 becomes a REAL !name = ‘fred’ becomes STRING !flag = TRUE becomes BOOLEAN Variables can be initialised to ensure only correct results can be set. All variable types can be set up the following way: !!number = real() !!text = string() 4.3.2 Expanding Variables To expand variables in AVEVA products on the command line use a $. When the line is read, the values of the variables will be used. VAR !XLEN (1000) VAR !YLEN (1000) VAR !ZLEN (1000) NEW BOX XLEN $!XLEN YLEN $!YLEN ZLEN $!ZLEN
  • 19. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 19 www.aveva.com 4.3.3 Expressions Expressions are calculations using PML variables. This can be done is a PML1 or PML2 style: PML1: VAR !Z ( |$!X| + |$!Y| ) PML2: !Z = !X + !Y In the PML1 example, !Z is set as a STRING variable. In the PML2 example, !Z is returned as a REAL, if !X and !Y are REAL Setting variables using the PML2 method is neater and more readable when compared to PML1. Any variable can be forced to be a STRING by putting a dollar in front of it. !x = 64 this returns a REAL. VAR !y (64) this returns a STRING IF(!x eq !y)THEN is invalid syntax because the comparison is mixing variable types. IF($!x eq !y)THEN valid because the dollar in front of !x forces it to be a STRING. 4.3.4 Expression operators There are a number of expression operators which are available for use. The actual syntax will depend on whether a PML1 or PML2 style has been adopted. Numeric operators: + - / * Comparison operators: LT GT EQ NE LE GE Logic operators: NOT AND OR Numeric functions: SIN COS TAN SQR POW NEGATE ASIN ACOS ATAN LOG ALOG ABS INT NINT For further examples, refer to PDMS Software Customisation Reference Manual: Some examples of expressions in use: !s = 30 * sin(45) !t = pow(20,2) (raise 20 to the power 2 (=400)) !f = (match(name of owner,|LPX|)gt 0) 4.3.5 Operator Precedence When PDMS reads an expression, there is a precedence that applied to it. This should be considered when writing one. The order is as follows: () * / + - EQ NE GT LT GE LE NOT AND OR e.g. (60 * 2 / 3 + 5) = 45
  • 20. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 20 www.aveva.com 4.3.6 PML 2 expressions PML 2 expressions may be of any complexity, they may contain calls to PML Functions and Methods and include Form gadget values ,object members and methods. For example: !NewVal = !!MyFunc(!OldVal) * !!Form.Gadget.Val / !MyArray.Method() 4.3.7 Using Variables In Expressions $ and quotes are not necessary when using the value of a variable in a PML2 expression: !X = 64 (instead of VAR !X (64)) !Y = 32 !Z = !X + !Y The same expression PML1 is still valid ( VAR !Z (|$!X| + |$!Y|) ), but in this case !Z is a STRING variable 4.3.8 Arrays 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 or it can be initialised as an empty ARRAY. If an ARRAY ELEMENT is itself an ARRAY, this will create a Multi-dimensional ARRAY. For example an example of an array, type out the following onto the command line: !x[1] = |ABCD| !x[2] = |DEFG| !y[1] = |1234| !y[2] = |5678| !z[1] = !x !z[2] = !y To query the information about !z, type q var !z. This will return the following information: <ARRAY> [1] <ARRAY> 2 Elements [2] <ARRAY> 2 Elements To find out more information about the elements within the Multi-dimensional array, type q var !z[1] or q var !z[2][1] 4.3.9 Concatenation Operator Values to be concatenated are automatically converted to STRING by the ‘&’ operator. Type the following onto the command line: !a = 64 !b = 32 !m = ‘mm’ !c = !a & !b & !m q var !c Compare this against the results of typing !d = !a + !b q var !d
  • 21. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 21 www.aveva.com Exercise 2 - The variable Centre of a Handwheel Write a parameterised macro to build the centre of a handwheel. ex1.mac will be the basis for the new macro. Also, add two extra primitives to represent an arm (a cylinder) and part of the wheel (a circular torus). Use the $d1=XXX syntax to replace the values used in ex1.mac with parameters $d1 should be used for the name of the equipment and the rest should be set as the required dimensions Give BOX1 a name so that it can be referred to. This will be useful when positioning the new cylinder and circular torus. As $1 is a string, a unique name can be created by using the variable with some additional characters e.g. /$1-XXX The new cylinder shall have a height of 500mm and should not overlap the original BOX1. Both the cylinder and circular torus shall have a diameter of 50mm. The centre line of the circular torus shall intercept the end of the new cylinder. The CONN method from exercise 1 can still be used, but instead of using PREV, we can reference other named elements. Think about the available PPoints when positioning the new primitives (Refer to Appendix A) The hierarchy created should look similar to the following: Save the file as c:pmltrainingex2.mac and run it on the command line by typing $m/c:pmltrainingex2.mac An example of the completed macro can be found in Appendix B Try running the macro again with a different equipment name variable to check it works
  • 22. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 22 www.aveva.com
  • 23. 23 www.aveva.com CHAPTER 5 5 PML Control 5.1 DO loop A DO loop is a way of looping within the PML macro allowing pieces of code to be run more than once. This is useful as it allows code to be reused and reduces the length of code. As an example, type out the following and save it a c:pmltrainingDoLoop.mac: DO !loopCounter FROM 1 TO 10 !value = !loopCounter * 2 q var !loopCounter !value ENDDO If the above example is run into PDMS, values of !loopCounter and !value with be printed to the command line for the full range of the defined loop. The step of the loop can be altered by adding BY to the loop definition: eg: DO !loopCounter FROM 1 TO 10 BY 2 5.1.1 DO loops with BREAK If you need a loop to run until a certain condition is reached, a BREAK command will exit the current loop: Type out the following example and save it a c:pmltrainingDoBreak.mac: !n = 0 DO !n = !n + 1 !value = POW(!n, 2) q var !value BREAK IF (!value GT 1000) ENDDO The BREAK command can also be called from within a normal IF construct. This is typically done if multiple break conditions need to be considered. e.g. IF (!value GT 1000) BREAK ENDIF The loop in the example will run until the BREAK condition is met. If the condition is never reached, then the code will run indefinitely! A DO loop of 1 to 100000 could be used instead, as it has an end. An open DO loop that never meets the break condition will run indefinitely
  • 24. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 24 www.aveva.com 5.1.2 DO loops with SKIP It is possible to skip part of the DO loop using the SKIP command. This could be useful if parts of a number sequence needs to be missed: Type out the following example and save it a c:pmltrainingDoSkip.mac: DO !n FROM 1 TO 25 SKIP IF (!n LE 5) OR (!n GT 15) q var !n ENDDO The SKIP command can also be called within a normal IF construct (as the BREAK command) 5.1.3 DO Index and DO Values DO Index and DO Values are ways of looping through arrays. This is an effective method for controlling the values used for the loops. Typically values are collected into an ARRAY variable then looped through using the following: DO !X VALUES !ARRAY !X takes each ARRAY element ENDDO DO !X INDEX !ARRAY !X takes a number from 1 to !ARRAY size ENDDO 5.1.4 DO Loops Examples Type out the following as an example of looping through an ARRAY of values. Save the following as c:pmltrainingDoArray.mac. VAR !Zones COLL ALL ZONES FOR SITE VAR !Names EVAL NAME FOR ALL FROM !Zones q var !Names DO !x VALUES !Names q var !x ENDDO DO !x INDEX !Names q var !Names[!x] ENDDO The example uses the COLL syntax as a method of defining an array. This syntax will be explained later in the manual. It shows how the two methods can extract the same information from the source array.
  • 25. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 25 www.aveva.com 5.2 IF Statements An IF statement is a construct for the conditional execution of commands. The commands will only be run if the conditions of the IF statement are met. 5.2.1 Simple IF construct. A simple example of an IF construct is shown below. The code within the IF construct is only run if the expression is TRUE. An example is as follows: IF ( !Number LT 0 ) THEN !Negative = TRUE ENDIF 5.2.2 IF, THEN, ELSEIF and ELSE Statements An IF construct can be extended by adding additional conditions. This is done by adding either ELSEIF or ELSE to it. When an IF construct is encountered, PML will evaluate its condition. If the condition is FALSE, PDMS will look to the next ELSEIF condition. Once a condition is found to be TRUE, that code will be run that proportional of the code and the IF construct is complete. If an ELSE condition is added, this portion of code will only be run if the other conditions are never met. This is a way of ensuring some code is always run. Type out the following example, and save it as c:pmltrainingNumCheck.mac. Run it with one real parameter. IF ($1 EQ 0) THEN $p Your value is zero ELSEIF ($1 LT 0) THEN $p Your value is less than zero ELSE $p Your value is Greater than zero ENDIF The ELSEIF and ELSE commands are optional, but there can only be one ELSE command in an IF construct. 5.3 Branching PML provides a way of jumping from one part of a macro to another using GOLABEL. LABEL /FRED Max length 16 characters, excluding (/) ... Some PML code ... GOLABEL /FRED The next line to be executed will be the line following LABEL /FRED, which could be before or after the GOLABEL command. The use of this method should be limited. It can make code hard to read and debug.
  • 26. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 26 www.aveva.com 5.4 Conditional Jumping Type out the following as an example of conditional jumping. Save it as c:pmltrainingConditional.mac. DO !A $P Processing $!A DO !B TO 10 !C = !A * !B GOLABEL /finished if (!C GT 100) $P Product $!C ENDDO ENDDO LABEL /finished $P Finished with processing = $!A Product = $!C If the expression !C GT 100 is TRUE there will be a jump to label /finished and PML execution will continue with the $P command. If the expression is FALSE, PML execution will continue with the command: $P Product $!C and go back through the DO loop. Exercise 3 - The Full Handwheel Introduce variables and calculations to reduce the number of parameters needed to build a handwheel. Use ex2.mac as a basis for the new macro and use a loop to complete the outer wheel. Create two SUBE elements. One will contain the primitives that make up the centre of the handwheel and the other the arm of the handwheel. Use a loop to copy the arm SUBE element to complete the outer wheel. When building the loop, consider how many copies are needed. When creating a copy, create the element as usual but append COPY /XXXX to the line. This will create a new element, but copy it from /XXXX e.g. NEW BOX COPY /XXXX As each arm will need to be rotated 90° from the previous, the ROTATE command can be used e.g. ROTATE BY AAA ABOUT BBB where AAA is the angle of rotation and BBB a direction to rotate around i.e. U. Think about how the loop can be used to change the angle of rotation and the name of the copied elements. The hierarchy created should look similar to the following Save the file as c:pmltrainingex3.mac and run it on the command line by typing $m c:pmltrainingex3.mac An example of the completed macro can be found in Appendix B
  • 27. 27 www.aveva.com CHAPTER 6 6 Boolean Expressions and IF Statements 6.1 Simple Boolean Expressions Expressions based on the operators such as EQ (equal to) and GT (greater than) give a BOOLEAN result which can be used directly in an IF construct. An example is as follows. Type out the example and save it as c:pmltrainingBoolean.mac. Run it as a single parameter macro. !value = int($1) IF ( !value NE 1 ) THEN !Test = FALSE ELSEIF ( !value.eq(1) ) THEN !Test = TRUE ENDIF q var !Test The expression can be a simple variable provided it is a BOOLEAN type variable: !Success = !Value GT 0 IF ( !Success ) THEN The expression could be a user-defined PML function or method that returns a BOOLEAN result: IF ( !!MyFunction() ) THEN 6.2 Converting a value to BOOLEAN There is a built-in PML method and a function for converting a value to BOOLEAN: !MyString = |TRUE| IF ( !MyString.Boolean() ) THEN ... The Boolean conversion is as follows: REAL zero becomes FALSE All other positive and negative REAL values become TRUE STRING ‘FALSE, ‘F’, ‘NO’ and ‘N’ become FALSE STRING ‘false, ‘f’, ‘no’ and ‘n’ become FALSE STRING ‘TRUE’, ‘T’, ‘YES’ AND ‘Y’ become TRUE STRING ‘true’, ‘t’, ‘yes’ and ‘y’ become TRUE 6.3 Valid Boolean expressions BOOLEAN constants are 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: if ( TRUE ) and if ( FALSE ) BOOLEAN OK if ( T ) and if ( F ) BOOLEAN OK if ( YES ) and if ( NO ) BOOLEAN OK if ( Y ) and if ( N ) BOOLEAN OK
  • 28. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 28 www.aveva.com 6.4 Invalid Boolean expressions The following do not return BOOLEAN values and are therefore invalid: if ( 1 ) and if ( 0 ) REAL invalid if ( |TRUE| ) and if ( |FALSE| ) STRING invalid if ( |T| ) and if ( |F| ) STRING invalid if ($Variable) where Variable = 1 REAL invalid 6.5 Boolean expressions PML1 upward compatibility 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: if ($Variable) where Variable = ‘TRUE’ STRING OK
  • 29. 29 www.aveva.com CHAPTER 7 7 Errors & Error Handling An error condition can occur when a command could not complete successfully. This is because of a mistake in the macro or function (either input or execution). An error normally has three effects: • An Alert box appears which the user must acknowledge. • An error message is outputted to the command line together with a trace back to the error source. • Any current running PML macros and functions are abandoned. 7.1 Example of Errors This example of an error is caused by an attempt to create an Equipment when in the wrong part of the hierarchy. (41,8) ERROR – Cannot create an EQUI at this level. The 41 is the program section which identified the error and 8 is the error code itself. 7.2 Error Handling If the input line was part of a PML macro or function, the error may optionally be HANDLED. This allows the designer of the macro to limit the errors the user will experience. Type out the following example and save it as c:pmltrainingErrorTest.mac. First run the macro at a SITE element, then at a ZONE element and then again at the same ZONE. Compare the return printed lines in the command window. NEW EQUI /ABCD HANDLE (41, 8) $p Need to be at a ZONE or below ELSEHANDLE (41, 12) $p That name has already been used. Names must be unique ELSEHANDLE ANY $p Another error has occurred ELSEHANDLE NONE $p Everything OK. EQUI created ENDHANDLE 7.3 Alert Objects Alert objects allow user-controlled pop-up forms to be used. 7.3.1 Alert Objects with no return value There are 3 types of alert with no return value: !!Alert.Error( |You cannot do this!| ) !!Alert.Message( |Saving your data now| ) !!Alert.Warning( |Incorrect value!| )
  • 30. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 30 www.aveva.com By default, all alert forms appear with the relevant button as near to the cursor as possible. To position an alert specifically, X and Y values can be specified as a proportion of the screen size. !!Alert.Error( |You cannot do this!| , 0.25, 0.1) 7.4 Alert Objects that return value There are three types of alert which return a value, confirm, question and input alerts. 7.4.1 Confirm Alerts Confirm alerts return ‘YES’ or ‘NO’ as strings e.g. !Answer = !!Alert.Confirm( |Are you sure!| ) After typing the above onto the command line, type q var !Answer 7.4.2 Question Alerts Answer alerts return ‘YES’ or ‘NO’ or ‘CANCEL’ as strings e.g. !Answer = !!Alert.Question( |OK to delete Site| ) After typing the above onto the command line, type q var !Answer 7.4.3 Input Alerts The first value is the prompt and the second is the default value. Input alerts return a value as a string. e.g. !Answer = !!Alert.Input( |Enter Width of Floor|,|10| ) After typing the above onto the command line, type q var !Answer
  • 31. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 31 www.aveva.com Exercise 4 – Error Handling Add some error handling to control any errors generated while running ex3.mac. Although you will not be able to handle every error, think about likely errors and how to handle them What would be a suitable response to an error? Should it be ignored? Or maybe some user-feedback provided? Maybe PDMS should do something automatically to correct it? An example of user-feedback could be to print a warning to the command line. To do this, start a line with $p followed by a space. Whatever is written after this shall be printed to the command line. e.g. $p Error Found To get you started, the following are examples of some errors which may occur: • At the wrong level in the hierarchy (i.e. at a PIPE element rather than a ZONE) • A suitable hierarchy level for equipment creation does not exist (or cannot be found) • An element called ‘HandWheel’ already exists Save the file as c:pmltrainingex4.mac and run it on the command line by typing $m/c:pmltraining ex4.mac An example of the completed macro can be found in Appendix B
  • 32. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 32 www.aveva.com
  • 33. 33 www.aveva.com CHAPTER 8 8 PML 1 Hierarchy All PML1 Macros are in a directory structure pointed at by the variable PDMSUI. The PDMSUI environment variable Set PDMSUI=C:AVEVAplantPDMS12.0.2pdmsui Standard AVEVA environment variable are set in a bat files called EVAR.bat in the executable directory. All PML1 macros and forms are called using synonyms For example the macros and forms associated with piping are called using the synonym CALLP $S CALLP=$M/%PDMSUI%/DES/PIPE/$s1 CALLP MPIPE This is why if all synonyms are killed that PDMS will no longer work properly 8.1 Modifications to PDMSUI It is normal practice to create a parallel hierarchy to contain any new or modified PML. Changes to AVEVA standard product may cause PDMS to function inappropriately These modifications can then be called by modifying the PDMSUI variable to point at a multi path. This can be done by putting a new file path in front of the %PDMSUI% definition. This will update the PDMSUI environment variable to include the specified file path. Set PDMSUI=c:pmltrainingPDMSUI %pdmsui% The new file path should go in front of %PDMSUI% so this area is checked first for content. Once content is found, other locations will not be searched. This modification should be done after the PDMSUI environment variable has been defined. This can be done at the bottom of the EVAR.bat file or in the PDMS.bat file (after the line which calls evar.bat). The environment variables can be checked with PDMS by using the q evar syntax q evar PDMSUI or q evar ‘SAM000’
  • 34. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 34 www.aveva.com
  • 35. 35 www.aveva.com CHAPTER 8 9 PML2 Functions and Objects 9.1 The pmllib environment variable The PMLLIB environment variable points to a PML2 directory structure Set PMLLIB= C:AVEVAplantPDMS12.0.2pmllib There are 3 new file extensions .pmlfnc for Functions, .pmlfrm for Forms and .pmlobj for Objects, with these extensions the files will be loaded by PDMS automatically when the program is started. Functions are loaded by PDMS and are run by typing the following !!mymac(). This runs file mymac.pmlfnc Forms are displayed by typing Show !!Myform or !!Myform.show() Objects have to be assigned to a variable before they can be used i.e. !x = object MyObject() 9.2 Modifications to pmllib It is normal practice to create a parallel hierarchy to contain any new or modified PML. Changes to AVEVA standard product may cause PDMS to function inappropriately These modifications can then be called by modifying the PMLLIB variable to point at a multi path. This can be done by putting a new file path in front of the %PMLLIB% definition. This will update the PMLLIB environment variable to include the specified file path. Set pmllib=c:pmltrainingPMLLIB %pmllib% The new file path should go in front of %PMLLIB% so this area is checked first for content. Once content is found, other locations will not be searched. This modification should be done after the PMLLIB environment variable has been defined. This can be done at the bottom of the EVAR.bat file or in the PDMS.bat file (after the line which calls evar.bat). In AVEVA products environment variables can be checked using the q evar syntax i.e. q evar pmllib
  • 36. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 36 www.aveva.com 9.3 Updating PDMSUI and PMLLIB Edit the Evar.bat file to include multi paths for PDMSUI and PMLLIB These settings should be made at the bottom of the evar.bat file Set pdmsui=c:pmltrainingpdmsui %pdmsui% Set pmllib=c:pmltrainingpmllib %pmllib% The setting of the variable can be checked in AVEVA Plant Design (PDMS) using the following commands: q evar pdmsui and q evar pmllib If a pmllib file is c once items have been loaded by PDMS, it needs to be reloaded. This can be done by typing either pml reload form !!NAME or pml reload object NAME If a new file is to pmllib, the files can be remapped so PDMS knows where it is located. This is done by typing pml rehash onto the command line. This will update the first file location in the search path. To update all search paths, type pml rehash all. 9.4 PML2 Objects An object is a PML grouping of information. It may have MEMBERS (used to hold data) ands METHODS (used to complete an action). Once assigned to a variable, that variable becomes an instance of that object. This means that variable will behave as the object definition. While it is possible to create user-defined objects (discussed later), PDMS is supplied with a large number of built-in objects. A full list of these can be found in the PDMS Software Customisation Reference Manual. For example, type !pos = object position() onto the command line. Query the variable and check the results against the members of a position object listed in the reference manual. Although a FORM is an object, it is a subject in its own and will be discussed later. 9.5 PML2 Methods When working with built-in objects, there may also be BUILT-IN METHODS (object dependant). These methods have been defined to complete certain actions applicable to object. For example, type the following into the command line: !value = |56| !result = !value * 2 This example will have caused an error as a string cannot be used in an expression like this. To avoid the error, refer to the STRING object in the Reference Manual and find the .real() method. This method translates the variable from a STRING to a REAL so that it can be used in the expression. The !value remains a string, but !results now becomes a REAL e.g. !value = |56| !result = !value.real() * 2 Within PML2, there are built-in methods for all the standard objects (ARRAY, TABLE, FORM, and STRING). Refer to PDMS Software Customisation Reference Manual for the available methods and information
  • 37. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 37 www.aveva.com 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 The type of value returned by 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 members. For methods, this column tells you whether the method MODIFIES the value of the object. For members, this column tells you whether the member is SETTABLE (by the user) or UNSETTABLE. Note that for the system-defined PDMS object types, members correspond to PDMS attributes ACTION This column tells you what the member or method does. A large number of methods have been provided for the built-in PML data types: For example, for STRING objects, you will find a method named Length. !Name = ‘Tony Blair’ !NumberOfLetters = !Name.Length() q var !NumberOfLetters This method returns a REAL value (the number of characters in the string), but has NO EFFECT on the variable itself. 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. The following method creates an ARRAY of STRINGS: e.g. !NameStrings = !Name.Split() 9.6 Method Concatenation It is possible to apply multiple methods to the same variable within the same line of code. This process will work providing the data passed at each stage is valid. Try the following on the command line: !line = 'hello world how are you' !newline = !line.upcase().split().sort() q var !line !newline <STRING> 'hello world how are you' <ARRAY> [1] <STRING> 'ARE' [2] <STRING> 'HELLO' [3] <STRING> 'HOW' [4] <STRING> 'WORLD' [5] <STRING> 'YOU'
  • 38. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 38 www.aveva.com 9.7 The !!CE Object A special GLOBAL PML variable !!CE always points to the current PDMS element and its attributes. Type q var !!CE onto the command line and compare it against typing q att. You will notice the returned attribute information is the same of the members list of the !!CE object. This means that the !!CE object can be used to assign the values of attributes to !variables For example, !BranchHeadBore = !!CE.Hbore assigns the HBORE attribute (taken from the current BRAN element) to the variable !BranchHeadBore making it real. If the !!CE object member is an object itself, that object will also have members so further information be obtained e.g. !HeadPosition = !!CE.Hpos.East East member from a POSITION object !Easting = !!CE.Href.Cpar[1] Cata parameter member (attribute) of a DBREF object If the !!CE object member is an object with built-in methods, these methods can also be called: !PosWRTValve = !!CE.Hpos.WRT(ZONE) POSITION object w.r.t the owning ZONE This process can also be reversed allowing the setting of attributes for the CE. This means that it is possible to record the current value of an attribute, modify and reassign back to the CE. For example, type out the following onto the command line: !Pos = !!CE.Pos q POS !Pos.Up = 2000 !!CE.Pos = !Pos q POS These lines will have moved the CE up by 2000. Try this example again with some other attributes. 9.8 PML2 Functions Functions are new style macros which are pre-loaded by PDMS and can be called directly. For example, to call the function called FuncName.pmlfnc, type !!FuncName() onto the command line. A function is defined within a .pmlfnc file stored within the PMLLIB file path. For an example of a function, type the following into a new file and save it as c:pmltrainingpmllibfunctionsNameCE.pmlfnc. define function !!NameCE() !ce = !!CE.fullname $p $!ce endfunction To run this function, type !!NameCE() onto the command line. You will notice the fullname is printed below it. This is an example of a NON-RETURN function with NO ARGUMENTS. If the function can be given arguments which are then assigned to variables with the function. If a variable is returned, this means that the function can be assigned to another variable or as part of a calculation. Type out the following, and save it as c:pmltrainingpmllibfunctionsArea.pmlfnc: define function !!Area(!Radius is REAL) is REAL !CircleArea = !Radius.Power(2) * 3.142 return !CircleArea endfunction As this function is an example of a RETURN function with an ARGUEMENT, it can be used as part of an expression. The returned value is based the functions argument and its type (REAL in this case):
  • 39. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 39 www.aveva.com !Height = 64 !CylinderVolume = !!Area(2.3) * !Height q var !CylinderVolume As indicated by the !!, functions are global. This means that once defined, they can be called by any form or method within PDMS minimising repetitive code. Synonyms are disabled inside functions Exercise 5(a) – Convert the Hose reel macro into a function This exercise will cover how to update existing macros to make use of updated functionality. The macro that will be updated is c:pmltrainingmacrosex5.mac. Have a look at the file. It uses the READ method and this technique is no longer valid. How can the required values be passed to the macro? A function can be used to allow input values. Save the updated macro as a function called ex5a.pmlfnc in the directory c:pmltrainingpmllibfunctions To begin with, define a function with one argument: The name of the equipment. Apply suitable error handling to the function and check it works. After typing PML REHASH ALL, type !!ex5a(‘HoseWheel’) and a new hose wheel will be created. Look at the macro and you will see it uses the same hand wheel we have defined so far. The function uses the variable !WheelDia to alter the diameter of the hand wheel. Update the function by adding another argument, the diameter of the hand wheel. Test your function and see the impact of altering this variable.
  • 40. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 40 www.aveva.com Exercise 5(b) – Adding arguments to the function Extend the function written in exercise 5a to accept two more arguments: • the width of the hosewheel • the diameter of the hose wheel. Rewrite parts of the functions so that hosewheel will change size based on these inputted numbers. How do the primitives in the hosewheel relate to these dimensions. Reduce the lines of code by introducing DO loops and PML2 syntax Save the updated function as a function called ex5b.pmlfnc in the directory c:pmltrainingpmllibfunctions Type show !!ex5plt to see an dimensioned plot file !!ex5b(|Hose-Reel-001|, 1000, 2000)
  • 41. 41 www.aveva.com CHAPTER 10 10 Forms 10.1 Forms Are Global Objects Forms now look like GLOBAL OBJECTS, with Gadgets as their MEMBERS. Once loaded, the information held within a form can be accessed at anytime. To find out information about the form, it can be queried as if it was an object. For example, lets use the Graphics Settings form (Settings>Graphics…) Type Show !!gphsettings onto the command line to see the form in question or choose it from the menu Type q var !!gphsettings onto the command line. The information is a list of the members of the form. Compare this list against some of the gadget s on the form. As gadgets are members of forms, we can find information about these. The first gadget listed is called OK (representing the OK button on the form). Type q var !!gphsettings.ok. The information returned is information about the button. Specific information about the gadget can be queried directly e.g.: q var !!gphsettings.ok.tag q var !!gphsettings.ok.val q var !!gphsettings.ok.active To get the name of a shown form, type show !!pmlforms. This form can list shown forms 10.2 Dynamic loading of Objects, Forms and Functions When a PML object is used for the first time, it is loaded automatically. This applies to both FORMS and OBJECTS e.g.: !Person = object PRIMEMINISTER() show !!MyInputForm Once an object is loaded by PDMS, the definition is held by PDMS. This means that if the object is changed whilst it is loaded, the form will need to be reloaded. To reload a form type pml reload form or object followed by the object name e.g.: pml reload form !!MyInputForm pml reload object PRIMEMINISTER If a new file is created whilst PDMS is open, the file will not be mapped (even if it is saved in an appropriate file path). The remap files type pml rehash. This will remap all the files within the first file path in the PMLLIB variable. The remap all files in all the file paths, type pml rehash all
  • 42. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 42 www.aveva.com 10.3 Form Definition... Forms are defined within .pmlfrm files and should be defined in the following way. A .pmlfrm file can contain the form setup definition and any methods created in association: setup form !!fname ... exit define method .init() ... Endmethod 10.3.1 Using the .net framework Form objects can now make use of the .net framework. This allows new features to be included on forms: • Docking forms (automatic resizing) • Anchoring gadgets (useful when resizing) • Multicolumn lists • Tabs on Forms • Menu Additions to existing applications: • Toolbar Additions to existing applications • DBAR Conversions Although it is now possible to dock forms, it does not apply to every form. There are some rules to consider when deciding if a form should dock: • Does the form need to remain open? • Is the form used heavily • If a form has an OK/Cancel button, it should not need docking • If a form has a menubar, it CANNOT be docked To declare a form as dockable, this has to be done on the top of the definition. By including dialog dock left, we are stating that the form is displayed, it shall already be docked to the left: setup form !!fnam dialog dock left To define a floating, dockable form, use the following line: setup form !!fnam dialog resizeable To define a form of a certain size in the centre of the screen, use the following line: setup form !!fnam document at xr 0.5 yr 0.5 size 100 100 If no additional details are included, the default form creation is a Dialog, non-resizeable, size adjusted automatically to fit contents form. For more examples, refer to the FORM object in the PDMS Software Customisation Reference Manual 10.3.2 Showing and hiding Forms Now forms can be found through the PMLLIB search path, there is no longer the need to load them individually. To show a form use show !!formname. This will load the form definition and show it in one go! Sometimes it is useful to have the form loaded with seeing it (e.g. to refer to stored information). A form can be loaded (but not shown) by typing loadform !!formname
  • 43. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 43 www.aveva.com 10.3.3 Built-in methods for Forms Although is possible to define user-defined methods within user-defined forms (discussed later), all FORM objects have built-in methods available. Try on the following on the command line: !!gphsettings.show() q var !!gphsettings.shown() !!gphsettings.hide() q var !!gphsettings.shown() In this example, the .show() method is used to show the form, the .shown() method returns whether the form is shown and the .hide() method hides the form. For more examples, refer to the FORM object in the PDMS Software Customisation Reference Manual 10.4 Callbacks If an object has a CALLBACK member, it can be given a callback string. This means that if the user interacts with the object, an action can be performed. The callback can do one of three things: • show a form • execute a command directly • run a function or method A FORM object has some special callbacks which are used when the form completes certain actions (e.g. Shown, closed) Copy out the following into a new file and save it as Callback.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files. To see the form, type show !!Callback. Press the buttons look at the command line. setup form !!Callback !this.formTitle = |Callback Example| !this.initcall = |!this.init()| !this.okcall = |!this.okCall()| !this.cancelcall = |!this.cancelCall()| !this.quitcall = |!this.quitcall()| button .ok ' OK ' OK button .can 'Cancel' at x30 CANCEL exit define method .Callback() $p --Constructor Method-- endmethod define method .init() $p --Initialise Method-- endmethod define method .okcall() $p --OK Method-- endmethod define method .cancelcall() $p --Cancel Method-- endmethod
  • 44. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 44 www.aveva.com define method .quitcall() $p --Quit Method-- endmethod At the top of the form, the callback members of the form where set user-defined methods within the form. • The CONSTRUCTOR method was called when the form loaded (notice, it has the same name as the form). • The INITCALL method is called everytime the form is shown (perfect for setting default values • The OKCALL method is called by any button gadget with the OK in its definition • The CANCELCALL method is called by any button gadget with CANCEL in its definition • The QUITCALL method is called by clicking the close button on the form. If no callbacks are defined for OKCALL, CANCELCALL and QUITCALL the default is to hide the form only 10.5 Form Gadgets There are many kinds of form gadgets, each an object that will have its own members and methods. When you are defining gadgets on a form, there are two common aims: • Define the area to be taken up on the form • Define the action to be taken if the gadget is selected It is the position and size of the gadget that determines the area taken up and its action is defined by its CALLBACK member. 10.5.1 Built-in members and methods for Gadgets As Gadgets are objects, there are a variety of useful members and built-in methods that can be used. Using the previous example (!!Callback), type the following onto the command line: To grey-out the OK button !!Callback.ok.Active = FALSE To hide the CANCEL button !!Callback.can.Visible = FALSE Apply a tooltip to the OK button !!Myform.ok.setToolTip(|This is an OK button|) For further information, PDMS Software Customisation Reference Manual
  • 45. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 45 www.aveva.com 10.5.2 Gadget positioning Gadgets are positioned on a form from top left using the AT syntax. The AT syntax defines the origin of the gadget in relationing to the owning object (i.e. FORM or FRAME). . Gadgets can be positioned explicity or in relation to other gadgets. When referring to other gadgets, there 6 known positions on a gadget: XMIN, XCEN, XMAX, YMIN, YCEN and YMAX. These refer to fixed position in the x and y directions on the referenced gadget. A gadget can be thought of as an enclosing box that will enclose the geometry of the gadget (including its name tag if specified). To position a gadget at a known position use: at x 0 y 0 To position the above CANCEL button use Xmax and Ymin of OK use: at xmax.ok + 10 ymin.ok To position a DISMISS button in the bottom corner of a form use: at xmax form – size ymax form For more positioning syntax, refer page 2-59 in the PDMS Software Customisation Reference Manual The available syntax and its order can be derived by referring to the SYNTAX GRAPHS in the reference manual. These diagrams are available for most Gadgets and can be used when initially defining them. The picture below is an example of the Syntax Graph for gadget positioning (<fgprl> refers to another graph): Refer PDMS Software Customisation Reference Manual for more guidance on these graphs
  • 46. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 46 www.aveva.com 10.5.2.1 Position Gadgets using the path command The path command can be used to define the logical position of subsequent gadgets. This method has been superseded by the previous method and has been included for information. After a gadget has been defined, the next gadget is positioned based on a PATH, HDIST or VDIST and HALIGN or VALIGN. As an example, see the picture below: Button .But1 $* default placement PATH down HALIGN centre VDIST 2 paragraph .Par2 width 3 height 2 $* auto-placed toggle .Tog3 $* auto-placed PATH right HDIST 3 VALIGN bottom List .Lis4 width 2 height 3 $* auto-placed PATH up HALIGN right Paragraph .Par5 width 3 height 3 $* auto-placed 10.5.3 Docking and Anchoring Gadgets After a gadget has been loaded its size and position are locked. To modify the position or size manually, the alterations have to be made in the file and the form reloaded. As forms can be resized, it is necessary for gadgets to move/resize so the layout of the form remains. There are two available syntax definitions that can help DOCK or ANCHOR. This syntax should be included when defining a gadget and can be included if <fgdock> or <fganch> are included in the gadgets syntax graph. The DOCK and ANCHOR are mutually exclusive so only one is defined per gadget ANCHOR controls the position of an edge of the gadget relative to the corresponding edge of its container. For example, if a DISMISS button is anchored to the Right + Bottom, it will remain in the bottom, right of the form if it is resized. DOCK forces gadget fill the available space in a certain direction. For example, if a list is docked to the left, it will maintain its width, but its height will change it fill its container. DOCK FILL is very useful for ensuring a gadget is the full size of its container. Copy out the following into a new file and save it as DockExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files. setup form !!DockExample dialog resizeable !this.formTitle = |Dock and Anchor| !buttpos = |xmax.f1 - size ymax.f1 - size| frame .f1 anchor ALL width 30 height 5 button .butt1 |Dock TOP| dock TOP button .butt2 |Anchor B+R| at $!buttpos anchor R+B exit exit
  • 47. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 47 www.aveva.com Resize the form and observe the results. Once a gadget is declared as Anchored or Docking it will remain so. If a change is required, the form definition should be updated and the form reloaded. Refer PDMS Software Customisation Reference Manual for the Syntax Graphs. 10.6 Paragraph Gadgets Paragraph gadgets are simple named gadgets which allow a piece of TEXT or a PIXMAP to be displayed on a form. It is a passive gadget that cannot be selected by the user so has no callback. Paragraph gadgets are used display either instructions or pictures. Copy out the following into a new file and save it as ParaExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files. setup form !!ParaExample !this.formTitle = |Paragraphs| para .para1 text |Normal paragraph gadget| width 20 para .para2 at x 0 ymax.para1 backg 6 text |A cyan paragraph gadget| width 20 para .para3 at x 0 ymax.para2 pixmap width 154 height 50 para .para4 at x 0 ymax.para3 + 0.5 text || wid 20 hei 2 exit define method .ParaExample() -- Update the displayed text using CONSTRUCTOR method !this.para4.val = |Above was a PIXMAP, this is on two lines| -- Use built-in method to apply picture !this.para3.AddPixmap(|c:pmltrainingpmllibimagesaveva.png|) Endmethod Refer to the Reference Manual and Guide for more examples The last value of the last gadget was set during the CONSTRUCTOR method. empty paragraph gadgets can be created to reserve space with values set after creation.. 10.7 Button Gadgets Button gadgets are typically used to invoke an action or to display a child form. Its CALLBACK can call a LOCAL METHOD, GLOBAL FUNCTION or OBJECT METHOD. If a callback and a child form are both specified, the callback command will be run before the child form is displayed. Copy out the following into a new file and save it as ButtonExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files. setup form !!ButtonExample dialog resizeable !this.formTitle = |Buttons| button .butt1 |Normal| button .butt2 |Green| backg 5 button .butt3 |Deactive| button .butt4 |form| form !!ParaExample button .butt5 toggle backg 4 call |!this.check()| pixmap wid 31 hei 21 exit define method .ButtonExample() -- Deactivate butt3 in CONSTRUCTOR method !this.butt3.active = FALSE -- Use built in method to apply pictures !this.butt5.AddPixmap(|c:pmltrainingpmllibimagesoff.png|, |c:pmltrainingpmllibimageson.png|)
  • 48. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 48 www.aveva.com endmethod define method .check() -- Return the toggle button value to the command line !check = !this.butt5.val $p $!check endmethod Refer to the Reference Manual and Guide for more examples As .butt5 was set as a toggle button, it has either a TRUE or FALSE state. This means that a toggle button holds a .val member which can be set or queried. 10.7.1 Linklabel The Linklabel, provides a purely textual button presentation, i.e. it has no enclosing box. It is often used to indicate a link to some application item, e.g. a hyperlink to a file, a link to an associated form. They do cause validation of any modified text fields of the form whenever they are pressed. The tag text is shown in a different colour to all other gadget's tag text. The link label gadget highlights by underlining when the mouse cursor passes over it. Pressing it causes a SELECT event to be raised and runs any associated call back. Linklabels have the following restrictions: • They don't support change of background colour. • They don't support 'pressed' and 'not pressed' value. • They can have popup menus, though this is not recommended. • They don't have Control Types e.g. OK, CANCEL etc. Copy out the following into a new file and save it as LinkLabelExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!LinkLabelExample dialog resizeable !this.formTitle = |LinkLabel| button .butt1 |Paragraph Form| linklabel form !!ParaExample exit 10.8 Text Entry Gadgets A text input gadget provides the user a way of entering a single value into PDMS. A TEXT gadget is defined by: WIDTH – determines the displayed number of characters. An optional scroll width can also be specified TYPE – determines the type of the variable created when inputting a value. This is important when PML uses the variable. You may also supply a FORMAT object (explained below) to format the value entered (e.g. whole number) Copy out the following into a new file and save it as TextExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files.
  • 49. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 49 www.aveva.com setup form !!TextExample !this.formTitle = |Text| path down text .txt1 |Val as String | width 10 is STRING text .txt2 |Only numbers | width 10 is REAL format !!REALFMT text .txt3 |Round numbers | width 10 is REAL format !!INTEGERFMT text .txt4 |For passwords | width 10 NOE is STRING text .txt5 |Limited scroll| width 10 scroll 1 is STRING text .txt6 |Not editable | width 10 is STRING exit define method .TextExample() -- Make Text 6 uneditable !this.txt6.val = |Cannot change!| !this.txt6.setEditable(FALSE) endmethod The benefit of making a text gadget uneditable (rather than deactivated) is so the user can select its contents. A deactive text box will be full greyed out and unselectable. Refer to the Reference Manual and Guide for more examples 10.9 Format Object A FORMAT object manages the information needed to convert a number (always in mm) to a STRING. It can also be used apply a format to a text gadget. A format objects are usually defined as global variables so that they are available across PDMS. For example, type the following onto the command line: !!OneDP = object FORMAT() !!OneDP.dp = 1 q var !!OneDp There are four standard FORMAT objects which are already defined in standard PDMS: !!DistanceFmt For distance units !!BoreFmt For Bore Units !!RealFmt To give a consistent level of decimal places on real numbers !!IntegerFmt To force real numbers to be integers(0 dp Rounded) To find out more information about these FORMAT object, query them as global variables on the command line q var !!BoreFmt For example the number of decimal places displayed using !!RealFmt could be set !!RealFmt.dp = 6 the default value is 2. These standard format objects are used within the forms of PDMS. Changing the definition of these objects will change the way standard product behaves.
  • 50. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 50 www.aveva.com 10.10List Gadgets A LIST gadget presents and ARRAY of values to the user. This can be a SINGLE or MULTI- DIMENSIONAL ARRAY All the values in the gadget are set by assigning an ARRAY. ARRAY variables can be applied to a LIST at any time. The choice between MULTIPLE, COLUMN and SINGLE has to be made when the gadget is defined. The values within a COLUMN list (headings and values) are set by using built-in gadget methods. Copy out the following into a new file and save it as ListExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!ListExample !this.formTitle = |Lists| !vshap = |width 15 height 6| list .lst1 |Single Array List| call |!this.value()| SINGLE ZEROSEL $!vshap list .lst2 |Multi-Select List| MULTI $!vshap list .lst3 |Appending List| call |!this.append()| $!vshap list .lst4 |Multi-column List| COLUMNS $!vshap exit define method .ListExample() -- Define values contained within the lists do !I from 1 to 5 !Dvalue[!I] = |Number| & !I !Rvalue[!I] = |<| & !I & |>| do !J from 1 to 2 !multi[!I][!J] = |col | & !J & |(| & !I & |)| enddo enddo !this.lst1.dtext = !Dvalue !this.lst1.rtext = !Rvalue !this.lst2.dtext = !Dvalue !single[1] = |Click to append values| !this.lst3.dtext = !single !this.lst4.setRows(!multi) !heading[1] = |One| !heading[2] = |Two| !this.lst4.setHeadings(!heading) endmethod define method .value() --Print the Dtext and Rtext values to the command line !dtext = !this.lst1.selection('Dtext') !rtext = !this.lst1.selection('Rtext') $p Selected Dtext is $!<dtext> (Rtext is $!<rtext> - hidden!) endmethod define method .append() -- Append value to List 3 !nextLine = !this.lst3.dtext.size() + 1 !val = |Appended | & !nextLine !this.lst3.add(!val) Endmethod
  • 51. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 51 www.aveva.com Refer to the Reference Manual and Guide for more examples
  • 52. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 52 www.aveva.com 10.11Frame Gadgets A FRAME is a cosmetic gadget which is used to surround a group of similar gadgets. This helps with organisation, positioning and user experience. A frame can also be declared as a TABSET or a RGROUP (explained later) and even a TOOLBAR (when defined for the main PDMS window). Copy out the following into a new file and save it as FrameExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!FrameExample dialog resizeable !this.formTitle = |Frames| frame .tabset TABSET anchor ALL wid 15 hei 5 frame .f1 |Docked| at 0 0 dock FILL frame .fA |Dock All| dock FILL frame .fB |Dock Right| dock RIGHT wid 10 frame .fC |Dock Bottom| dock B hei 4 exit exit exit exit frame .f3 |Other| at 0 0 dock FILL !pos = |at xcen.fG - 0.5 * size ymax| frame .fG |Deactive| wid 15 hei 4 button .but1 |Try and click!| at 1 1 exit button .but |Show Frame| $!pos backg 8 call |!this.showF()| frame .fH |Hidden Frame| at xmin.fG ymax.but2 width.fG hei.fG exit exit exit exit define method .FrameExample() !this.fG.active = FALSE !this.fH.visible = FALSE endmethod define method .showF() if !this.but.val.eq(TRUE) then !this.fH.visible = TRUE !this.but.tag = |Hide Frame| else !this.fH.visible = FALSE !this.but.tag = |Show Frame| endif endmethod When creating a FRAME gadget, for every FRAME there must be an associated EXIT. If insufficient exits are provided, this will cause an error and the form will NOT LOAD. As the error occurred in side the FORM DEFINITION, the command line will still be in form definition mode and will not function as usual. To exit this mode, type EXIT on the command line until and ERROR is received. This will mean that form definition mode has been exited and normal commands will work again. It is good practise to provide 2 spaces when working inside a code block. This provides an easy way to spot missing exits.
  • 53. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 53 www.aveva.com 10.11.1 Fold Up Panel Frames This is like a Panel but has a formal title bar, which displays the tag text and provides an icon which can be clicked to fold-up and hide, or unfold and show the contained gadgets. Copy out the following into a new file and save it as FoldUPFrameExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!FoldUPFrameExample dialog resizeable !this.formTitle = |Fold Up Frames| path down frame .tabset1 foldup 'Frame Active' anchor ALL wid 25 hei 5 text .text1 'Text 1' width 10 is STRING text .text2 'Text 2' width 10 is STRING text .text3 'Text 3' width 10 is STRING text .text4 'Text 4' width 10 is STRING exit frame .tabset2 foldup 'Frame Not Active' anchor ALL wid 25 hei 3 button .butt1 |Normal| button .butt2 |Green| backg 5 exit exit define method .FoldUPFrameExample() !this.tabset1.expanded = true !this.tabset2.expanded = false endmethod 10.12Textpane Gadgets A TEXTPANE gadget provides an area on a form into which a user may edit multiple lines of text and cut/paste from elsewhere on the PML screen. The inputted value is stored as an ARRAY of STRINGS and can be set and read from the gadget. Copy out the following into a new file and save it as TextpaneExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!TextpaneExample !this.formTitle = |Textpane| !this.initCall = |!this.init()| text .txt1 call |!this.append()| width 30 is STRING textpane .txtp |Compiled text| at x 0 ymax wid 40 hei 5 button .but1 |Swop Line| at xmax - size y 0 call |!this.swop()| exit define method .init() !this.txt1.val = |Enter a STRING to swop| do !I from 1 to 10 !val[!I] = |Text on Line Number | & !I enddo !this.txtp.val = !val endmethod define method .swop() !lineNO = !this.txtp.curPos() !line = !this.txtp.line(!lineNo[1]) !this.txtp.setLine(!lineNo[1], !this.txt1.val) !this.txt1.val = !line endmethod
  • 54. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 54 www.aveva.com This example will demonstrate that the TEXTPANE has some useful built-in methods for extracting information. A TEXTPANE cannot be assigned a callback, but cursor position can be derived (or set). Select a line on the TEXTPANE and press the button to set the value of the line. 10.13Option Gadgets An OPTION gadget offers a single choice from a list of items. It may contain either PIXMAPS or STRINGS, but not a mixture. The gadget displays the CURRENT choice in the list. When the user presses the option gadget, the entire set of items is shown as a drop-down list and the user can then select a new item by dragging cursor to the option required. The width of a text option gadget must be specified. A tag name is optional and is displayed to the left of the gadget. The available options is stored as an ARRAY of STRINGs as the gadgets DTEXT or RTEXT and can be updated by altering this array. Copy out the following into a new file and save it as OptionExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!OptionExample !this.formTitle = |Options| option .opt1 |Normal| at 0 0 width 7 option .opt2 |Pixmap| at xmax.opt1 y 0 pixmap width 16 height 16 exit define method .OptionExample() !dtext[1] = |Red| !dtext[2] = |Yellow| !dtext[3] = |Green| !dtext[4] = |Cyan| !this.opt1.dtext = !dtext do !I from 1 to 4 !files[!I] = |/c:temppmllibimages| & !I & |.gif| enddo !this.opt2.dtext = !files !this.opt2.rtext = !dtext endmethod Try querying the Rtext of the pixmap gadget by using a built-in gadget method: q var !!OptionExample.opt1.selection() q var !!OptionExample.opt2.selection() 10.14Toggle Gadgets TOGGLE gadgets are used for independent on/off settings. This means they are used in situations where the user has two choices i.e. is it bold or not? Is it on or off? A toggle will return a BOOLEAN state under is val member, but can also store different descriptions for selected and unselected. Copy out the following into a new file and save it as ToggleExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!ToggleExample !this.formTitle = |Toggles| path right toggle .tog1 |Normal| call |!this.state(!this.tog1)| toggle .tog2 |Changed States| call |!this.state(!this.tog2)| states |NO| |YES| exit
  • 55. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 55 www.aveva.com define method .state(!gad is GADGET) if (!gad.val) then q var !gad.onvalue else q var !gad.offvalue endif endmethod 10.15Radio Gadgets A RADIO GROUP is used to give a user a single choice between a small fixed number of choices. Two objects can be used to define a radio group: RGROUP or RTOGGLE. An RGROUP element defines the entire object and the tags contained; an RTOGGLE is contained within a normal FRAME object. An RGROUP object has been superseded by the RTOGGLE, but both methods are still valid RGROUP objects can be displayed vertically or horizontally. RTOGGLE objects can be arranged within a FRAME as required and can be placed alongside other gadgets. Copy out the following into a new file and save it as RGroupExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!RGroupExample !this.formTitle = |Radio Groups| rgroup .vert |RGroup| FRAME vertical callback |!this.rg(!this.vert)| add tag |Left| select |L| add tag |Centre| select |C| add tag |Right| select |R| exit frame .rtog |RToggle| at xmax + 1 y 0 path down rToggle .left |Left| states || |L| rToggle .cen |Centre| at ymax – 0.5 states || |C| rToggle .righ |Right| at ymax – 0.5 states || |R| exit exit define method .RGroupExample() !this.rtog.callback = |!this.rt(!this.rtog)| endmethod define method .rg(!gad is GADGET) q var !gad.val q var !gad.selection() endmethod define method .rt(!gad is GADGET) q var !gad.val !rtog = !gad.rtoggle(!gad.val) q var !rtog.onvalue endmethod Notice the appearance of the two gadgets are very similar
  • 56. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 56 www.aveva.com 10.16Form Member Variables As a FORM is an OBJECT, it may be given MEMBERS. These will be used to store data, effectively created global variables. The benefit of this method is that data is global without having large numbers of individual variables. Form members replaces the previous method of USERDATA (PML1 style data storage), and are given a PML data type. These variables have the same lifetime as the form and are deleted when the form itself is unloaded. The below example shows how the concept of a CE button is implemented (used on AVEVA standard forms). The CE is set when the form is shown, and does not update until the CE button is pressed. Copy out the following into a new file and save it as FmemExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!FmemExample !this.formTitle = |Form Members| !this.initcall = |!this.init()| button .ce |CE| callback '!this.init()' para .ceName width 30 hei 1 member .ceRef is DBREF member .Storage is ARRAY exit define method .init() !this.ceRef = !!CE !this.ceName.val = !!CE.FLNN !this.Storage.append(!this.ceRef) endmethod Test the members by typing q var !!FmemExample.ceRef or q var !!FmemExample.Storage 10.17Tooltips Tooltips are small help boxes which pop up when you move the mouse over an active gadget. The following gadgets can have a tooltip defined: Button Text Toggle Option An example of creating a tooltip: BUTTON .B1 |SAVE| PIXMAP TOOLTIP |Save Work| Refer to the correct Syntax Graph from the PDMS Software Customisation Reference Manual for more info.
  • 57. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 57 www.aveva.com 10.18Progress Bar The application main window now has an inbuilt progress indicator in the status bar along its base. This can be accessed from PML via methods on the FMSYS object. Method Name Result Purpose Progress( ) real Get the current Integer value in percent shown by the progress bar, in the range 0 to 100. Zero means the bars is invisible. SetProgress( !percent ) no result Set the Integer value in percent to be displayed in the progress bar. Values will be forced into the range 0 to 100. Resultant value of 0 will cause the bar to become invisible. setup form !!ProgressBar !!ProgressBar.formtitle = |Progress Bar| button .DoIt ' Show Progress ' Call |!this.doit()| exit define method .DoIt() !!FMSYS.setProgress(0) do !cou from 1 to 100 !!FMSYS.setProgress(!cou) enddo !!FMSYS.setProgress(0) endmethod
  • 58. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 58 www.aveva.com Exercise 6(a) - Calculation methods Create a basic calculation form that will performance a temperature conversion. The form will allow the user to enter a temperature value and specify a type, then the form shall convert it. The converted temperature should then be displayed to the user. Supply a TEXT and RADIO GROUP gadget for the user to enter the input values and a TEXT gadget for the results. Also provide a PARAGRAPH gadget to provide the user with the type of the converted temperature. The displayed text of this paragraph gadget will change depending on the input temperature type. You should organise the input and output gadgets into FRAME gadgets and given them the same width and height. Write a method that will convert the inputted value into the required output. The CALLBACK on both input gadgets shall call this method. By doing this, the output value will be calculated if either input gadget is used. The equations you will need are as follows °C = ( °F x 1.8 ) + 32 °F = ( °C – 32 ) / 1.8 The required method needs to know the unit of the input value so the correct equation can be used. Only one equation needs to be used at a time. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex6a.pmlfrm and show it on the command line by typing show !!ex6a (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 59. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 59 www.aveva.com Exercise 6(b) - Loops This exercise will expand the form created in exercise 6a by adding another calculation. The new calculation will take a RANGE of temperature values (in °C) as an input and fill in a TABLE with the equivalent °F values. Three TEXT gadgets (min value, max value and step size) shall be provided for user input. The output should be a LIST gadget with the headings No., Centigrade, Fahrenheit. You may wish to add a fourth column (between the two temperature values) that will contain an ‘=’ symbol Create another two FRAME gadgets to contain the new gadgets and ensure that they are the same width as the previous frames and that new ones are the same height. Check that the gadgets are aligned. When defining the LIST gadget, we need it to fill the FRAME that contains it. What method is available to do this that saves us having to define its size? Write a CONSTRUCTOR method that will set the headings of the LIST gadget and will set some default values in the other gadgets. Add a method to take the input values and fill in the list. This method should loop through the range of input values to compile an ARRAY. Once the ARRAY OF STRINGS has been defined, use the .setRows() method to add it to the list. Add a BUTTON that will call this method and fill in the table A FORMAT object could be used to round any calculated value. It can be referred to when setting the type of the TEXT gadget, or when converting a REAL to a STRING You could also add a method to check the input values to ensure they are valid: e.g. Should the min value be greater than the max value? Should a value be less than -273? Should the step size be equal to zero? These checks could be carried out when the user enters the values. If the values are incorrect, what would be a suitable response (i.e. error message, auto correction)? An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex6b.pmlfrm and show it on the command line by typing show !!ex6b (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 60. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 60 www.aveva.com Exercise 6(c) – Concatenation This exercise will use a TEXTPANE gadget to store information entered by the user and append it to the data already collected. Add two new FRAME gadgets to the bottom of the form created in exercise 6b. The input FRAME should hold three TEXT gadgets allowing the user to enter a value for Input Temp., Safe Temp, and Range. The output frame should be filled with a TEXTPANE gadget. Write a method which reads the inputted values, collects them into a single string and appends them to the textpane gadget. The form of the collected string shall be: 1. 100°C is 212°F - 15°C/59°F - ABOVE safe range Where 1. is the line number, 100 is the Input Temp, 15 is the amount the input temp is outside the safe temperature range and ABOVE safe range is a statement about the number. The Fahrenheit numbers are converted from the centigrade values. Modify the existing temperature conversion method so that it can be used for the above calculation. The modified method should still work for exercise 6a. Inputted values and calculated values are to be compiled into a single string. The format of any calculated value may need to be set before adding to the string. After creating this string, append it to the current TEXTPANE value. Add a BUTTON gadget to carry out this method. A method is needed to empty the TEXTPANE so that new information can be inserted. This does not necessarily need a new user-defined method. Most gadgets have a default .clear() method which can be called. Add a BUTTON that clears the TEXTPANE. A TEXTPANE gadget can be selected, copied, edited on the form by the user. This means that individual lines or whole gadget can be manually cleared. Try selecting the contents of the gadget and pressing delete! An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex6c.pmlfrm and show it on the command line by typing show !!ex6c (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 61. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 61 www.aveva.com Exercise 6(d) – String manipulation This exercise will look at string manipulation and how available methods can be used together to carry out a number of steps in a single line of code. The form will continue from the form created in exercise 9. Add another two FRAME gadgets, both with two TEXT gadgets. In the input frame the user will be asked to enter an input string and a delimiting character. The output boxes will return a modified string value and the number of delimiters encountered. The input string shall be a number of centigrade values, separated by a single character e.g. 10°C/30°C/20°C/5°C The method shall modify the string in the following steps: • Split the string based on the delimiter • Count how many temperature values are being converted • Remove the °C characters • Convert the remaining number to Fahrenheit • Compile all the converted values in order, including °F and separated by a space. Add a BUTTON to the form that carries out this method An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex6d.pmlfrm and show it on the command line by typing show !!ex6d (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 62. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 62 www.aveva.com Exercise 7 – Storing and resetting defaults This exercise shall use a form member to store default values so that the user of the form can reset any values entered. The user should also be able to update the values. Add two new BUTTON gadgets to the form: an APPLY and a RESET Add a MEMBER to the form that will store the values for the INPUT TEXT gadgets as an ARRAY. Write a method that if the user presses the RESET button, the values from the member will be transferred to the input text gadgets. The APPLY button should overwrite the values in the member with the values from the text gadgets. Methods can accept input arguments. This can be used to identify which gadget called the method, meaning that one user-defined method could be produced for the above ARRAYs of information can be of one variable type (e.g. STRING). Values may need to be converted before being stored. Consider how the user would use this method. Add some appropriate checks/error handling to ensure that the desired results are achieved. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex7.pmlfrm and show it on the command line by typing show !!ex7 (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 63. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 63 www.aveva.com 10.19Open Callbacks An OPEN CALLBACK is a means of providing change information about the gadget the user is interacting with. It means that for every change, the callback will be called. Two pieces of information are passed during an open callback (1) the name of the gadget being altered and (2) a keyword (as a STRING). These keywords indicate the event which caused the callback. Different keywords will be generated by different gadgets, under different circumstances e.g. a multi – selection gadget may have a ‘SELECT’ ‘UNSELECT’, as well as the more standard ‘START’ ‘STOP’ PDMS recognises an open callback if a method only has one bracket e.g. call |!this.opencall(| For an open callback to work, there must be an appropriate method defined. An open callback method must be able to accept two arguments (1) the gadget and (2) the keyword e.g. define method .opencall(!a is GADGET, !b is STRING) As the method is called at every significant event, the open callback method should be written to recognise keywords. The following example shows how an open callback can be used on a SLIDER gadget to update a TEXT gadget. It shows how an open callback can change its method based on a different event keyword. In this case, the MOVE events are counted then written to the text gadget once a STOP event is encountered. Copy out the following into a new file and save it as OpenCallExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!OpenCallExample !this.formTitle = |Open Callback| slider .slide anchor L+R horizontal range 0 100 step 5 val 50 wid 30 text .text |Value of slider| at xmax - size ymax + 1 anchor B+R wid 5 is REAL text .moves |Number of moves| at xmax.text - size ymax anchor B+L wid 5 is REAL member .store is REAL exit define method .OpenCallExample() !this.slide.callback = |!this.slideMove(| !this.moves.val = 0 !this.store = 0 !this.text.val = !this.slide.val endmethod define method .slideMove(!gad is GADGET, !val is STRING) !this.text.val = !gad.val !this.text.refresh() if !val eq |MOVE| then !this.store = !this.store + 1 elseif !val eq |STOP| then !this.moves.val = !this.store !this.store = 0 endif endmethod The .refresh() method has been applied to the .text gadget to ensure its value updates as the slider is moved. The number of moves is stored as a member of the form. This saves a new global variable from being defined and means the increasing value can be shared between the open callbacks.
  • 64. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 64 www.aveva.com An open callback can be given to any gadget that accepts a callback. Different gadgets may generate different event keywords Exercise 8 – Tabsets and Open Callbacks This exercise will take the form from exercise 7 and add tabs to it. The input and output FRAME elements from the previous form should now be converted to tabs. Remove all the form buttons from within the frames. These methods shall now be called when the RESULTS tab is SHOWN. To do this there should be an OPEN CALLBACK on the RESULTS tab. The open callback will report the status of the tab and when it is ‘Shown’, a method will call all the conversions so that the RESULTS tab is filled in. Remember: Callbacks can only be applies to a frame during the constructor method Instead of a CLEAR LIST button, why not modify the Temperature Check method so that if the user leaves the Input Temp. value UNSET, the list is cleared. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex8.pmlfrm and show it on the command line by typing show !!ex8 (after typing pml rehash) An example of the completed form can be found in Appendix B
  • 65. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 65 www.aveva.com 10.20Bar Menus Forms may have a bar menu gadget which appears as a row of options across the top of the form. A bar menu is defined within form definition and specifies the options the user has to choose from. There are three types that can be added: Choose – displays a user-defined menu object Window – displays a list of the open forms Help – displays the standard help options After the bar command, use the built-in method .add() to add extra options to the bar menu. E.g. bar !this.bar.add(|Choose|,|Menu1|) !this.bar.add(|Window|,|Window|) !this.bar.add(|Help|,|Help|) Bar menus can only be added to forms which are not dockable Menu1 is a menu object which has been created by adding it to the bar object. Other references to MENU objects will require the MENU object to have been defined. 10.20.1 Defining a Menu Object Within the form definition the menu sub-command creates a named menu object. You can then use the menu’s .add() method to add named menu fields. A menu field can do one of three things: Execute a callback Display a form Display a sub-menu You can also add a visual separator between fields. !menu = !this.newmenu(|Menu1|, |MAIN|) !menu1.add(|CALLBACK|,|Query|,|q ban|) !menu1.add(|FORM|,|Hello…|, |hello|) !menu1.add(|SEPARATOR|) !menu1.add(|MENU|,|Pull-right1|,|Pull1|) This creates a menu called menu1 with 3 fields - Query, Hello… and Pull-right1 with a separator between the last two fields The Query field when picked will execute the callback command ‘q ban’ The Hello... field when picked will load and display the form !!hello. By convention, the text on a menu field leading to a form ends with three dots, which you must include with the text displayed for the field. The SEPARATOR, usually a line, will appear after the previous field. The Pull-right1 field when picked will display the sub-menu !this.Pull1 to its right. A menu field leading to a sub-menu ends with a > symbol: this is added automatically.
  • 66. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 66 www.aveva.com
  • 67. 67 www.aveva.com CHAPTER 11 11 PML Objects 11.1 Built in PML OBJECT Types There are a large number of standard objects within PML2. These are All Variable types, BORE, DIRECTION, DBREF, FORMAT, MDB, ORIENTATION, POSITION, FILE, PROJECT, SESSION, TEAM, USER, ALERT, FORM, all form Gadgets and various graphical aid objects. Each object has a set of built in methods for setting or formatting the object contents. ARRAY - Arrays can contain any data types including other arrays and can be sparse BLOCK - Blocks are used to store commands for a special form of working on arrays. The block contains a list of commands and “block Evaluation” is used to perform the actions on an array BOOLEAN - Boolean is true or false 0 and 1 will not do! FILE - File is in principle a file name, but the file object contains built in methods for working on the file. OBJECT - REAL - Real is a number. There is no integer! STRING - String is a text string in quotes’ ‘ or vertical bars | | DATETIME - returns current Date and Time information BANNER BORE - a bore object is a single variable which only accepts bore input. The purpose of a bore only object is to allow bore units to be dealt with implicitly. Setting a bore unit !bore = 80 does not work DB - a DB object is an object representing a database. Can be used to interrogate information about type, team, access, claim type DBREF - a dbref object a ref to a database it has members(access, file, name, number, foreign, type, description, claim(string) and team(team)) DBSESS DIRECTION - a Direction object has members (direction, origin(dbref), up, east, north(real)) MACRO MDB - MDB object has members (name and description, both string) ORIENTATION - an orientation object has members(alpha(real), origin(dbref), Gamma and beta(reals)) POSITION - a position object has members(origin(dbref) up, east, north(reals) POSTUNDO PROJECT - a project object has one member (evar(string)) SESSION TEAM - a team object has members (name and description(reals)) UNDOABLE USER - a user object has members(access, name, description(strings)) FORMAT - Format is a way of formatting data for example metric or imperial]
  • 68. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 68 www.aveva.com 11.2 Forms and Menus Objects ALERT BAR BUTTON COMBOBOX CONTAINER FMSYS FORM FRAME LINE LIST MENU NUMERIC OPTION PARAGRAPH RTOGGLE SELECTOR SLIDER TEXT TEXTPANE TOGGLE VIEW ALPHA AREA PLOT VOLUME 11.3 3D Geometry Objects ARC LINE LINEARGRID LOCATION PLANE PLANTGRID POINTVECTOR POSTEVENTS POSTUNDO PROFILE RADIAL GRID XYPOSITION
  • 69. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 69 www.aveva.com 11.4 Methods Available to All Objects The table following lists the methods available to all objects. The table gives the name of each method and the type of result you get back from it. The third column of the table describes what the method does. Name Result Purpose Attribute( 'Name') ANY To set or get a member of an object, providing the member name as a STRING. Attributes() ARRAY OF STRINGS To get a list of the names of the members of an object as an array of STRING. Delete() NO RESULT Destroy the object - make it undefined EQ(any) BOOLEAN Type-dependent comparison LT(any) BOOLEAN Type-dependent comparison (converting first to STRING if all else fails) Max(any) ANY Return maximum of object and second object Min(any) ANY Return minimum of object and second object NEQ(any) BOOLEAN TRUE if objects do not have the same value(s) ObjectType() STRING Return the type of the object as a string Set() BOOLEAN TRUE if the object has been given a value(s) String() STRING Convert the object to a STRING Unset() BOOLEAN TRUE if the object does not have a value Refer to the Software Customisation Reference Manual for further details.
  • 70. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 70 www.aveva.com 11.5 The File Object The FILE object is an example of how older functionality has been replaced with a PML2 style object. This object replaces the old ‘openfile’ ‘readfile’ ‘writefile’ ‘closefile’ syntax and provides increased functionality (file path, if the file is open etc). it is now possible to Read or Write to a file in a single operation. To create a file object: !input = object file(’C:FileName’) !output = object file(’C:FileName.out’) To Open a file: !output.open(’WRITE’) Avaiable options = READ, WRITE, OVERWRITE, APPEND 11.5.1 Using file objects To read a line from file: !line = !input.ReadRecord() File must be open To write a line to file: !output.WriteRecord(!line) File must be open To read all the input file: !filearray = !input.ReadFile() Files are opened and Closed automatically To write all of the data to file !output.WriteFile(‘WRITE’,!filearray) Files are opened and Closed automatically The .ReadFile() method has a default maximum file size which it can read. This can be increased by passing the method a REAL argument (representing the number of lines in the file) Copy out the following into a new file and save it as FileExample.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!FileExample !this.formTitle = |File Object| text .txt1 |File Path| call |!this.read()| width 25 is string para .par1 at x 0 ymax text || width 35 para .par2 at x 0 ymax text || width 35 exit define method .read() !file = object file(!this.txt1.val) !file.open('READ') !n = 0 do !line = !file.ReadRecord() if !line.unset() then BREAK else !n = !n + 1 endif enddo !file.close() !date = !file.DTM() !this.par1.val = |Number of Lines in file = | & !n & |; File size = | & !file.size() !this.par2.val = |Date modified = | & !date Endmethod
  • 71. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 71 www.aveva.com 11.5.2 Use Notepad to open file. You could use the “syscom” command to open an external program like Notepad, by adding an & to the end of the line will opens a new process. If you do not use then & PDMS will be suspended until the program is closed. !file = object file(|C:temppmllibformsex6a.pmlfrm|) syscom |c:/WINDOWS/notepad.exe $!file&| Exercise 9 – Menubar This exercise will add a menu bar to the form to replace the remaining buttons on the form !!ex8. Add a MENU BAR to the form. The bar should contain the following: Control > Close, Seperator, Load Defaults… Defaults> Update Defaults, Reset to Defaults Help> (standard help menu) To close the form, the user will click on Control>Close (replacing the Dismiss button) To load default values from an external file, the user shall choose Control>Load default files Defaults>Update Defaults should replace the Apply button and Defaults>Reset to Defaults should replace the Reset button Make Control>Load Defaults… call a standard AVEVA function - !!FILEBROWSER. This built in function can be used to set up the standard AVEVA file browser form and this form can be used to navigate to the required file. The function call should be in the following form: call !!fileBrowser(''AAA'', ''BBB'', ''CCC'', DDD, ''EEE'') Where AAA is the starting file path for the form to open at (e.g. c:); BBB is the required file type (e.g. *.txt); CCC is a string that will feature at the top of the file browser form; DDD is a BOOLEAN value stating if the file has to exist; EEE is the callback string for the file browsers OK button. This callback string should call a method from our form (explicitly referenced) that will read the chosen file. For example call !!fileBrowser('c:pmltraining', '.txt', 'Load Defaults', false, '!!ex9.loadFile()')
  • 72. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 72 www.aveva.com
  • 73. 73 www.aveva.com CHAPTER 12 12 User-Defined Objects User Defined Objects can contain any variable or object type as members. Information is grouped with an object for ease of reference and standard reference. User-defined objects can also contain user-defined methods that will use the information stored within the object. These methods may represent a calculation, or information retrieval. After an object has been declared as a variable, the methods can be applied to the variable. For example: define object ELEMENT member .Type is STRING member .Material is STRING endobject define method .FullDesc() is STRING return !this.Type & ‘ ‘ & !this.Material endmethod Once a variable is declared as an ELEMENT object then the method can be applied. !item = object ELEMENT() !Item.Type = |Flange| !Item.Material = |Carbon Steel| !name = !item.FullDesc() A method with no arguments but the same name as the type of the object is called the default constructor method. More than one method can be given the same name as the object, provide only one has no arguments Copy out the following into a new file and save it as UserBox.pmlobj. Put the file into the appropriate file path c:pmltrainingpmllibobjects and remap the files ------------------------------------------------------------------ -- object to hold information about a USERBOX. ------------------------------------------------------------------ define object USERBOX member .xlen is REAL member .ylen is REAL member .zlen is REAL endobject define method .USERBOX() !this.xlen = 0 !this.ylen = 0 !this.zlen = 0 endmethod define method .USERBOX(!x is REAL, !y is REAL, !z is REAL) !this.xlen = !x !this.ylen = !y !this.zlen = !z endmethod define method .volume() is REAL return !this.xlen * !this.ylen * !this.zlen
  • 74. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 74 www.aveva.com endmethod define method .surfaceArea() is REAL return !this.xlen * !this.zlen * 2 + !this.ylen * !this.zlen * 2 + !this.xlen * !this.ylen * 2 endmethod To test this object works, type out the following onto the command line. !aaa = object USERBOX() q var !aaa.volume() <REAL> 0 q var !aaa.surfacearea() <REAL> 0 !aaa.userbox(10,20,30) q var !aaa.volume() <REAL> 6000 q var !aaa.surfacearea() <REAL> 2200
  • 75. 75 www.aveva.com CHAPTER 14 13 Collections A very powerful feature of the PDMS database is the ability to collect and evaluate data according to rules. There are two available methods for collection (1) PML1 syntax (2) PML2 objects. Both methods are still valid 13.1 The Collection Syntax (PML 1) Before typing out the following onto the command line, ensure the STABILISER plant is the CE var !zone collect all zones for site var !name eval name for all from !zone q var !zone !name var !equi coll all equi with owner eq /EQUIP q var !equi !!CE = !equi[1].dbref() var !box coll all box for ce var !volume eval (xlen * ylen * zlen) for all from !box q var !volume These examples show that elements can be collected, but also evaluated to extract further information Because this uses the var command, all collected items are STRINGs not DBREFs 13.2 The Object Collection Syntax (PML 2) Before typing out the following onto the command line, ensure the STABILISER plant is the CE !equiColl = object COLLECTION() !equiColl.type(‘EQUI‘) !equiColl.scope(!!ce) !expr = object EXPRESSION(|PURP eq ‘PUMP’|) !equiColl.filter(!expr) !results = !equiColl.results() q var !results For this method to work, a collection object must be declared and used. For the COLLECTION’s .filter() method to be used, it must be given an EXPRESSION object as an argument. Using a collection object makes its built-in methods available for users. Because this uses the collection object, all collected items are DBREFs not STRINGs.
  • 76. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 76 www.aveva.com Exercise 10 – Equipment Collections This exercise will create a new form that will act as an Equipment Checker. It will allow user to see information about the chosen piece of equipment. Start a blank form and add to it an OPTION gadget (to hold the available pieces of equipment) and a LIST gadget (to hold the nozzles for the selected piece of equipment). You may wish to put these gadgets inside a FRAME gadget. When the user chooses a piece of equipment from the option gadget, the nozzle list shall update showing the equipment’s nozzles. Write a method that collects all the EQUI elements for the ZONE of the CE. Try and write the collection part of the method in a PML 1 style. What happens if no pieces of equipment are found in the ZONE? Call this method from within the initcall method. Write a method that runs after the piece of equipment has been chosen. This method should collect all the NOZZ elements for that EQUI element. Try writing the collection part of the method in a PML 2 style. After the method has run, set the full names of the collected NOZZ elements to the LIST. Add a button to the form which updates the available EQUI elements in the option gadget. This will ensure the form can be updated without having to be reloaded. Make sure that if the OPTION gadget is updated by the user, the LIST gadget is also updated. PML 2 collections return DBREF numbers of the collected elements. Do not forget to convert these values into the full name values before updating the LIST gadget. Use Query>Attributes in Design to find a suitable attribute. It is recommended that although the user will wish to see the fullname, it is worth storing the collected elements. This will allow easier navigation between elements. This could be an opportunity to user the Dtext/Rtext members. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex10.pmlfrm and show it on the command line by typing show !!ex10 (after typing pml rehash)
  • 77. 77 www.aveva.com CHAPTER 14 14 Pop-Up Menus Pop-up Menu is an MENU objects that are displayed within a gadget by right-clicking on it. This is a useful method of providing the user with relevant functionality relating to the gadget selected !menu = !this.newMenu('listPopup') !menu.add(|callback|, |Find|, |!this.init()|) !menu.add(|separator|) !menu.add(|callback|, |Modify...|, |!this.listPopupCallback()|) !this.eqpl.setPopup(!this.listPopup) In this above example, a MENU object is defined that contains two callbacks. Find calls the .init() method (refreshing the form) and Modify calls a specific method. The MENU object is applied to the LIST gadget (called eqpl) by using the .setPopup() method. This method can be used whenever it is a valid method of the gadget Refer to the PDMS Customisation Reference Manual for the available methods for different gadgets
  • 78. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 78 www.aveva.com Exercise 11(a) – Pop-up menu This exercise will develop the form created in exercise 10 by adding a POP-UP menu that will allow the user to navigate to a selected nozzle. Define a MENU object for the popup and assign it to the LIST gadget. This menu should call a user- defined method that will assign the !!CE object with the dbref of the chosen nozzle. If the collected DBREF() information was stored within the RTEXT member of the LIST gadget it will be easier to obtain the selected nozzle’s dbref. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex11a.pmlfrm and show it on the command line by typing show !!ex11a (after typing pml rehash)
  • 79. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 79 www.aveva.com Exercise 11(b) – Equipment Checking Extend the form by adding a NOZZLE CHECKING method. This method should look at each of the collected nozzles and check that various conditions are met. This will provide the user with the information about the nozzles, quickly highlighting which require further checking. Write a method that looks at each collected NOZZ element and checks the following: Is it connected? This can be decided by checking the NOZZ element’s CREF attribute. If the attribute is unset or the reference is invalid, then the user will have to check that nozzle Is it attached? Check the positions of the NOZZ and PIPE elements and if they are different, then the NOZZ should be checked Is it aligned? Check the directions of the NOZZ and PIPE elements. If they are different, then they should be checked Is it sized correctly? Compare the diameter of the PIPE to the size of NOZZ. If they are different, then they should be checked. If the NOZZ is not connected, does the user need to be informed about its alignment? Use the Query>Attributes form in design to identify the attributes available for use. Add a BUTTON to refresh the LIST gadget. This button will re-run the nozzle check method after the user has updated the NOZZ elements. An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex11b.pmlfrm and show it on the command line by typing show !!ex11b (after typing pml rehash)
  • 80. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 80 www.aveva.com Exercise 11(c) – Setting Equipment attributes This exercise will develop the form created in exercise 11b by giving the user the chance to edit some of the EQUI elements attributes. Add a TEXTPANE to the form and set the three default attributes as Description, Function and Purpose. Write a method that reads these attributes from the EQUI element and displays the correct values. This method should be run every time a new piece of equipment is chosen. As it is a TEXTPANE gadget, it is possible for users to add additional information to it. We shall use this feature as part of the method. Extend the method so that values from the TEXTPANE are read and the EQUIs attributes are updated. The method should also include any additional attributes which the user may have entered. Add a BUTTON to update the EQUI attributes This method will have to read each line of the gadget, split it and use the split values to set the attributes. When a new EQUI element is chosen, attributes values should be read and gadgets text updated accordingly. Add error handling methods to cover unknown attributes, or incorrect attribute values. If the user enters an incorrect attribute, advise the user of this. Ensure the title of LIST gadget always includes the name of the chosen EQUI An example of a form which completes the exercise is shown below: Save the file as c:pmltrainingpmllibformsex11c.pmlfrm and show it on the command line by typing show !!ex11c (after typing pml rehash)
  • 81. 81 www.aveva.com CHAPTER 15 15 View Gadgets VIEW gadgets are named gadgets which are used to display the information from available databases. The way the information is displayed depends on the VIEW gadget type. General View Types: ALPHA views for displaying text output and / or allowing command input. PLOT views for displaying non-interactive 2D plotfiles. Application-specific View Types AREA views for displaying interactive 2D graphical views. VOLUME views for displaying interactive 3D graphical views. Refer to the correct VIEW element type in the PDMS Customisation Reference Manual for more information 15.1 Alpha Views Save the file as c:pmltrainingpmllibformsAlphaView.pmlfrm and show it on the command line by typing show !!AlphaView (after typing pml rehash) setup form !!alphaView !this.formTitle = |Alpha View| view .Input AT X 0 Y 0 ALPHA height 20 width 40 channel REQUESTS channel COMMANDS exit path down button .Button1 'Apply' path right button .Button2 'Dismiss' at xmax form -size exit This gadget is the same as is used for the standard command line. It provides information direct from the current database in text format. 15.2 Plot View Example Save the file as c:pmltrainingpmllibformsPlotView.pmlfrm and show it on the command line by typing show !! PlotView (after typing pml rehash) setup form !!plotView !this.formTitle = |Plot View| view .view1 plot width 41 hei 15 exit exit define method .plotView () !this.view1.borders = FALSE !this.view1.add(|/C:pmltrainingpmllibformshosewheel.plt|) endmethod
  • 82. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 82 www.aveva.com A PLOT view can be used to provide the user with extra information. The extra information would be contained in a .plt file and is applied to the view during the constructor method. A PLOT view is used within standard PDMS is describe design parameters 15.3 Volume View example Save the file as c:pmltrainingpmllibformsVolumeView.pmlfrm and show it on the command line by typing show !!VolumeView (after typing pml rehash) setup form !!volumeView !this.formTitle = |Volume View| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Focus on CE', '!this.init()') view .view3D volume width 41 height 15 limits auto isometric 3 exit button .but |Focus on CE| at xmax form - size ymax call |!this.init()| exit define method .volumeView() !this.view3D.borders = FALSE !this.view3D.background = |darkslate| !this.view3D.shaded = TRUE !this.view3D.projection = |PARALLEL| !this.view3D.radius = 100 !this.view3D.range = 500.0 !this.view3D.eyemode = FALSE !this.view3D.step = 25 !this.view3D.setpopup(!this.pop1) endmethod define method .init() !limits[1] = !!CE.wvol[1] !limits[2] = !!CE.wvol[4] !limits[3] = !!CE.wvol[2] !limits[4] = !!CE.wvol[5] !limits[5] = !!CE.wvol[3] !limits[6] = !!CE.wvol[6] !this.view3D.limits = !limits endmethod The above example makes use of an attribute WVOL. This is a pseudo-attribute (available for most elements) that returns the world coordinates for an enclosing box (at world orientation). The value of this attribute was used to set the limits of the volume view. Notice: the WVOL array is arranged differently to that required by the Volume Views limits member The limits of the view are reset everytime the form is shown, or when the button/pop menu are used.
  • 83. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 83 www.aveva.com Exercise 12(a) – Adding a Volume View Add a VOLUME VIEW to the form so that users can see the chosen piece of equipment Add a VIEW gadget to the form and set its type to VOLUME. This view gadget will now act like the main PDMS 3D window. This means that the drawlist items which are seen in the main window will also be seen in this gadget. To make the gadget more useful, we want to focus on the piece of equipment chosen on the form. Write a method to update the limits of the view to focus on the chosen piece of equipment. This method should be called everytime a new piece of equipment is chosen. Refer to the PDMS Software Customisation Reference Manual for the VIEW commands that can be used.
  • 84. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 84 www.aveva.com Exercise 12(b) – Adding a Clipbox to the view Add a CLIPBOX to the volume view created in exercise 12(a). This clipbox shall be sized to the chosen piece of equipment ensuring the extra elements outside the equipments volume will not be seen. The key to solving this exercise is to investigate how clipboxes are created. The process is not documented, but we can investigate how standard PDMS implements clipboxes. Add a GPHCLIPBOX MEMBER to the form which will store the clipbox definition. This object type was identified by using the show !!pmlforms form to look at the main PDMS window. After adding a GPHCLIPBOX as a member to the form, type show !!pmlforms onto the command line. Check the “only shown forms” toggle and select your form from the top list. At the bottom of the form the members will be listed. By selecting the GPHCLIPBOX member, its properties are listed. It is these properties which will hold the clipbox definition (e.g. VIEW is the view gadget the clipbox is linked to; ACTIVE sets whether it is turned on; BOX holds the dimension information). Write a method that will calculate the size, position and limits of the clipbox (to ensure it is displayed correctly). The calculated limits and clipbox should then be applied to the 3D view gadget. The method should use the chosen equipment as the basis for this calculation and be run every time a new piece of equipment is chosen. Add this line to your code CLIP XLENGTH AA YLENGTH BB ZLENGTH CC POSITION DD ORIENTATION EE, where AA, BB, CC, DD and EE are values the macro shall derived. After this line edit the VIEW gadget and type clipbox enable To derive the occupied volume, is there a suitable attribute (or pseudo-attribute) that can be referenced?
  • 85. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 85 www.aveva.com Exercise 12(c) – Dynamically modify a clipbox The clipbox that was created in exercise 12b was fixed to the dimension of the piece of equipment. What if the user needs to see nearby items, such as flanges connecting to the nozzles. Add a SLIDER gadget to the form to allow users to expand/ contract the clipbox as required. Add an open callback method to the SLIDER to change the values of XLEN, YLEN and ZLEN of the clipbox. After changing these values the macro should update the VIEW gadget dynamically. Gadgets have a .refresh() method. Use this method to refresh the VIEW gadget whenever the SLIDER is moved. Add two TEXT gadgets that will contain the minimum and maximum values for the SLIDER. Add a method that will allow users to type in new values and update the range of the slider. This is important as EQUI elements can vary in scale. The step of slider should be calculated from the min and max values Add a TOGGLE gadget to allow the users to decide whether the VIEW limits are changed by the slider. Update the slider method to check the status of this toggle. If the clipbox set larger than the view limits then you will notice that parts of the model will not be displayed correctly
  • 86. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 86 www.aveva.com Exercise 12(d) – Add Nozzle tagging Add a method for users to tag the nozzles in the VIEW gadget Add two TOGGLE BUTTONs to the form. One will tag a single nozzle and the other will tag all nozzles. When a button is selected, items will be tagged and tags will be removed when the buttons are unselected. Pictures have been provided to make pixmap buttons. Add the following line to the forms constructor method: gadget.AddPixmap(!!PML.GetPathName('AAAA’), !!PML.GetPathName(‘BBBB’)) where AAAA is the reference picture for the unselected button and BBBB is for when it is selected. The !!PML.GetPathName function is a built-in function to derive the file path of the picture. This is useful as it means the file path does not need to be hard coded. Write a method that will tag a single nozzle. The nozzle that will be tagged should be the one selected in the nozzle list. The command to tag an item is as follows: AID TEXT NUMBER $!NO '$!TAG' AT $!POS where !NO is a reference number used to identify the tag, !TAG is the text that will be displayed in the tag and !POS is the position of the tag (bottom left corner). To remove a tag, we can use a built-in PDMS method. As it is a PML 1 method, we can call it in the following way: $m/%PDMSUI%desgraphicsGAIDCLEAR $<AAAA> where AAAA is the tag reference number. To remove all tags, do not include $<AAAA>. To remove a single tag, it will need to have a unique reference number Add a member to the form to keep track of which nozzles are tagged. Add a method to the callback from the nozzle list to check whether a nozzle is tagged. If the chosen nozzle is already tagged, the method should make the tag button selected (to allow users to untag).
  • 87. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 87 www.aveva.com Exercise 12(e) – Add Highlighting Provide a way of the user seeing the results of the nozzle check graphically. Elements in the 3D view can be assigned a colour that will override its auto-colour. Colours are expressed as numbers. enhance AAAA col 1 where AAAA is the name of the element to be highlighted and the number after col is a PDMS index colour. The colours which are able to be used are shown on the AVEVA standard form !!colourselect. Add a new FRAME gadget to the form and within it create four new BUTTONs. These buttons will display the highlight colours that will be used to colour the EQUI. The four colours will highlight (1) the piece of equipment (2) connected nozzles (3) unconnected nozzles and (4) nozzles which the user needs to check Also add another FRAME within the new one that will hold 50 small coloured buttons. These buttons will display the colours available to the user. Instead of manually creating these buttons, why not use a DO loop? Set the visibility of this FRAME to FALSE. When setting the background colour of these buttons what values should be used. Is there a source that can be referenced? Perhaps another form? Add a method to the 4 buttons that will make the colour picker FRAME visible. Add methods to the colour picker buttons that will apply the colour of the picked button to the button which displayed the colour picker frame. After the colour has been chosen, hide the colour picker frame again. Add a PIXMAP TOGGLE BUTTON to the form that will highlight the elements in the view using the specified colours To remove the highlight colours, use the following code: unenhance all
  • 88. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 88 www.aveva.com
  • 89. 89 www.aveva.com CHAPTER 16 16 Event Driven Graphics (EDG) The EDG has been developed to allow a common interface for the AppWare developer to use when setting up the graphic canvas for graphical selection. This method is relatively simple and easily extendible. This will allow the developer to concentrate on the development of their own application without the need to know the underlying mechanism (core implementation) of the EDG interaction handlers and system. The system handles all the underlying maintenance of the current events stacked e.g. associated forms, initialisation sequences, close sequences, etc. The current implementation of the system has mainly been developed for interaction with the 3D graphic views in the Design module. However, the interface can be used with any of the modules that use the same executable and the standard 3D graphic views. EDG supersedes the old ID@ syntax 16.1 Simple EDG Save the file as c:pmltrainingpmllibformsEDGExample.pmlfrm and show it on the command line by typing show !!EDGExample (after typing pml rehash) setup form !!EDGexample !this.formtitle = |EDG Example| button .but1 |Pick Element| call |!this.pick()| exit define method .pick() -- define event packet !packet = object EDGPACKET() -- define standard element pick !packet.elementPick(|Pick Element <esc> to finish|) -- return information about picked item !packet.action = |q var !this.return[1].item| -- when finished, doing following !packet.close = |$p Finished| -- add the event packet to the EDG object !!EDGCntrl.add(!packet) endmethod The above example shows how information is returned from for the elements picked. The form of the returned information is dependant on the type of pick that has been used. Refer to the EDG Interface manual for further explanation EDG is based around a number of objects with built-in methods. These examples only cover the basic implementation of EDG. For more in depth information and examples, refer the EDG interface manual.
  • 90. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 90 www.aveva.com 16.2 Using EDG Copy out the following into a new file and save it as PickEquip.pmlfrm. Put the file into the appropriate file path c:pmltrainingpmllibforms and remap the files setup form !!pickEquip !this.formTitle = |Pick Equipment| !this.initcall = |!this.init()| !this.quitcall = |!this.clear()| button .pick |Start Pick| call |!this.init()| textpane .txt1 |Picked Equipments| at x 0 ymax width 25 height 10 member .storage is array exit define method .init() !this.clear() !packet = object EDGPACKET() !packet.elementPick(|Pick Equipments <esc> to add to list|) !packet.description = |Identify Equipment| !packet.action = |!!pickEquip.identify(!this.return[1].item)| !packet.close = |!!pickEquip.setInfo()| !!EDGCntrl.add(!packet) endmethod define method .identify(!pick is DBREF) do if !pick.type.eq(|EQUI|) or !pick.type.eq(|WORL|) then break else !pick = !pick.owner endif enddo if !pick.type.eq(|EQUI|) then !name = !pick.name if !this.storage.findfirst(!pick.flnn).unset() then enhance $!name col 215 !this.storage.append(!pick.flnn) else !this.storage.remove(!this.storage.findfirst(!pick.flnn)) unenhance $!name endif endif endmethod define method .setInfo() !this.txt1.val = !this.storage endmethod define method .clear() do !i values !this.storage unenhance /$!i enddo !!edgCntrl.remove(|Identify Equipment|) !this.txt1.clear() !this.storage.clear() endmethod This example shows how a method can take the returned information and use it. In this case, the picked element type is checked whether it is a piece of equipment. If it is not, the method loops up the hierarchy until one is found (or the world is reached).
  • 91. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 91 www.aveva.com There is a different method for the pick action to the close action. For this reason, the picked elements are collected a form member. The close method applies the form member to the textpane gadget. Exercise 13 – Using EDG This exercise will add Event Driven Graphics to some of the forms created. Exercise 13(a) – Add EDG to !!ex10 Add a BUTTON to the form that will allow users to identify pieces of equipment in the main PDMS 3D window. Once they have picked a piece of equipment, that piece of equipment is automatically chosen in the option gadget and the nozzle list should update. Add a PIXMAP BUTTON to the form that will run a method initialising the EDG. Add another method that will be run by the EDG method. This method should do the following steps: • Turn the EDG event off after something has been chosen • Identify the type of element chosen • If an EQUI has been chosen, OK • Otherwise, loop up the hierarchy to find an EQUI. • If an EQUI cannot be found, report to the user and re-initialise the EDG • Find the chosen EQUI in the OPTION gadget and set it to the correct equipment • Run the nozzle collection method To remove an EDG instance, use !!edgCntrl.remove(|AAA|), where AAA is the description of the EDG
  • 92. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 92 www.aveva.com Exercise 13(b) – Add EDG to !!ex11b Extend the previous exercise by allowing users to identify either a nozzle or a piece of equipment. If a piece of equipment is chosen, update the option gadget to that EQUI. If a nozzle is chosen, make that nozzle selected in the nozzle list. What happens if the user chooses a nozzle on another piece of equipment?
  • 93. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 93 www.aveva.com Exercise 13(c) – Add EDG to !!ex12b Extend the previous method by allowing users to pick inside the 3D VIEW gadget on the form. Add a TEXT gadget at the top of 3D view (called .prompt). This will act as the user feedback for the view. Update the VIEW gadget to make it compatible with EDG. Using !!pmlforms, look at the properties of the main PDMS 3D window and compare it with the 3D view on the form. The differences should show how the form’s 3D view should be updated. Add the VIEW gadget to the EDG event.
  • 94. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 94 www.aveva.com
  • 95. 95 www.aveva.com CHAPTER 17 17 Miscellaneous The following sections described some other useful PML actions. 17.1 Recursive Pml2 Functions PML2 functions may be called recursively. This can be used to produce iterative solvers: define function !!Fibonacci(!Last is REAL, !Previous is REAL) !Next = !Last + !Previous !!ResultArray.Append(!Next) if (!!ResultArray.Size() LT 100 ) then -- Here the function calls itself !!Fibonacci(!Next, !Last) endif endfunction This iterative solver can be used to compile an array of Fibonacci numbers (an increasing series of numbers, where the next number is the sum of the previous two). These can be used for such things as Fibonacci rectangles, golden ratio and the value of Phi. 17.2 Undo and Redo If you build an application that creates or deletes items from the PDMS Database it is good practice to handle the ability to undo the modifications. Undo is a useful feature that users expect to be able to use. 17.2.1 Marking the database The undo button goes back to the last database mark or savework so your application should mark the database before modification. MarkDB ‘Comment’ The text string is output if the Undodb command is used 17.2.2 Undo and Redo Database Commands UndoDB - Undo the database back to the last database mark RedoDB - Redo the last Undo These actions can be performed by including the above lines within your code. There is also an UNDOABLE object with built-in methods which can extend this functionality further.
  • 96. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 96 www.aveva.com 17.3 Error tracing It is possible to list all the commands that PDMS runs when a PML operation is carried out. This list can either be printed to the command window, or written to an external file. Type $r109 /c:log.log onto the command line where c:log.log is the output file name (it shall be created if it does not exist) Now every PML action will be written to the external file. The file will list every line of code and action carried out. Lines read will be indicated by a line number in square brackets. Lines not read will be indicated by a line number between round brackets. Entry and exit points between methods, functions and objects are indicated as well as any errors. Type $r110 onto the command line to print the same lines to the command window. Printing to the screen should only be done when a small number of lines are to be printed. A large number of lines will take a long time to print to the screen and there is also a limit to the number of lines which can be contained by the command window. For large operations, print to a file Once you are finished with error tracing, type $r to the command line. This will need to be typed before the output file can be opened
  • 97. 97 www.aveva.com CHAPTER 18 18 Menu Additions Previous to 11.6, if you required additions to the menus, you copied the FSYSTEM/DBAR files and manually edited them to add new menus. Every time a new version of PDMS is released, you have to update any files you have copied. As part of the .net work, this process has been removed so that no update will be needed in subsequent versions of PDMS. This process has been replaced with the new ADDIN File syntax. To add new menus and toolbars to PDMS 11.6 or later, the ADDIN file syntax (FSYSTEM/DBAR) is no longer valid. 18.1 Miscellaneous Notes To find out the menus currently contained within a model, use q var !!appcatmain for Paragon and q var !!appdesmain for Design. More examples can be found in directory pmllib/design/objects. All the add-in application objects begin with the letters app****.pmlobj e.g. appaccess.pmlobj. Forms with menus cannot be docked. 18.2 Modules that use the new Addins functionality Addins are available in modules that have a form named appxxxmain.pmlfrm where xxx is the module such as des, cat, dra etc. These modules are Design (des), Draft (dra), Paragon (cat) and Spooler. The spooler form is named spooler.pmlfrm but still uses addins. Isodraft currently uses the old FSYSTEM and cannot use addins. Admin and Monitor use separate forms named adminapplic.pmlfrm and monitormain.pmlfrm and also cannot use addins. 18.3 Adding a Menu/Toolbar For a file created in %PDMSUI%DESADDINS directory, the name doesn’t matter, except for identification. The file will contain similar information to the old applications file in %PDMSUI% This file is used for menu additions, new toolbars and standard application switching 18.4 Application Design Below is an example of an ADDIN file which is used to load the Equipment application within design. Notice how the file only contains a number of file references. The addin file is automatically run by PDMS, so whatever this file references will also be run. name: EQUI directory: EQUI showOnMenu: TRUE object: appEqui title: Equipment callback: CALLE XEQUIAPP synonym: CALLE startup: $M /%PDMSUI%DESEQUIINIT Macro to call when the menu is selected Synonym to call equipment macros Macro to run on startup of the EQUI application (for the first time)
  • 98. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 98 www.aveva.com 18.5 Form and Toolbar Control Forms are controlled using the APPFORMCNTRL object. Forms can be registered to: Appear only in certain applications Be reshown when PDMS restarts (serialisation) !!appFormCntrl.registerForm(!form is FORM) Toolbars are controlled using the APPTBARCNTRL object: to avoid having too many toolbars on screen, each is enabled only when the user is in the right application. Users can add more forms/toolbars to these control objects, and those items will be shown to the user. 18.6 Converting Existing Applications For users upgrading from the FSYSTEM/DBAR method, it is possible to transfer your existing files to the ADDIN syntax: Existing application has an entry in the PDMSUI%DESDFLTSAPPLICATIONS file New application has an add-in definition file in %PDMSUI%DESADDINS OLD # Equipment Application ApplicationDirectory: EQUI Title: Equipment Form: _CDEQUIAPP Callback: CALLE XEQUIAPP Synonym: CALLE NEW Name: EQUI ShowOnMenu: TRUE Directory: EQUI Title: Equipment Object: APPEQUI Callback: CALLE XEQUIAPP Synonym: CALLE Startup: $M /%PDMSUI%DESEQUIINIT Previously, the main form was swapped when changing application. Existing applications defined menus and toolbars in the DBAR macro, which was called from the FSYSTEM macro. Now the main form stays the same and menus are shown and hidden as needed. Menus and toolbars are defined in an add-in object.
  • 99. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 99 www.aveva.com 18.6.1 DBAR and Add-in Object The contents of the ADD-IN object and the DBAR macro are very similar. The difference is the syntax used. 18.6.2 Bar Menu and Toolbar Add to bar menu OLD label /BAR add |Position| _POSITION add |Orientate| _ORI add |Connect| _CONN return NEW define method .barMenu() !bmenu = object APPBARMENU() !bmenu.add('Position', 'POSITION') !bmenu.add('Orientate', 'ORI') !bmenu.add('Connect', 'CONN') !!appMenuCntrl.addBarMenu(!bmenu, 'EQUI') endmethod 18.6.3 Define toolbar OLD label /DATA -- define buttons -- for toolbar return NEW define method .toolbars() frame .equiToolbar toolbar 'Equipment Toolbar' -- define buttons for toolbar exit !!appTbarCntrl.addToolbar('equiToolbar', 'EQUI') endmethod 18.6.4 Adding to Menus OLD label /CREATE add sep add |Equipment...| FORM _CDEQUI add |Sub-Equipment...| FORM _CDSUBEQ add |Primitives...| FORM _CDPRIM add |Standard...| form !!equCreateStd NEW define method .createMenu() !menu = object APPMENU('sysCrt') !menu.add('SEPARATOR') !menu.add('FORM', 'Equipment...', 'CDEQUI', 'equiEquipment') !menu.add('FORM', 'Sub-Equipment...', 'CDSUBEQ', Add to bar menu Add to Create menu Define toolbars Add new menus to form DBAR macro ADD-IN object
  • 100. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 100 www.aveva.com return 'equiSubEquipment') !menu.add('FORM', 'Primitives... ', 'CDPRIM', 'equiPrimitives') !menu.add('FORM', 'Standard... ', 'equCreateStd', 'equiStandard') !!appMenuCntrl.addMenu(!menu, 'EQUI') endmethod 18.6.5 Adding new menus to form OLD label /MENU menu _POSITION add |Explicitly (AT)...| |!!pos3DExplicit()| add |Relatively (BY)...| |CALLIBD X3DPOSR| add |Move| MENU _MOVE add |Drag| MENU _DRAG add |Plane Move| MENU _PLMOVE add SEPARATOR add |Equipment Point| MENU _PPEAT exit … return NEW define method .menus() !menu = object APPMENU('POSITION') !menu.add('CALLBACK', |Explicitly (AT)...|, |!!pos3DExplicit()|, 'Explicitly') !menu.add('CALLBACK', |Relatively (BY)...|, |CALLIBD X3DPOSR|, 'Relatively') !menu.add('MENU', |Move|, 'MOVE', 'Move') !menu.add('MENU', |Drag|, 'DRAG', 'Drag') !menu.add('MENU', |Plane Move|, 'PLMOVE', 'PlaneMove') !menu.add('SEPARATOR') !menu.add('MENU', |Equipment Point|, 'PPEAT', 'EquipmentPoint') !!appMenuCntrl.addMenu(!menu, 'EQUI') … endmethod
  • 101. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 101 www.aveva.com 18.7 Example object including toolbars, bar menus and menus This is only an example showing adding toolbars, bar menus and menus. The effect of this object will be to add a new toolbar and main menu. It will also add some extra menu options to the EQUI application, including some under the Utilities menu. It will demonstrate how user-defined forms/functions/callbacks can be added to the PDMS menu system. The methods .modifyForm() and .modifyMenus() run automatically, so can be used to call the objects methods. Type out the following and save it as appcompa.pmlobj define object APPCOMPA endobject ------------------------------------------------------------------ -- Method: .modifyForm() -- Description: Standard method -- Makes modifications to the main form ------------------------------------------------------------------ define method .modifyForm() !this.toolbars() endmethod ----------------------------------------------------------------- -- Method: .modifyMenus() -- Description: Standard Method -- Runs all other menu creation methods ----------------------------------------------------------------- define method .modifyMenus() !this.barMenu() !this.menus() !this.specificMenus() !this.UtilsMenu() endmethod ------------------------------------------------------------------ -- Method: .UtilsMenu() -- Description: Adds to the Utilities menu in the EQUI application ------------------------------------------------------------------ define method .UtilsMenu() !menu = object APPMENU('SYSUTIL') !menu.add('SEPARATOR') !menu.add('CALLBACK', |EQUI Form A...|, |$p Form A|) !menu.add('CALLBACK', |EQUI Form B...|, |$p Form B|) !!appMenuCntrl.addMenu(!menu, 'EQUI') endmethod ------------------------------------------------------------------- -- Method: .toolbars() -- Description: Creates toolbar for all applications ------------------------------------------------------------------- define method .toolbars() frame .MyFormToolbar toolbar 'CompanyA Toolbar' !iconSize = !!comSysOpt.iconSize() !Pixmap1 = !!pml.getPathName('createpipe-' & !iconSize & '.png') !Pixmap2 = !!pml.getPathName('exclamation-' & !iconSize & '.png') button .but1 'Show Form A' tooltip 'Show Company Form A' $ pixmap /$!<Pixmap1> width $!iconSize height $!iconSize callback |$p Form A| button .but2 'Show Form B' tooltip 'Show Company Form B' $
  • 102. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 102 www.aveva.com pixmap /$!<Pixmap2> width $!iconSize height $!iconSize callback |$p Form B| exit !!appTbarCntrl.addToolbar('CompAToolbar', 'ALL') endmethod ------------------------------------------------------------------ -- Method: .barMenu() -- Description: Adds options to the bar menu for all applications ------------------------------------------------------------------ define method .barMenu() !bmenu = object APPBARMENU() !bmenu.add(|Company A|, 'CompAMenu') !!appMenuCntrl.addBarMenu(!bmenu, 'ALL') endmethod ------------------------------------------------------------------ -- Method: .menus() -- Description: Creates menus to the bar for all applications ------------------------------------------------------------------ define method .menus() !menu = object APPMENU('CompAMenu') !menu.add('CALLBACK', |Company Form A...|, |$p Form A|) !menu.add('CALLBACK', |Company Form B...|, |$p Form B|) !!appMenuCntrl.addMenu(!menu, 'ALL') endmethod ------------------------------------------------------------------ -- Method: .menus() -- Description: Creates menus to the bar for specific applications ------------------------------------------------------------------ define method .specificMenus() !menu = object APPMENU('CompAMenu') !menu.add('SEPARATOR') !menu.add('CALLBACK', |EQUI specific form...|, |$p EQUI specific|) !!appMenuCntrl.addMenu(!menu, 'EQUI') endmethod To call the above object, copy out the following into a new file called COMPA (no file extension) and save it into %PDMSUI%desaddins. Update %PDMSUI% in PDMS.bat if not done already. name: COMPA title: Company A app showOnMenu: FALSE object: APPCOMPA Where Name is the unique id for user and addin code Title is the text description of the add-in ShowOnMenu determines whether the add-in has an entry on the Applications menu, i.e. whether the add-in defines an application (false by default). If it were an application addin like MDS this would be TRUE. Object is the object file that is used to define the menu/toolbar additions. These are some optional lines that can be included. Callback (typically CALLE XEQUI Macro to call when the menu is selected) Startup (typically $m/%pdmsui%/des/equi/init Macro to run on startup of the equi app (for first time)) ModuleStartup ( the callback run when the PDMS module first starts) StartupModify (Name of application to modify and the callback run when an application is first started, separated by a colon.e.g. EQUI:!!equiAppStartupCall()) SwitchModify (Name of application to modify and the callback to run when the application is switched to, separated by a colon. e.g. PIPE:!!pipeAppSwitchCall() )
  • 103. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 103 www.aveva.com To add a startup macro to more than one application, add more entries into the add-in file typically:- SwitchModify:EQUI:!!equiAppStartupCall() SwitchModify:PIPE:!!equiAppStartupCall() SwitchModify:GEN:!!equiAppStartupCall() The following keys are only used for applications, i.e. add-ins that have a menu option on the Applications menu and can be switched to. Menu Entry for application on the applications menu (the title is used if this isn’t specified) Directory Name of the application directory under %PDMSUI%module Synonym Synonym created for the directory (only used if the directory is specified) Group Group number (applications with the same group number are put into a submenu together) GroupName Description of submenu to appear on main menu Exercise 14 – Add a Utility and Toolbar menu Create some additional menus that will sit within the Equipment application and allow you access to your forms. Create an addin file that will point to the definition of the new menus. Call your file PML (with no file extension) and save it to %pdmsui%/des/addins. Create a file named apppml.pmlobj containing four methods: .UtilsMenu() .toolbars() .modifyMenus() - calling .UtilsMenu() .modifyForm() - calling .toolbars() Add two new menus (Calculator and Equipment Checker) to the Utilities drop down menu in the Equipment application (see the above picture). To each of these menus add a further sub-menu that lists the forms you have created. Define these menus in the .UtilsMenu() method Add a toolbar to the .toolbar() method. This toolbar should be titled ‘PML’ and contain two buttons that will open two of your forms. You may wish to use pixmap buttons (with the images provided) When you have completed and saved apppml.pmlobj, type PML REHASH ALL into the command line, then type Design. This will reload the design session and you should see the additions you have made. Please note that even a simply spelling mistake in the above exercise can prevent design from loading
  • 104. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 104 www.aveva.com If Design fails to load, do the following: Read the error message in the command window and action appropriately If objects are “not found”, check the file paths and type PML REHASH ALL Once the error has been fixed, type DESIGN onto the command line and Design should load. If typing DESIGN generates an error, the command line is still in setup mode and needs exiting – type EXIT To close the command line, type FINISH
  • 105. 105 www.aveva.com CHAPTER 19 19 Upgrading from PML1 to PML2 19.1 Points to watch out for Only Algebraic expressions are allowed, (No reverse-polish notations after “=“ sign) Creating numeric variable with “=“ creates a REAL Some PML1 macros using the “=“ will now create variables of the wrong type. VAR !name value will now create a STRING value. DO variables are now REAL rather than STRING If “=“ has been used in existing PML code and problems are found, re-write the code using PML2 technology, or revert to PML1 VAR technology. Conversion utility “eq2var” (Currently runs through an “awk” script) DO variables in PML2 are automatically deleted to ensure that they can be created, This can upset other variables if of the same name. On exit DO variables remain REAL; previously they would have been STRING +1 if loop ran to completion. Variable in “do values” is deleted on exit. DO from to are required to be REAL, Existing macros are unaffected by this ($) Change variable names to avoid DO variables Check DO expressions, re-write as necessary Results of an expression in IF must be TRUE or FALSE. An error will occur where ZERO=FALSE e.g. if ($value) then - - (PML1) will have to be either if ($value EQ 1) then or if ( BOOLEAN($value)) then Most common occurrence PML1 if ( match ($!String1,$!String2)) then PML2 if ( match ($!String1,$!String2) GT 0 ) then Check Form and Global Variable Names Forms are now GLOBAL variables, and cannot have the same names as a Global Variable. Form and Gadget Names Must be Unique and Start with a Letter Forms & Menus enforces the rule that gadget names must start with a letter, and must be unique, (Gadget names can be re-used in different forms). New Forms & Menus Error Messages. No longer possible to use setup form from within .INIT macro. Gadgets that are outside the form are now ERRORS. More than one OK,CANCEL or HELP will generate an error. Var list & do list are restricted to LIST gadgets, for TEXTPANES & SELECTOR gadgets use var pane,selector & do selector DOT in variable, Form and Gadget Names Is now used as separator between a Form or Object name and the name of one of its members or functions. i.e. !Array.size() var !String ‘comment’
  • 106. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 106 www.aveva.com !Old.Name = ‘!String’ could now use:- !Size = $!<Old.name>.length() or !Size = $!Old.name$N.length() Negative Array Subscript is now an Error. Array subscripts MUST now be positive or zero, Zero is permitted but many of the array methods ignore the zero’th element. Macros which make use of negative array subscripts will need to be revised. $MKn & $MK-n Withdrawn. These commands may have had a role when macros were run directly from a terminal, but are incompatible with form-driven software. Macros will have to be re-written. Synonyms are NOT Available in PML Functions but are still available in Macros. = in PDMS10 is not compatible with = in PDMS11 Components in Function to the Right of “=“ Existing “var” code is not affected. Add brackets if PML1 code has none. To convert to “text” add “$” !X = 32 , !Y = 52 !Z = !X + !Y Result = REAL …..84 !Z = ‘$!X’ + ‘$!Y’ Result = STRING …..3252 Notes for PML1 users $Wn Will Break the GUI Software. Numbered Variables Are no longer available. Macros Avoid Mixing with PML Functions. Global Variables for results Use Function “Return”. $M- $M+ $MK Only for debugging, not LIVE code. $R+ $R- Withdrawn, (PML TRACE ON/OFF) Synonyms Not permitted in PML Functions. VAR Syntax Use “=“ Where possible. VAR Name READ Use ALERT object or Form. Expressions in ( ) Brackets not needed after “=“ !VALUE = NAME Use !VALUE = !!CE $ Use variables without $ Don’t Quote variables With no $, quotes not needed. @ cursor functions Use Event Driven Graphics !ARRAY[-ve] Not allowed in PML2 !ARRAY[0] Not advised to use at PML2 Dots “.” in Names New meaning at PML2 Form EDIT syntax Use direct setting.
  • 108. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 108 www.aveva.com
  • 109. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 109 www.aveva.com
  • 110. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 110 www.aveva.com
  • 111. 111 www.aveva.com APPENDIX B Appendix B – Example code This appendix contains examples of code that provide solutions to each of the exercises. As some exercises required existing forms to be updated, new code or code which has been changed is show in Red for completion all code is included. Appendix B1 - Example ex1.mac ------------------------------------------------------------------ -- Programming Macro Language Training Course -- Exercise 1 - PML1 Macro to build centre of a Handwheel ------------------------------------------------------------------ -- 1. Create a new piece of equipment -- 2. Create primitives, positioning them relative to each other NEW EQUIPMENT /HandWheel NEW BOX XLEN 100 YLEN 100 ZLEN 100 NEW CYLINDER DIAM 80 HEIG 5 CONN P1 TO P3 OF PREV NEW BOX XLEN 50 YLEN 50 ZLEN 15 CONN P6 TO P2 OF PREV NEW DISH DIAM 50 HEIG 15 CONN P2 TO P3 OF PREV ADD /HandWheel AUTO /HandWheel -- Note: to run this macro type into the command line: -- $m/c:/pmltraining/ex1.mac
  • 112. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 112 www.aveva.com Appendix B2 - Example ex2.mac ------------------------------------------------------------------ -- Programming Macro Language Training Course -- Exercise 2 - Parameterised Macro to build centre of a Handwheel -- and single part of outer wheel ------------------------------------------------------------------ -- 1. Convert ex1 to include parameters -- 2. Add extra primitives to represent the outer wheel $d1=HandWheel $d2=100 $d3=80 $d4=5 $d5=50 $d6=15 $d7=500 $d8=525 $d9=575 NEW EQUIPMENT /$1 NEW BOX /$1-Centre XLEN $2 YLEN $2 ZLEN $2 NEW CYLINDER DIAM $3 HEIG $4 CONN P1 TO P3 OF PREV NEW BOX XLEN $5 YLEN $5 ZLEN $6 CONN P6 TO P2 OF PREV NEW DISH DIAM $5 HEIG $6 CONN P2 TO P3 OF PREV NEW CYLINDER DIAM $5 HEIG $7 CONN P1 TO P2 OF /$1-Centre NEW CTORUS RINS $8 ROUT $9 CONN P0 TO P0 OF /$1-Centre ADD /$1 AUTO /$1 -- Note: to run this macro type into the command line: -- $m/c:/pmltraining/ex2.mac HANDWHEEL 100 80 5 50 10 500 525 575 New primitives reference the newly named BOX1
  • 113. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 113 www.aveva.com Appendix B3 - Example ex3.mac ------------------------------------------------------------------ -- Programming Macro Language Training Course -- Exercise 3 - Parameterised Macro to build centre of a Handwheel -- and outer wheel using a loop ------------------------------------------------------------------ -- 1. Convert ex2 to include less parameters (include calculations) -- 2. Introduce sub-equipments to organise primitives -- 3. Add a loop to copy and rotate the arm sub-equipment $d1=HandWheel $d2=100 $d3=50 $d4=500 !WashDia = $2 - 20 !WashThk = $2 / 20 !BoltSize = $2 / 2 !BoltThk = $2 / 10 !Dia1 = $4 + ( $2 / 4 ) !Dia2 = !Dia1 + $3 NEW EQUIPMENT /$1 NEW SUBE /$1-Centre NEW BOX /$1-Centre-Box XLEN $2 YLEN $2 ZLEN $2 NEW CYLINDER DIAM $!WashDia HEIG $!WashThk CONN P1 TO P3 OF PREV NEW BOX XLEN $!BoltSize YLEN $!BoltSize ZLEN $!BoltThk CONN P6 TO P2 OF PREV NEW DISH DIAM $!BoltSize HEIG $!BoltThk CONN P2 TO P3 OF PREV NEW SUBE /$1-Arm-1 NEW CYLINDER DIAM $3 HEIG $4 CONN P1 TO P2 OF /$1-Centre-Box NEW CTORUS RINS $!Dia1 ROUT $!Dia2 CONN P0 TO P0 OF /$1-Centre-Box do !p from 2 to 4 NEW SUBE /$1-Arm-$!p COPY PREV ROTATE BY 90 ABOUT U enddo ADD /$1 AUTO /$1 -- Note: to run this macro type into the command line: -- $m/c:/pmltraining/ex3.mac HANDWHEEL 100 50 500 Loop to create copies 6 variables created from the 4 parameters
  • 114. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 114 www.aveva.com Appendix B4 - Example ex4.mac ------------------------------------------------------------------ -- Programming Macro Language Training Course -- Exercise 4 - Add error handling ------------------------------------------------------------------ -- 1. Add error handling -- 2. Handle error if try to create at wrong part of hierarchy -- 3. Handle error if equipment already exists ZONE handle ANY !!Alert.Error(|Need to be at a ZONE element, or below|) elsehandle NONE $d1=HandWheel $d2=100 $d3=50 $d4=500 !WashDia = $2 - 20 !WashThk = $2 / 20 !BoltSize = $2 / 2 !BoltThk = $2 / 10 !Dia1 = $4 + ( $2 / 4 ) !Dia2 = !Dia1 + $3 !n = REAL() NEW EQUIPMENT /$1$!n handle ANY !n = 0 LABEL /NameRepeat !n = !n + 1 name /$1$!n handle ANY GOLABEL /NameRepeat endhandle endhandle NEW SUBE /$1$!n-Centre NEW BOX /$1$!n-Centre-Box XLEN $2 YLEN $2 ZLEN $2 NEW CYLINDER DIAM $!WashDia HEIG $!WashThk CONN P1 TO P3 OF PREV NEW BOX XLEN $!BoltSize YLEN $!BoltSize ZLEN $!BoltThk CONN P6 TO P2 OF PREV NEW DISH DIAM $!BoltSize HEIG $!BoltThk CONN P2 TO P3 OF PREV NEW SUBE /$1$!n-Arm-1 NEW CYLINDER DIAM $3 HEIG $4 CONN P1 TO P2 OF /$1$!n-Centre-Box NEW CTORUS RINS $!Dia1 ROUT $!Dia2 CONN P0 TO P0 OF /$1$!n-Centre-Box do !p from 2 to 4 NEW SUBE /$1$!n-Arm-$!p COPY PREV ROTATE BY 90 ABOUT U enddo EQUI REM ALL ADD /$1$!n AUTO /$1$!n endhandle -- Note: to run this macro type into the command line: -- $m/c:/pmltraining/ex4.mac HANDWHEEL 100 50 500 First error handle: error generated if PDMS cannot navigate to a ZONE element Second error handle: Error generated when new element is given the name of an existing one. Variable !aa updated to the number of members in the zone. This provides a unique number to append to the
  • 115. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 115 www.aveva.com Appendix B5 - Example ex5a.pmlfnc define function !!ex5a(!name is STRING) VAR !CENTRE (100) VAR !WHEELDIA (500) VAR !TUBEDIA ($!CENTRE / 2) NEW EQUIP /$!NAME NEW SUBE /$!NAME-BASE REM ALL ADD /$!NAME AUTO /$!NAME EQUIP $P $P DONE! $P endfunction Middle code as ex5.mac
  • 116. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 116 www.aveva.com Appendix B6 - Example ex5b.pmlfnc define function !!ex5b(!name is STRING, !wheelDia is REAL, !wheelWidth is REAL) NEW EQUIP /$!name -- Admin controlled parameters !centre = 100 !axleDia = 100 !baseThk = 50 !wheelThk = 10 !hoseDia = 150 -- Calculations based on parameters !axleHeight = (!wheelDia / 2) + 250 !TwheelWidth = !wheelWidth + (2 * !wheelThk) + !baseThk !tubeDia = !centre / 2 !HwheelDia = !wheelDia / 3 !BwheelDia = !wheelDia / 2 !No = !wheelWidth / !hoseDia !loops = !No.int() NEW SUBE /$!NAME-Base NEW BOX XLEN ($!TwheelWidth + 200) YLEN ($!TwheelWidth + 200) ZLEN $!baseThk POS E 0 N 0 U ($!baseThk / 2) do !I from 0 to 1 NEW EXTRUSION HEIG ($!baseThk / 2) !mod = !TwheelWidth - ($!baseThk / 2) POS W 0 S (($!TwheelWidth / 2) - ($!mod * $!I)) U 0 ORI Y is E and Z is N NEW LOOP NEW VERTEX POS E $!baseThk S ($!TwheelWidth / 2) U 0 NEW VERTEX POS E $!baseThk N ($!Twheelwidth / 2) U 0 NEW VERTEX POS E $!axleHeight N ($!BwheelDia / 2) U 0 NEW VERTEX POS E ($!axleHeight + ($!BwheelDia / 2)) N ($!BwheelDia / 2) U 0 FRAD ($!BwheelDia / 2) NEW VERTEX POS E ($!axleHeight + ($!BwheelDia / 2)) S ($!BwheelDia / 2) U 0 FRAD ($!BwheelDia / 2) NEW VERTEX POS E $!axleHeight S ($!BwheelDia / 2) U 0 enddo NEW CYLINDER /$!NAME-Base-Axle DIAM $!axleDia HEIG ($!Twheelwidth + 50) POS E 0 N 0 U $!axleHeight ORI Y is E and Z is N NEW SUBE /$!NAME-Hose POS E 0 N 0 U $!axleHeight ORI Y is D and Z is S do !I from -1 to 1 by 2 NEW CYLINDER DIAM $!wheelDia HEIG $!wheelThk POS E 0 N 0 U ((($!hoseDia * ($!loops / 2)) + ($!wheelThk / 2)) * $!I) enddo do !I from 0 to (!loops - 1) do !J from 0 to 1 NEW CTORUS RINS (($!wheelDia / 2) - 50 - $!hoseDia) ROUT (($!wheelDia / 2) - 50) ANGL 180 POS E 0 N 0 U ((($!hoseDia * ($!loops / 2))) - ($!hoseDia / 2) - ($!hoseDia * $!I)) ROTATE BY ($!J * 180) ABOUT S wrt /* enddo enddo NEW CYLINDER DIAM $!hoseDia HEIG ($!wheelDia / 3) CONN P1 TO P2 OF PREV NEW CYLINDER DIAM ($!hoseDia + 40) HEIG 25 Increase the number of variables controlled by the owner of the function Whole number of hose loops calculated Loop to create the two extrusions. Position controlled by the loop value
  • 117. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 117 www.aveva.com CONN P1 TO P2 OF PREV NEW CYLINDER DIAM ($!hoseDia + 10) HEIG 50 CONN P1 TO P2 OF PREV NEW CYLINDER DIAM ($!hoseDia + 40) HEIG 25 CONN P1 TO P2 OF PREV NEW CONE DTOP ($!hoseDia + 10) DBOT 100 HEIG ($!hoseDia * 1.5) CONN P1 TO P2 OF PREV NEW REVOLUTION ANGL 360 NEW LOOP NEW VERTEX NEW VERTEX POS W 10 N 0 U 0 NEW VERTEX POS W 10 N 60 U 0 FRAD 5 NEW VERTEX POS W 0 N 60 U 0 FRAD 5 REVO CONN P1 TO P2 OF PREV ROTATE BY 90 ABOUT D NEW SUBE /$!NAME-Centre NEW BOX /$!NAME-Centre-Box XLEN $!centre YLEN $!centre ZLEN $!centre CONN P6 TO P2 OF /$!NAME-Base-Axle NEW CYLINDER DIAM ($!centre - 20) HEIG ($!centre / 20) CONN P1 TO P3 OF PREV NEW BOX XLEN ($!centre / 2) YLEN ($!centre / 2) ZLEN ($!centre / 10) CONN P6 TO P2 OF PREV NEW DISH DIAM ($!centre / 2) HEIG ($!centre / 10) CONN P2 TO P3 OF PREV NEW SUBE /$!NAME-Arm-1 !box = /$!NAME-Centre-Box !!CE.pos = !box.worpos NEW CYLINDER DIAM $!tubeDia HEIG ($!HwheelDia - ($!tubeDia / 2) - ($!centre / 2)) CONN P1 TO P2 OF /$!NAME-Centre-Box NEW CTORUS RINS ($!HwheelDia - $!tubeDia) ROUT $!HwheelDia CONN P0 TO P0 OF /$!NAME-Centre-Box do !p from 2 to 4 !angle = (!p - 1) * 90 NEW SUBE /$!NAME-Arm-$!P COPY /$!NAME-Arm-1 ROTATE BY $!angle ABOUT S enddo REM ALL ADD /$!name AUTO /$!name EQUIP $P $P DONE $P Endfunction Navigate back to the Revolution primitive so it can be connected by primitive
  • 118. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 118 www.aveva.com Appendix B7 - Example ex6a.pmlfrm setup form !!ex6a dialog resizeable !this.formTitle = |Exercise 6(a) Form| frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| call |!this.tempConv()| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempOut |Temperature conversion (Output)| anchor L+T+R at xmax.tempin + 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL exit define method .ex6a() !this.tempin.callback = |!this.tempConv()| !this.temp.val = 0 !this.tempIn.val = 1 endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.temp.val * 1.8 + 32 !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = (!this.temp.val - 32 ) / 1.8 !this.text2.val = |°C| endif endmethod Depending whether C of F is entered by the user, the correct equation is d
  • 119. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 119 www.aveva.com Appendix B8 - Example ex6b.pmlfrm setup form !!ex6b dialog resizeable !this.formTitle = |Exercise 6(b) Form| path down frame .input |Inputs| at x 0 anchor T+L+B frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| call |!this.tempConv()| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| anchor ALL at x1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY exit exit frame .results |Results| at xmax + 1 y 0 anchor ALL frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor ALL at x1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit exit button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL exit define method .ex6b() !this.tempin.callback = |!this.tempConv()| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) !headings.append(| |) !headings.append(|Fahrenheit|) !this.table1.setHeadings(!headings) !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.temp.val * 1.8 + 32 !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = (!this.temp.val - 32 ) / 1.8 !this.text2.val = |°C| endif endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val As the step value should be a whole number, we shall use a PDMS standard format Define default values as part of the constructor method If the FILL button is pressed, a loop collects the required values in an array and applies them to the output table.
  • 120. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 120 www.aveva.com !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif endif endmethod Use !flag variable to identify which gadget initiates the method Series of checks to make sure the entered values are correct
  • 121. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 121 www.aveva.com Appendix B9 - Example ex6c.pmlfrm setup form !!ex6c dialog resizeable !this.formTitle = |Exercise 6(c) Form| path down frame .input |Inputs| at x 0 anchor T+L+B frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| call |!this.tempConv()| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| at x 1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY exit frame .tempCheck |Temperatue Check| anchor ALL at x1 width.tempIn text .inputTemp |Input Temp.| call || width 10 is REAL text .safeTemp |Safe Temp. | call || width 10 is REAL text .range |Range (±) | call || width 10 is REAL button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY exit exit frame .results |Results| at xmax + 1 y 0 anchor ALL frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor L+T+R at x1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x1 ymin.tempCheck width.tempCheck height.tempCheck textpane .table2 dock fill width 1 height 1 exit exit button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL exit define method .ex6c() !this.tempin.callback = |!this.tempConv()| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) !headings.append(| |) !headings.append(|Fahrenheit|) !this.table1.setHeadings(!headings) !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 !this.inputTemp.val = 100 !this.safeTemp.val = 75 !this.range.val = 10 endmethod
  • 122. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 122 www.aveva.com define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.CtoF(!this.temp.val) !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = !this.FtoC(!this.temp.val) !this.text2.val = |°C| endif endmethod define method .CtoF(!val is REAL) is REAL !fahren = !val * 1.8 + 32 return !fahren endmethod define method .FtoC(!val is REAL) is REAL !centi = (!val - 32 ) / 1.8 return !centi endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif Method updated to use conversion methods which return converted temperatures Equations moved to separate methods so they can be used by other methods.
  • 123. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 123 www.aveva.com endif endmethod define method .compile() !compile = ARRAY() !compiled = !this.table2.val !No = !compiled.size() + 1 if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then !diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val) !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range| elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then !diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range| else !compareString = || endif !newLine = !No & |. | & !this.inputTemp.val & |°C is | & !this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString !compiled.append(!newLine) !this.table2.val = !compiled endmethod Calculate the differences using the new conversion methods. Concatenate the new values into a single string and append to the existing value Read the existing table value and the number of the next line
  • 124. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 124 www.aveva.com Appendix B10 - Example ex6d.pmlfrm setup form !!ex6d dialog resizeable !this.formTitle = |Exercise 6(d) Form| path down frame .input |Inputs| at x 0 anchor T+L+B frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| call |!this.tempConv()| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| at x 1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY exit frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn text .inputTemp |Input Temp.| call || width 10 is REAL text .safeTemp |Safe Temp. | call || width 10 is REAL text .range |Range (±) | call || width 10 is REAL button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY exit frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn text .stringIn |Input | width 24 is STRING text .delim |Delimiter | width 10 is STRING button .split | Split >> | call |!this.split()| at xmax.delim + 2 ymin.delim APPLY exit exit frame .results |Results| anchor ALL at xmax + 1 y 0 frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck width.tempCheck height.tempCheck textpane .table2 dock fill width 1 height 1 exit frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT text .result |Result | width.stringIn is STRING exit exit button .dismiss | Dismiss | at xmax form-size ymax form anchor R+B CANCEL exit define method .ex6d() !this.tempin.callback = |!this.tempConv()| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) !headings.append(| |) !headings.append(|Fahrenheit|) !this.table1.setHeadings(!headings)
  • 125. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 125 www.aveva.com !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 !this.inputTemp.val = 100 !this.safeTemp.val = 75 !this.range.val = 10 !this.stringIn.val = |10°C/30°C/20°C/5°C| !this.delim.val = |/| endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.CtoF(!this.temp.val) !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = !this.FtoC(!this.temp.val) !this.text2.val = |°C| endif endmethod define method .CtoF(!val is REAL) is REAL !fahren = !val * 1.8 + 32 return !fahren endmethod define method .FtoC(!val is REAL) is REAL !centi = (!val - 32 ) / 1.8 return !centi endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif
  • 126. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 126 www.aveva.com elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif endif endmethod define method .compile() !compile = ARRAY() !compiled = !this.table2.val !No = !compiled.size() + 1 if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then !diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val) !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range| elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then !diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range| else !compareString = || endif !newLine = !No & |. | & !this.inputTemp.val & |°C is | & !this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString !compiled.append(!newLine) !this.table2.val = !compiled endmethod define method .split() !split = !this.stringIn.val.trim().split(!this.delim.val) !this.number.val = !split.size() !result = || do !I index !split !result = !this.CtoF(!split[!I].substring(1, !split[!I].length() – 2 ).real()).string(!!INTEGERFMT) & |°F | & !result enddo !this.result.val = !result endmethod Loop through the split values, convert them and recompile as a string Read the input string and split it on the input delimiter
  • 127. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 127 www.aveva.com Appendix B11 - Example ex7.pmlfrm setup form !!ex7 dialog resizeable !this.formTitle = |Exercise 7 Form| path down frame .input |Inputs| at x 0 anchor T+L+B frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| call |!this.tempConv()| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| at x 1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT button .fill | Fill >> | call |!this.fill()| at xmax.step + 2 ymin.step APPLY exit frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn text .inputTemp |Input Temp.| call || width 10 is REAL text .safeTemp |Safe Temp. | call || width 10 is REAL text .range |Range (±) | call || width 10 is REAL button .clear |Clear List| call |!this.table2.clear()| at xmax.range + 2 ymin.range button .compile |Compile >>| call |!this.compile()| at xmin.clear ymin.clear - size APPLY exit frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn text .stringIn |Input | width 24 is STRING text .delim |Delimiter | width 10 is STRING button .split | Split >> | call |!this.split()| at xmax.delim + 2 ymin.delim APPLY exit exit frame .results |Results| anchor ALL at xmax + 1 y 0 frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck width.tempCheck height.tempCheck textpane .table2 dock fill width 1 height 1 exit frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT text .result |Result | width.stringIn is STRING exit exit button .apply | Apply | at x 0 ymax form anchor L+B call |!this.setData(1)| button .reset | Reset | at xcen form - 0.5 * size ymin.apply anchor L+B call |!this.setData(2)| button .dismiss | Dismiss | at xmax form-size ymin.apply anchor R+B CANCEL member .data is ARRAY exit define method .ex7() !this.tempin.callback = |!this.tempConv()| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) Form member to store data
  • 128. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 128 www.aveva.com !headings.append(| |) !headings.append(|Fahrenheit|) !this.table1.setHeadings(!headings) !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 !this.inputTemp.val = 100 !this.safeTemp.val = 75 !this.range.val = 10 !this.stringIn.val = |10°C/30°C/20°C/5°C| !this.delim.val = |/| !this.setData(1) endmethod define method .setData(!flag is REAL) -- Either save the values, or bring them back (array of strings) if !flag.eq(1) then !this.data[1] = !this.temp.val !this.data[2] = !this.tempIn.val !this.data[3] = !this.mini.val !this.data[4] = !this.maxi.val !this.data[5] = !this.step.val !this.data[6] = !this.inputTemp.val !this.data[7] = !this.safeTemp.val !this.data[8] = !this.range.val !this.data[9] = !this.stringIn.val !this.data[10]= !this.delim.val else !this.temp.val = !this.data[1] !this.tempIn.val = !this.data[2] !this.mini.val = !this.data[3] !this.maxi.val = !this.data[4] !this.step.val = !this.data[5] !this.inputTemp.val= !this.data[6] !this.safeTemp.val = !this.data[7] !this.range.val = !this.data[8] !this.stringIn.val = !this.data[9] !this.delim.val = !this.data[10] !this.tempConv() !this.fill() !this.split() endif endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.CtoF(!this.temp.val) !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = !this.FtoC(!this.temp.val) !this.text2.val = |°C| endif endmethod define method .CtoF(!val is REAL) is REAL !fahren = !val * 1.8 + 32 return !fahren endmethod Method created to store/change appropriate default values.
  • 129. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 129 www.aveva.com define method .FtoC(!val is REAL) is REAL !centi = (!val - 32 ) / 1.8 return !centi endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif endif define method .compile() !compile = ARRAY() !compiled = !this.table2.val !No = !compiled.size() + 1 if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then !diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val) !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - ABOVE safe range| elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then !diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = | - | & !diff & |°C/| & !diffFahr & |°F - BELOW safe range| else !compareString = ||
  • 130. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 130 www.aveva.com endif !newLine = !No & |. | & !this.inputTemp.val & |°C is | & !this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F| & !compareString !compiled.append(!newLine) !this.table2.val = !compiled endmethod define method .split() !split = !this.stringIn.val.trim().split(!this.delim.val) !this.number.val = !split.size() !result = || do !I index !split !result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result enddo !this.result.val = !result endmethod
  • 131. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 131 www.aveva.com Appendix B12 - Example ex8.pmlfrm setup form !!ex8 dialog resizeable !this.formTitle = |Exercise 8 Form| path down frame .tabSet TABSET 'tabset' anchor all frame .input |Inputs| at x 0 y 0 dock fill frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| at x 1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT exit frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn text .inputTemp |Input Temp.| call || width 10 is REAL text .safeTemp |Safe Temp. | call || width 10 is REAL text .range |Range (±) | call || width 10 is REAL exit frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn text .stringIn |Input | width 24 is STRING text .delim |Delimiter | width 10 is STRING exit exit frame .results |Results| at x 0 y 0 dock fill frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck width.tempCheck height.tempCheck textpane .table2 dock fill width 1 height 1 exit frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT text .result |Result | width.stringIn is STRING exit exit exit button .apply | Apply | at x 0 ymax form anchor L+B call |!this.setData(1)| button .reset | Reset | at xcen form - 0.5 * size ymin.apply anchor L+B call |!this.setData(2)| button .dismiss | Dismiss | at xmax form-size ymin.apply anchor R+B CANCEL member .data is ARRAY exit define method .ex8() !this.results.callback = |!this.tabCall(| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) !headings.append(| |) !headings.append(|Fahrenheit|) Tabset added and buttons removed Callback applied to results tab
  • 132. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 132 www.aveva.com !this.table1.setHeadings(!headings) !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 !this.inputTemp.val = 100 !this.safeTemp.val = 75 !this.range.val = 10 !this.stringIn.val = |10°C/30°C/20°C/5°C| !this.delim.val = |/| endmethod define method .tabCall(!gad is GADGET, !type is STRING) if !type eq |SHOWN| then !this.tempConv() !this.fill() !this.compile() !this.split() endif endmethod define method .compile() if !this.inputTemp.val.unset() then !this.table2.clear() else !compile = ARRAY() !compiled = !this.table2.val !No = !compiled.size() + 1 if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then !diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val) !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = !diff & |°C/| & !diffFahr & |°F - ABOVE safe range| elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then !diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = !diff & |°C/| & !diffFahr & |°F - BELOW safe range| else !compareString = || endif !newLine = !No & |. | & !this.inputTemp.val & |°C is | & !this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F - | & !compareString !compiled.append(!newLine) !this.table2.val = !compiled endif endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.CtoF(!this.temp.val) !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = !this.FtoC(!this.temp.val) !this.text2.val = |°C| endif endmethod define method .CtoF(!val is REAL) is REAL !fahren = !val * 1.8 + 32 return !fahren Method updated to check for an unset input temperature Open callback calls all methods once the results tab is SHOWN
  • 133. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 133 www.aveva.com endmethod define method .FtoC(!val is REAL) is REAL !centi = (!val - 32 ) / 1.8 return !centi endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif endif endmethod define method .split() !split = !this.stringIn.val.trim().split(!this.delim.val) !this.number.val = !split.size() !result = || do !I index !split !result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result enddo !this.result.val = !result endmethod define method .setData(!flag is REAL)
  • 134. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 134 www.aveva.com -- Either save the values, or bring them back (array of strings) if !flag.eq(1) then !this.data[1] = !this.temp.val.string() !this.data[2] = !this.tempIn.val.string() !this.data[3] = !this.mini.val.string() !this.data[4] = !this.maxi.val.string() !this.data[5] = !this.step.val.string() !this.data[6] = !this.inputTemp.val.string() !this.data[7] = !this.safeTemp.val.string() !this.data[8] = !this.range.val.string() !this.data[9] = !this.stringIn.val !this.data[10]= !this.delim.val else if !this.data.size().eq(10) then !this.temp.val = !this.data[1].real() !this.tempIn.val = !this.data[2].real() !this.mini.val = !this.data[3].real() !this.maxi.val = !this.data[4].real() !this.step.val = !this.data[5].real() !this.inputTemp.val= !this.data[6].real() !this.safeTemp.val = !this.data[7].real() !this.range.val = !this.data[8].real() !this.stringIn.val = !this.data[9] !this.delim.val = !this.data[10] !this.tempConv() !this.fill() !this.split() endif endif endmethod
  • 135. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 135 www.aveva.com Appendix B13 - Example ex9.pmlfrm setup form !!ex9 dialog resizeable !this.formTitle = |Exercise 9 Form| bar !this.bar.add('Control', 'Menu1') !this.bar.add('Defaults', 'Menu2') !this.bar.add('Help', 'Help') !menu1 = !this.newmenu( 'Menu1', 'MAIN') !menu1.add('CALLBACK', 'Close', '!this.hide()', 'Close') !menu1.add('SEPARATOR') !menu1.add('CALLBACK', 'Load Defaults...', 'call !!fileBrowser(''c:'', ''*.txt'', ''Load Defaults'', false, ''!!ex9.loadFile()'')') !menu2 = !this.newmenu( 'Menu2', 'MAIN') !menu2.add('CALLBACK', 'Update Defaults', '!this.setData(1)') !menu2.add('CALLBACK', 'Reset to Defaults', '!this.setData(2)') path down frame .tabSet TABSET 'tabset' anchor all frame .input |Inputs| at x 0 y 0 dock fill frame .tempIn |Temperature conversion (Input)| at x 1 text .temp |Temperature| width 10 is REAL rToggle .Cent |C| tagwid 3 at xmax.temp + 2 ymin.temp rToggle .Fahr |F| tagwid 3 at xmax.Cent ymin.temp exit frame .tempRange |Temperature Range| at x 1 width.tempIn text .mini |Minimim C | call |!this.check(1)| at x 1 width 10 is REAL text .maxi |Maximum C | call |!this.check(2)| at x 1 width 10 is REAL text .step |Step Size | call |!this.check(0)| at x 1 width 10 is REAL format !!INTEGERFMT exit frame .tempCheck |Temperatue Check| anchor ALL at x 1 width.tempIn text .inputTemp |Input Temp.| call || width 10 is REAL text .safeTemp |Safe Temp. | call || width 10 is REAL text .range |Range (±) | call || width 10 is REAL exit frame .strIn |Temperture Split| anchor L+B+R at x 1 width.tempIn text .stringIn |Input | width 24 is STRING text .delim |Delimiter | width 10 is STRING exit exit frame .results |Results| at x 0 y 0 dock fill frame .tempOut |Temperature conversion (Output)| anchor L+T+R at x 1 width.tempIn height.tempIn text .out |Temperature| call || width 10 is REAL para .text2 at xmax.out ymin.temp text || width 5 exit frame .tempRangeOut |Temperature Results| anchor L+T+R at x 1 width.tempRange height.tempRange list .table1 dock fill columns width 1 height 1 exit frame .tempCheckOut |Compiled Temperature Checks| anchor ALL at x 1 ymin.tempCheck width.tempCheck height.tempCheck textpane .table2 dock fill width 1 height 1 exit frame .strOut |Temperature Split Result| anchor L+B+R at x 1 ymin.strIn width.strIn height.strIn text .number |No. of Temp| width 10 is REAL format !!INTEGERFMT text .result |Result | width.stringIn is STRING exit exit exit member .data is ARRAY Bar menu added to replace buttons
  • 136. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 136 www.aveva.com exit define method .loadFile() !file = !!filebrowser.file if !file.IsOpen() then !file.close() endif !lines = !file.ReadFile() !n = 0 do !I values !lines if !I.substring(1, 2).eq(|--|) or !I.eq(||) then else !n = !n + 1 !collect[!n] = !I endif enddo if !collect.size().eq(10) then !this.data = !collect !this.setData(2) else !!Alert.Warning(|Please check the chosen default file|) endif endmethod define method .ex9() !this.results.callback = |!this.tabCall(| !headings = ARRAY() !headings.append(|No.|) !headings.append(|Centigrade|) !headings.append(| |) !headings.append(|Fahrenheit|) !this.table1.setHeadings(!headings) !this.temp.val = 0 !this.tempIn.val = 1 !this.mini.val = 0 !this.maxi.val = 100 !this.step.val = 25 !this.inputTemp.val = 100 !this.safeTemp.val = 75 !this.range.val = 10 !this.stringIn.val = |10°C/30°C/20°C/5°C| !this.delim.val = |/| endmethod define method .tabCall(!gad is GADGET, !type is STRING) if !type eq |SHOWN| then !this.tempConv() !this.fill() !this.compile() !this.split() endif endmethod define method .tempConv() if !this.tempIn.val.eq(1) then !this.out.val = !this.CtoF(!this.temp.val) !this.text2.val = |°F| elseif !this.tempIn.val.eq(2) then !this.out.val = !this.FtoC(!this.temp.val) !this.text2.val = |°C| endif Method takes file name from standard PDMS file browser form Loop through the read file, collecting the lines of interest Check the amount of the collected information is as expected
  • 137. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 137 www.aveva.com endmethod define method .CtoF(!val is REAL) is REAL !fahren = !val * 1.8 + 32 return !fahren endmethod define method .FtoC(!val is REAL) is REAL !centi = (!val - 32 ) / 1.8 return !centi endmethod define method .fill() !n = 0 do !temp from !this.mini.val to !this.maxi.val by !this.step.val !n = !n + 1 !temps[!n][1] = !n.string() !temps[!n][2] = !temp.string() !temps[!n][3] = |=| !fahren = !temp * 1.8 + 32 !temps[!n][4] = STRING(!fahren,!!RealFMT) enddo !this.table1.setRows( !temps ) endmethod define method .check(!flag is REAL) if !flag.eq(0) then if !this.step.val.eq(0) then !this.step.val = 1 endif elseif !flag.eq(1) or !flag.eq(2) then if !this.maxi.val.unset() then !this.maxi.val = !this.mini.val + !this.step.val elseif !this.mini.val.unset() then !this.mini.val = !this.maxi.val - !this.step.val endif if (!this.mini.val.lt(-273)) then !this.mini.val = -273 if (!this.maxi.val.leq(!this.mini.val)) then !this.maxi.val = -272 endif elseif (!this.maxi.val.lt(-273)) then !this.mini.val = -273 !this.maxi.val = -272 endif if (!this.maxi.val.leq(!this.mini.val)) then if !flag.eq(1) then !this.maxi.val = !this.mini.val + !this.step.val elseif !flag.eq(2) then !this.mini.val = !this.maxi.val - !this.step.val endif endif endif endmethod define method .compile() if !this.inputTemp.val.unset() then !this.table2.clear() else !compile = ARRAY() !compiled = !this.table2.val
  • 138. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 138 www.aveva.com !No = !compiled.size() + 1 if !this.inputTemp.val.gt(!this.safeTemp.val + !this.range.val) then !diff = !this.inputTemp.val - (!this.safeTemp.val + !this.range.val) !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = !diff & |°C/| & !diffFahr & |°F - ABOVE safe range| elseif !this.inputTemp.val.lt(!this.safeTemp.val - !this.range.val) then !diff = (!this.safeTemp.val - !this.range.val) - !this.inputTemp.val !diffFahr = !this.CtoF(!diff).string(!!INTEGERFMT) !compareString = !diff & |°C/| & !diffFahr & |°F - BELOW safe range| else !compareString = || endif !newLine = !No & |. | & !this.inputTemp.val & |°C is | & !this.CtoF(!this.inputTemp.val).string(!!INTEGERFMT) & |°F - | & !compareString !compiled.append(!newLine) !this.table2.val = !compiled endif endmethod define method .split() !split = !this.stringIn.val.trim().split(!this.delim.val) !this.number.val = !split.size() !result = || do !I index !split !result = !this.CtoF(!split[!I].substring(1, !split[!I].length() - 2).real()).string(!!INTEGERFMT) & |°F | & !result enddo !this.result.val = !result endmethod define method .setData(!flag is REAL) -- Either save the values, or bring them back (array of strings) if !flag.eq(1) then !this.data[1] = !this.temp.val.string() !this.data[2] = !this.tempIn.val.string() !this.data[3] = !this.mini.val.string() !this.data[4] = !this.maxi.val.string() !this.data[5] = !this.step.val.string() !this.data[6] = !this.inputTemp.val.string() !this.data[7] = !this.safeTemp.val.string() !this.data[8] = !this.range.val.string() !this.data[9] = !this.stringIn.val !this.data[10]= !this.delim.val else if !this.data.size().eq(10) then !this.temp.val = !this.data[1].real() !this.tempIn.val = !this.data[2].real() !this.mini.val = !this.data[3].real() !this.maxi.val = !this.data[4].real() !this.step.val = !this.data[5].real() !this.inputTemp.val= !this.data[6].real() !this.safeTemp.val = !this.data[7].real() !this.range.val = !this.data[8].real() !this.stringIn.val = !this.data[9] !this.delim.val = !this.data[10] !this.tempConv() !this.fill() !this.split() endif endif endmethod
  • 139. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 139 www.aveva.com Appendix B14 - Example ex10.pmlfrm setup form !!ex10 !this.formTitle = |Exercise 10 form| !this.initcall = |!this.init()| frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| exit exit define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext endif endif endmethod
  • 140. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 140 www.aveva.com Appendix B15 - Example ex11a.pmlfrm setup form !!ex11a !this.formTitle = |Exercise 11a form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| exit exit define method .ex11a() !this.nozz.setpopup(!this.pop1) endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext endif endif endmethod Constructor method add to apply pop-up menu to gadget.
  • 141. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 141 www.aveva.com Appendix B16 - Example ex11b.pmlfrm setup form !!ex11b !this.formTitle = |Exercise 11b form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| exit exit define method .ex11b() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !this.nozz.setpopup(!this.pop1) endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| Method reads the nozzles in the list gadget. This means it could be run on its own. Check method runs through the attributes of the nozzles and checks the attributes: Cref: connection reference Check to see if the nozzle is attached. If an error occurs when navigating to the cref connection needs checking Href or Tref: pipe head/tail ref A pointer on the pipe which should point back at the connected nozzle Hpos, Hdir, Hbore, Tpos, Tdir and Tbore: pipe attributes Check these attributes against the nozzle to check for problems. If problems are found, a value of “check” is used Constructor method adds headings to the list gadget Method now calls .checkNozz() method
  • 142. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 142 www.aveva.com !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod .setrows() method overwrites the Rtext, therefore rtext remember then reset.
  • 143. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 143 www.aveva.com Appendix B17 - Example ex11c.pmlfrm setup form !!ex11c !this.formTitle = |Exercise 11c form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| exit exit define method .ex11c() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) endif endif endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then Method runs in a “read attribute” mode or a “write attribute” mode – decide by !fl Read the attributes already typed into the text pane Constructor method default values to the textpane Method now calls .updateAtt() method – passing 1 as an arguement
  • 144. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 144 www.aveva.com !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I.eq(1) then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else Calculate new attribute values for the chosen equipment Compile new strings for the textpane and apply to the gadget Add a error array to record errors Handle any errors relating to date type (Real, String etc) Apply to attribuite values to the chosen equipment If handles don’t solve it, record the !attrib variable to the error array If errors exist, report them to the user. Loop through the members of the array to compile one string
  • 145. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 145 www.aveva.com !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod
  • 146. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 146 www.aveva.com Appendix B18 - Example ex12a.pmlfrm setup form !!ex12a !this.formTitle = |Exercise 12a form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') view .view3d at x 0.5 y0.5 VOLUME width 45 aspect 0.707 border off shading on isometric 3 exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| exit exit define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() endif endif endmethod define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !limits[1] = !equip.wvol[1] - !add !limits[2] = !equip.wvol[4] + !add !limits[3] = !equip.wvol[2] - !add !limits[4] = !equip.wvol[5] + !add !limits[5] = !equip.wvol[3] - !add !limits[6] = !equip.wvol[6] + !add !this.view3d.limits = !limits endmethod define method .ex12a() Volume View element added (shaded, isometric 3) Method now calls .limits () Set the limits of the view based on the world volume of the chosen equipment. Notice that the limits array is in a different order to wvol array.
  • 147. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 147 www.aveva.com !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK|
  • 148. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 148 www.aveva.com else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else
  • 149. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 149 www.aveva.com !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod
  • 150. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 150 www.aveva.com Appendix B19 - Example ex12b.pmlfrm setup form !!ex12b !this.formTitle = |Exercise 12b form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') view .view3d at x 0.5 y0.5 VOLUME width 45 aspect 0.707 border off shading on isometric 3 exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| exit member .clipbox is GPHCLIPBOX member .limits is ARRAY exit define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !limits[1] = !equip.wvol[1] - !add !limits[2] = !equip.wvol[4] + !add !limits[3] = !equip.wvol[2] - !add !limits[4] = !equip.wvol[5] + !add !limits[5] = !equip.wvol[3] - !add !limits[6] = !equip.wvol[6] + !add !this.limits = !limits !this.view3d.limits = !limits !pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2 !pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2 !pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2 !this.clipbox.box.position.east = !pos[1] !this.clipbox.box.position.north = !pos[2] !this.clipbox.box.position.up = !pos[3] !this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add !this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add !this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add !this.clipbox.view = !this.view3d !this.clipbox.active = FALSE !this.clipbox.view.owner().clipbox.set() !this.view3d.clipping = TRUE endmethod define method .ex12b() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) Member added to store clipbox definition Method extended to calculate clipbox information Once clipbox is calculated, the clipbox is applied to the view
  • 151. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 151 www.aveva.com !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() !this.view3d.refresh() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href
  • 152. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 152 www.aveva.com handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif
  • 153. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 153 www.aveva.com !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod
  • 154. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 154 www.aveva.com Appendix B20 - Example ex12c.pmlfrm setup form !!ex12c !this.formTitle = |Exercise 12c form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') view .view3d at x 0.5 y0.5 VOLUME width 45 aspect 0.707 border off shading on isometric 3 exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46 slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5 text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5 exit exit member .clipbox is GPHCLIPBOX member .limits is ARRAY exit define method .ex12c() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) !this.minslide.val = -1000 !this.maxslide.val = 5000 endmethod define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !this.limits[1] = !equip.wvol[1] - !add !this.limits[2] = !equip.wvol[4] + !add !this.limits[3] = !equip.wvol[2] - !add !this.limits[4] = !equip.wvol[5] + !add !this.limits[5] = !equip.wvol[3] - !add !this.limits[6] = !equip.wvol[6] + !add !this.limits = !limits Slider gadget added Constructor method default values to the textpane Method updated to point at new form member
  • 155. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 155 www.aveva.com !this.view3d.limits = !this.limits !pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2 !pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2 !pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2 !this.clipbox.box.position.east = !pos[1] !this.clipbox.box.position.north = !pos[2] !this.clipbox.box.position.up = !pos[3] !this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add !this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add !this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add !this.clipbox.view = !this.view3d !this.clipbox.active = FALSE !this.clipbox.view.owner().clipbox.set() !this.view3d.clipping = TRUE endmethod define method .slide() !value = !this.slide.val if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or (!this.clipbox.box.zlength + !value lt 0) then else if !this.incl.val.eq(TRUE) then !modlimit = ARRAY() !limits = !this.limits !modlimit[1] = !limits[1] - !value !modlimit[2] = !limits[2] + !value !modlimit[3] = !limits[3] - !value !modlimit[4] = !limits[4] + !value !modlimit[5] = !limits[5] - !value !modlimit[6] = !limits[6] + !value !this.view3d.limits = !modlimit endif !this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value !this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value !this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value !this.view3d.refresh() endif endmethod define method .updateRange() !range[1] = !this.minslide.val !range[2] = !this.maxslide.val !range[3] = 100 !this.slide.range = !range !this.slide.refresh() endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif Limits modified based on the value of the slider gadget Method to modify range of slider gadget
  • 156. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 156 www.aveva.com VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() !this.view3d.refresh() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif
  • 157. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 157 www.aveva.com if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY
  • 158. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 158 www.aveva.com !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod
  • 159. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 159 www.aveva.com Appendix B21 - Example ex12d.pmlfrm setup form !!ex12d !this.formTitle = |Exercise 12d form| !this.initcall = |!this.init()| !this.quitcall = |!this.clear()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') view .view3d at x 0.5 y0.5 VOLUME width 45 aspect 0.707 border off shading on isometric 3 exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip call |!this.check()| columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| button .tagNozzles toggle tooltip 'Tag All Nozzles' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.tag(2)| width 16 height 16 button .tagNozz toggle tooltip 'Tag Selected Nozzle' pixmap at xmin.tagNozzles - size ymax.nozz call |!this.tag(1)| width 16 height 16 textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46 slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5 text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5 exit exit member .clipbox is GPHCLIPBOX member .limits is ARRAY member .tagged is ARRAY exit define method .ex12d() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) !this.minslide.val = -1000 !this.maxslide.val = 5000 !this.tagNozz.AddPixmap(!!PML.GetPathName('single.png'), !!PML.GetPathName('single_x.png')) !this.tagNozzles.AddPixmap(!!PML.GetPathName('multi.png'), !!PML.GetPathName('multi_x.png')) endmethod New member added to store tagged information. Constructor method adds the pictures to the pixmap buttons
  • 160. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 160 www.aveva.com define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() !this.tagged.clear() do !I from 1 to !this.nozz.dtext.size() !this.tagged[!I] = FALSE enddo !this.clear() endif endif endmethod define method .tag(!type is REAL) !nozz = !this.nozz.selection().dbref() !no = !this.nozz.val if !type.eq(1) then if !this.tagNozz.val.eq(TRUE) then !nozzname = !nozz.namn !nozzpos = !nozz.pos AID TEXT NUMBER 1500$!no '$!nozzname' AT $!nozzpos !this.tagged[!no] = TRUE else $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!no$> !this.tagged[!no] = FALSE endif !testtagged = !this.tagged !testtagged.unique() if !testtagged.size().eq(1) and !testtagged[1].eq(TRUE) then !this.tagNozzles.val = TRUE endif elseif !type.eq(2) then if !this.tagNozzles.val.eq(TRUE) then do !i index !this.nozz.rtext !nozzname = !this.nozz.rtext[!i].dbref().namn !nozzpos = !this.nozz.rtext[!i].dbref().pos AID TEXT NUMBER 1500$!i '$!nozzname' AT $!nozzpos !this.tagged[!i] = TRUE enddo !this.tagNozz.val = TRUE else do !i index !this.nozz.rtext $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$> !this.tagged[!i] = FALSE enddo !this.tagNozz.val = FALSE Depending which button is pressed and its value, nozzles are tagged or t d Unique tag numbers needed. Created based on the tags position in the l li t Extra check if nozzles tagged individually. If they are all tagged, or if there is only one nozzle, the tag all button is toggled Part of the method to tag all nozzles. Method now resets the stored tagged information
  • 161. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 161 www.aveva.com endif endif endmethod define method .check() !check = !this.tagged[!this.nozz.val] if !check.eq(TRUE) then !this.tagNozz.val = TRUE else !this.tagNozz.val = FALSE endif endmethod define method .clear() do !i index !this.nozz.rtext $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$> enddo !this.tagNozz.val = FALSE !this.tagNozzles.val = FALSE endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() !this.view3d.refresh() endhandle endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir New callback on nozzle list runs this method. It checks if the chosen nozzle is already tagged and sets the status of the tag button.
  • 162. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 162 www.aveva.com !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim()
  • 163. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 163 www.aveva.com !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !limits[1] = !equip.wvol[1] - !add !limits[2] = !equip.wvol[4] + !add !limits[3] = !equip.wvol[2] - !add !limits[4] = !equip.wvol[5] + !add !limits[5] = !equip.wvol[3] - !add !limits[6] = !equip.wvol[6] + !add !this.limits = !limits !this.view3d.limits = !limits !pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2 !pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2 !pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2 !this.clipbox.box.position.east = !pos[1] !this.clipbox.box.position.north = !pos[2] !this.clipbox.box.position.up = !pos[3] !this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add !this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add !this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add !this.clipbox.view = !this.view3d !this.clipbox.active = FALSE !this.clipbox.view.owner().clipbox.set() !this.view3d.clipping = TRUE endmethod define method .slide()
  • 164. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 164 www.aveva.com !value = !this.slide.val if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or (!this.clipbox.box.zlength + !value lt 0) then else if !this.incl.val.eq(TRUE) then !modlimit = ARRAY() !limits = !this.limits !modlimit[1] = !limits[1] - !value !modlimit[2] = !limits[2] + !value !modlimit[3] = !limits[3] - !value !modlimit[4] = !limits[4] + !value !modlimit[5] = !limits[5] - !value !modlimit[6] = !limits[6] + !value !this.view3d.limits = !modlimit endif !this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value !this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value !this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value !this.view3d.refresh() endif endmethod define method .updateRange() !range[1] = !this.minslide.val !range[2] = !this.maxslide.val !range[3] = 100 !this.slide.range = !range !this.slide.refresh() endmethod
  • 165. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 165 www.aveva.com Appendix B22 - Example ex12e.pmlfrm setup form !!ex12e !this.formTitle = |Exercise 12e form| !this.initcall = |!this.init()| !this.quitcall = |!this.clear()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') view .view3d at x 0.5 y0.5 VOLUME width 45 aspect 0.707 border off shading on isometric 3 exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip call |!this.check()| columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| button .tagNozzles toggle tooltip 'Tag All Nozzles' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.tag(2)| width 16 height 16 button .tagNozz toggle tooltip 'Tag Selected Nozzle' pixmap at xmin.tagNozzles - size ymax.nozz call |!this.tag(1)| width 16 height 16 textpane .atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| button .hlNozz toggle tooltip 'Highlight Nozzles' pixmap at xmin.tagNozz - size ymax.nozz call |!this.highlight()| width 16 height 16 frame .limitslide |Edit Clip Volume| at xmin.atta ymax.updateAtta width 46 slider .slide call |!this.slide()| dock t horizontal range -1000 +5000 step 100 val 0 width 1 height 1.5 text .minslide at xmin.limitslide+0.2 ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL text .maxslide at xmax.limitslide-size ymin.limitslide+2.5 call |!this.updateRange()| width 5 is REAL toggle .incl |Update view limits?| at xmax.minslide + 5 ymin.limitslide+2.5 exit frame .colour |Edit Highlight Colour| at xmin.equipframe + 0.5 ymax.limitslide width.limitslide para .para1 at xmin.colour + 0.5 ymin.colour + 0.75 text |Current equipment | para .para2 at xmin.colour + 0.5 ymax.para1 text |Connected nozzles | para .para3 at xmin.colour + 0.5 ymax.para2 text |Unconnected nozzles| para .para4 at xmin.colour + 0.5 ymax.para3 text |Check nozzles | button .butt1 | | at xmax.para1 - 3 ymin.para1 call |!this.colourpick('A' )| button .butt2 | | at xmax.para2 - 3 ymax.para1 call |!this.colourpick('B' )| button .butt3 | | at xmax.para3 - 3 ymax.para2 call |!this.colourpick('C' )| button .butt4 | | at xmax.para3 - 3 ymax.para3 call |!this.colourpick('D' )| frame .colourpick at xmax.butt1 + 4 ymin.colour + 0.5 width 10 !val = 0 do !I from 1 to 10 do !J from 0 to 4 !val = !val + 1 !no = !I & |000| & !J !x = (!I * 2) - 1 !y = (!J * 0.75) + 0.5 button .butt$!no | | pixmap at x$!x ymin.colourpick + $!y call |!this.colourpick($!val)| backg $!val width 10 aspect 1 enddo enddo exit exit exit Loop to create 50 buttons Each button applied unique name, position and colour (based on colours read from !!colourselect). Pixmap buttons used to esure small
  • 166. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 166 www.aveva.com member .clipbox is GPHCLIPBOX member .limits is ARRAY member .col is REAL member .tagged is ARRAY member .highlight is ARRAY exit define method .ex12e() !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) !this.minslide.val = -1000 !this.maxslide.val = 5000 !this.colourpick.visible = FALSE !this.butt1.background = 1 !this.butt2.background = 20 !this.butt3.background = 18 !this.butt4.background = 23 !this.tagNozz.AddPixmap(!!PML.GetPathName('single.png'), !!PML.GetPathName('single_x.png')) !this.tagNozzles.AddPixmap(!!PML.GetPathName('multi.png'), !!PML.GetPathName('multi_x.png')) !this.hlNozz.AddPixmap(!!PML.GetPathName('highlight.png'), !!PML.GetPathName('highlight_x.png')) endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() !this.view3d.refresh() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) New members added highlight information Constructor method adds the pictures to the highlight button, initial colours the pick buttons and hides the colourpick frame
  • 167. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 167 www.aveva.com !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() !this.tagged.clear() do !I from 1 to !this.nozz.dtext.size() !this.tagged[!I] = FALSE enddo !this.clear() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK|
  • 168. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 168 www.aveva.com else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !this.highlight = !nozzinfo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' Check information stored ready for use with the highlight method
  • 169. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 169 www.aveva.com do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements: $!err|) endif endif endmethod define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !limits[1] = !equip.wvol[1] - !add !limits[2] = !equip.wvol[4] + !add !limits[3] = !equip.wvol[2] - !add !limits[4] = !equip.wvol[5] + !add !limits[5] = !equip.wvol[3] - !add !limits[6] = !equip.wvol[6] + !add !this.limits = !limits !this.view3d.limits = !limits !pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2 !pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2 !pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2 !this.clipbox.box.position.east = !pos[1] !this.clipbox.box.position.north = !pos[2] !this.clipbox.box.position.up = !pos[3] !this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add !this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add !this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add !this.clipbox.view = !this.view3d !this.clipbox.active = FALSE !this.clipbox.view.owner().clipbox.set() !this.view3d.clipping = TRUE !this.view3d.refresh() endmethod define method .slide() !value = !this.slide.val if (!this.clipbox.box.xlength + !value lt 0) or (!this.clipbox.box.ylength + !value lt 0) or (!this.clipbox.box.zlength + !value lt 0) then else if !this.incl.val.eq(TRUE) then !modlimit = ARRAY() !limits = !this.limits !modlimit[1] = !limits[1] - !value !modlimit[2] = !limits[2] + !value !modlimit[3] = !limits[3] - !value !modlimit[4] = !limits[4] + !value !modlimit[5] = !limits[5] - !value !modlimit[6] = !limits[6] + !value !this.view3d.limits = !modlimit endif !this.view3d.clipBoxXlen = !this.clipbox.box.xlength + !value !this.view3d.clipBoxYlen = !this.clipbox.box.ylength + !value !this.view3d.clipBoxZlen = !this.clipbox.box.zlength + !value !this.view3d.refresh() endif endmethod
  • 170. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 170 www.aveva.com define method .updateRange() !range[1] = !this.minslide.val !range[2] = !this.maxslide.val !range[3] = 100 !this.slide.range = !range !this.slide.refresh() endmethod define method .tag(!type is REAL) !nozz = !this.nozz.selection().dbref() !no = !this.nozz.val if !type.eq(1) then if !this.tagNozz.val.eq(TRUE) then !nozzname = !nozz.namn !nozzpos = !nozz.pos AID TEXT NUMBER 1500$!no '$!nozzname' AT $!nozzpos !this.tagged[!no] = TRUE else $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!no$> !this.tagged[!no] = FALSE endif !testtagged = !this.tagged !testtagged.unique() if !testtagged.size().eq(1) and !testtagged[1].eq(TRUE) then !this.tagNozzles.val = TRUE endif elseif !type.eq(2) then if !this.tagNozzles.val.eq(TRUE) then do !i index !this.nozz.rtext !nozzname = !this.nozz.rtext[!i].dbref().namn !nozzpos = !this.nozz.rtext[!i].dbref().pos AID TEXT NUMBER 1500$!i '$!nozzname' AT $!nozzpos !this.tagged[!i] = TRUE enddo !this.tagNozz.val = TRUE else do !i index !this.nozz.rtext $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$> !this.tagged[!i] = FALSE enddo !this.tagNozz.val = FALSE endif endif endmethod define method .check() !check = !this.tagged[!this.nozz.val] if !check.eq(TRUE) then !this.tagNozz.val = TRUE else !this.tagNozz.val = FALSE endif endmethod define method .colourpick(!colour is ANY) !col = !colour.string() if !col.eq('A') then !this.col = 1 !this.colourpick.visible = TRUE elseif !col.eq('B') then !this.col = 2 Method shows/hides the colour pick frame (depending on the t)
  • 171. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 171 www.aveva.com !this.colourpick.visible = TRUE elseif !col.eq('C') then !this.col = 3 !this.colourpick.visible = TRUE elseif !col.eq('D') then !this.col = 4 !this.colourpick.visible = TRUE else if !this.col.eq(1) then !this.butt1.background = !col.real() elseif !this.col.eq(2) then !this.butt2.background = !col.real() elseif !this.col.eq(3) then !this.butt3.background = !col.real() elseif !this.col.eq(4) then !this.butt4.background = !col.real() endif !this.colourpick.visible = FALSE endif endmethod define method .highlight() !ce = !this.equip.selection().dbref().flnn !cecol = !this.butt1.background enhance /$!ce col $!cecol if !this.hlNozz.val.eq(TRUE) then !nozz = !this.highlight do !I index !nozz !nozzle = !this.nozz.rtext[!I].dbref().flnn if !nozz[!I][2].eq(|OK|) then !col = !this.butt2.background elseif !nozz[!I][2].eq(|Check|) then !col = !this.butt3.background endif if !nozz[!I][3].eq(|Check|) or !nozz[!I][4].eq(|Check|) or !nozz[!I][5].eq(|Check|) then !col = !this.butt4.background endif enhance /$!nozzle col $!col enddo else unenhance /$!ce do !i index !this.nozz.rtext !nozzle = !this.nozz.rtext[!i].dbref().flnn unenhance /$!nozzle $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$> enddo endif endmethod define method .clear() !ce = !this.equip.selection().dbref().flnn unenhance /$!ce do !i index !this.nozz.rtext !nozzle = !this.nozz.rtext[!i].dbref().flnn unenhance /$!nozzle $m/%PDMSUI%desgraphicsGAIDCLEAR $<1500$!i$> enddo !this.tagNozz.val = FALSE !this.tagNozzles.val = FALSE endmethod Run through the stored check information and apply the colours as required
  • 172. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 172 www.aveva.com Appendix B23 - Example ex13a.pmlfrm setup form !!ex13a !this.formTitle = |Exercise 13a form| !this.initcall = |!this.init()| frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| button .pick tooltip 'Identify Equipment' pixmap at xmin.equipframe + 0.5 ymax.title call |!this.pick()| width 16 height 16 option .equip at xmax.pick ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| exit exit define method .ex13a() !this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png')) endmethod define method .pick() !packet = object EDGPACKET() !packet.elementPick(|Identify Equipment|) !packet.description = |Identify Equipment| !packet.action = |!!ex13a.identify(!this.return)| !!edgCntrl.add(!packet) endmethod define method .identify(!pickInfo is ANY) !item = !pickInfo[1].item !!edgCntrl.remove(|Identify Equipment|) -- Loop to find the EQUI element do break if (!item.type eq |EQUI|) or (!item.type eq |WORL|) !item = !item.owner enddo if !item.type eq |WORL| then !!Alert.Warning(|Choose a piece of equipment|) !this.pick() else -- Find the EQUI in the OPTION gadget !this.equip.val = !this.equip.dtext.FindFirst(!item.flnn) handle ANY !!Alert.Warning(|The picked equipment is not avaiable in the current OPTION gadget|) endhandle !this.collNozz() endif endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE Apply pixmap to pick button Create an EDG packet Set the packet action to run a method on this form. As EDG is separate for the form, full name is required This method processes the EDG info Loop up hierarchy till either type equals EQUI or WORL If WORL is found, need to repick Option gadget updated to chosen equipment. Handle any errors
  • 173. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 173 www.aveva.com !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext endif endif endmethod
  • 174. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 174 www.aveva.com Appendix B24 - Example ex13b.pmlfrm setup form !!ex13b !this.formTitle = |Exercise 13b form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') frame .equipframe at x 0 y 0 para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| button .pick tooltip 'Identify Nozzle' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.pick()| width 16 height 16 exit exit define method .ex13b() !this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png')) !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !this.nozz.setpopup(!this.pop1) endmethod define method .pick() !packet = object EDGPACKET() !packet.elementPick(|Identify EQUI or NOZZ - Escape to cancel|) !packet.description = |Identify Element| !packet.action = |!!ex13b.identify(!this.return)| !!edgCntrl.add(!packet) endmethod define method .identify(!pickInfo is ANY) !item = !pickInfo[1].item !!edgCntrl.remove(|Identify Element|) -- Loop to find the EQUI element !posNOZZ = 1 !pickedNozz = || do if !item.type eq |NOZZ| then !pickedNozz = !item.flnn endif break if (!item.type eq |EQUI|) or (!item.type eq |WORL|) !item = !item.owner enddo if !item.type eq |WORL| then !!Alert.Warning(|Choose either a nozzle or piece of equipment|) !this.pick() else -- Find the EQUI in the OPTION gadget !this.equip.val = !this.equip.dtext.FindFirst(!item.flnn) !this.collNozz() -- Pick the chosen NOZZ if !pickedNozz.length() gt 0 then Add pixmap to new button Method as before, but now advising user they can pick either EQUI or NOZZ Set initial variable values Loop up through hierarchy to find NOZZ or EQUI (remember both) Set the option gadget to the chosen piece of equipment
  • 175. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 175 www.aveva.com do !I indices !this.nozz.dtext !splitDTEXT = !this.nozz.dtext[!I].split() if !pickedNozz eq !splitDTEXT[1] then !posNozz = !I endif enddo endif !this.nozz.val = !posNozz endif endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results() if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref Select the identified nozzle in the nozzle list. If a piece of EQUI was chosen, the first nozzle in the list will be highlighted
  • 176. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 176 www.aveva.com !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod
  • 177. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 177 www.aveva.com Appendix B25 - Example ex13c.pmlfrm setup form !!ex13c !this.formTitle = |Exercise 13c form| !this.initcall = |!this.init()| !this.newMenu(|pop1|) !this.pop1.add('CALLBACK', 'Go to Nozzle', '!!CE = !this.nozz.selection().dbref()', 'NOZZ') para .prompt at x0 y0 text |Navigate : | width 46 lines 1 view .view3d at x 0.5 y0.5 call '!!edgCntrl.canvasPick(' prompt .prompt VOLUME width 45 aspect 0.707 border off shading on isometric 3 inmode create _default type |DES_NAVIGATE| inmode create _pick type |DES_PICK| exit frame .equipframe at xmax.view3d + 0.5 ymin.view3d width 45 height.view3d para .title at xmin.equipframe + 0.5 ymin.equipframe + 0.5 text |Available Equipment| option .equip at xmin.equipframe + 0.5 ymax.title call |!this.collNozz()| width 10 list .nozz at xmin.equipframe + 0.5 ymax.equip columns width 45 length 5 button .site |Update| at xmax.equip + 0.5 ymax.title call |!this.init()| button .refreshNozz |Refresh| at xmax.nozz - size ymax.nozz call |!this.checkNozz()| button .pick tooltip 'Identify Nozzle' pixmap at xmin.refreshNozz - size ymax.nozz call |!this.pick()| width 16 height 16 textpane.atta |Equipment Attributes| at xmin.equipframe + 0.5 ymax.refreshNozz width 47 height 5 button .updateAtta |Update Atts| at xmax.nozz - size ymax.atta call |!this.updateAtt(2)| exit member .clipbox is GPHCLIPBOX member .limits is ARRAY exit define method .ex13c() !this.pick.AddPixmap(!!PML.GetPathName('pickidentify.png')) !nozz = ARRAY() !nozz.append(|Name|) !nozz.append(|Connected?|) !nozz.append(|Attached?|) !nozz.append(|Aligned?|) !nozz.append(|Size check?|) !this.nozz.setHeadings(!nozz) !info[1] = 'Description - Unset' !info[2] = 'Function - Unset' !info[3] = 'Purpose - Unset' !this.atta.val = !info !this.nozz.setpopup(!this.pop1) endmethod define method .pick() !packet = object EDGPACKET() !packet.elementPick(|Identify EQUI or NOZZ - Escape to cancel|) !packet.description = |Identify Element| !packet.action = |!!ex13b.identify(!this.return)| !!edgCntrl.addView(!!ex13c.view3d) !!edgCntrl.add(!packet) endmethod define method .identify(!pickInfo is ANY) !item = !pickInfo[1].item !!edgCntrl.remove(|Identify Element|) !!edgCntrl.RemoveView(!!ex13c.view3d) Canvaspick open callback applied to the VIEW element. Prompt text gadget added to feedback to user Add another view to the Once finished, remove view
  • 178. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 178 www.aveva.com -- Loop to find the EQUI element !posNOZZ = 1 !pickedNozz = || do if !item.type eq |NOZZ| then !pickedNozz = !item.flnn endif break if (!item.type eq |EQUI|) or (!item.type eq |WORL|) !item = !item.owner enddo if !item.type eq |WORL| then !!Alert.Warning(|Choose either a nozzle or piece of equipment|) !this.pick() else -- Find the EQUI in the OPTION gadget !this.equip.val = !this.equip.dtext.FindFirst(!item.flnn) !this.collNozz() -- Pick the chosen NOZZ if !pickedNozz.length() gt 0 then do !I indices !this.nozz.dtext !splitDTEXT = !this.nozz.dtext[!I].split() if !pickedNozz eq !splitDTEXT[1] then !posNozz = !I endif enddo endif !this.nozz.val = !posNozz endif endmethod define method .init() if !!CE.type.eq(|SITE|) then !level = |SITE| else !level = |ZONE| endif VAR !coll COLL ALL EQUIP FOR $!level handle ANY !!Alert.Error(|Make sure you are at an EQUI, ZONE or SITE element|) elsehandle NONE if !coll.size().eq(0) and !level.eq(|ZONE|) then VAR !coll COLL ALL EQUIP FOR SITE !!Alert.Message(|No equipment found in current ZONE, so whole SITE will be searched|) endif VAR !name EVAL FLNN FOR ALL FROM !coll !this.equip.dtext = !name !this.equip.rtext = !coll !this.collNozz() endhandle endmethod define method .collNozz() !equipRef = !this.equip.selection().dbref() if !equipRef.unset() then --!!Alert.(|Make sure you are at an EQUI or ZONE element|) !this.nozz.clear() else !nozzColl = object COLLECTION() !nozzColl.type('NOZZ') !nozzColl.scope(!equipRef) !results = !nozzColl.results()
  • 179. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 179 www.aveva.com if !nozzColl.size().geq(1) then do !I from 1 to !nozzColl.size() !dtext[!I] = !results[!I].flnn !rtext[!I] = !results[!I].string() enddo !this.nozz.dtext = !dtext !this.nozz.rtext = !rtext !this.checkNozz() !this.updateAtt(1) !this.limits() endif endif endmethod define method .checkNozz() do !I index !this.nozz.rtext !nozz = !this.nozz.rtext[!I].dbref() !nozzPos = !nozz.pos !nozzDir = !nozz.pdir[1] !nozzSize = !nozz.cpar[1] !pipe = !nozz.cref !piperef = !pipe.href handle ANY !connected = |Check| !aligned = |N/A| !size = |N/A| !attached = |N/A| elsehandle NONE !connected = |OK| if !pipe.href.eq(!nozz) then !pipePos = !pipe.hpos !pipeDir = !pipe.hdir !pipeSize = !pipe.hbore else !pipePos = !pipe.tpos !pipeDir = !pipe.tdir !pipeSize = !pipe.tbore endif if !nozzPos.eq(!pipePos) then !attached = |OK| else !attached = |Check| endif if !nozzDir.eq(!pipeDir) then !aligned = |OK| else !aligned = |Check| endif if !nozzSize.eq(!pipeSize) then !size = |OK| else !size= |Check| endif endhandle !nozzInfo[!I][1] = !nozz.flnn !nozzInfo[!I][2] = !connected !nozzInfo[!I][3] = !attached !nozzInfo[!I][4] = !aligned !nozzInfo[!I][5] = !size enddo !rtext = !this.nozz.rtext
  • 180. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 180 www.aveva.com !this.nozz.setrows(!nozzInfo) !this.nozz.rtext = !rtext endmethod define method .updateAtt(!flag is REAL) !equip = !this.equip.selection().dbref() !this.atta.tag = !equip.flnn & ' Attributes' !contents = !this.atta.val if !flag.eq(1) then !n = 0 do !I index !contents !n = !n + 1 !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val[!I] = !equip.Attribute(!attrib) handle ANY !n = !n - 1 elsehandle NONE if !val[!I].string().eq('') or !val[!I].string().eq('UNSE') then !val[!I] = |Unset| endif !out[!n] = !attrib & | - | & !val[!I] endhandle enddo !this.atta.val = !out elseif !flag.eq(2) then !errors = ARRAY() do !I index !contents !text = !contents[!I] !split = !text.split('-') !attrib = !split[1].trim() !val = !split[2].trim() if !attrib.substring(1,4).upcase().eq('PURP') and !val.upcase().eq('UNSET') then !originalCE = !!CE !!CE = !equip $!attrib nul !!CE = !originalCE else !equip.$!attrib = !val handle ANY !equip.$!attrib = '$!val' handle ANY !errors.append(!attrib) endhandle endhandle endif enddo if !errors.unset() then else !err = '' do !I from 1 to !errors.size() if !I eq 1 then !err = |(1) | & !errors[!I] else !err = !err & ', (' & !I & |) | & !errors[!I] endif enddo !!Alert.Error(|The following attributes types or attribute values are not valid for EQUI elements:
  • 181. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 181 www.aveva.com $!err|) endif endif endmethod define method .limits() !equip = !this.equip.selection().dbref() !add = 5 !limits[1] = !equip.wvol[1] - !add !limits[2] = !equip.wvol[4] + !add !limits[3] = !equip.wvol[2] - !add !limits[4] = !equip.wvol[5] + !add !limits[5] = !equip.wvol[3] - !add !limits[6] = !equip.wvol[6] + !add !this.limits = !limits !this.view3d.limits = !limits !pos[1] = (!equip.wvol[1] + !equip.wvol[4]) / 2 !pos[2] = (!equip.wvol[2] + !equip.wvol[5]) / 2 !pos[3] = (!equip.wvol[3] + !equip.wvol[6]) / 2 !this.clipbox.box.position.east = !pos[1] !this.clipbox.box.position.north = !pos[2] !this.clipbox.box.position.up = !pos[3] !this.clipbox.box.xlength = !equip.wvol[4] - !equip.wvol[1] + !add !this.clipbox.box.ylength = !equip.wvol[5] - !equip.wvol[2] + !add !this.clipbox.box.zlength = !equip.wvol[6] - !equip.wvol[3] + !add !this.clipbox.view = !this.view3d !this.clipbox.active = FALSE !this.clipbox.view.owner().clipbox.set() !this.view3d.clipping = TRUE endmethod
  • 182. AVEVA Plant (12 Series) Programmable Macro Language - TM-1401 182 www.aveva.com Appendix B26 - Example ex14 Addin – filename: PML name: PMLTraining title: PML Training showOnMenu: FALSE object: appPML Object – filename: apppml.pmlobj define object appPML endobject define method .UtilsMenu() !menu = object APPMENU('SYSUTIL') !menu.add('SEPARATOR') !menu.add('MENU', |Calculator|, 'CalcForm') !menu.add('MENU', |Equipment Checker|, 'EquipCheck') !!appMenuCntrl.addMenu(!menu, 'EQUI') !menu = object APPMENU('CalcForm') !menu.add('FORM', |Exercise 6(a)...|, |ex6a|) !menu.add('FORM', |Exercise 6(b)...|, |ex6b|) !menu.add('FORM', |Exercise 6(c)...|, |ex6c|) !menu.add('FORM', |Exercise 6(d)...|, |ex6d|) !menu.add('FORM', |Exercise 7...|, |ex7|) !menu.add('FORM', |Exercise 8...|, |ex8|) !menu.add('FORM', |Exercise 9...|, |ex9|) !!appMenuCntrl.addMenu(!menu, 'EQUI') !menu= object APPMENU('EquipCheck') !menu.add('FORM', |Exercise 10...|, |ex10|) !menu.add('FORM', |Exercise 11(a)...|, |ex11a|) !menu.add('FORM', |Exercise 11(b)...|, |ex11b|) !menu.add('FORM', |Exercise 12(a)...|, |ex12a|) !menu.add('FORM', |Exercise 13(a)...|, |ex13a|) !!appMenuCntrl.addMenu(!menu, 'EQUI') endmethod define method .toolbars() frame .PMLToolbar toolbar 'PMLToolbar' !calcPixmap = !!pml.getPathName('calculator.png') !equiPixmap = !!pml.getPathName('spanner.png') button .calc 'Show Calculator' tooltip 'Show Calculator ' pixmap /$!<calcPixmap> width 16 height 16 callback |show !!ex9| button .equi 'Show Equipment Checker' tooltip 'Show Equipment Checker ' pixmap /$!<equiPixmap> width 16 height 16 callback |show !!ex12a| exit !!appTbarCntrl.addToolbar('PMLToolbar', 'EQUI') endmethod define method .modifyMenus() !this.UtilsMenu() endmethod define method .modifyForm() !this.toolbars() endmethod Define the menu names first and add them to the Utilities menu Once defined, submenus can be applied Toolbar needs to be in a frame (containing the reference toolbar) Pixmap buttons added Standard modfy methods run the methods above methods