Tips_todo   >   Misc   >   Miscellaneous
Hey, everything needs a "Miscellaneous" category! This section is the odds and ends that didn't fit in the other categories.
Some good stuff in here - none the less.Any expression in Omnis will evaluate to true or false (or NULL) when used in boolean logic, so there is no need to compare the expression to kTrue or kFalse.
I'm still trying to catch on to using Boolean logic in my code. Reg helped me out with the above tip, and examples as follows.
Instead of '$ref.$selected=kTrue', use '$ref.$selected'
Instead of '$ref.$selected=kFalse, use 'not($ref.$selected)'
If you want to reverse selection:
Instead of 'Calculate $ref.$selected as pick($ref.$selected=kTrue,kTrue,kFalse)'
use 'Calculate $ref.$selected as not($ref.$selected)'
You can break into your code at any OK message.
Wintel: Press the "Pause" key.
Mac: Press Option+Command+Delete
This is hugely helpful for debugging. Slap in some helpful OK messages where you are trying to solve a problem in your code. Run the code as many times as you need. Any time you want to break into your code to start stepping through it, press the correct key combination and bingo, you are into the method editor at the location of the OK message!
I must have been sleeping when they taught this trick in Omnis 101! What an amazing revelation for me to find out about this. Try it out yourself by clicking the "Run Demo" button.
Many thanks to Reg Paling for this tip!You might run into a situation where you want to call a class method without first creating an instance of the class.
The trick for doing this is to use the "Do code method" command. The "Do code method" is not limited to "code classes" but can be pointed to any class method of any type of class.
So for example, in StudioTips I have a method called "setClassVariable" in the window class "wPreassignVariables". I can run the class method with the following line of code:
Do code method [$clib().$name].wPreassignVariables.SetClassVariable ('cName',Value)
Now when the window opens the the class variable value for "cName" will be [Value].
NOTE: The object-oriented programming police might give you a speeding ticket for doing this. :-)
Thanks to Reg Paling for this tip!Omnis allows you to change the font sizes in most of the IDE (Interactive Developer Environment) windows. This can be especially help if you are doing a presentation.
To change the font size of the code editor, methods treelist, or properties list, etc.
Click on the field so it has the current focus, then:
Ctrl/Cmd+] to increase the size.
Ctrl/Cmd+[ to decrease the size.
Ctrl/Cmd+] to increase the size.
Ctrl/Cmd+[ to decrease the size.
STRG+* to increase size (German keyboard layout)
STRG+† to increase size (German keyboard layout)
To save the font size for the IDE window, Ctrl/Cmd+S.
Thanks to Michael Lange for the German-Keyboard-Layout tip.
If you know of other language keyboard font size changes, please email them to me.Here's a unique tip submitted by Laurent Chaudoreille.
Calculate #F as sys(4019)
This opens a dialog with an object browser that lets you examine properties, functions, events... of each object in Studio.
Press the "Run Demo" button to try it out.If you ever need to print checks, you'll need to convert the dollar value of the check to text.
Included in StudioTips is an object class called "oConvertNumberToText".
You can send this object any 2dp number from 0.01 to 999 million and it returns an english text string of the number ready to print on the check.
Feel free to copy "oConvertNumberToText" to your own application.
With modifications you could get it to print in other languages as well.Here's a handy trick I noticed Jim Pistrang use in his "Studio does SQL" presentation at Euromnis 2000. If you want an "optional breakpoint" in your code use the following:
If #SHIFT
Breakpoint
End If
If you aren't holding the shift key, the code executes without stopping. Hold the shift key and you hit the breakpoint.
Great for debugging and for code demo presentations!To delete an instance variable from a class, you right-click on the variable in the variables pane and select "Delete variable" in the context menu. As long as the variable is not used in any code, Studio will prompt you with a "Delete variable No/Yes" dialog. In some rare situations, Studio won't let you delete an instance variable, even though you have deleted every piece of code that contains the instance variable.
Find and replace comes up empty and you've closed and reopened the class, but the stubborn ivar can't be deleted. (Some sort of minor Studio bug) One trick for getting rid of a stubborn instance variable is to drag it from the instance variable list in the variables pane to the class variables tab in the variables pane. For some reason, once you've do that Studio allows you to delete the class variable.The $desc property is found is several different location in Omnis Studio:
The class desciption can be modified by selecting the class in the F2 Browser > pressing F6 Property Manager > selecting the General tab and clicking on the $desc property. If you have your F2 Browser set to "Detail View" you can also view and edit the description in the F2 Browser headed list.
The method description for public methods (prefixed with $ character) can be viewed/modified through the Interface Manager. In the F2 Browser right-click on a class > select Interface Manager. At the bottom of the Interface Manager click the Description tab to view and modify the description property of the method.
The method description for private methods exists but is not accessible through the Omnis Studio IDE. You can access the $desc property through Code Documentor, or using notation.
The variable descriptions are accessed through the variables pane of the method editor.
Click the "Run Demo" button to find out the maximum length of each $desc property.I asked Tech Support if there was any difference between the developer, runtime, and web server version so Omnis Studio. The following is the response I received from Tech Support.
They are not the same. The runtimes contain less resources in order to have a smaller footprint.
A developer installation is 52 megabytes in size versus a runtime which is 13 megabytes and the web server is in between.
Technically you can serialize a developer as a runtime but you would not be able to do the opposite since the runtime does not contain debug resources.This obsure little command has an interesting feature which I discovered while working on the context menu for the treelist in StudioTips. In the StudioTips treelist the context menu calls are directed back to the treelist field's methods. For the $openBookmark method I wanted to pass the call to the class method of the same name in the wTips_Treelist window. I used the following line of code:
Do redirect $cinst
If $openBookmark is called from the Tips menu, the Tips menu calls $openBookmark in the StudioTips Browser window. $openBookmark in the browser window has the following line of code:
Do redirect irSubWinTreelist ;; an item reference to the Treelist subwindow field
The interesting feature I discovered was that I did not have to declare any parameters. Do redirect passes the incoming parameters without declaring them. COOL! (At least I thought it was.)
Note: You can only redirect to a method of the exact same name.When you install a newer version of Omnis Studio you can avoid having to reenter the serial number.
Copy your old Omnis.cfg file to the new Omnis Studio > Studio folder. Omnis Studio should start up like a champ.
Thanks to Scotte Meredith for this tip!Omnis Studio is localized for different languages. The localized versions replaces the Yes/No/OK prompt button text wtih the appropriate local language text. It may also default to different separator characters in $prefs.$separators.
$separators is a 5 character string.The characters in this string are:
Character 1: the decimal point character
Character 2: the decimal number thousands separator
Character 3: the function parameter separator
Character 4: the import/export decimal point character
Character 5: the import/export comma delimiter character
I ran into trouble with the function parameter separator and the German localized version.
In the English version character 3 is a , comma.
In the German version character 3 is a ; semi-colon.
In the English version concatentate looks like this:
Calculate FullName as con(FirstName,' ',LastName)
If you opened the same library in the German version, you code would look like this:
Calculate FullName as con(FirstName;' ';LastName)
Your normal Omnis code will run without a problem in the English or German version. The problem will be write some code that assumes what the separator will be. The problem I hit in StudioTips was with a replaceall() function.
I wanted to determine then text of the tab strip which the user clicked on. The $event code for the tab strip object was something like this.
CODE THAT BROKE WHEN USING THE GERMAN VERSION OF OMNIS STUDIO.
On evClick
Find out the text string represented by the tab strip.
Calculate TabStripTabs as irTabStrip.$tabs
e.g. About StudioTips, Basics Tutorial, Miscellaneous
Convert the string for use in a pick statement. Replace each comman with quote-comma-quote ','
Calculate ReplaceValue as "','" ;; quote-comma-quote
Calculate PickString as replaceall(TabStripTabs,",",ReplaceValue)
e.g. About STP',' Basics Tutorial',' Miscellaneous
Add opening and closing quotes.
Calculate PickString as con("'",PickString,"'")
Prepare the pick() statement string to and evaluate it.
Calculate EvalString as con('pick(',pTabStripNum-1,',',PickString,')')
Calculate TabStripName as eval(EvalString)
The above code failed with the German localized version because I had assumed the comma separator in the replaceall() function, and in the evali(pick()) function.
FIXED CODE THAT WORKS WITH THE ENGLISH AND GERMAN VERSIONS OF OMNIS STUDIO.
To fix above code I modified it as follows:
On evClick
Find out the text string represented by the tab strip.
Calculate TabStripTabs as irTabStrip.$tabs
e.g. About StudioTips, Basics Tutorial, Miscellaneous
Find out the Omnis Studio localized function separator.
Calculate FnSep as mid($prefs.$separators,3,1) ;; English comma, German semi-colon
Convert the string for use in a pick statement. Replace each comman with quote-comma-quote ','
Calculate ReplaceValue as con("'",FnSep,"'") ;; quote-FnSep-quote
Calculate PickString as replaceall(TabStripTabs,",",ReplaceValue)
e.g. About STP',' Basics Tutorial',' Miscellaneous ;; English
e.g. About STP';' Basics Tutorial';' Miscellaneous ;; German
Add opening and closing quotes.
Calculate PickString as con("'",PickString,"'")
Prepare the pick() statement string to and evaluate it.
Calculate EvalString as con('pick(',pTabStripNum-1,FnSep,PickString,')')
Calculate TabStripName as eval(EvalString)
TESTING YOUR OWN APPLICATION
Testing your own application for different localized version of Omnis Studio is quite simple to do.
In the Omnis Studio > local folder, there is a file named omnisloc.df1.
1. Quit Omnis Studio if you have it open.
2. Rename omnisloc.df1. eg. English_omnisloc.df1.
3. Drag another language omnisloc.df1 file into the local folder.
4. Open Omnis Studio again, and you are running with the new localized version.
To keep file confusion to a minimum, after your are done testing:
1. Rename the omnisloc.df1. e.g. German_omnisloc.df1.
2. Copy the original omnisloc.df1 and rename the copy to omnisloc.df1.
You now have 3 files. Each time you need to test a language, toss the current omnisloc.df1, copy the omnisloc.df1 of the language you want to test and name it omnisloc.df1.
The English, French, and German versions of the omnisloc.df1 files are in the studiotips_stuff >$prefs.$maxcachedclasses
Way back in 1999 with Studio version 1 engineering added this property to save my application from disaster. The problem I was running into was as more and more windows opened the application would get slower and slower.
There is no clear answer on the best setting for this property. The default is 100. At the time of writing this tip I have set to 200 in the Startup_Task of my main library to make sure runtime users of my application are automatically set to 200.
Do $prefs.$maxcachedclasses.$assign(200)
Setting $maxcachedclasses to some wildly high number is not advisable as it could start to hamper performance.
ADVICE FROM TECH SUPPORT
Some developers have noticed that issuing $definefromsqlclass causes a sizeable performance hit.
The following is advice from Tech Support on this issue:
At present I am unable to fully explain exactly what is happening here. Our thought is that this may be connected to class caching. In that the sqlclasses are not in the cache and must be read from disk. This may mean that you need to adjust $root.$prefs.$maxcachedclasses to remove this problem. We have not seen the problem and therefore this may not be the case.
I include the details on the sys functions that may be used to analyse the caching performance.
sys(190) returns the number of times Omnis has loaded a class from disk and added it to the memory class cache.
sys(191) returns the number of times Omnis deleted a memory class cache entry, when it added aI wanted to be able to open PDF files from Omnis Studio.
MAC PLATFORM
On the Mac platform that's pretty easy to do:
Send Finder event {Open Files (FilePath)}
Note: This Omnis command does not affect the flag. So you can't test flag true or false.
WINDOWS PLATFORM
Life gets a little more complicated on the Windows platform. Tech Support was kind enough to provide me with sample code.
You have to use the Omnis commands Register DLL and Call DLL. These Omnis commands are not available to you in Omnis Studio when you are using a Mac.
Here's what we ended up with for the Windows platform:
Register DLL ("SHELL32.DLL","ShellExecuteA","JJCCCCJ") Call DLL ("SHELL32.DLL","ShellExecuteA",0,"open",FilePath,"","",0) Returns HINST_EXPLORER
NOTES:
1. You can only edit this code on a Windows machine.
If you look at this code on a Mac, it will looks more like this:
X250825050 ("SHELL32.DLL","ShellExecuteA","JJCCCCJ")
X250825051 ("SHELL32.DLL","ShellExecuteA",0,"open",FilePath,"","",0) Returns HINST_EXPLORER
2. HINST_EXPLORER is long integer, representing a handle on the instance of the launched program.
3. JJCCCCJ is the calling convention for the parameters passed, so that Call DLL knows how to typecast the parameters passed.
4. The code should work for any registered file type.
CROSS-PLATFORM CODE
Putting it together in a Switch/Case for cross-platform use, we end up with the following:A word of caution about the 'Optimize method' command. I, among other Omnis programmers have been burned by this command.
The documentation says you can add this command to the first line of a method which you call frequently. The optimized version of the method will be stored in memory and used each time the method is called.
HOWEVER, Optimize method, has not proven to be reliable.
It caused my payroll program to completely crash Studio when I added it to a method which included 12 Switch/Cases. Others have reported various problems.
Personally, I didn't find any speed improvement. I think 'Optimize method' had its purpose when we were running slow clunky computers. But in this age of faster and faster computers, Optimize method, has much less impact.
You decide whether or not you want to use 'Optimize method'. For my peace of mind, I won't be using it in any application I write. I'll focus on writing more efficient code.To rename the Omnis application to include its version number, so you can distinguish it lists and menus from other running versions of Omnis is easy in Windows and Mac OS 9. You simply rename the Omnis Studio application file.
If you try that in Mac OS X when you launch Omnis Studio you'll see a zoom rectangle, but then nothing happens.
With Mac OS X there are a few more steps you need to do.
1. Quit the Omnis Studio application if you have it open.
2. Rename the Omnis application file name. (e.g. Omnis > Omnis 3.2 dev)
3. Right-click on the Omnis application file and select > Show Package Contents.
4. In the window that opens, open the Contents folder.
5. Open the Info-macos.plist file. (Use TextEdit or BBEdit.)
6. Near the bottom of the file you will find:
7. Change Omnis to the renamed file name, save changes and close the file.
8. Open the MacOS folder in the Contents folder. Rename the Omnis file to the renamed file name.
9. Close the package windows.
10. Double-click the renamed Omnis application file. Your new name will show up in the dock and in the top menu bar.
Thanks to Kelly Burgess for this tip!The Mac OS X Aqua Interface draws a thick bluish border around the entry field which has the focus. This can be a problem if you have entry fields that are tightly spaced, or if you are using a different method for showing which field has the current focus.
The Omnis Studio preferences allow you to turn on the Mac OS X system focus.
You can set this preference in your application's Startup_Task notationally as follows:
Do $prefs.$showsystemfocus.$assign(kFalse)If you use a lot of calls and subclass to objects somewhere along the line you may hit the dreaded "Too many methods ...." error message. There a couple things you can do.
1. Increase the $stacklimit using the following line of code in your Startup_Task.
Do $root.$modes.$stacklimit.$assign(14)
The above line increase the stacked methods limit from default 10 to 14. Don't raise it too high. My application won't run on the default of 10.
2. Use "Do method" rather than "Do $cinst.$MethodName" for calling methods within the same class. "Do method" does not add to the stacklimit, "Do $cinst.$MethodName" adds to the methods stack.
Note: "Do method $cinst.$MethodName" also adds to the method stack.
Ever wish you could use arguments in a Switch/Case? You can!
Mark Phillips came up with an interesting twist on the use of Switch/Case.
Calculate Value as 10
Switch kTrue
Case Value<1
do something
Case Value<50
do something else
Default
do something for 50 or more
End Switch
________
David Swain added a few more comments to the thread.
Switch kTrue
Case Value<10,Value>50
OK message {Either less than 10 or greater than 50}
Default
OK message {Default case}
End Switch
The case now simply excludes values between 10 and 50 inclusive. The Case command allows us to
include multiple cases combined by OR logic, but only one Case block will be executed in a pass through the Switch master block.
How can you tell for sure that a reference is valid? Testing for a valid reference is easy.
If Ref
Valid reference.
Else
Not a valid reference.
End If
The problem is if you are trying to just trap an invalid reference.
The problem is the old testing for NULL confusion. (See "Trapping NULL")
If not(Ref) ;; Will give you a problem if the reference is NULL.
If not(Ref) ;; Won't trap an "Unset Reference".
An interesting solution, thanks to Jason Bye, is to test the $ident property of the reference.
Click the "Run Demo" button to step through the TEST CODE below.
If not(Ref.$ident)
NULL or Unset Reference.
End If
Trapping NULL, Blank, or Zero is a nasty thing to do cleanly in Omnis.
One might expect the following If statement to catch the 3 possibilities:
If isnull(VAR)|VAR=''|VAR=0 ;; but it doesn'twork.
If VAR=NULL, then the 2nd test, VAR='', is testing NULL=''.
Omnis can't evaluate NULL='', and therefore it can't properly evaluate the If statement.
Switch/Case doesn't help much either.
The difficulty with many solutions is that they may work if VAR=Character but fail if VAR=Numeric
(or visa versa)
Here's a bullet proof, one liner test for NULL, blank, or zero!
If pick(isnull(VAR),VAR,'')=''
OK message TRUE {NULL or Empty (or Zero for numbers)}
Else
OK message FALSE {[VAR]}
End If
Thanks to Bob Preston for the, If pick(isnull(VAR),VAR,'')='' , solution! You have restored my sanity :-)
To avoid repeating the { If pick(isnull(VAR),VAR,'')='' } If statement all over your code, you may want to add it as a method in your "oFunctions" object class. The following $isNullBlankZero method is included with the "oFunctions" object class in StudioTips. Feel free to copy it to your own library.
$isNullBlankZero method (included in oFunctions)
If pick(isnull(pfVariable),pfVariable,'')=''
Quit method kTrue
End If
Quit method kFalse
If oFunctions is instantiated using the Startup_Task variable 'fn', you could do the following in your code.
If fn.$isNullBlankZero(Variable)
; action if null blank zero
End If
or test the reverse
If not(fn.$isNullBlankZero(Variable)
; action if not null blank zero
End If
Try to reserve the return value for kTrue and kFalse, indicating whether or not the method executed correctly.
In order reserve the return value for kTrue or kFalse, you need to use 'Field Reference' parameters to 'return' the value.
The downside on using Field Reference parameters are:
1. You must first calculate the value to a Field, before sending it to the method. (Rarely a problem)
2. You can not use Field reference returning methods as 'in-line' methods.
The following code demonstrates the 2 styles.
The code in the 2 methods being called is as follows:If you use an eval() function in your code and there is an error in you eval() how do you find the error?
You can use "Test for valid calculation" with #ERRTEXT. The beginning of the#ERRORTEXT will tell you the first and last character of your string which is causing the error in the eval().
For example:
Calculate string as 'midx(#S1,1,3)'
Test for valid calculation{ evalf(string) }
#ERRCODE will be 835 (not sure what constant this maps to), and #ERRTEXT will be something like
"0:4:Unrecognized variable name, item name or attribute"
Set $firstsel/$lastsel to those values at the front of the string to highlight the erroneous part of the calculation.
Thanks to Kelly Burgess for this tip!