Tips   >   Notation   >   Notation (All Contents)
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.
Omnis notation can be addictive. Be careful. :-)
Using the
in conjunction with the 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
button in the window to learn how to use the and for writing notation. The demo gives you a step by step well commented walk through using and 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
Thanks to engineering for setting this up so we can use them interactively while stepping through and writing code! and the ... an amazing team!If you select a library in the $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.
and look at the tab in the you will see aIf 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)
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.
Variables are part of the $?vardefs group.
You can find the variable groups using the
.The syntax for adding a variable using notation is as follows:
Do VarDefsGroupRef.$add('VarName',pkDataType,pkDataSubType,pkDataSubLen,pbIsParamater) Returns VarRef
You can check
> > and 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
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.If you need to clear the instance variables for any instance you can use $sendall to clear them.
Do $cinst.$ivars.$sendall($ref.$assign(''))
The above $sendall will blow away your row and list definitions.
You can copy any object and all it's attributes using notation.
; 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
button in the for a demo.If the source object has any methods you will need to copy the methods to the target object.
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)
The notation alternative to Do inherited Returns FlagOK is:
Do $cinst.$inherited.[$cmethod().$name]() Returns FlagOK
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.
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
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
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 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
For years I thought if I was using [] square brackets in the Calculate everything had to be inside the square brackets. For example:
of aCalculate [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.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
Do not add opening and closing parethesis after $cando(). The above test would fail if we used: If rSubWin.$setMode.$cando()
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
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
button in the 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.
A method can't add an $lvar to itself. An instance can't add an $ivar to itself.
$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 button in the to see an example.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 button in the to see an example.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)
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 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)
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.
This section covers current objects notation ($ctask, $clib, $cinst, $c...) and provides demos for each. Current notation is very helpful in shortening notation strings and making your code flexible and generic.
From the Omnis Help Notes
Under $root, Omnis contains a number of global state variables that tell you about how Omnis is currently executing, or what objects, instances, and methods are currently being used. These objects provide a shortcut to the current object or instance that is currently executing. Mostly their names begin with $c.
You can use the current objects in place of the full notation for a specific object to make the object and its code reusable and portable between libraries. For example, you can use $cinst in a method within a window instance to refer to itself, rather than referring to it by name.
Within the class instance you can use $cinst rather than $root.$iwindows.WindowInstanceName
You can refer to the current library using $clib. For example, to make the current library private using:
Do $clib.$isprivate.$assign(kTrue)
is more generic than:
Do $libs.MyLibrary.$isprivate.$assign(kTrue)$cclass
is the class which the method is located in.
Click the $cclass of this method.
button to see theIf you are dealing with superclass methods, $cclass in a superclass method will evaluate to the class of the superclass, not the class of the subclass. To evaluate to the class of the subclass use $cinst().$class.
The field where the current method is executing.
For some window objects I add a $construct method so that the field will set some of its own properties when the window is being instantiated or if I want to set an ivar to point to the object. $cfield works great for those situations.
Do $cfield.$edgefloat.$assign(kEFposnClient)
Set reference irButton to $cfield
The current instance; usually the instance containing the currently executing method.
Almost everything you run in Omnis Studio is an instace of the actual class, not the class. Code classes, schema classes, and search classes are exceptions.
Think of an instance as a photocopy of the original. You can have as many photocopies as you want. Each photocopy has a $name property which is automatically assigned, or can be assigned using notation.
Click the button to see the $cinst of this object class.$clib
is the library the current class is located in.
Click the button to see the $clib of this object class.The currently executing method.
Click the button to see the $cmethod of this method.The current object that received a $event message.
$cobj should be used whereever possible in your event handling methods. You could be 3 methods away from the pushbutton that was clicked and $cobj still gives you a direct reference to the pushbutton.
Click the button to test $cobj of the run demo pushbutton.The current recipient of an event; if a custom method is being processed, $crecipient is the recipient of that method.
Methods inside of any container can refer to their container using $crecipient
Calculate FieldName as $crecipient().$name
The $crecipient container is the object or class that the executing method is contained in.
If the method belongs to a window field, then $crecipient will be the field. If the method is a class method of a window, then $crecipient is the window class.
An interesting discovery while making the demo is that using:
Do method $ClassMethodName
does not change the $crecipient.
whereas:
Do method $cinst.$ClassMethodName
or
Do $cinst.$ClassMethodName
does change the $crecipient.
I recall a discussion that Do method $ClassMethodName does not add to the method stack (affecting max stacked methods), whereas, Do method $cinst.$ClassMethodName and Do $cinst.$ClassMethodName do add to the method stack. The fact that Do method does not change the $crecipient might be related to the above discovery.
You can test all of the above by clicking the button.A reference to the target field, that is, the field which currently has the focus (shows the caret and is sent keyboard events)
Set reference rField as $ctarget
You can $assign the $carget to set the focus on a visible field.
Do $ctarget.$assign(rField)
This is the notational equivalent of Queue set current field.
You can not use Queue set current field for subwindow fields from a method outside the window's window instance, whereas you can use $ctarget.
The window/pane must already be visible (in front) before you issue $ctarget. You can not use $ctarget.$assign during the $construct of a window instance. If you are changing tabs in a tab pane, make sure the evTabSelected event has been processed before you attempt to use $ctarget. The field you are attempting to set the $ctarget must be enabled at the time you attempt to $assign the $ctarget.
If there are other events in event queue which will affect the $ctarget, you can assign the $ctarget in your code, but it will be changed when the other events are processed. In those cases Queue set current field is the only reliable solution... but you must execute Queue set current field from a method within the window class of the field. I have a public method in my superclass window called $setCurrField which I use for setting the current field.
When you open a library, Omnis Studio sends looks for a task named Startup_Task. If found, Omnis Studio automatically opens and instance of the Startup_Task and sends it a $construct message.
The Startup_Task instance name defaults to the same name as the library name which the Startup_Task task class is located in.
Any class instances (menu instance, toolbar instances, window instances) which you open from the $construct by are by default contained within the Startup_Task instance.
Any additional class instances opened by those class instances (e.g. A menu line is selected by the user to open a window instance or run a report instance) are also by default contained within the originating task instance. (even if those classes are from different libraries)
Each library can have it's own task and you can open additional tasks. Many applications just run under one task instance, the Startup_Task instance.
$ctask is the current task
Click the button to see the $ctask of this object class instance.The current window instance.
For subwindow window instances $cwind is the outermost parent window instance. Don't use $cwind if $cinst will work for you. $cwind changes depending on which window is the outermost parent, this could change cause your code to break. Always think for minute before you use $cwind.
For window menus and window toolbars, you would use $cwind to send a message from the menu or toolbar to the window. Each menu and toolbar has its own instance so from inside those intances $cinst would point to the menu or toolbar instance, and $cwind would point to the window which owns the window menu orwindow toolbar. However, a better ways it to use the observer design pattern. See menus on-the-fly for more details and a demo.
If you need to find out whether or not a window is a subwindow, compare $cinst to $cwind.
; Test for a subwindow instance.
If $cwind=$cinst
; This window instance is the outermost window instance.
Else
; This window instance is a subwindow.
End If
The topmost open window instance.
Click the button to test $topwind.A reference is a variable of item reference type which is pointing to something in Omnis. A reference could be pointing to a window instance, window class, window object, object method, list variable...
If you are using notation, you will either write very long notation strings or use references and write much shorter notation strings. You can use references to make your code more stable and efficient.
REFERENCES EXPLAINED
I still get confused by references. When to include $ref, when not to, and a few other issues. The following was taken from a list server posting by Tim Stewart. It should help your understanding.
Tim wrote a quick overview of the various references. The posting is listed in the sample code below.Window objects inside container objects can be referenced notationally directly as window objects. You can leave the 'containers' out of the notation string, and the reference will still be valid. This also applies to subwindow window instance fields. The subwindow's fields become part of the parent window
All of the following references are valid and will work
Set reference rField to $cinst.$objs.SCROLLBOX.$objs.NESTEDSCROLLBOX.$objs.ENTRYFIELD
Do rField.$forecolor.$assign(kRed)
Set reference rField to $cinst.$objs.SCROLLBOX.$objs.ENTRYFIELD
Do rField.$forecolor.$assign(kGreen)
If you are going to use notation to manipulate the properties of any window object, an easy way to get a reference to that object is:
This will set the ivar reference to the correct field in a manner that is impervious to renaming of the object or even copying and pasting the object into another window.
Example
I might have a treelist object in a window and a class method named $buildTreeList.
The $construct method of the treelist object has the following line of code in it:
Set reference irTree to $cfield
From the $buildTreeList method I can execute any treelist methods and set any treelist properties using the ivar irTree. If later on I move the treelist object into a scroll box or a tab pane object the $buildTreeList code does not break because the treelist object's $construct method always correctly sets the reference for irTree.There are several ways which you can get or set a reference to something.
Thanks to Mark Phillips I rarely use the "Set reference" Omnis command anymore.
Mark taught me about $findname and then testing the return value for null. I've been using it ever since.
One advantage of using $findname is that it doesn't get messed up by $ characters in a public method name.
The following Set reference will fail.
Set refererence $cclass.$methods.$construct to rMethod
Using $findname won't fail.
Do $cclass.$methods.$findname('$construct) Returns rMethod
The $cclass.$methods.$findname notation won't find any inherited superclass methods when you are in the subclass