PDMS PML Manual - 2
PDMS PML Manual - 2
2016 v.1.
Page 101/178
This positions the origin of the new toggle gadget with respect to the extremities of the
lastcreated gadget (indicated by the absence of an explicit gadget name in the AT
command). The new gadgets origin is at the coordinates (XMIN, YMAX+1) of the last
gadget:
positions a new gadget relative to extremities of the previous gadget gadget1. The effect is
similar to that illustrated above.
toggle .OnOff AT XMIN gadget1-2 YMAX gadget1+1
positions the new gadget to the left of gadget1 as the specified X offset is negative.
***** THANK GOD THAT WE HAVE AVEVA PDMS BECAUSE ALL OTHER PLANT SOFTWARE REALLY SUCK *****
XMAX FORM and YMAX FORM refer to the maximum X and Y coordinates for the entire
form so far. XMAX FORM - SIZE subtracts the current gadgets size so that the form will not
expand. The net result of the above command is to add the OK button so that in the Xdirection it just finishes at the forms current maximum extent without increasing the form
width, and in the Y-direction the gadgets origin is placed at the forms current maximum
depth and extends it to include the gadgets height. The result is:
2016 v.1.
Page 103/178
places .t1 with respect to XMIN of one gadget and YMAX of a different gadget.
toggle .t2 AT XMAX YMAX.gadget2 + 0.25
places .t2 with respect to XMAX of the last placed gadget and YMAX of a specific gadget
gadget2.
PATH down
toggle .t3 AT xmin.gadget1
places .t2 with respect to XMIN of gadget .gadget2, whilst the Y coordinate for .t2 is
autoplaced at current VDIST value below the last placed gadget.
17.9. AT Syntax
The AT syntax is used to define the position of a gadgets origin within a form. The position
may be specified absolutely (in form layout grid units) or relative to the extremities of existing
gadgets, or relative to the size of the form and the gadget. The AT syntax graph is the
easiest way of illustrating all the possible options, and so it is included here:
2016 v.1.
Page 104/178
2016 v.1.
Page 105/178
The width of fr1 is set to the width of gadget gad6 and its height is set to the height of the
last (most recently defined) gadget, where the meaning of Size is gadget type dependent as
explained in the previous section. A gadget's width and/or height components can also be
specified as the distance from its position co-ordinate to the positional extent of another
gadget, e.g.
frame fr2 |Frame 2| ... Width to min.fr1 Height to max
The width of fr2 extends from its specified (or implied) X-position to the XMIN-position of
gadget fr1, and its height extends from its specified (or implied) Y-position to the
YMAXposition of the most recently defined gadget. Note that the positional extents always
refer to the full gadget box.
17.10.4. Gadget Size Syntax
The full syntax for gadget size (width and height) is as follows:
2016 v.1.
Page 106/178
Where:
1. val is a real value
2. <gname> is a gadget dot-name such as .gadgetA
3. MIN, CEN, MAX refer to the gadget or FORM limits
4. HDIST and VDIST are the horizontal and vertical auto-placement increments for
the layout path
5. PADDING is the extra spacing that F&M adds to left, right, top and bottom of a
frame or the form.
The following example is valid syntax, which could be used to construct a frame .fr2 within
an existing frame .fr1 (note that the space before and after the * is mandatory):
Frame .fr2 ... wid to max.fr1 * 0.5 + hdist hei to max.fr1 * 0.5 - padding
2016 v.1.
Page 107/178
7. It is not usually necessary to set the frame width and height, except for specific alignment
purposes
8. You can use the 'form - size' and .gad - size constructs to right align gadgets in a
dynamic frame, e.g.
button .nextPage linklabel 'Next' anchor bottom + right at xmax form-size ymin
9. There are some instances with layout of docking dialogs that sometimes the calculated
frame size is slightly smaller than actual, it is always useful to compare with a simple
dialog (with and without 'resize' set).
2016 v.1.
Page 108/178
18.
Frame
2016 v.1.
Page 109/178
2016 v.1.
Page 110/178
If only one pixmap file is supplied, it will be used for all states.
If the Selected pixmap is unset, then it reverts to the Unselected one.
19.3.2. AddPixmap Method
The AddPixmap method is the best way of setting or changing a gadget's associated
pixmaps.
AddPixmap( !pixmap is STRING ) !pixmap
!pixmap1 corresponds to the Un-selected state of the gadget, and pixmap2 corresponds to
the Selected state. Specifying !pixmap1 as the null string ' ', will leave the current Selected
pixmap unchanged. PARAGRAPH gadgets only have one pixmap which is represented by
the .VAL member, and so can be directly set or changed using !this.myPara.val =
'<pixmap-pathname>.
Notes:
1. The PML function !!PML.GetPathname ('<myPixmap>.png') returns the required pixmap
pathname for pixmaps held in the standard PDMS Appware pixmap directories.
2. It is recommended that when you define the gadget you set its size to encompass the
largest pixmap which you will later add. Failure to do this may give rise to unexpected
behaviour.
3. Historically you could add a third pixmap which was used when the gadget was
deactivated. This practice is no longer necessary as the gadget pixmapped is automatically
greyed-out on de-activation.
2016 v.1.
Page 111/178
When a gadget is de-activated, it has a greyed-out appearance and the user is prevented
from interacting with it.
19.4.1. Greying Out Gadgets on Forms
You can de-activate or re-activate all the gadgets on a form using the form method:
!MyForm.setactive( TRUE )
!MyForm.setactive( FALSE )
If you want most of the gadgets on the form to be de-activated, you can de-activate all
gadgets on the form (and then activate the ones you want, individually) using the following
form methods:
SetGadgetsActive( active is BOOLEAN )
SetActive( active is BOOLEAN )
SetActive(false)greys out all gadgets on the form, but doesnt set their Active status, so that
SetActive(true) restores the form to the precise state it was in before greyingout, that is, any
inactive gadgets will still be inactive. The command:
SetGadgetsActive( false )
Greys-out all gadgets on the form and sets their active status to inactive i.e. their previous
active state is lost. Similarly SetGadgetsActive( true )greys-in all gadgets and sets their
active status to active.
To make invisible the gadgets owned by a frame, you can set the visible status of the frame
to false. Conversely, to make them visible again you can set the visible status to true. The
frames visible property will automatically apply to all of its children, but will not overwrite
their corresponding property values. So, for example, if frame .f1 contains button .b1 and f1
and b1 both have Visible =true. The command:
!!form.f1.visible = false
will cause the frame and all its gadgets to be hidden, but the query:
!value = !!form.b1.visible
2016 v.1.
Page 112/178
The keyboard focus can be moved at any time to one of the following types of gadget by
calling the setfocus() method on the target gadget:
TEXT
TEXTPANE
BUTTON
TOGGLE
RTOGGLE
SLIDER
LIST
SELECTOR
OPTION
ALPHA VIEW
For example:
!!MyForm.Textfield.Setfocus()
Warning: Refreshing gadgets should be used sparingly, especially for View gadgets,
as it will cause their content to be regenerated.
2016 v.1.
Page 113/178
2016 v.1.
Page 114/178
2016 v.1.
Page 115/178
2016 v.1.
Page 116/178
2016 v.1.
Page 117/178
2016 v.1.
Page 118/178
2016 v.1.
Page 119/178
2016 v.1.
Page 120/178
2016 v.1.
Page 121/178
2016 v.1.
Page 122/178
will cause the frame and all its contained gadgets to be hidden, but the query:
!value = !!form.b1.visible
Frame Size
During form definition, once a frame is positioned on the form the origin remains fixed but the
frame automatically expands downwards and to the right to contain any gadgets added to it.
You cannot add gadgets to it at negative coordinates relative to the frames origin. You can
optionally declare a minimum size for the frame. For example:
Frame frame1 frame 1 SIZE 10 20
This is relevant only for NORMAL and TABSET frames; for TOOLBAR frames, the gadgets
appear as a single row in the order defined i.e. gadget positions are ignored.
20.2.2. Frame Radio Groups
A FRAME may have a set of RTOGGLE gadgets defined directly within it which act in
concert as a radio group. An example of a FRAME with a directly defined radio group looks
like this:
2016 v.1.
Page 123/178
Note: The forms keyboard focus is initially placed on the OK button to prevent it being
assigned (by Windows) to the first RTOGGLE rad1 (effectively the first interactive gadget on
the form as the text field Selection is read-only) The form constructor method assigns a
simple callback, the form method RGroupSelectionChanged(), to the frame rg1 (radio
group). It then initialises the gadget values and selects the second RTOGGLE as the default
selection.
2016 v.1.
Page 124/178
The group callback uses the FRAMEs VAL member to get the current selected index and
hence the current RTOGGLE and its OnValue member value. If the selected RTOGGLES
value is radio then the selected program is read from the RADIO option gadget. Finally the
selected program string is displayed in the Selection (read-only) text gadget.
define method .RGroupSelectionChanged( )
-- Service radiogroup select event
!Frame = !this.rg1
!index = !Frame.val
!rTog = !Frame.RToggle(!index)
!value = !rTog.onValue
-- Do some application actions
if( !value eq 'radio' ) then
!value = !this.Radio.selection('dtext')
endif
!this.choice.val = !value
endmethod
The callback on the RADIO option gadget, detects if the Radio: RTOGGLE rad5 is current
and if so it deselects it leaving no current selection, and clears the Selection text field.
define method .selectProgram( !rtog is GADGET )
-- Select new program from option list
if( !this.rg1.val eq !rtog.index ) then
-- rtog is current, so deselect it within group
!this.rg1.val = 0
!this.choice.clear()
endif
endmethod
2016 v.1.
Page 125/178
2016 v.1.
Page 126/178
2016 v.1.
Page 127/178
2016 v.1.
Page 128/178
2016 v.1.
Page 129/178
For multi-line paragraphs the text is line-wrapped and formatted into the available space. It
can contain explicit newlines to achieve the desired format.
20.4.2. Pixmap Paragraph Gadgets
A pixmap paragraph gadget has a fixed width and length that may be specified explicitly
in terms of width and height in pixels of the largest pixmap that is to be displayed, or defined
implicitly by the initial value. Once it has been defined, the size of the gadget cannot be
changed. The default size for a pixmap is 32x32 pixels.
paragraph .picture AT . . .
pixmap /filename
paragraph .picture AT . . .
pixmap /filename width 256 height 200
The pixmap may be changed at any time by assigning a new value to the .val member:
!!MyForm.picture.val = /newfilename
You can specify the width of the BUTTON independently of any tag text string it contains
using the WIDTH syntax. You can also define its height with the HEIGHT syntax, allowing
you to define textual BUTTONs taller than a single character in height. For example:
Button .btn1 |reject selection| at ... width 10 height 1.5
Note: The BUTTONs tag is always centre-aligned within the define area.
20.5.1. Buttons of Type Toggle
Buttons can optionally be used in toggle mode, where they show visually differentiated
pressed and unpressed states, similar to TOGGLE gadgets. Buttons with Pixmaps For
these buttons, the Unselected and Selected pixmaps swap whenever the button is pressed,
so alternating between the two images in the pressed and un-pressed states. Textual
Buttons Toggle buttons will highlight when pressed. For example on toolbars they will turn
2016 v.1.
Page 130/178
The buttons value-member !button.val is a BOOLEAN and reflects the buttons state,
having the value TRUE when the button is pressed and FALSE when it is not.
20.5.2. Buttons of type 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:
The sub-type of any Button gadget can be queried using the it's Subtype method.
20.5.3. Form Control Attributes
A button may optionally have a form control attribute, such as OK, which takes effect after
the callback command is invoked. It is convenient, but not essential, to give a button the
same PML name and displayed tag name as its control attribute. If no form control attribute
is specified, the effect of the button depends entirely on the callback or the showing of a
child form. You can only have one of each type of control attribute on any form, apart form
APPLY which may be used on several buttons.
OK Allows the user to approve the current gadget settings and action the form. The form
nests OKCALL callbacks are run (see Form OK and CANCEL Callbacks) and the nest is
hidden. Any callback on the OK button is ignored.
APPLY Similar to OK in that the gadget settings are approved and the form is actioned but
not removed from the screen. There may in fact be several APPLY buttons for different
sections of form (ideally each section within its own Frame). A form with one or more APPLY
buttons should also be given a DISMISS button for removing it from the screen.
CANCEL Allows the user to decides not to proceed with the form. The form nests
CANCELCALL callbacks are run and the nest is hidden. All gadget values are reset to their
initial settings or to the values established at the last APPLY.
RESET Returns the values of all gadgets on the form to the values they had when the form
was displayed. If the user has since pressed an APPLY button, the form gadgets are reset to
the values they had when the APPLY button was last pressed. The callback is then invoked
in which your PML code should ensure that anything that needs undoing is indeed undone.
HELP Invokes online help.
The effect of OK and CANCEL on gadgets is more extensive if a form family is involved, as
described in Free Forms and Form Families. Examples:
2016 v.1.
Page 131/178
Note that this button deliberately does not have a callback. When this button is pressed, the
form nest is removed from the screen and its CANCELCALL callbacks executed.
They are named Bold, Italic and Underline, and they are tagged with corresponding text,
enclosed in quotes. More examples:
toggle .Italic 'Italic' AT . . .
toggle .GridOn pixmap /filename callback '!!MyFunction()'
The value of a toggle gadget is set and used via the .val member which is a BOOLEAN
value:
!!MyForm. Italic.val = TRUE
if ( !!MyForm.GridOn.val ) then
...
else
...
endif
2016 v.1.
Page 132/178
2016 v.1.
Page 133/178
Where Dtext is the text to be displayed in the option list, and Rtext is the replacement text for
the new field. If Rtext is not specified, it will be set to the Dtext string by default.
20.8.1. Textual Option Gadgets
The width of a textual option gadget, in grid units, must be specified. A tag name is
optional and is displayed to the left of the gadget.
option .Colour 'Colour' width 10
The current value in a textual option gadget is scrollable using the left- and right-arrow keys.
This means you can specify a gadget thats narrower than the options displayed in the
dropdown list. The OPTION gadget actually contains two parallel lists of the same length,
the display values (or Dtext ) and the replacement values (or Rtext). The list of display
values must be supplied by assigning an array of values to the gadget's Dtext member. This
is the list of choices displayed to the user. In Examples, the lines in the default constructor
method define the Colour option gadget values as follows:
!ColourArray[1]='Black'
!ColourArray[2]='White'
!ColourArray[3]='Red'
!ColourArray[4]='Green'
!ColourArray[5]='Blue'
!This.Layout2.Colour.Dtext=!ColourArray
Other examples:
option .Colour 'Colour:' AT . . . callback '!!MyFunc()' width 20
2016 v.1.
Page 134/178
The replacement-texts, if needed, are set by assigning an array of values to the Rtext
member.
!CircleRtextsArray[1] = 'Specify centre and radius'
!CircleRtextsArray[2] = 'Pick three points on the
circumference'
!!MyForm.Circle.Rtext = !CircleArray
You can read the current selection using the selection() method. This will return the
replacement-text (or the display-text if replacement-texts were not defined):
!SelectedText = !This.List.Selection()
The .val member reads the index number of the currently selected value:
!ChosenNumber = !!Form.List.Val
The clear() method will discard both display- and replacement-text lists:
!!MyForm.Colours.clear()
2016 v.1.
Page 135/178
The callbacks for action START and MOVE are not followed by an automatic update, for
efficiency reasons, so you may need to follow some gadget modifications carried out in the
callback with a !gadget.refresh(), e.g. modifying a TEXT gadget to track the SLIDERs
current value. The MOVE callback is generated at each step increment in the SLIDERs
range.
2016 v.1.
Page 136/178
More examples:
2016 v.1.
Page 137/178
As with the option gadget, the list gadget actually contains two parallel lists, of the same
length, one containing display values (Dtext) and the other containing replacement values
(Rtext). The Dtext values must be supplied, but the replacement values are optional. If you
dont supply the Rtext values they will default to the Dtext values. The Rtext values are
often used to assign callback strings to each field of the list. Resetting a list gadget's displaytexts automatically deletes the existing display and replacement-texts and clears any current
selections. For example, the contents of gadget
!Choices[ 1 ] = 'Tea'
!Choices[ 2 ] = 'Coffee'
!Choices[ 3 ] = 'Chocolate'
!This.List.Dtext = !Choices
You can replace the lists Rtext with a new array of the same length without disturbing the
current Dtexts:
!newRtext[1] = drink6
!newRtext[2] = drink4
!newRtext[3] = drink12
!This.List.Rtext = !newRtext
You can use the new Add methods to add a single new entry to be appended to LIST and
SELECTOR gadgets:
Add( !Dtext is STRING )
Add( !Dtext is STRING, !Rtext is STRING )
Where Dtext is the text to be displayed in the option list, and Rtext is the replacement text
for the new field. If Rtext is not specified, it will be set to the Dtext string by default.
20.12.1. Single Choice List Gadgets
You can set and get the current selection in a single-choice list using the display-text,
replacement text, or .val member. For example:
!This.List.val =2 - selects second list field
!This.List.Select( 'Dtext', 'Coffee' )
!This.List.Select( 'Rtext', 'drink4' )
!fieldNumber = !This.List.val
!Rtext = !This.List.selection()
!Dtext = !This.List.selection(Dtext)
The val member now allows programmatic de-selection of the current field. For Single choice
lists the keyword NORESELECT disables UnSelect and Select events when the currently
selected field is clicked with the mouse, for example:
2016 v.1.
Page 138/178
list .l1 |List gadget| zeroSel noReselect width 15 length 5 tooltip 'single choice list'
For ZeroSelection lists it is now possible to interactively deselect the selected field by
clicking in unused rows or after the last column. Single choice List gadgets support
UNSELECT events. Typically when a field is selected, an UNSELECT event is raised for the
previously selected field (if any) and then a SELECT interactively deselected.
Notes:
1. UNSELECT events are not notified to PML unless an open callback has been specified
(so that SELECT and UNSELECT events can be differentiated).
2. Typically the UNSELECT action allows Appware to manage consequences of deselection
for any dependent gadgets or forms.
3. It is recommend that you do not change the List's selection programmatically in an
UNSELECT event.
20.12.2. Multiple Choice List Gadgets
You can read the current selections in a multiple-choice list using the selection() methods.
This will return the replacement-texts:
!Xarray = !This.List.selection() - returns selected replacement texts by default
!Xarray = !This.List.selection(Dtext) - returns selected display texts
To read the index numbers of the currently selected fields of a multi-choice list gadget:
!ChosenNumbersArray = !!Form.List.Val
You can read back the current Dtexts or Rtexts as an array or simply as strings:
!array = !This.List.Dtext - get all the Dtexts
!string = !This.List.Rtext[3] - get Rtext of the third list field
You can select fields of this list either singly (additive) or by array of Dtext or Rtext, using its
select() methods:
!This.List.select(Rtext, Tea)
!This.List.select(Dtext, !array)
2016 v.1.
Page 139/178
2016 v.1.
Page 140/178
The Dtexts for each column of each row of the list can be provided as a PML array, where
each element is an array of STRING. This can be row oriented or column oriented.
!This.List.SetRows( !rows )
!rows is an array of row arrays, and its size determines the number of rows in the list.
!This.List.SetColumns( !columns )
!columns is an array of column arrays, and its size must match the number of columns of
the list. The size of all the column arrays must be the same and determines the no of rows in
the list. The default width of each column is determined by the longest header or Dtext value
supplied. Rtext values for each row are supplied as for single column lists. Selection within
the list applies to the entire row not individual cells, but rows of the list can be selected on
the basis of a columns Dtext:
Select( !column is REAL, !dtext is STRING )
2016 v.1.
Page 141/178
Note that for a selector gadget, the Rtext and Dtext are always the same as one another.
2016 v.1.
Page 142/178
You must:
Specify the WIDTH, which determines the maximum number of character spaces
visible. Optionally you may specify a larger SCROLL width, which is the maximum
number of characters that the gadget can hold, and scroll through. The default
scrollwidth is 132 characters. The maximum is 256 characters.
Specify a data type using IS which determines how a value assigned to the gadget will
be displayed and how a value typed by the user will be interpreted by your PML
code. You may also supply a FORMAT object which specifies in detail how a value
is to be displayed or interpreted (see below).
You may optionally
Specify a tag name to be displayed to the left of the gadget.
Specify a callback command.
Specify a position on the form.
Specify a NOECHO keyword that indicates any characters typed should be displayed
as stars: a typical use would be a gadget for the user to enter a password.
Give the text gadget an initial value, which will be the value accessed by your PML
code if it is not modified by the user. To set an initial value for a text input gadget,
use its .val member:
This.name.val = 'PIPE-1'
Specify whether the text displayed is editable interactively or is read only. When you
type into a text gadget its background color changes from white to beige to indicate
that has been modified. Its content is actioned when you press Enter while the text
gadget has focus, or if you press a button on the form.
When a field is actioned its content is read and validated according to the fields type (see
Validating Input to Text Fields). If an error is detected, then the fields background colour
changes to gold to indicate an error and focus is returned to it so that the user can correct
the error. If no error was detected then the text gadgets callback (if any) is executed To get
the current value of a text input gadget:
!Value = !This.name.val
The data type of the variable !Value will be the same as the type of the text gadget. To get
the textual value use:
!string = !Value.String()
2016 v.1.
Page 143/178
Currently the only attribute supported is HANDLEMOIFY which may have the integer values:
0 MODIFIED events off (default).
1 Generate MODIFIED event at first user modification only.
Note: MODIFIED events are not notified to PML unless the field is editable, modified events
are enabled and an open callback has been specified (so that MODIFIED and SELECT
events cannot be differentiated) Typically, the first MODIFIED event is used to allow
AppWare to gain control and modify the properties (e.g. ACTIVE status) of dependent
gadgets, which possibly the user should not have access to until the text fields VALIDATE
and SELECT events have been handled.
The code fragment below defines an RTOGGLE that allows a user specified TV program to
be typed into an associated TEXT gadget.
rToggle .rad6 tagwid 7 |TV:| States '' 'TV'
text .TV width 10 is STRING
!this.rad6.callback = '!this.RGroupSelectionChanged('
-- set open callback on text field and option list
!this.TV.callback = '!this.selectProgram('
!this.Radio.callback = '!this.selectProgram('
- handle first Modified event only
!this.TV.setModified( handleModify, 1 )
The extended (open) callback selectProgram(, shown below, intelligently handles the TEXT
gadget and OPTION list. The open callback RGroupSelectionChanged sets the value of the
TV RTOGGLE from the TEXT gadget.
define method .selectProgram( !gad is GADGET, !event is STRING )
-- Select new program from option list or text input field
if( !gad.type( ) eq 'TEXT' ) then
-- Control active state of R-toggle according to modified
state of textfield
!rtog = !this.rad6
if( !event eq 'MODIFIED' ) then
-- deactivate R-toggle
!rtog.active = false
2016 v.1.
Page 144/178
2016 v.1.
Page 145/178
The display-text of 11' 6 will be shown in the text gadget. To switch from displaying feet-andinches to displaying mm all that is necessary is to change the setting of the units member of
the format object RealFMT from FINCH to MM. The associated format also determines what
can be typed into the field. If the associated format is FINCH or MM then you can enter
distances in either inches or feet and inches. For example:
Chosen Units
FINCH
INCH
INCH
MM
Typed-in Value
138
138
11' 6
3505.2
Displayed Value
11' 6
138
138
3505.2
Note that in every case the text field value is actually held in millimetres so that the
command:
q var !!Form.Dist.val
prints 3505.2.
You can use the format object in your PML code when converting a value to a STRING:
!StringValue = !!Form.Dist.val.String(!!RealFMT)
2016 v.1.
Page 146/178
When a text input field is actioned (by modifying it and pressing ENTER, or when a button on
the form is pressed or the form's OKcall is executed), it is automatically checked to ensure
that the typed-in value matches the field's TYPE and its FORMAT constraints. If so, then the
user's VALIDATECALL is actioned. The VALIDATECALL is used to apply any checks you
want. If an error is encountered then the callback raises the error and returns. Note: The
validation callback must not attempt to change the value of the text field. It should just detect
and raise an error. When an error is raised, an error alert is displayed and the text field is left
with keyboard focus and error highlight. No further form or gadget callbacks are executed
and the form is not dismissed from the screen. The User can then modify the field and reaction it.
The VALIDATECALL is a standard callback, and so it can be a single command, a PML
function, method or macro, or an open PML method or function. For an open callback, for
example:
!textField.validateCall = !this.textvalidate( the corresponding method must be:
define method .1textvalidate( !textin is GADGET, !action is STRING )
where the action string will be 'VALIDATE'.
2016 v.1.
Page 147/178
If the values type fails to match the field type, a trappable error is raised.
If the types match, the value is validated and the VALIDATECALL is run, if there is
one.
If the value is invalid then a trappable error is raised. If the field is shown then it is set
'in error', and the focus is returned to it so that the user can edit the value.
If the value is valid then the method executes the field callback if !doCallback is true.
2016 v.1.
Page 148/178
The value of a textpane is its current contents as an array of strings, where each element of
the array corresponds to a line of text in the gadget. To make the textpanes contents readonly, use the seteditable method:
!This.text.seteditable(FALSE)
To enquire how many lines of text a textpane gadget currently contains, use the count
method:
!Nlines = !This.text.count
To set the current cursor position within a textpane gadget to line 21, character 15 you can
use:
!This.text.setcurpos(21, 15)
or
!ArrayRowColumn[1] = 21
!ArrayRowColumn[2] = 15
!This.text.SetCurPos( !ArrayRowColumn )
2016 v.1.
Page 149/178
Example
SETUP FORM !!textbug dialog dock right NoAlign VarChars
TITLE |Text input and output (!!textbug)|
-- Text pane -------------------------------------------Path down
hdist 1
vdist 0.1
--Default: variable spaced font
textpane .tp1 |text pane| at xmin form anchor l+r+t wid 43 hei 9
define method .initialise()
-- initialise on show
-- add data into textpane
!s[1] = | 1 Ford Escort|
!s[2] = | 2 Ford Fiesta|
!s[3] = | 3 Vauxhall Nova|
!s[4] = | 4 Vauxhall Astra|
!s[5] = | 5 Vauxhall Lotus|
!s[6] = |16 LandRover RangeRover 62000|
!s[7] = |17 LandRover Defender 23999|
!this.tp1.val = !s
2016 v.1.
Page 150/178
For a selector gadget you must use do selector so that the do counter takes the displayed
value of each of the currently selected rows of the list in turn:
do !field selector !!FormA.SelectorB
$P Selected field replacement-text is $!field
enddo
For a textpane gadget you must use do pane so that the do counter takes the value of each
of the displayed lines in turn:
do !line pane !!FormA.TextPaneD
$P Text line value is $!line
enddo
Note: That on exit from the loop PML destroys the do variable for each of these gadget
types
ALPHA views for displaying text output and/or allowing command input.
PLOT views for displaying non-interactive 2D plotfiles.
Interactive 2D graphical views
Interactive 3D graphical views
2016 v.1.
Page 151/178
The command sequence may optionally be given on a single line, without the exit:
view .MyView AT . . . viewtype height 10 width 20 contents attributes
Where the contents and attributes that depend on the type of View. You do not have to set
any attributes and we recommend that you set the views attributes in the forms default
constructor method rather than in the form setup definition.
20.17.2. Resizable View Gadgets
When the size of the form is changed by the operator, the size of a view gadget is
automatically adjusted to fill the space available in its container. The origin of the view (the
top left-hand corner) always remains fixed in position and the views bottom right-hand
corner adjusts according to the available space. Note that view gadgets do not support the
ANCHOR and DOCK attributes. If you want a view that has these behaviours, you can place
it in a frame gadget that you declare with the attribute you desire. Since the view will expand
to fill the frame, it will be as if you had an anchored or docked the view gadget.
20.17.3. Pop-up Menus in Views
When you create a view, it will automatically be created with a default popup menu, which
will enable users to control the attributes of the View, such as the action of the mouse
buttons, and whether borders are displayed. You can assign popup menus to view gadgets
using the gadgets setpopup() method, with the name of the popup menu as the argument to
the method. For example:
!MyForm.MyView.setpopup( !MyForm.pop1 )
Note: The standard graphical view forms in AVEVA products are normally supplied with fully
customised popup menus, so you should not assign your own ones to these views
20.17.4. Defining Alpha Views
view .Input AT . . . ALPHA
height 20 width 40
channel COMMANDS
exit
view .InputOutput AT . . . ALPHA
height 20 aspect 2.0
channel REQUEST
channel COMMANDS
exit
Borders and scroll bars cannot be turned off and the area they occupy is in addition to the
size you specify for the gadget. To define the data channel via which the gadget derives its
alphanumeric content, use the channel command:
channel COMMANDS causes the alpha view to have a command input field and displays
command lines and error messages in the scrollable output region
2016 v.1.
Page 152/178
This command will also dissociate the view from the current PDMS Requests IO-channel if
necessary. Thus request output will no longer go to this alpha view. The method is valid only
on a form that has been mapped to the screen, and will cause an error (61, 605) if used
during form definition.
Note that you can add the channel back again by assigning to the gadgets .channel
member:
!alpha.channel = Requests
This adds the requests channel to the gadget, and causes it to become the current PDMS
requests region, if the form is mapped, and displaces any previous association. When the
user clicks on an alpha view it will automatically associate itself with the PDMS requests
channel or the commands channels, or both, according to its current channel settings.
The Alpha view gadget supports multiple line copy and paste of text. The simple command
window form below shows the appearance
2016 v.1.
Page 153/178
The highlight colour is the colour used to highlight selected items in the view. You can set it
by
!view.Highlight = white
!view.Highlight = 1
2016 v.1.
Page 154/178
Cursor Type
CROSSHAIR
CROSSHAIR
POINTER
You may use the CURSortype attribute command to set an initial cursor type within the
gadget definition. For example:
Cursor POINTER
2016 v.1.
Page 155/178
The area occupied by borders and scroll bars is within the area you specify for the gadget
If the border is switched off, the actual display area expands to fill the available space. When
borders are turned off, the PLOT view becomes fixed and you cannot zoom or pan within it.
This may be useful if you are using PLOT views as if they were paragraphs; for example, as
decoration or for information. To define the contents of the view specify the PLOTFILE
pathname with the .add() method. To remove a PLOT from the current PLOT view, use the
.clear() method. This will leave the view empty. If you want to replace the displayed PLOT
with another one then just re-use the .add() method with the new PLOT file.
20.17.7. Defining DRAFTs Area (2D) Views
setup form !!MyForm . . .
view .DrawingAT . . .AREA
height 20 width 40
put /SITE1/SHEET
limits 200 100 TO 600 500
exit
exit
define method !!MyForm( )
-- form constructor method
-- Initialise AREA view gadget
!this.drawing.borders = true
!this.drawing.background( beige )
!this.drawing.highlight( red )
endmethod
The area occupied by borders and scroll bars is within the size you specify for the gadget.
To define the colour items are displayed in when picked with the left-hand mouse button, use
the .sethighlight() method with one of the standard DRAFT colour numbers or colournames.
The contents of the view may be any valid 2D graphical element, such as a DRAFT SHEET,
VIEW, LIBRARY, etc. To define the contents of the view, use the put command thus:
Command
put CE
put /SITE1/SHEET
Effect
Draws the current element
Draws the named Sheet element
If you put new content into an area view that already contains a drawing, the original content
will be replaced by the new, not added to it.
Note: There is currently no .put() method! So to replace the view contents you will need to
use the old PML1 syntax:
edit view !!MyForm.drawing AREA put /site/sheet2
2016 v.1.
Page 156/178
where the limits define two opposite corners of the required area in sheet co-ordinates. For a
full list of VIEW members and methods,
20.17.8. Defining DESIGNs Volume (3D) Views
setup form !!MyForm . . .
view .ModelAT . . .VOLUME
height 20 width 40
limits auto
look east
exit
exit
define method !!MyForm( )
-- form constructor method
-- Initialise 3D view gadget
!this.model.borders = false
!this.model.background( darkslate )
!this.model.shaded( true )
!this.model.projection( PERSPECTIVE )
!this.model.radius( 100 )
!this.model.range( 500.0 )
!this.model.direction( !dir )
!this.model.eyemode( .false. )
!this.model.through( !thru )
!this.model.walkthrough( true )
!this.model.step( 25 )
endmethod
The area occupied by borders and sliders is within the area you specify for the gadget. To
enable colour-shaded representation use the .shaded() method. By default a wireline
representation .shaded(false) is used. All aspects of the 3D view transformation may be
specified:
To enable PERSPECTIVE mode use the .projection(PERSPECTIVE) method. By default
the projection is PARALLEL. The view direction is controlled via the 3D views .direction
member. This is a 3 element array of REAL, representing a direction vector in model space (
DEAST, DNORTH, DUP ). So to look east you would specify:
!dir[1] = 1.0
!dir[2] = 0.0
!dir[3] = 0.0
!this.model.direction = !dir
The 3D view gadget labels the view direction information in 'ENU' (East-West, North-South,
Up-Down) format within the view status line and scroll borders, by default. The
LABELSTYLE member allows the user to specify either 'ENU' or 'XYZ' labelling. In the 'XYZ'
scheme the form of the view direction display in the status line is x<bearing>y<elevation>z,
where the bearing angle is in the range [-180, 180] and the elevation angle is in the range [-
2016 v.1.
Page 157/178
The .radius() method specifies the radius of the view in current units - an imaginary sphere
around the through point. The .range() method specifies how far away from the Through
point you want the Eye point to be. To enable WALKTHROUGH mode specify
.walkthrough(true) together with the walking step size in current units using the .step()
method.
Setting Aspects of the View Transformation by Syntax
The commands below allow aspects of the view transformation to be set using the old
syntax:
edit view !!MyForm.Model VOLUME
Effect
Looks from the East.
Looks towards the East.
Looks towards specified direction.
Looks through specified point.
Looks through named elements origin.
Prompts for cursor pick on Through-point.
Prompts for cursor pick on Valve for through-point.
looks from specified point (defines eye position)
Looks from named element (as eye position).
Prompts for cursor pick on from-point.
Prompts for cursor-on Valve for from-point.
Looks towards the given direction.
Looks towards named element .
Looks in specified isometric direction.
Looks down (default).
View Limits
Each volume view needs to know what region of the design model is to be displayed (the 3D
view limits). The DESIGN application has the notion of a current limits box. Unless you
specify otherwise, the limits set for a new view gadget will default to the DESIGN current
limits box (as set by, say, the LIMITS or AUTOLIMITS commands in DESIGN). In addition,
each volume view has an AUTO flag associated with it, which determines whether or not that
view will be updated automatically whenever the DESIGN current limits box is changed. To
define the view limits and the way in which they are to be updated, use the old syntax:
edit view !!MyForm.Model VOLUME
followed by one of
2016 v.1.
Page 158/178
In DESIGN you may change the current limits box at any time by using one of the command
formats
AUTOLIMITS N1000 E2500 U0 TO N3000 E5000 U2000
AUTOLIMITS /EQUI2 /EQUI4
Any volume views which have LIMITS AUTO set will be redrawn to match the new limits.
Mousemode
3D views have a mousemode member which can be set to Zoom, Pan, Rotate, or Walk
Saving and Restoring 3D Views 3D views have two methods which are used to save and
restore up to four views, until the user leaves DESIGN:
!!view.saveview( !n )
!!view.restoreview( !n )
Where 1 <= !n <= 4.
2016 v.1.
Page 159/178
which allow users to set and query the default layout mode. This can be used to help test
any existing appware which is using setup form !!formname . . . ,in either mode to determine
which forms need ayout adjustment. For example:
!!FMSYS.SetDefaultFormLayout(VarChars)
will cause any forms (without a VarChars or FixChars keyword) which are loaded and shown
to use the new variable character widths layout. If you kill and re-show a previously shown
(unqualified) form, it will have the new layout, so it is easy to compare the difference.
In VarChars Mode
Forms which have avoided alignment by space-padding (e.g. by using TagWidth and Width)
should not be adversely affected. There may be some overall reduction in form width.
Possible problems are:
Padding of text with spaces to achieve alignment of a set of gadgets will no longer
work (note, this was not recommended anyway).
Some uses of Align Right may fail with the message Attempt to place gadget off limits of
form, because the actual sizes of the aligned gadgets will have changed relative to
oneanother. Minimal adjustment could be just adding the FixChars keyword to restore the
old presentation, but a layout revamp would obviously be better.
2016 v.1.
Page 160/178
2016 v.1.
Page 161/178
This method may be useful for wide screen and twin screen devices
This method should be useful when constructing callbacks for menus or gadgets which are
not on the current document form, i.e. where the context is not the current form or view
gadget, e.g. callbacks from the Main menu system or from pullright menus on Addin forms.
!myDocument = !!FMSYS.currentDocument()
If the form exists then the method returns a reference to the form object. If it doesnt exist,
then an attempt is made to force load its definition. If this fails then an unset form reference
is returned. You can check for this using the Unset method on the form object.
2016 v.1.
Page 162/178
Notes:
1. OKCurfnView('g2d') is equivalent to OKCurfnView('g2d', 'ANY')
2. OKCurfnView('ANY ', 'NORMAL') will look for both 2D Draft and 3D Design views
where !!fmt must be a global variable. After calling the method the value can later be
retrieved by referencing the DefaultFormat() method as follows:
!text=!myVar.String(!!fmsys.DefaultFormat())
2016 v.1.
Page 163/178
2016 v.1.
Page 164/178
2016 v.1.
Page 165/178
where APPNAME is the name of the application to modify and callback is the callback to be
assigned to it. If an application with name APPNAME is not defined, the callback is not run.
22.1.4. Add-in Object
A user-defined object type, the add-in object, is used to define toolbars and menus for an
add-in. An instance of this object is created and its methods are run at specific points. The
method .modifyForm() of each add-in object is called during definition of the main form so
that add-ins may create their own toolbars on the main form; .modifyMenus() is called when
starting PDMS to create menu options. For applications, .initialiseForm() is called when
switching to the application. It is not mandatory for all these methods to be present, and if
one is not present, execution continues as normal. It is possible to specify no object if you
wish only to use the other
properties of the add-in.
22.1.5. Initialisation
The add-in definitions are loaded from file during PDMS startup using the function
!!appReadAppDefns(!module is STRING), where !module is the 3-letter identifier for the
module. This creates the global !!appCntrl object, which holds information about the add-ins.
After reading the definitions of all add-ins, !!appCntrl assigns all callbacks to the applications.
For backward compatibility, if an add-in is an application, a directory is specified for the
application and the file module\directory\INIT exists, then this file is added as a startup-call.
Similarly, if the file module\directory\ISYSTEM exists, it is added as a switch call.
22.2. Menus
Each add-in is able to specify menus that can be shown, along with the application in
which they can be shown. Menus are created by running the .modifyMenus() method of
the add-in object when PDMS first starts.
22.2.1. APPMENU Object
The APPMENU object provides a means of adding menu fields to menus using the usual
PML 2 syntax while allowing the menu controlling object to retain information about the fields
created. This information is used to show and hide menu fields depending on the application.
22.2.2. Addition of Menu Items
To add menu fields to an application, proceed as follows:
Create an APPMENU object:
!menu = object APPMENU('menuName')
This associates the object with the menu named menuName on the main form, creating the
menu if it does not already exist. Add items to the menu using the methods of the
APPMENU object. The arguments for these methods are exactly the same as the menu
creation functions provided by PML. A unique fieldname for each field in a menu can be
specified. You may specify a field name when adding menu items in this way; if no field
name is specified, then the Dtext of the menu field is used as the field name. To add to the
end of the menu, use the commands
2016 v.1.
Page 166/178
Note: If a menu field with the same field name is already present, the field will not be added.
This is so two add-ins can define the same menu field, and it will appear independently of
whether one or both add-ins are present. This method does not always add an item to the
end of the menu. If a function tries to add a menu field with the same field name as one
thats already present, the next menu field created (unless its inserted explicitly before or
after another field or its a separator) will appear after the existing field. The reason for this is
to preserve the intended order of the fields. To insert a new field relative to existing named
field, use
!menu.insertBefore('<TargetFieldName>', '<FieldType>', '<Dtext>', '<Rtext>' {, '<FieldName>'})
!menu.insertAfter('<TargetFieldName>', '<FieldType>', '<Dtext>', '<Rtext>' {, '<FieldName>'})
!menu.insertBefore('<TargetFieldName>', 'SEPARATOR' {, '<FieldName>'})
!menu.insertAfter('<TargetFieldName>', 'SEPARATOR' {, '<FieldName>'}).
To register the APPMENU object with !!appMenuCntrl, specifying the applications in which
the menu field should be visible, use:
!appMenuCntrl.addMenu('APP', !menu)
It is possible to add menu fields from an APPMENU object to every application. The
application name 'ALL' has been reserved for this purpose.
22.2.3. Removing Menu Items
The APPMENU object can also be used to remove menu fields from an application. The
method .remove(!fieldName is STRING) hides the field with unique field name !fieldName.
The following commands can be used to remove the field named removeField from the
menu menuName in the general application.
!menu = object APPMENU('menuName')
!menu.remove('removeField')
!!appMenuCntrl.addMenu(!menu)
This automatically associates the object with the bar menu on the main form. You can then
change the contents of the bar menu using the following commands.
!bmenu.add(!dtext is STRING, !menuName is STRING)
Adds a menu to the end of the bar menu, use the command. This adds the menu
!menuName to the bar menu with label !dtext. The menu is automatically positioned before
the Window and Help menus if they are present.
!bmenu.insertBefore('<TargetMenuName>', '<Dtext>', '<MenuName>')
!bmenu.insertAfter('<TargetMenuName>', '<Dtext>', '<MenuName>')
2016 v.1.
Page 167/178
22.3. Toolbars
Toolbars are defined by creating a frame of type toolbar on the main form, using the
following syntax.
frame .toolbarName toolbar 'Toolbar description'
[PML commands to define buttons, toggle gadgets, option
gadgets and text gadgets]
exit
It is not possible to add toolbars to a form once it has been created, so all toolbars must be
defined before any application is started. The method .modifyForm() of the add-in object is
run during building of the form so that each add-in can add its own toolbars.
22.3.1. Toolbar Control
Toolbar visibility in different applications is controlled by the object APPTBARCNTRL. A
global instance !!appTbarCntrl is created when starting PDMS. Each toolbar is registered
with a list of applications in which it can be active. !!appTbarCntrl then controls the active
state and visibility of the toolbar as applications are switched. Toolbars can be shown and
hidden using the popup menu which appears when you right click on a toolbar or menu bar
of the main form. If a toolbar is shown in one application, then it will be shown in all other
applications for which it is registered. To register a toolbar, use the command
!!appTbarCntrl.addToolbar(!toolbarName is STRING,
!appName is STRING, !visible is BOOLEAN),
where !toolbarName is the name of the toolbar frame, !appName is the name of the
application to register the toolbar in and !visible is whether the toolbar is visible by default.
Instead of registering a toolbar in multiple applications individually, an array of applications
can be specified:
!!appTbarCntrl.addToolbar(!toolbarName is STRING,
!appNames is ARRAY, !visible is BOOLEAN)
registers the toolbar for all applications in the array !appNames. The application name 'ALL'
has been reserved so that toolbars can be registered in every application. To register a
toolbar in all applications, use
!!appTbarCntrl.addToolbar(!toolbarName is STRING, 'ALL', !visible is BOOLEAN)
where !toolbarName is the name of the toolbar and !visible is whether it is visible by default.
The command
!!appTbarCntrl.addToolbar(!toolbarName is STRING)
is a shorthand way of registering the toolbar to be visible in all applications, making it visible
by default. Any toolbars on the main form that are not registered are automatically detected
and hidden by default. They are registered to be active in all applications.
2016 v.1.
Page 168/178
where !gadgets is a space-separated list of the gadgets to hide and !appName is the name
of the application in which to hide them.
where !gadgets is a space separated list of the gadgets to inactivate and !appName is the
name of the application in which to hide them.
22.4. Forms
The APPFORMCNTRL object allows control of the behaviour of forms on application
switching and re-entering PDMS. A global instance !!appFormCntrl is created when PDMS
starts. If a form is to be controlled, it must register itself with the object during the constructor
method.
22.4.1. Registering a Form
The most complete syntax for registering a form is
!!appFormCntrl.registerForm(!form is FORM, !visibleInApps
is ARRAY, !requiredApps is ARRAY, !showOnStartup is BOOLEAN, !showOnSwitch is
BOOLEAN)
registers the form so that it is re-shown on startup if it is shown when PDMS exits. It does
not depend on any other applications and its visibility is not otherwise controlled.
22.4.2. Hiding Forms when Exiting Applications
Previously, the main form was swapped when switching applications. Forms opened as
children of the main form were hidden when switching out of an application. Since the main
form is no longer swapped when switching applications, this no longer occurs so
!!appFormCntrl controls the hiding of forms. When switching between applications, if a form
is shown as a child of the main form and is not registered to be shown in the new
application, then it is hidden. (Descendants of this form will therefore also be hidden.)
Dockable forms are shown as free forms, so will be not be closed. However, the effect can
2016 v.1.
Page 169/178
The form will be hidden when switching from the application 'APP' and will not be shown
next time the application is started.
22.4.3. Storing Data Between Sessions
APPFORMCNTRL also provides a means for forms to store data so that they can restore
their state next time the module is loaded. For each form that is registered,
APPFORMCNTRL calls the .saveData method of the form when leaving PDMS: the form
can return an array of strings of data to be stored. When the form is next shown, it can
retrieve this data using the following method:
!data = !!appFormCntrl.getFormData(!form is FORM).
The contents of the array !data will be the strings in the array returned by the .saveData
method when PDMS exited. If no data has been stored for that form, it will be an empty array
You can also use the command:
data = !!appFormCntrl.getFormData(!formName is STRING)
if only the name of the form that stored the data is known.
Note: The form must be able to cope if no data is returned. This will happen the first time
PDMS is run or if the form was not open the previous time the user exited PDMS. The
following example shows a form that stores the state of some of its gadgets between
sessions.
setup form !!testForm
title 'Test of form data storage'
text .name 'Name' width 10 is STRING
toggle .toggle 'Toggle'
exit
define method .testForm()
-- register form with form controlling object
!!appFormCntrl.registerForm(!this, ARRAY(), ARRAY(), true, true)
-- retrieve data if available
!data = !!appFormCntrl.getFormData(!this)
-- restore name and state of toggle if data present
if (!data.empty().not()) then
!this.name.val = !data[1]
!this.toggle.val = !data[2].boolean()
endif
endmethod
define method .saveData() is ARRAY
!return[1] = !this.name.val
!return[2] = !this.toggle.val.string()
endmethod
2016 v.1.
Page 170/178
where !module is the name of the module in which the add-in is used, !appNameStr is the
name of the application (e.g. PIPE), !outputDir is the directory in which to put the add-in
object and !addinFileDir is the directory in which to put the add-in file. Then run the .convert()
method of the object to perform the conversion: !convert.convert().
This creates the add-in object and corresponding add-in file. Information about the existing
application is stored in the %PDMSUI%\module\DFLTS\APPLICATIONS file. This
information is read and used to create the add-in file. Therefore, the application being
converted must have an entry in the APPLICATIONS file in the current PDMSUI path.
2016 v.1.
Page 171/178
Register the APPMENU object with !!appMenuCntrl, so the menu is visible in the Pipework
application
!!appMenuCntrl.addMenu(!menu, 'PIPE')
The same method can be used to add fields to any menu descended from the bar menu of
the main form. A sample add-in object definition, which must be put in the PMLLIB path, is
shown below.
define object APPADDQUERYMENUFIELD
endobject
define method .modifyMenus()
!this.queryMenu()
Endmethod
define method .queryMenu()
-- define APPMENU object associated with the Query menu
!menu = object APPMENU('sysQry')
-- add field to query the owner of the current element
!menu.add('CALLBACK', 'Query Owner', 'q owner', 'QueryOwner')
-- register the APPMENU object to be visible in the Pipework
-- application
!!appMenuCntrl.addMenu(!menu, 'PIPE')
endmethod
The corresponding add-in definition file, which is put in the DES\DFLTS\ADDINS directory,
contains:
Name: ADDQUERYMENUFIELD
Object: APPADDQUERYMENUFIELD
2016 v.1.
Page 172/178
Register the object with !!appMenuCntrl so the menu item is replaced in all applications.
!!appMenuCntrl.addMenu(!menu, 'ALL')
The callback of the Delete button on the main toolbar can also be modified.
!!appDesMain.mtbDeleteCe.callback = '!!customDelete()'
A sample add-in object definition, which must be put in the PMLLIB path, is shown below.
define object APPCUSTOMDELETE
endobject
define method .modifyForm()
-- change callback on Delete toolbar button
!!appDesMain.mtbDeleteCe.callback = '!!customDelete()'
endmethod
define method .modifyMenus()
!this.deleteMenu()
endmethod
define method .deleteMenu()
!menu = object APPMENU('sysDel')
-- replace CE option on menu with custom delete function
!menu.remove('CE')
!menu.insertAfter('CE', 'CALLBACK', 'CE', '!!customDelete()','customDelete')
-- we want the menu to be replaced in all applications, so
-- register this object in all applications
!!appMenuCntrl.addMenu(!menu, 'ALL')
endmethod
The corresponding add-in definition file, which is put in the DES\DFLTS\ADDINS directory,
contains:
Name:CUSTOMDELETE
Object:APPCUSTOMDELETE
2016 v.1.
Page 173/178
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.
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
2016 v.1.
Page 174/178
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).
2016 v.1.
Page 175/178
24. PML.NET
Using AVEVA Plant 12, it is now possible to customise the product using .NET through
.NET controls and objects. PML .NET allows you to instantiate and invoke methods on .NET
objects from PML proxy objects. PML proxy class definitions are created from .NET class
definitions at run time. These proxy classes present the same methods as the .NET class
which are described using custom attributes. The PML proxy objects behave just like any
other PML object. PML callable assemblies are loaded by PDMS using the IMPORT syntax.
Assemblies may be defined in potentially any .NET language (for example managed C++,
C# or VB.NET). The PML.Net Engine loads a given assembly and once loaded instances of
PMLNetCallable classes may be created. No additional code to interface between PML and
.NET is necessary. This is provided by the PMLNetEngine.
2016 v.1.
Page 176/178
Index (integer) for multiple strings, the index of the filter currently selected
After this, the constructor method would define the .NET object and apply it to the container
gadget
using namespace 'Aveva.Pdms.Presentation'
!this.netControl = object NETGRIDCONTROL()
!this.netFrame.control = !this.netControl.handle()
The user is now able to specify event methods to control the .NET gadget:
!this.netControl.addeventhandler('OnPopup', !this, 'rightClickExplorer')
This example allows the forms .rightClickExplorer() method to be run when the .NET object
is right clicked.
2016 v.1.
Page 177/178
2016 v.1.
Page 178/178