Tips   >   Notation   >   Notation

Notation

Notation allows you to do some very powerful things in Omnis Studio. I admit to being a notation junkie. Once you get then hang of notation in Omnis Studio it actually gets to be very easy to figure out. Virtually anything you can do in Omnis Studio manually or using Omnis commands, you can do using notation. This section cover tips, tricks, and pitfalls with notation.

Warning

Omnis notation can be addictive. Be careful. :-)

Notation Inspector

Using the F4 Notation Inspector in conjunction with the F6 Property Manager can help you out big time with learning/using/writing notation. It took me over year to figure this out ... had I known it, I could have saved a lot of time learning and writing notation in Omnis Studio.

Click the Run Demo button in the StudioTips Browser window to learn how to use the Notation Inspector and Property Manager for writing notation. The demo gives you a step by step well commented walk through using Notation Inspector and Property Manager while writing notation. The demo adds a button and method to the demo window instance.

This demo was a lot of work to put together... so be sure to try it out. :-)

The F4 Notation Inspector and the F6 Property Manager ... an amazing team!

Thanks to engineering for setting this up so we can use them interactively while stepping through and writing code!

Notation Errors

If you select a library in the F2 Brower and look at the Prefs tab in the F6 Property Manager you will see a $reportnotationerrors property. If set to kTrue Omnis Studio will halt code executing whenever there is an error in your notation. I recommend setting this property to kTrue. It will help you catch a lot of code errors that you would otherwise miss.

If you attempt to send a message to any class instance (call a public method), and the recipient method does not exist, Omnis Studio will halt method execution and open the IDE at the offending method call. Without $reportnotationerrors set to kTrue Omnis Studio will simply pass over the line of code in your method and continue execution.

You will run into problems with $reportnotation errors set to kTrue if your code is structured such that optional messages are sent to a class or object instance and your code isn't concerned whether or not a recipient method exists.

A situation where this might occur is if you use $sendall to send a message to all of the field objects in a window.

; Give all the window objects an opportunity to set their own
; properties for 'edit' mode by sending them a $setMode message.
; Only objects that have a $setMode method will receive the message.
Do $cinst.$objs.$sendall($ref.$setMode('edit'))

If none of the window objects have an $setMode method, Omnis Studio will report a notation error. The solution to this problem is to add a $cando test to the $sendall conditions.

; Add $cando test to avoid notation errors.
; The $setMode message will only be sent to objects that have a $setMode method.
Do $cinst.$objs.$sendall($ref.$setMode('edit'),$ref.$setMode.$cando)

Tip

In Omnis Studio v4.2 an optional 3rd $sendall parameter, bIgnoreUnrecognizedCustomAttribute=kFalse, was added. Setting the 3rd parmeter to kTrue overcomes the above notation error problem.

Add Variable

Variables are part of the $?vardefs group.

You can find the variable groups using the F4 Notation Inspector.

The syntax for adding a variable using notation is as follows:

Do VarDefsGroupRef.$add('VarName',pkDataType,pkDataSubType,pkDataSubLen,pbIsParamater) Returns VarRef

You can check F9 Catalog > Constants > Data type and Data subtypes for the possible parameters.

Not all data types have a data subtype or data sublength. (See the sample list below.)

The pbIsParameter variable is only applicable to the $lvardefs group and is only needed if you want the variable to be a parameter. Sending kTrue as pbIsParameter will make the variable to be the next parameter for the method. To the best of my knowledge you cannot insert a parameter before an existing parameter, it can only be added to the end of the existing parameters. If you are notationally copying parameters, you first need to make a list of the $lvardefs and sort the $lvardefs group by the $parmno property, then loop through the list of adding the local variables so that they will remain in the same order. Remember to include any extra comma(s) in the list of parameters when adding a parameter that doesn't have a data subtype or data sublength.

Set Reference LocalVarsGroupRef to $libs.LIBRARY.$classes.CLASS.$methods.METHOD.$lvardefs

Do LocalVarsGroupRef.$add('pLineNum',kInteger,kLongInt,,kTrue) Returns VarRef
Do LocalVarsGroupRef.$add('pIsInsert',kBoolean,,,kTrue) Returns VarRef

Warning

You can not have a method add a local variable or parameter to itself. The variable must be added from outside of the method. You can not add an instance variable to an instance of a class, the variable must be added before the class is instantiated. A work around for adding instance variables to an instance is to include a row variable (e.g. iVarsRow) in the window class which you can then add dynamically add columns after the window has been instantiated.

The following is a sample list of the variables and their subtypes.

$add('Col_Char',kCharacter,kSimplechar,100)
$add('Col_NatChar',kCharacter,kNatchar,100)
$add('Col_Longint',kInteger,kLongint)
$add('Col_Shortint',kInteger,kShortint)
$add('Col_Date',kDate,kDate2000)
$add('Col_Bool',kBoolean)
$add('Col_NumFloatdp',kNumber,kFloatdp)
$add('Col_Fieldref',kFieldreference)
$add('Col_Itemref',kItemref)
$add('Col_Binary',kBinary)
$add('Col_List',kList)
$add('Col_Object',kObject)
$add('Col_Picture',kPicture)
$add('Col_Row',kRow)
$add('Col_Sequence',kSequence)

To add a datetime variable

$add('Col_DateTime',kDate,kDatetime,16)

Where the sublength of 16 is the 16th item in the $clib's #DFORMS system table list. Typically, this list starts out with only eight datetime formats; but can be expanded to include up to 30 datetime formats. It allows for custom date time formats.

Clear instance variables

If you need to clear the instance variables for any instance you can use $sendall to clear them.

Do $cinst.$ivars.$sendall($ref.$assign(''))

Warning

The above $sendall will blow away your row and list definitions.

Copy Window Object using Notation

You can copy any object and all it's attributes using notation.

  1. Set a reference to the source object you want to copy.
  2. Add the same object type to the target, returning a reference to it.
  3. Step through the attributes group of the source object, setting the target object attributes to the same values.

; Open the target window
Do $clib.$windows.wNotationCopyWindowObject2.$openonce() Returns rWin

; Set a reference to the object to copy.
Set reference rSource to $cinst.$objs.Object 1

; Find out what the $add method parameters are
Do rWin.$objs.$add.$desc() Returns #S1
; $add(type[,cComponentLibrary,cComponentControl],iTop,iLeft,iHeight,iWidth[,bInvisible=kFalse,bDisabled=kFalse])

; Add the object to the target window, returning a reference.
Do rWin.$objs.$add(rSource.$objtype,rSource.$top,rSource.$height,rSource.$left,rSource.$width) Returns rTarget

; Make a list of the attributes group for this object
Do rSource.$attributes.$makelist($ref.$name) Returns List

; Loop through the attributes group, assigning each to the next object
For List.$line from 1 to List.$linecount step 1
   Do rTarget.[List.C1].$assign(rSource.[List.C1])
End For

Click the Run Demo button in the StudioTips Browser for a demo.

Warning

If the source object has any methods you will need to copy the methods to the target object.

Copy a Class

Copying a class using notation is very easy.

; Set a reference to the source class.
Set reference rSourceClass to $clib.$objects.ClassName

; Add a new object class named "oFunctions2".
Do $clib.$objects.$add('NewClassName') Returns rNewClass

; Copy the $classdata from the source class to the new class.
Do rNewClass.$classdata.$assign(rSourceClass.$classdata)

Do inherited

The notation alternative to Do inherited Returns FlagOK is:

Do $cinst.$inherited.[$cmethod().$name]() Returns FlagOK

Warning

If the superclass method has parameters, you will need to create the parameters in the overridden subclass method and include the parameters inside the parenthesis. It is not necessary to create the parameters in the subclass method if you are using Do inherited unless you need access to the parameters in your subclass method or which to see them as you step through the code.

Overloading Properties

While developing StudioTips I ran into snag with the $destruct method in my window. I was using a superclass $destruct method to save the last closed size and location of the subwindow class.

The method failed because the subclassed window's $top, $left, $height, $width properties were inherited from the superclass. To make the code work I had to overload these attributes for each subwindow using notation.

Class properties that can be inherited from a superclass have an $isinherited property which you can assign using notation. You can override or inherit a class property by setting the $isinherited property to kFalse or kTrue respectively.

The following sample code shows the solution I used to override and then store the subclass window size and location.

; $destruct method of the superclass window.

; Using the $cinst window location and size, $assign those values to the windows $class so that it will reopen
; the same size and location as the user closed it. First check and overload $isinherited if needed.

Set reference rSubWinClass to $cinst.$class

; Is the $top property inherited? If so overload the window size/location attributes.
If rSubWinClass.$top.$isinherited
   Do rSubWinClass.$top.$isinherited.$assign(kFalse)
   Do rSubWinClass.$left.$isinherited.$assign(kFalse)
   Do rSubWinClass.$height.$isinherited.$assign(kFalse)
   Do rSubWinClass.$width.$isinherited.$assign(kFalse)
End If

; Update this window's class size/location attributes so it will reopen the same size/location
Do rSubWinClass.$top.$assign($cinst.$top)
Do rSubWinClass.$left.$assign($cinst.$left)
Do rSubWinClass.$height.$assign($cinst.$height)
Do rSubWinClass.$width.$assign($cinst.$width)

Quit method kTrue

Parents of a Reference

You have a valid reference to an object, now you want to find out what library it is in, what class it is in, etc. (Anything in the $fullname notation string of the item.

To find this information, you add the name of the parent after the reference, then (), then $name or any valid attribute.

Example:

; Set a reference to the first object in the tips browser window.
Do $libs.tipsBase.$windows.wTipsBrowser.$objs.$first() Returns rField

; The field's name.
Do rField.$class().$name

; The name of the field's containing class.
Do rField.$class().$name

; The name of the field's containing library.
Do rField.$lib().$name

Send Message to All Objects

You can use $sendall to send a message to all to objects in a window.

In the process of doing the demo windows for StudioTips I tripped across an interesting idea.

In the "Lists - $merge" demo I had 3 lists, each with their own $construct which created their own lists. After doing each merge demo I wanted to reset all the lists to their original state.

Behind the Reset button I added a single line of code:
Do $cinst.$objs.$sendall($ref.$construct())

It worked like a charm! You can check it out by clicking the Run Demo button.

Think about it, you could have a special method in all your window objects and with a single $sendall each object with that method could do something or return something. You could control the action take at the object level. There's some interesting possibilities...

Setting References

Setting a reference to a class, class instance, method, or object is fairly easy to do. You create an item reference variable and then use the Set Reference command or use $findname to point the item reference variable to the the class, instance, method, or object.

; Set reference the field in its $construct method.
Set reference irWin to $cfield

; Set reference using $findname.
Do $clib.$windows.$findname('wWinName') Returns irWin

Setting a reference to a variable can be done using a setter method which receives the variable through a field reference parameter and then sets an item reference variable to point to the passed in variable.

; Method: $setListRef ;; Set a reference to a list variable passed in by the parameter.
; Parameter: pfList - field reference variable.
; Instance Variable: irList - item reference variable.

; Set a reference to the list variable.
Set reference irList to pfList.$ref
Quit method kTrue

Returning a reference to a variable can be done using a method which returns a reference to the variable.

; Method: $retListRef - Return a reference to a list variable.

; Return a reference to the list variable.
; $ref.$ref is needed to return a reference instead of the whole list
Quit method iList.$ref.$ref

You can also use a getter method which passes a reference to the variable via a field reference parameter.

; Method: $getListRef - Pass a reference to a list variable via the field reference parameter.
; Parameter: pfList - field reference variable.

; Pass a reference to the list variable to the sender.
Set reference pfList to iList.$ref
Quit method kTrue

Square Brackets in Field Name

For years I thought if I was using [] square brackets in the Field name of a Calculate everything had to be inside the square brackets. For example:

Calculate [con('Field',Num)] as 'Some value'

Much to my surprise, I noticed code written by another developer which had some of the text outside of the

Calculate Field[Num] as 'Some value'

I tested it, and it worked! Much simpler.

$cando

You can use $cando to test whether or not a recipient method exists before attempting to send a message (call the method).

A situation where I use this is when sending messages from a parent window to a contained subwindow. It might be an optional message like $initialize or $setMode which the subwindow may or many not have. For these situations I use $cando to first test for a recipient method.

; Test for recipient method in the subwindow instance.
If rSubWin.$setMode.$cando
   
   ; The method exists, send the message.
   Do rSubWin.$setMode('edit') Returns FlagOK
Else
   Calculate FlagOK as kTrue
End If
Quit method FlagOK

Note

Do not add opening and closing parethesis after $cando(). The above test would fail if we used: If rSubWin.$setMode.$cando()

$container

Objects that are inside of any container field have an added property called $container.

$container gives you a reference to the container of the object.

Examples of container objects are: kScrollbox, kGroupBox, kComplexGrid, kTabPane, kPagedPane

; Set reference to a field's container.
Set reference rContainer to rField.$container

; Using parenthesis you can get any attribute of the $container
Calculate Name as rField.$container().$name
Calculate Color as rField.$container().$forecolor

$desc

The $desc method has to be one of the handiest tricks I learned for doing notation.

If you want to $add something to a group but can't remember what all the possible parameters are, $decs can be used to figure them out.

Let's say you want to add a local variable to a method using notation. You know variables are in the $lvardefs group of the method, but can't remember the parameters for $lvardefs.$add.

Add $desc to the end of the notation which you know, and return the result to #S1, then look at the value of #S1. If you right-click on #S1 you can copy the result to the clipboard and then paste it into a comment line in your code. Handy!

Click the Run Demo button in the StudioTips Browser to try this out. The demo code will take you to a breakpoint where you will proceed to step through the code.

; Use the $desc property for finding out the parameters for notation.

; Set a reference to this class.
Set reference rClass to $cclass

; Find out the parameters and info for adding a variable to the group.
Do rClass.$cvardefs.$add.$desc() Returns #S1

; Hover over #S1 with your mouse to see the current value of #S1.
Breakpoint {#S1}

; Right-click on #S1 and select "Variable #S1...". Then copy the value to the clipboard.
; Pasting the clipboard to a comment line(below) in your code gives you a "hard copy" of the help tip.

; $add(cName,type,subtype,iLength,bIsparameter) inserts a new field or variable and returns an item reference to it
Do rClass.$cvardefs.$add('NewClassVar',kCharacter,kSimplechar,100,kFalse) Returns rVar

; Click the Variables "Class" tab to see if the "NewClassVar" now exists.

Warning

A method can't add an $lvar to itself. An instance can't add an $ivar to itself.

$fullname

$fullname

gives the full notation path to any valid item reference.

If you have a reference to a class or object, appending ().$fullname to the reference returns the full notation path to the class or object.

You may ask, why did we include the open and close () parenthesis in front of $fullname?

Good question!

You can't always rely on using $fullname without the () prefix. In some cases it will return notation instead of the actual property name. To be safe, I've gotten into the habit of alway prefixing $fullname with ().

Click the Run Demo button in the StudioTips Browser to see an example.

$name

Omnis use $name for accessing the name property of a library, class, or object.

If you have a reference to a class or object, adding ().$name to the reference returns the name property.

You may ask, why did we include the open and close () parenthesis in front of $name?

Good question!

You can't always rely on using $name without the () prefix. In some cases it will return notation instead of the actual property name. To be safe, I've gotten into the habit of alway prefixing $name with ().

Click the Run Demo button in the StudioTips Browser to see an example.

$sendall

The $sendall method is a powerful Omnis Studio notation method. You can use $sendall to send a message to a group.

The group can be a group of libraries, group of classes, group of methods, group of window instances, group of window fields, group of rows in a list variable, etc.

Any group in the Omnis Studio notation ends with the letter s. ($libs, $classes, $methods, $menus, $objs, $bobjs, $iwindows, $itasks, etc.)

To send a $close method to all of the window instances:

; Close all the windows.
Do $iwindows.$sendall($ref.$close)

Warning

Prior to Omnis Studio v4.2 there was a potential problem with using $sendall to send a call a public method, of a group of class or field instances. If the library preference $reportnotationerrors was kTrue and none of the objects in the group had a recipient method an error would be reported. In Omnis Studio v4.2 an optional 3rd parameter, bIgnoreUnrecognizedCustomAttribute=kFalse, was added. Setting the 3rd parmeter to kTrue overcomes this problem.

To send a $saveMyData message to all of the window instances:

; Send a $saveData custom method to all windows belonging to the current task.
Calculate bIgnoreUnrecognizedCustomAttr as kTrue
Do $iwindows.$sendall($ref.$saveTheData,$ref.$task=$ctask,bIgnoreUnrecognizedCustomAttr)


$sendallref

$sendallref is an item reference to the item currently receiving the message sent with $sendall. This solves the problem with you can run into when wanting to use $ref deeper inside a $sendall.

For example:

; This $sendall will NOT work.
Do $cinst.$bobjs.$sendall($ref.$text.$assign(StringTable.$gettext($cclass.$objs.[$ref.$ident].$text)))

; This $sendall using $sendallref WILL work.
Do $cinst.$bobjs.$sendall($ref.$text.$assign(StringTable.$gettext($cclass.$objs.[$sendallref.$ident].$text)))

In the first $sendall the $ref.$ident refers to the $getText custom attribute of the StringTable external component. Not what we were after.

In the second $sendall the $sendallref.$ident refers to the background object receiving the message, precisely what we were after.

The following example shows where $sendallref is helpful when using $sendall to group of rows in a list variable.

; This $sendall will NOT work.
Do List.$sendall($ref.value.$assign($ref.value+1),$ref.$selected)

; This $sendall using List instead of $ref WILL work.
Do List.$sendall($ref.value.$assign(List.value+1),$ref.$selected)

; This $sendall using $sendallref instead of $ref WILL work.
Do List.$sendall($ref.value.$assign($sendallref.value+1),$ref.$selected)

Warning

The $sendallref method was added in Omnis Studio v4.2. You can not use it if you want to maintain compatibility with earlier versions of Omnis Studio.