Académique Documents
Professionnel Documents
Culture Documents
TigerLogic Corporation
September 2009
03-092009-03
The software this document describes is furnished under a license agreement. The software may be used or copied only in accordance with the terms of the agreement. Names of persons, corporations, or products used in the tutorials and examples of this manual are fictitious. No part of this publication may be reproduced, transmitted, stored in a retrieval system or translated into any language in any form by any means without the written permission of TigerLogic. TigerLogic Corporation, and its licensors 2009. All rights reserved. Portions Copyright Microsoft Corporation. Regular expressions Copyright (c) 1986,1993,1995 University of Toronto. 1999-2009 The Apache Software Foundation. All rights reserved. This product includes software developed by the Apache Software Foundation (http://www.apache.org/). OMNIS and Omnis Studio are registered trademarks of TigerLogic Corporation. Microsoft, MS, MS-DOS, Visual Basic, Windows, Windows 95, Win32, Win32s are registered trademarks, and Windows NT, Visual C++ are trademarks of Microsoft Corporation in the US and other countries. SAP, R/3, mySAP, mySAP.com, xApps, xApp, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and in several other countries all over the world. IBM, DB2, and INFORMIX are registered trademarks of International Business Machines Corporation. ICU is Copyright 1995-2003 International Business Machines Corporation and others. UNIX is a registered trademark in the US and other countries exclusively licensed by X/Open Company Ltd. Sun, Sun Microsystems, the Sun Logo, Solaris, Java, and Catalyst are trademarks or registered trademarks of Sun Microsystems Inc. J2SE is Copyright (c) 2003 Sun Microsystems Inc under a licence agreement to be found at: http://java.sun.com/j2se/1.4.2/docs/relnotes/license.html MySQL is a registered trademark of MySQL AB in the United States, the European Union and other countries (www.mysql.com). ORACLE is a registered trademark and SQL*NET is a trademark of Oracle Corporation. SYBASE, Net-Library, Open Client, DB-Library and CT-Library are registered trademarks of Sybase Inc. Acrobat is a trademark of Adobe Systems, Inc. Apple, the Apple logo, AppleTalk, and Macintosh are registered trademarks and MacOS, Power Macintosh and PowerPC are trademarks of Apple Computer, Inc. HP-UX is a trademark of Hewlett Packard. OSF/Motif is a trademark of the Open Software Foundation. CodeWarrior is a trademark of Metrowerks, Inc. This software is based in part on ChartDirector, copyright Advanced Software Engineering (www.advsofteng.com). This software is based in part on the work of the Independent JPEG Group. This software is based in part of the work of the FreeType Team. Other products mentioned are trademarks or registered trademarks of their corporations.
Table of Contents
Table of Contents
ABOUT THIS MANUAL................................................... 10 CHAPTER 1DEVELOPING WEB APPLICATIONS 11 OMNIS WEB ARCHITECTURE ................................................. 11 REMOTE FORMS ....................................................................12 Creating Remote Forms .................................................... 12 Remote Form Components ............................................... 15 Events ............................................................................... 16 Icons and Icon Pages........................................................ 18 Programming Remote Forms ........................................... 19 Client Method Execution .................................................. 22 Client Method Debugging ................................................ 23 Drag and Drop .................................................................25 Cursors ............................................................................. 25 Tooltips ............................................................................. 25 Subforms ........................................................................... 25 Form Caching ...................................................................26 Changing forms ................................................................ 27 Multiple forms...................................................................28 Opening Remote forms on the thick client ........................ 29 Features not supported in the Web Client ........................ 30 REMOTE MENUS ....................................................................30 Creating Remote Menu Classes ........................................30 Remote Context Menu Events ........................................... 30 REMOTE TASKS .....................................................................31 Creating Remote Task Classes using Wizards .................. 32 Creating a New Remote Task Class ..................................34 Remote Task Instances...................................................... 34 Remote Task Events .......................................................... 35 Client Messages ................................................................ 35 Client Access Properties ................................................... 36 Secure Sockets ..................................................................37 THE OMNIS SERVER .............................................................. 38 Multiple Method Stacks .................................................... 38 Using the Server ............................................................... 39 Database Access ............................................................... 39 Omnis Server Commands ................................................. 40 SQL Session Pools ............................................................ 42 Server Load Sharing ......................................................... 42 3
Table of Contents Socket Binding ..................................................................45 DEPLOYING YOUR OMNIS WEB APPLICATION ....................... 46 Installing the Omnis Server .............................................. 47 Installing the Web Server Plug-in.....................................50 Web Server Plug-in Configuration ...................................53 Web Client Plug-in Installers ........................................... 57 Web Client Deployment tools ........................................... 61 Editing your HTML Pages ................................................ 65 ULTRA-THIN OMNIS ............................................................... 72 HTML Forms and Remote Tasks ......................................72 Using Task Methods to Process Requests ......................... 75 Returning Content to the Client ........................................77 HTTP Headers ..................................................................81 Persistent Remote Tasks ................................................... 81 Multipart Form Data ........................................................ 82 DIRECT CLIENT CONNECTIONS .............................................. 83 CHAPTER 2DEVELOPING MOBILE APPLICATIONS INTRODUCTION ......................................................................86 THE OMNIS MOBILE CLIENT .................................................. 87 CREATING MOBILE FORMS .................................................... 88 Screen Size and Orientation ............................................. 88 Form Width and height ..................................................... 89 Screen Events....................................................................90 TESTING MOBILE FORMS ....................................................... 91 Troubleshooting ................................................................ 91 CONFIGURING THE MOBILE CLIENT .......................................92 Mobile Client Updates ...................................................... 93 The End User Experience ................................................. 94 MOBILE CLIENT DESIGN CONSIDERATIONS ............................ 94 Font table ......................................................................... 94 Style table ......................................................................... 95 Design DPI .......................................................................95 Borders and Themes ......................................................... 95 Scrollbars ......................................................................... 95 Default context menu for lists ........................................... 95 Keyboard Interface ........................................................... 95 Control Appearance ......................................................... 95 Formflds ........................................................................... 96 Icons on 192dpi devices.................................................... 96 Hyplinks ............................................................................ 96 Unsupported Controls ...................................................... 96 MOBILE FORM EVENTS ......................................................... 97 DEPLOYMENT ........................................................................97 4 86
Table of Contents Windows Mobile Deployment tool ....................................97 Single Mobile Client ......................................................... 99 Server and Client Requirements .....................................100 DIRECT CLIENT CONNECTIONS ............................................ 100 CHAPTER 3WEB COMMUNICATIONS................. 101 SSL SECURITY ....................................................................101 OpenSSL ......................................................................... 102 Certificate Authority Certificates ....................................102 IMAP .................................................................................. 103 MULTI-THREADING .............................................................. 105 EMAIL HEADERS..................................................................105 CHAPTER 4OMNIS GRAPHS ...................................106 CHART TYPES ......................................................................106 XY Charts........................................................................ 106 Pie Charts ....................................................................... 108 Polar Charts ...................................................................109 Meter Charts ...................................................................110 The Graph2 Example Library ......................................... 110 COMMON GRAPH PROPERTIES ............................................. 111 Setting the major and minor type ...................................113 COMMON GRAPH METHODS ................................................ 114 XY CHARTS ........................................................................ 116 XY chart properties ......................................................... 116 XY chart methods ............................................................ 117 List data structure for XY charts.....................................118 Data presentation in XY charts....................................... 124 PIE CHARTS ......................................................................... 126 Pie chart properties ........................................................ 126 Pie chart methods ........................................................... 127 List data structure for Pie charts ....................................127 POLAR CHARTS ...................................................................129 Polar chart properties .................................................... 129 Polar chart methods ....................................................... 130 List data structure for Polar charts ................................ 130 METER CHARTS ...................................................................133 Meter chart properties .................................................... 133 Meter chart methods ....................................................... 134 List data structure for Meter charts ................................ 134 Adding Pointers .............................................................. 135 Adding Rings ..................................................................137 GRAPH LAYERS AND THE PRELAYOUT EVENT ..................... 138 Adding layers to charts ................................................... 138 5
Table of Contents GRAPH CLICKS AND DRILLDOWN ........................................ 140 CHANGING THE COLOR OF GRAPH ELEMENTS...................... 141 ADDING COLORED ZONES ................................................... 142 PARAMETER SUBSTITUTION AND FORMATTING ................... 142 Parameters for Pie charts ............................................... 143 Parameters for all XY Chart Layers ............................... 143 Additional Parameters for HLOC and CandleStick Layers145 Additional Parameters for Box Whisker Layers ............. 145 Additional Parameters for Trend Layers ........................ 145 Parameters for Polar Charts .......................................... 146 Parameters for Axis ........................................................ 146 Number Formatting ........................................................ 146 Date/Time Formatting .................................................... 147 Further formatting options ............................................. 148 LABELS................................................................................ 150 Adding Text to a Chart ................................................... 150 USING GRAPHS IN REPORTS ................................................. 151 USING GRAPHS IN THE WEB CLIENT ....................................153 Drilldown in Web Client graphs .....................................154 CHAPTER 5OMNIS .NET OBJECTS ....................... 156 INTRODUCTION ....................................................................156 Why use .NET .................................................................156 SOFTWARE REQUIREMENTS ................................................. 157 Omnis Studio ..................................................................157 Microsoft .NET Framework ............................................ 157 Windows ......................................................................... 157 SETTING UP.......................................................................... 158 Registering the component ............................................. 158 Deployment .....................................................................158 The .NET Example Library ............................................. 159 CREATING .NET OBJECTS ................................................... 159 Defining .NET Objects .................................................... 159 Constructing .NET Objects ............................................. 162 SUBCLASSING .NET OBJECTS .............................................. 164 USING .NET OBJECTS ......................................................... 166 Parameter Data Types .................................................... 166 Passing Parameters ........................................................ 167 Passing Simple Parameter Types ...................................168 Passing Complex Parameter Types ................................ 168 Returning Values From .NET Methods........................... 170 Obtaining constant (or Enum) values ............................. 170 Adding .NET Classes ...................................................... 171 Error Handling ............................................................... 171 6
Table of Contents .NET OBJECTS EXAMPLE LIBRARY ......................................172 The RSS feed component ................................................ 172 The RSS feed library ....................................................... 173 METHOD METHOD OVERLOADING AND PATTERN MATCHING176 Pattern Matching ............................................................ 176 Overloaded Data Types .................................................. 176 Char and Byte Pattern Matching ....................................179 Calling Overloaded Methods Directly ............................ 180 NESTED OBJECT ARRAYS .................................................... 181 OVERLOADED TYPES ........................................................... 182 Omnis Character types ................................................... 182 Omnis Binary types ......................................................... 182 Omnis Number Long Integer types .................................183 Omnis Number Floating dp types ...................................183 CHAPTER 6JAVA OBJECTS ....................................184 SETTING UP ......................................................................... 184 Software Requirements ................................................... 184 Java Example Library .................................................... 185 Environment Variables ................................................... 185 Memory Allocation ......................................................... 188 The Java Class Cache..................................................... 188 CREATING JAVA OBJECTS.................................................... 189 Defining Java Objects .................................................... 189 Constructing Java Objects .............................................. 190 SUBCLASSING JAVA OBJECTS .............................................. 192 USING JAVA OBJECTS .......................................................... 193 Parameter Data Types .................................................... 193 Passing Parameters ........................................................ 194 Passing Simple Parameter Types ...................................194 Passing Complex Parameter Types ................................ 195 Returning Values From Java Methods ........................... 196 Data type mapping and performance ............................. 197 Getting Values From Java Objects .................................198 Adding Java Classes at Runtime.....................................199 Error Handling ............................................................... 201 Development Tips ........................................................... 202 METHOD OVERLOADING AND PATTERN MATCHING ............ 203 Pattern Matching ............................................................ 203 Overloaded Data Types .................................................. 203 Char and Byte Pattern Matching ....................................206 CALLING OVERLOADED METHODS DIRECTLY ..................... 207 NESTED OBJECT ARRAYS .................................................... 208 MODIFYING THE SYSTEM PACKAGE LIST ............................ 209 7
Table of Contents Adding Extra System Packages ......................................209 Removing System Packages ............................................ 210 OVERLOADED TYPES ........................................................... 210 The Omnis Character Type ............................................. 210 The Omnis Binary Type .................................................. 210 The Omnis Number Long Integer Type........................... 211 The Omnis Number Floating dp Type ............................ 211 FREQUENTLY ASKED QUESTIONS ........................................ 211 CHAPTER 7REMOTE STUDIO APPLET ............... 213 HOW DOES IT WORK? ........................................................... 213 OBJECT INTERFACES ........................................................... 214 Server Object methods & properties ............................... 214 Variable Object methods ................................................ 215 STUDIO REMOTE TASKS ...................................................... 216 REMOTE STUDIO EXAMPLES ................................................ 217 Studio server remote task format ....................................217 Use of the Server applet in Visual Basic......................... 218 Use of the complex variables and Server applet in Omnis Studio Use of the Server applet in PHP .....................................220 CHAPTER 8AUTOMATION .....................................221 INSTANTIATING AN AUTOMATION SERVER .......................... 221 DETERMINING WHAT FUNCTIONALITY AUTOMATION SERVERS PROVIDE 222 BUILT-IN METHODS ............................................................. 224 LIFETIME OF AN AUTOMATION SERVER INSTANCE .............. 224 AUTOMATION EVENT HANDLING......................................... 225 AUTOMATION TO OMNIS VARIABLE CONVERSION ............... 226 AUTOMATION ERRORS AND LIMITATIONS ........................... 227 AUTOMATION EXAMPLES .................................................... 228 XML ................................................................................ 228 DAO ................................................................................ 229 Outlook 2000 ..................................................................229 CHAPTER 9ENCRYPTION ....................................... 230 BLOWFISH ENCRYPTION ...................................................... 230 BINARY ENCRYPTION .......................................................... 231 STRING ENCODING .............................................................. 231 CHAPTER 10ACCESSING THE WINDOWS REGISTRY OMNIS REGADMIN .............................................................. 232 Creating a RegAdmin Object .......................................... 233 Opening a Key ................................................................ 233 Creating new Keys and Values ....................................... 234 8 232
219
Table of Contents Retrieving Key and Value names ....................................234 Reading Values ............................................................... 234 Deleting Keys and Values ............................................... 235 Error Handling ............................................................... 235 CHAPTER 11DDE ....................................................... 236 CREATING A DDE LINK ....................................................... 236 OMNIS AS CLIENT ................................................................ 236 OMNIS AS THE SERVER ........................................................ 240 PRINTING REPORTS TO A DDE CHANNEL ............................ 240 THE SYSTEM TOPIC ............................................................. 241 EVENTS DURING DDE ......................................................... 242 ACK BITS............................................................................. 242 PROGRAMMING WITH DDE.................................................. 243 USING DDE WITH WORD ..................................................... 243 CHAPTER 12APPLE EVENTS ..................................245 APPLE EVENT GROUPS ........................................................ 245 TERMINOLOGY ....................................................................246 SENDING AND RECEIVING APPLE EVENTS............................ 247 SCRIPTS ............................................................................... 249 Running Apple Scripts directly from Omnis ................... 254 INDEX ............................................................................... 256
10
Chapter 1Developing Web Applications source although this is not recommended for most web applications when there may be high volumes of concurrent users and transactions. The Omnis Server is the main engine that runs your web and mobile applications. It is a multi-threaded server that runs your Omnis application, executing all the business logic, accessing your server database(s), and handling all the client interactions to-and-from your web and mobile clients. Web access to the Omnis Server is restricted to a specified number of users determined by the server license, which you must purchase separately.
Remote Forms
You can create and test the remote forms on your own machine using your own web browser, that is, you can develop your Omnis library before installing your web server, the web server plug-in and Omnis Server, or before setting up your HTML pages; these are described later in this manual. (Note that some editions of Omnis Studio do not allow you to test remote forms.) You can create Omnis remote forms from scratch or using the templates and wizards available in the Studio Browser. The wizards give you complete control over the fields and components contained in your form and can save you a lot of time. All the wizards create a new remote task or use an existing remote task to link to the new remote form.
12
Remote Forms Password creates a standard password form containing Password and Username fields. The wizard specifies these two fields by default, but you can change these or add your own fields and their instance variables. In the resulting form you need to program the Submit button to send the contents of the username and password fields to your server application. Plain creates a blank form and links it to a remote task; you must add your own instance variables and web components to this form Report creates a remote form that allows you to print a report to HTML; the wizard prompts you for an existing report class or it can create an example report Sidebar with pages creates a form containing a paged pane and a sidebar component. In the wizard, you can specify the groups and group items for the Sidebar component. The wizard creates a list containing the group items in your sidebar. The wizard lets you specify the fields for each pane and allows you to link each pane to a particular group in the sidebar component. The wizard also creates an instance variable for each field Sidebar creates a form containing a number of fields, their instance variables, and a sidebar component. In the wizard, you can specify the groups and group items for the Sidebar component. The wizard creates a list containing the group items in your sidebar. When you have created your form, you will have to add some programming behind the sidebar to allow it do respond to clicks or double-clicks. Submit creates a standard submit form containing fields that you specify, and Submit and Clear buttons. The wizard also lets you specify the instance variables for the fields. In the resulting form, you need to program the Submit button to process the contents of the form Tabs creates a remote form containing a tab strip and paged pane component. In the wizard you can add fields and components to each pane in the form. The resulting form lets the user enter data on a number of panes by clicking the tabs to change page Wizard creates a remote form containing a paged pane component, and Next, Previous and Finish buttons. The resulting form is rather like a wizard in that it allows the user to enter data on a number of panes using the Next button, and gives you more control over the order in which the user is prompted for information. In the wizard you can add fields and components to each pane in the form. When you have created the form you need to program the Finish button to process the contents of the form
13
Chapter 1Developing Web Applications All the wizards prompt you for a remote task class: a remote task instance manages the connection to the client, and is a container for all the instances on a particular client. You can select an existing remote task in your library, or you create one based on the templates provided. For most types of remote form, you can select the Plain Remote Task template. All wizards generate an HTML template in the HTML folder of the main Omnis folder. This HTML page lets you test the form in design mode using Ctrl/Cmnd-T and provides a template for the final HTML pages for your web site. All wizards that create forms containing data fields or components prompt you for the $dataname and component type of each field you require on your form. An instance variable is created for every field you add to a form. All remote forms created using a wizard have a $construct() method containing a parameter variable called pParams of type Row Variable. This row variable contains the parameters of the plug-in in the HTML page. There is a column for each parameter. If you inspect the source of the HTML page, you will note the nine parameters called Param1-9. The value of each of these parameters has the format name=value, where name becomes the name of a column in the row variable pParams, and value becomes its value. You can use these parameters to send additional information to the form. Having created your remote form(s) using the Remote Form Wizards, you can modify them or add instance variables and web components, as appropriate, to complete your remote forms.
14
Remote Forms
Open your remote form in design mode Press F3/Cmnd-3 to open the Component Store or to bring it to the top Click on the WEB Components button in the Component Store; note that background objects, such as Label, Border, Wash, and Tile, are listed under the WEB Background Objects group in the Component Store Drag the required component from the Component Store and drop it onto your remote form
For development purposes, all the web components are installed in the Webcomp folder in the Omnis tree; any new components should be added to this folder.
Chapter 1Developing Web Applications or external property using a double colon (::) before its name. For example, the tab bar component has the property $::currenttab which you must refer to using the notation:
Do $cinst.$objs.tabbar.$::currenttab.$assign(2)
Events
The majority of the web components generate one or more events, although the events for a component may not be enabled by default. You may have to enable specific events for a component by setting its $events property in the Property Manager (note this is a property, and not to be confused with the $event method for a component). For example, the evClick event for a pushbutton is enabled by default in the $events property, but no events are enabled for the single-line edit field: in this case you have to enable specific events, such evAfter, in the $events property for the field. When enabled, events are passed to the $event() method for the web component. You can add code to the $event() method for a component, which is called when the event is triggered. Event handling methods can be set to run on the client (Right-click on the method and select Execute on Web Client), and for most simple methods and calculations this is advisable. By default, an event is sent back to the Omnis Server, the client is momentarily suspended while the event handling method is processed on the server, and when the method is finished control is passed back to the client. In many cases, this is not a problem, but it makes sense to avoid the network delay if possible. It depends what the method has to do and what information it requires: in general, any method that changes the user interface on the client can be executed on the client, while a method that needs to fetch data or write data to your server database needs to execute on the Omnis Server. See the Client Method Execution section for more information.
16
Remote Forms When an event is triggered, a number of event parameters are sent from the client to the event handling method. The first of these parameters is always the name of the event that occurred, and all subsequent parameters are specific to the event and describe it in more detail. For example, a click on a list passes the click event in the first parameter (pEventCode=evClick) and the list line on which the user clicked in the second parameter (pLineNumber). For more information about handling events, see the Omnis Programming manual.
Other web components have their own particular events. For example, the Sidebar component triggers the evIconPicked, and evSetPicked events (note you must enable these in the $events property of the component); the first one is passed when an icon is selected, the other is reported when the user selects an icon strip or group. The Sidebar component is used in the Books example library and has the following $event() method, which is executed when the user selects an icon:
17
18
Remote Forms You can add icon pages using the notation RemoteFormRef.$iconpages.$add(iconID). Omnis adds the name of the page containing the specified icon to the $iconpages property of the remote form.
19
Chapter 1Developing Web Applications Overriding the data handling behavior You can override the defaultdata handling behavior in Omnis and use the $senddata() method to explictely state which variables are sent to the client. $senddata() is a method of remote form instances. To use the $senddata() method, you must set the $enablesenddata property to kTrue in your remote task (note this property can only be set in design mode). Once an event occurs and $cinst.$senddata(ivVar1,ivVarN) has been executed in a remote form instance, Omnis will only return the data of the specified variables. Note that the $senddata() method does not work in a method executed on the client: in all cases, it has to execute on the Omnis Server in order to retrieve any data and send the variable.
Do $cinst.$senddata(iTransactions,iAccountName,iFinalBalance) ; will send iTransactions, iAccountName, iFinalBalance to the client
When you change the data for a component, normally it is enough to issue a $redraw() for the component using $cobj.$redraw() to inform the component to reload the data. If you want to manage data transfer yourself, you can issue a $senddata() method, specifying the dataname of the component. You may execute a $senddata() method more than once, and you can specify the same instance variable more than once. If you issue a $cinst.$senddata() without specifying any instance variables, it will clear the send state of previously specified variables, and all variables will be sent, unless you issue another $senddata(). If you do issue another $senddata(), only the newly specified variables will be sent. The notation $cinst.$senddata(#NULL) stops Omnis from sending any data. You can also use $cinst.$senddata(#NULL,ivVar1) to ensure that only ivVar1 is sent. Note that when the $enablesenddata property is set to kTrue and you do not use the $senddate() method to send specific variables to the client, Omnis will send all data variables in the current remote form instance whether they have changed or not.
20
Remote Forms You also need to consider the result of using any command or notation that opens a window class, installs a menu or toolbar, prints a report, and so on. These commands all do something in the server application, and the result of any such command will be displayed on the Omnis Server and will not visible in the clients browser. For example, if you run the Open window command, an Omnis window class is opened in the server application and not in the client browser; this is Ok for a server admin window, for example, but is of no use for the client. Therefore, bear in mind that all user interaction over the web must occur using remote forms opened in the client. OK Messages You can display a message on the client from a server executed method using the $showmessage() method of a remote form instance. For example, the following code for a pushbutton opens a message box on the client.
On evClick ;; button must have evClick enabled Do $cinst.$showmessage('Message://Hello WWW','Title')
displays an HTML page in a new browser window or frame, where cURL specifies the URL of the HTML page, and cFrameName specifies the HTML frame name. If cFrameName is empty the page is displayed in a new window, otherwise it is displayed in the specified frame of the current browser window.
21
Chapter 1Developing Web Applications The optional parameter cBrowserProperties is ignored if cFrameName is not empty. Otherwise, it has the same format as the Javascript argument to window.open, for example "toolbar=0,menubar=1" which specifies that the browser window will have a menubar, but not a toolbar. The possible keywords are: toolbar status menubar scrollbars resizable location directories width height top left specifies if the browser window has a toolbar specifies if the browser window has a status bar specifies if the browser window has a menu bar specifies if the browser window has scrollbars specifies if the browser window is resizable specifies whether the browser window has a location bar specifies whether the browser window displays Web directories width of browser window height of browser window top coordinate of browser window left coordinate of browser window
The keywords are all Boolean (0 or 1) except for the width, height, top and left, which are numbers in pixel units. Be aware that some browsers do not fully support these properties.
To set a method to execute on the client, open the Method Editor for the remote form, Right-click/Cmnd-click on the method name, and select the Execute On Web Client option from the context menu. When you try to specify that an existing method should execute on the client, Omnis checks to see if it contains any commands that cannot be run on the client. In this case, Omnis returns an error and names the offending command, or the first command if the method contains many commands that do not allow client execution. Omnis
22
Remote Forms also checks the notation and functions used in the method. If the method can be run on the client it is shown in pink (the default) and the command list (bottom left of method editor) is modified to include only those commands that can be executed on the client. In the context of a client method, the functions and hash variables tabs of the catalog window only display functions and hash variables available to client methods. To optimize your web client application, you should perform as much processing as you can on the client, and only when necessary use methods on the server. This will reduce the network traffic and possible delays in the client. Methods have the property $clientexec which is kTrue if the method is set to run on the client, or kFalse if it should run on the server. Some remote form methods, such as $senddata(), will not work if they are contained in a method that executes on the client. Note you can debug methods that are marked to execute on the client as well as server executing methods.
23
24
Remote Forms
Cursors
A useful property of several web components, such as pushbuttons and button areas, is the $cursor property which lets you assign a cursor to the object. When the users mouse enters the object the mouse cursor changes to the specified cursor. You can choose a cursor icon from the Omnispic or Userpic icon data file, or you can add your own cursor to the #ICONS system table and assign it to an object. To specify your own cursor you need to set $cursor to kcursCustom and specify the iconid and size of your cursor icon. Remember that you need to include the name of the page containing your cursor in the $iconpages property of the remote form.
Tooltips
You can add a $tooltip to some Remote form objects, such as single-line edit fields, pushbuttons, and heading lists. When the user places their mouse over such objects the tooltip is displayed in the web browser.
Subforms
You can add subforms to your remote forms allowing you to embed one or more remote form classes into a single remote form. The subform object is available in the Component Store in the Web Components group. Using subforms allows you to create web pages containing multiple forms, rather like using frames in a standard set of HTML pages. You specify the remote form to appear in a subform object via its $classname property, plus you can assign to $classname at runtime using the notation.
Creating Subforms
A subform object is a type of web component available in the Component Store along with all the other web components. To create a subform:
Open an existing remote form or create a new remote form that is going to contain the subform Open the Component Store and select the Web Components group 25
Drag a Subform onto the existing remote form In the Property Manager for the subform object, assign a remote form name to the $classname property
When you place the subform field it will resize to accommodate the subform class. You can edit the subform class at any time by right-clicking on the subform field and selecting Subform Class from the context menu. You can test the subform using Ctrl/Cmnd-T. If you enable the $nobackground property, under the Appearance tab, the background of the subform field becomes the same color and pattern as the parent remote form. If the remote form class inside the subform field has only one field you can override its dataname using the $dataname property for the subform field. For example, your subform class may contain a single headed list field that takes its data from a particular list variable. However you can change the list assigned to the headed list by setting the subform fields $dataname property to the name of another list. You could do this in the $construct() method of the subform field. You can send parameters to the subforms $construct() method by including a list of parameters in the $parameters property when you create or modify the subform field. Opening a remote form containing a subform field or any number of subform objects creates an instance of each form, which belong to the same task as the parent remote form instance. Omnis calls the $construct() methods of all the subform classes first in tabbing order, then the $construct() method of the parent form instance. The reverse happens on closing the parent form, with the subforms being destructed after the parent form instance.
Subform Caching
The $multipleclasses property tells Omnis to keep a set of remote form instances open for use in the subform object, rather than constructing a new instance each time the class is changed. When you assign a new remote form name to $classname at runtime, the new remote form is downloaded to the client and displayed in the clients browser. If the $multipleclasses property is enabled, the previous remote form is cached and hidden on the client, otherwise the remote form instance is destroyed. If any previous remote forms have been cached in this way using $multipleclasses, you can switch back to them instantaneously, otherwise they have to be reloaded each time you assign to $classname of the subform object.
Form Caching
Server Form Caching
In order to improve performance at connection time, the Omnis Server caches various items when the first client of a remote form connects. Subsequent connections will return this cached data. The following items are cached: the class data, the instance variables definition, the icon pages, and the font tables. 26
Remote Forms You can implement some sort of update process while the system is live, for example, the remote form has been changed, but the cache needs to be cleared. If the cache isnt cleared new connections will continue to use the old data in the cache. You can use the $root method $clearcachedforms() in your application to clear all the cached items on the Omnis Server.
Changing forms
The remote task instance has a method, $changeform(), which enables you to replace the form currently in use on the client, with another form in the same library. $changeform() has a single argument, which is the new remote form name. When it executes, the current form instance destructs, and the web client constructs an instance of the new form to display in the users browser. You can use task variables in the remote task instance to pass information between the destructed remote form instance, and the new remote form instance. There are some restrictions to note: $changeform() cannot be used in the $construct() or $destruct() method of a remote form instance or remote task instance. If used, Omnis generates a runtime error. Multiple calls to $openform() (described later) or $changeform() during the processing of a single event will result in only the last call to $openform() or $changeform() having any affect. If you switch to a form that is larger than the initial form, the area occupied by the new larger form is not expanded and therefore parts of the new form may be truncated (this situation may occur if you want to switch from a simple logon form to a much larger data entry form). To work around this you could make the initial form the same size as the larger form you are changing to. 27
Chapter 1Developing Web Applications One scenario for using $changeform() is where the end user is required to log onto your web application, whereby the initial logon form prompts the user for a name and password, and the application changes to another form when the user has successfully submitted a valid name and password.
Multiple forms
You can open more than one form within a single web client connection, that is, within a single remote task instance. At any one time, only one of these multiple instances is visible, and the forms must be from the same library. There are two methods of a remote task instance which you can use to manage multiple forms: $openform() and $closeform(). Like $changeform(), both these methods take a single argument, the form name. If the form passed to $openform() already has a remote form instance open in the context of the remote task instance, it becomes the visible form for the remote task. Otherwise, Omnis constructs a new instance of the remote form in the remote task, and makes the new remote form instance the visible form. This behavior is analogous to the $openonce() method of a window class. The $closeform() method closes (destructs) the remote form instance for the named form, without closing the task instance or any other forms that may be open within the task. It is possible to close the last remaining remote form instance, but this is not recommended, since the end user will be presented with a blank screen. If the referenced form is not visible, the client observes no affect; otherwise, the most recently visible open remote form instance becomes visible. There are some further restrictions to note: $closeform() and $openform() cannot be used in the $construct() or $destruct() method of a remote form instance or remote task instance. If used, Omnis generates a runtime error. Multiple calls to $openform() or $changeform() during the processing of a single event will result in only the last call to $openform() or $changeform() having any affect. Calling $showurl() or $showmessage() in the $destruct() method of a remote form has no affect. All forms must be in the same library. You can use task variables to handle communication between multiple remote form instances in a remote task instance. To facilitate communication between different remote form instances, remote forms can also receive one event, evFormToTop. In design mode, you can enable this event for a form, using the $events property of the form. The event generates a call to the $event()
28
Remote Forms method of the remote form. evFormToTop occurs when an existing remote form is about to become visible on the client as a result of a call or calls to $openform() or $closeform().
29
Remote Menus
The Remote menu class allows you to add to remote forms and individual objects. From the users point of view, the remote menu class provides context menus for remote forms or objects, which can be displayed in your web browser based applications and on mobile devices. In addition, you can use the new remote menu class to provide left and right menus exclusively for the menu bar on Windows Mobile based devices.
30
Remote Tasks context menu for the innermost enclosing container that has a context menu, or no context menu if none can be found. The default menu of an object is included in these checks. After the user has Right-clicked on a form or object, and a context menu has been located, the client generates an evAfter for the current field, followed by an evOpenContextMenu event. This event is sent to the object that has the context menu property set. It has an event parameter, pClickedField, which is an item reference to the object on which the user has Right-clicked, as opposed to the field which has the context menu property set. It also has an event parameter, pContextMenu. This is an item reference to the remote menu instance for the menu that is about to open. You can also access this menu instance, using the notation $cinst.$remotemenu ($cinst refers to the remote form instance). If you want to use any context menu events in your code, such as evOpenContextMenu, you have to enable the events in the $events property of the remote form. The remote menu instance exists only during the evOpenContextMenu event. evOpenContextMenu can be processed on the client, or on the server. You use the remote menu instance to modify the menu before it is displayed on the client. One key property of a remote menu instance object is $remotemenu: for hierarchical menus, this is the item reference to the remote menu instance of the attached remote menu. After evOpenContextMenu completes (note that you can discard the event to prevent the menu from being displayed), the client displays the menu: If the user dismisses the menu without selecting an item, no further event occurs. If the user selects a remote menu item, the client sends an evExecuteContextMenu event to the form or form control that received evOpenContextMenu, passing the event parameter pCommandID set to the value of $commandid for the selected menu line. In the case of Windows Mobile, the mechanism is identical when the user opens one of the menus on the menu bar. In this case, the remote form receives the events, and pClickedField is a reference to the remote form. In addition, the $order property of the remote menu instance allows you to determine which menu was used: it has the value kRMOContext, kRMOLeft or kRMORight.
Remote Tasks
A remote task is a type of Omnis class that handles the connection between a remote form on the client and your Omnis application, and in some cases performs some server-side event handling and processing. Therefore, all remote forms require a remote task, that is, a remote form instance must be instantiated inside a remote task instance. When you create a remote form using one of the remote form wizards, Omnis creates a remote task class for you automatically, so in most cases you can use this one, but you can create your own. As an alternative to using the Omnis web client and remote forms, Omnis lets you interact with your Omnis application and database over the Internet using standard HTML forms 31
Chapter 1Developing Web Applications and remote tasks. In this case, your HTML forms connect to a remote task class directly, and no remote forms are required for this type of interaction.
Select your library in the Studio Browser Click on Class Wizard and then the Remote Task option Select the wizard you want, name the new class and click on Create
The following wizards/templates are available: Plain Remote Task creates an empty remote task containing an $event method with code for evBusy and evIdle events Monitor creates a task and window to monitor remote connections. HTML Report creates a task to generate HTML reports on the fly Submit creates a task and HTML file containing a submit form which interacts directly with Omnis.
32
Remote Tasks Create New Monitor Task option. If, however, your library contains a monitor task, you can specify the Use Existing Monitor Task option to add the new plain task you are currently adding to your library to the existing monitor. See the next section about the Monitor Remote Task Wizard for further details.
33
Remote Tasks Quit method The Error message. In this case the task instance is destroyed and the connection is terminated. If you dont return an error, Omnis will now instantiate an instance of the remote form class and call the $construct() method of the form.
In addition, tasks report the evRejected event which is generated when Omnis rejects a connection by a client. Usually this occurs if there are too many users trying to connect to Omnis, or $maxusers of the remote task has been exceeded. The parameter pErrorText is "Too many users connecting to server" for the first case, and "Too many users connecting to task [taskname]" for the second.
Client Messages
The $showmessage() method allows you to display a message on the client machine. This method only applies to remote tasks that are associated with remote forms, that is, the method does not work for remote tasks that handle HTML forms or ultra-thin clients. (Note the OK message command, and other commands in the Message command group, should not be used for web client based applications, since they will open on the Server, not in the client.) $showmessage(cMessage,cTitle) displays an Ok message on the client machine using the specified cMessage and cTitle. Only one message can be shown in response to a single
35
Chapter 1Developing Web Applications event. Executing $showmessage() more than once in response to the same event results in a single Ok message with the text of the last call to $showmessage.
Timeouts
You can control how long someone is connected to the Omnis Server and how long a single client connection can remain idle, using the following properties. $maxtime the maximum time in minutes that a client is allowed to stay connected; the default value is 0 which means the client can stay connected indefinitely.
36
Remote Tasks $timeout the maximum time in minutes that a client is allowed to stay idle; the default value is 0 which means the client is allowed to stay idle indefinitely.
Client Connections
Remote task instances have some properties that tell you about the current client connection. $clientaddress the TCP/IP address of the current client. Note that this may not be the exact TCP/IP address of the client machine, due to the possible presence of proxy servers and firewalls between the client machine and the web server. $connectionid the id of the current client connection; ids are allocated dynamically by the Omnis Server and numbers are not reused unless the server is restarted. $connectiontime the time and date the client connected to the Omnis Server, i.e. the time the current task instance was instantiated. $lastresponse the time and date the client last accessed the remote task instance on the Omnis Server.
Secure Sockets
Omnis will use secure sockets (HTTPS), if available, if the WebServerUrl parameter in your HTML specifies a full URL using the https: prefix. However, remote tasks have the $issecure property that lets you turn secure mode on and off dynamically, by assigning to the property for the current task at runtime.
37
The Omnis Server As method stacks are allocated dynamically, it is very likely that a remote client will not get the same method stack every time it executes a method on the server. Each method stack contains its own state which, apart from during an individual method call, does not belong to any particular client. This state includes the Current Record Buffers (CRBs) for all files and variables (apart from class variables) and such modes as the current list. A client cannot rely on any properties or values of this state being preserved across different method calls. The only things belonging to the client are its instance and task variables. So a client must do such things as setting the main file and current list each time one of its methods is executed, and should not rely on such things as the values of memory-only fields being maintained across method calls. As a special case, the class variables for the remote task and remote form classes are shared amongst all clients so can be used to hold shared data (see below for the warnings about the care needed when using shared variables).
Database Access
If you are accessing a server database in your web application, and using the Multi-threaded Server, you must use the multi-threaded Data Access Modules (DAMs) or Object DAMs (these were introduced in Omnis Studio 3.0). Using the Object DAMs, you can connect
39
Chapter 1Developing Web Applications directly to Oracle, MySQL, PostgreSQL, DB2, and Sybase, as well as most ODBC- and JDBC-compliant databases such as MS SQL Server. The old DAMs supplied with Studio 3 or earlier do not work on the Multi-threaded Omnis Server. The Object DAMs are implemented as external components and use object variables based on the Object DAMs, and interact with a DAM using the methods of the object. Using this approach, you create object variables of a particular DAM class. There is a group of common methods that apply to all DAM objects and a set of DAM specific methods based on the type of object. Various chapters in the Omnis Programming manual provide more information about accessing your data using the DAMs.
Start server
The Start server command is used to create the client method stacks and associated threads. It takes an optional stack initialization method as a parameter. The command clears the flag if it is used in a copy of Omnis which is not capable of supporting multi-threading or your serial number does not allow clients to connect. A fatal error is generated if for some other reason it is not possible to create the stacks and threads.
Stop server
The Stop server command stops the server from responding to client requests. Once the server has been started you should stop it before quitting Omnis, before using Omnis for anything apart from serving client requests (e.g. running a standard LAN-based Omnis application), or before opening or closing any Omnis data files or libraries. The Stop server command disposes of all remote task and form instances. The resources used by the client stacks and threads are not released, but they will be reused by the next Start server command. 40
Here cList is a class variable which is shared amongst the clients and the critical block is used to prevent other clients from accessing the list whilst it is being built. Generally class variables should only be used when the shared functionality is essential and only with care:
Calculate cString as 'abc' ;; OK Calculate cString as $cinst.$xyz() ; only OK inside a critical block
Simple atomic operations such as the first line of the above example are safe, but when a method call is involved it may be interrupted by other threads and cause problems. Class variables should not be used as bind variables or as the return list for SQL operations.
41
Any other command which would cause a dialog to be displayed on the server is not available for methods running on the Multi-threaded Server. In addition, there is a lot of notation, such as the notation for opening and closing libraries and data files, that will not work in a method running on the Multi-threaded Server.
42
The Omnis Server To use load sharing, you prefix this property with a name for the pool of Omnis Server processes and a comma, for example Omnis,6000, or Omnis,194.131.70.197:6000. In this case, the address information in the property no longer addresses an Omnis Server. Instead, it addresses a new module, a load sharing process. When a new connection arrives at the Omnis web server plug-in, the plug-in inspects the syntax of the OmnisServer parameter. If it is prefixed by a pool name, the plug-in connects to the load sharing process, and sends it a message that asks for the address of a server process in the pool. The load sharing process typically returns the address and port number of the least busy process in the pool. The plug-in then connects to this process, and sends the web client connection to it. When the plug-in responds to the client, it includes the address of the Omnis Server process in the response. When the client sends subsequent messages to the web server for this web client connection, it sends the address passed in the connect response instead of the OmnisServer parameter. Thus the only additional overhead imposed by load sharing occurs during connection setup. So how does Omnis know (1.) which Omnis Server processes exist, and (2.) which Omnis Server process is the least busy? The load sharing process (LSP) has a .ini file, which contains the pool names for the pools for which it is responsible, and for each pool, the addresses of the Omnis Server processes in the pool. Periodically, the load sharing process polls each Omnis Server process, and asks it for the percentage of web client connections currently in use (using the serial number as the maximum), and information about how much time the server has spent processing requests. The load sharing process combines this information to determine which process is the least busy. You can configure the time interval between polls of each Omnis Server process via the .ini file. Once every 10 or 20 seconds is usually frequent enough.
43
Chapter 1Developing Web Applications The commands for the lsp are: omnislsp -start omnislsp -stop
(with the omnislsp.ini in the same directory as the program) The Port entry in the .ini file identifies the TCP/IP port number on which the LSP listens for requests from the Omnis web server plug-in. The QuietMode entry in the .ini file indicates if the LSP generates OK messages, or messages to the console, to report its status. When set to zero, it will generate messages. When set to one, it will not. The LogLineThreshold entry in the .ini file indicates when the text log generated by the LSP will be reduced in size. If the LSP writes a line to the log, and the file contains LogLineThreshold lines, it will reduce the file size to LogLineThreshold/2 lines, maintaining the most recently written lines, before writing the line to the log. The log is in the same directory as the omnislsp program. The BucketSize entry specifiess how the LSP breaks up the server processes into groups, based on how busy they are. It is a value in milliseconds. The LSP divides the processes into 10 buckets, based on the average time to process a request obtained from the information it gathers by polling the server processes periodically. The buckets are numbered 1-10, where 1 contains the least busy servers, and 10 the most busy servers. A server is in the smallest numbered bucket, for which its average time to process a request is less than or equal to (bucket number)*BucketSize. If a server is so busy that this calculation does not allocate it to a bucket, it belongs to bucket 10. You may need to experiment with possible settings for BucketSize, in order to determine the optimum setting for your application. Each pool has its own section in the .ini file. The PollTimer entry indicates the frequency in seconds at which the LSP polls the server processes in the pool for information. The ServerN entries identify the TCP/IP address and port of each server process in the pool. You also need to edit the 'OmnisServer' parameter in your HTML file containing the web client plug-in, for example:
OmnisServer="Omnis,6001" or OmnisServer="Omnis,123.456.789.010:6001"
where Omnis is the name of a pool of Omnis Server processes and 6001 is the port number of the LSP. On the LSP servers The Omnis Servers may be stopped and restarted without the need to stop the LSP. Load Sharing Mechanism The load sharing process periodically polls the processes in a pool of Omnis Server processes. Each server returns the current number of connections to the server, the maximum number of concurrent connections allowed to the server (specified by the serial 44
The Omnis Server number), the number of requests since the last poll, and the total elapsed time in milliseconds taken to process the requests. The load sharing process organizes the servers into buckets, based on the results of the information returned from polling the servers. When a connection request arrives at the load sharing process, it allocates a server to the request as follows. It traverses the buckets, starting with that for the least busy servers, looking for a server that has some free connections. Within a bucket, it looks for the server with the smallest percentage of connections in use, using the results of the last poll. If there is more than one server with the same smallest percentage of connections in use, the process allocates the connection to the server to which it least recently allocated a connection. At this point, the load sharing process also updates the connection statistics from the last poll, to reflect the new connection. The traversal stops when a free process has been found. If all servers are fully utilized, the LSP allocates the connection to a server at random; in this case, it is likely that the server will reject the request, and return a suitable error to the client.
In the case where there are two addresses in the OmnisServer property, separated by a semicolon, the first address will be used by 3.x clients, and the second by 2.x clients. The address for 2.x clients must directly address an Omnis Server, that is all load sharing parameters are irrelevant and should not be included. Omnis Studio 4.x clients can connect to a 3.x server, but it is not possible to download any components.
Socket Binding
For the development version, Omnis will retry the bind 5 times, once a second, and then report an error via the trace log; this behavior is the same as previous versions. For a Runtime or Service with a web client serial number, Omnis will retry indefinitely once a second. When running as a Service, after a few bind attempts, Omnis outputs a message to the system event log (if the event log is being used for Studio), Failed to bind web client socket - will retry indefinitely. If the bind is eventually successful, Omnis outputs a second message, Successful bind of web client socket.
45
Chapter 1Developing Web Applications Note that you can stop the service while the indefinite retries are occurring, but you cannot use the tray to bring Omnis to the front (or do anything else with the Studio service) as the web client bind occurs quite early in the initialization of Studio. When running as a Runtime, Omnis displays a working message while the retries are occurring; this allows the end-user to cancel the retry loop.
46
where xx denotes the Omnis version, so Studio version 5.0 will install files into:
/usr/local/tigerlogic/os50web/
and in subdirectories below. After the Omnis Server files have been created, you need to run a script to set up the correct Omnis environment. To do this, move to the Omnis root directory (let's assume Studio version 5.0) and execute the omset script with the commands:
cd /usr/local/tigerlogic/os50web/ ./omset
After that, the user root can start Omnis with the command
/usr/local/tigerlogic/os50web/omnisI386
and will be prompted with the serialisation dialog. At this stage, you should enter your company details including the Omnis Server serial number you purchased. When accessing the Omnis Server, end users need to have privileges to write into certain subdirectories below the Omnis root directory. Rather than giving global write privileges to all files, you might want to define a group and assign access rights to the group.
47
NT Service Setup
For Windows servers only (NT, 2000, XP, and Vista), a program called NTSERV.EXE is provided on the Studio DVD, which installs an NT service to run the Omnis Server. Installing Omnis as an NT service allows you to manage it from the standard NT Services window (usually accessed via the Control Panel), and means that Omnis will not be visible on the desktop when it is running. Under Windows Vista, you must have Administer Rights to install and register the NTSERV.EXE program. By default the NT service name is Omnis Server. Do not confuse NT service with the TCP/IP service names which you can specify in the $serverport property for communication. They are unrelated. If you did not set up Omnis as an NT service during installation you can register it now by running NTSERV.EXE with the following command line:
NTSERV -install
To remove Omnis as a service, run the following from the command line:
NTSERV -remove
To run Omnis as console application for debugging, run the following from the command line:
NTSERV -debug <params>
It is important that whenever you use the NTSERV.exe that the file is in the same folder as the Omnis.exe that you are using. Omnis Server event logging When running as a service on Windows NT/2000, XP, or Vista, the Omnis Server uses the application section of the system event log to report a number of events. Most of these events were previously sent to the trace log (and indeed they continue to be sent to the trace log when Omnis is not running as a service). The following events are generated in this way: 1. Web client method execution errors in client methods. 2. Web client method execution errors in the multi-threaded server. 3. An indication at service startup that the server is ready to receive connections from clients. 4. An indication at service shutdown that the server is no longer listening for new connections from clients. 5. Various unexpected socket errors that occur when communicating with the client. This includes failure to bind to the socket port. 6. Failure to load external or external component DLLs.
48
Deploying Your Omnis Web Application 7. An attempt to execute an OK, Yes/No or No/Yes message. In this case, Omnis writes the message to the event log, and generates a suitable default response, as if the message was cancelled if there is a cancel button requested, or the default button was clicked if there is no cancel button. If you want to disable this behavior (so that the message boxes display on the server), you can execute (in both design and runtime versions) $modes.$dotoolmethod(kEnvToolBrowser,103,kTrue). To restore this behavior execute $modes.$dotoolmethod(kEnvToolBrowser,103,kFalse). 8. There is a file, studiomsgs.dll, in the same directory as Omnis.exe. This contains the message definitions used by the event viewer. You can disable event logging by removing studiomsgs.dll before starting the service, in which case messages go to the trace log as they did before, and Ok messages, and so on, will cause the server to wait for a user response.
Chapter 1Developing Web Applications The Omnis Server port number is stored in the Omnis.cfg file in the Studio folder under the main Omnis folder.
Copy mod_omnis.so to the Apache modules directory, e.g. on RedHat 9.x this is /etc/httpd/modules Add the following lines at the end of access.conf:
<Location /omnis_apache> SetHandler omnis-apache </Location>
Add the following lines to httpd.conf, at the end of each block of similar directives:
LoadModule omnis_module modules/mod_omnis.so AddModule mod_omnis.cpp
You need to restart httpd (restarting the system is the simplest way to do this). After installing the Apache module, you can address it using /omnis_apache in the WebServerScript parameter of the web client Netscape plug-in or ActiveX.
50
To install the servlet on your web server, such as the Apache Tomcat server, you should place the whole servlet folder in the Webapps folder within the Tomcat installation. If you wish, you can rename the servlet folder. You will need to restart the webserver in order for the servlet to be loaded. Web server parameters for the Java Servlet The WebServerUrl and WebServerScript parameters in your HTML containing your remote form must have the correct format to access a web server with the Java Servlet. WebServerUrl this must be the URL to the tomcat webserver
51
Chapter 1Developing Web Applications WebServerScript thia must have the servlet name and path, such as "/servlet/%servletname%" Note if you haved renamed the servlet folder you should use the new name in the WebServerScript parameter instead of servlet; The default value for %servletname% is 'rdtaservlet'. You can modify this or add others by modifying the web.xml file. The following xml can be added to the <web-app> element in the document to add a new servlet alias name. For example
<servlet-mapping> <servlet-name>RdtaServ</servlet-name> <url-pattern>/%servletname%</url-pattern> </servlet-mapping>
Secure Sockets
You can use secure sockets (HTTPS), if available. The web client uses a secure connection to connect to the web server, if the browser supports secure connections, and if you prefix the URL or IP_address in the WebServerUrl parameter, with https://, for example:
https://remainderOfFullURL
The HTML page containing the web client does not need to have a secure (HTTPS) URL, but you may want to make this the case, since it is then more obvious to the user that they are running over a secure connection. In addition, remote tasks have the $issecure property that lets you turn secure mode on and off dynamically, by assigning to the property at runtime. Secure socket connections do not support the "address:port" format for the Webserverurl parameter of a web client object.
52
nph-omniscgi Rename the nph-omniscgi.exe to nph-omniscgiini.exe for Windows, or rename nphomniscgi to nph-omniscgiini for Linux. omnisapi.dll For Windows IIS based servers, rename omnisapi.dll to omnisapiini.dll. rdtaserv.dll If you are using the Web Services enabled Web Server plug-in, rename rdtaserver.dll to rdtaserverini.dll. 53
Note that the local IP address in the configuration file cannot be resolved. Imagine the server plug-in and the Omnis server are on the same machine, with an IP address of 192.168.0.3. If the incoming request was of the form OmnisServer=5920, the configuration file has to match this form. So if you want to allow only connections to port 5920, you would have to add this line to the [AllowConnectionsTo] section: address1=5920. If you 54
Deploying Your Omnis Web Application use the expanded form of the address, i.e. address=192.168.0.3:5920, the server plug-in would deny the request. In the event of a denial of service the plug-in returns a HTTP 403 error with the following message Access to the resource has been denied. Default Connections You can provide default connection parameters in the [DefaultConnection] section of the configuration file. This section provides a means of adding missing values into an HTTP post, or in effect, providing a complete set of default parameters if none are provided in the HTTP post. When they are present in the HTTP request, the values in DefaultConnection are ignored and the values are taken from the original request. The DefaultConnection section can contain the following keys: OmnisServer OmnisClass OmnisLibrary PostDataParamName Any number of additional parameter pairs in the form Parameter Name=value The OmnisServer, OmnisClass and OmnisLibrary mirror the operation of the identically named remote form parameters. The value of the PostDataParamName key specifies a variable name for all the content of the HTTP post. All other keys are assumed to be parameters. They are passed to the Omnis remote task and appear as columns in the row variable. The column name is the key name and the value matches the value of the key. One thing to note, if the parameter is present in the original request and the configuration file also contains a definition for the parameter, the value is always taken from the request even if the parameter has no associated value. For example:
[DefaultConnection] OmnisServer=192.168.0.1:5920 OmnisClass=remoteTask OmnisLibrary=TEST param1=value1 param2=value2 PostDataParamName=PostData
In the context of the above DefaultConnection section, consider the following URL which attempts to connect to Omnis:
/omnis_apacheini?OmnisClass=remoteTask¶m1=1234
The OmnisClass and param1 values are taken from the URL while the other values are taken from the DefaultConnection section. In this case, no OmnisServer and OmnisLibrary parameters are provided in the query string, so those values are taken from the configuration file. Therefore the plug-in will amend the query string to:
55
Note PostData is empty as the content-type is application/x-www-form-urlencoded, so in this case the data is not passed to Omnis. Overriding Connections You can override the server parameters passed to the Omnis Server by an HTTP post by including a [OverrideConnection] section in your configuration file. In this case, all the values in the request are ignored, and the Omnis Server uses values from the configuration file. The OverrideConnection section may contain the following keys with associated values: OmnisServer OmnisClass OmnisLibrary PostDataParamName Any number of additional Parameter Name=value These keys function exactly as described in the DefaultConnection section. An example OverrideConnection section is as follows:
[OverrideConnection] OmnisServer=192.168.0.1:5920 OmnisClass=rtTest OmnisLibrary=TEST param1=value1 param2=value2 PostDataParamName=PostData
In the context of the above OverrideConnection section, consider the following URL which attempts to connect to Omnis:
/omnis_apacheini?OmnisClass=remoteTask¶m1=1234
In this case, the values in OmnisClass and param1 submitted in the post are ignored, and all the values for the post are taken from the DefaultConnection section in the configuration file. Therefore the query string is amended to:
/omnis_apacheini?OmnisClass=rtTest&OmnisServer=192.168.0.1:5920& OmnisLibrary=TEST¶m1=value1¶m2=value2&PostData=
Note PostData is empty as the content-type is application/x-www-form-urlencoded, so in this case the data is not passed to Omnis.
56
Under Vista, the Omnis Web Client ActiveX is considered to be a low-integrity component, and should therefore be installed in the LocalLow folder which allows write access to such low-integrity components. If the Web Client plug-in is installed elsewhere on Vista, then unless the web site containing your Web Client page is listed in the trusted sites setting of IE, performance is likely to be poor, or the plug-in may not run at all. The location of the Web client plug-in specified during installation is written to the Windows environment variable MOZ_PLUGIN_PATH to allow the plug-in to work for Firefox. Likewise, a registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Omnis Firefox\extensions is added (or overwritten) to make the plug-in work in Safari.
57
58
Deploying Your Omnis Web Application omupdate.exe the web client update program (used when the client files update themselves to a later version) orfcexec.dll contains the code necessary to execute client methods. If your application does not make use of this feature, this component is not required on the client omnisxi.so on the Linux platform only, the orfc also includes the file omnisxi.so The remote form class objects are external components written specially for the remote form class. No other Omnis objects can be placed in a remote form class. The web client installer includes all the web components needed to display any type of remote form, including all standard entry fields, list objects, sidebar, progress bar, and so on, as well as the background components. The web client engine itself includes the paged pane component.
59
Chapter 1Developing Web Applications Component file name formback formcal formclok formcord formfade formfile formfish formflds Description Background Label and Border components Calendar component Clock component Accordion component Fadepict component FormFile component FishEye component Field components including Pushbutton, Single line and Multi line entry field, Checkbox, Radio group, List box, Drop list, Combo box, Heading list and Picture Gif component Data grid component Hotpict component IconArray component UserInfo or cookie component JPEG component Hyperlink component Marquee component Masked entry field component FormPort component Printing component Progress component Quicktime or Movie Player component Remote launch component Roll button component Side bar component Slider component String Label component Tab bar component Tile component FormTimer component Transbutton component Web Tree component Wash component
formgif formgrid formhpic formicon forminfo formjpeg formlink formmarq formmask formport formpri formprog formqt3 formrmlh formroll formsbar formslid formstrg formtbar formtile formtime formtran formtree formwash
Reistering orfc.dll Under Windows, the web client installer package must register the orfc.dll file under the regsvr32 command, e.g.
regsvr32 C:\Webclient\orfc.dll
60
Deploying Your Omnis Web Application assuming the web client files are installed into C:\Webclient in Windows XP; under Vista the web client is normally nstalled into the end users LocalLow folder.
Windows Vista Under Windows Vista, the web client is installed into the LocalLow folder, something like:
C:\Users\<user-name>\AppData\LocalLow\TigerLogic\webclient
Mac OS X Under Mac OS X, the web client is installed into your Internet Plug-ins folder:
/Library/Internet Plug-ins/webclient.plugin
61
Chapter 1Developing Web Applications your web server and Omnis Server. You can use this HTML file to deploy your Omnis web application. Alternatively, you can use the Remote Form Deployment option in the Web Client Tools dialog, opened using the Tools>>Add-Ons>>Web Client Tools option on the main Omnis menubar. It has the following options. Library the name of the Omnis library you want to deploy on the Omnis Server; this should be the library file name minus the .lbs extension Remote form The remote form you wish to deploy WebServerURL the URL of your web server, either an IP address, Domain name (for example http://www.mydomain.com), or address:port; this can be prefixed https:// for a secure connection WebServerScript the location of the Omnis web server plug-in on your web server, such as omnisapi.dll for IIS servers; the server plug-in would typically be in the /cgi-bin, /scripts, or /webapps folder depending on your web server and operating system OmnisServer the port number of the server, or service name, which is registered on the server, and specified in the $serverport preference in Omnis. The OmnisServer parameter can also be in the form IpAddress:port, if the Omnis Server is running on a different machine to your web server You can create a web page that will detect the browser and platform of the client and therefore use the correct web client plug-in type (ActiveX or Netscape type). The automatic page can be specified as an ASP, JavaScript, or SSI type page that will be evaluated on the web server when loaded. In addition, you can specify the title and location of the file. If you view the HTML page created using this wizard, you will see the web client parameters specified inside the OBJECT or EMBED section of the HTML code. You can test your web application using this HTML page but you may want to copy the relevant sections to your own HTML templates to integrate into your web site to maintain the overall design.
Deploying Your Omnis Web Application When a client connects to the Omnis Server, the server returns a list of available components and their versions in the response to the connect request. The web client analyzes the form and the components already installed on the client, and if it needs to, downloads any missing or out-of-date components. The web client prompts the user, asking them if they want to download the new or updated component(s). Assuming the user clicks OK, the web client downloads the component(s), and the remote form is displayed. If the user cancels the download, the form will not be displayed. If the web client itself needs to be updated, there is an additional step where the browser automatically restarts. Web Component database The database of web components is stored in an Omnis datafile called ctrlmgr.df1, which is located in the Studio folder under the main Omnis folder in the Development and Server versions of Omnis. The database contains a record for each web component, for each supported platform. It also contains a record for the orfc files, which enables the web client to update itself if the client is running an out-of-date version of the orfc. There is a library, called the Control Download Manager or ctrlmgr.lbs, also in the Studio folder, which manages this data file. You can access the Control Manager library using the Web Client option on the Tools>>Add-Ons>>Web Client Tools menu. The Download Manager option opens the Control Manager library which lets you add, delete, or extract components in the data file, but only on the platform to which the web component belongs. The components in the data file are in a compressed format. If you create your own web components (externals) they must be added to the Control Manager. The version number should be set to a number appropriate to your Omnis Server version, that is, the component should be set to 3.x for a version 3 Server or 4.x for a version 4 Omnis Server. If you change the contents of the Download Manager data file, you must update the one on your Omnis Server with your local ctrlmgr.df1 data file (located in your local Omnis\Studio folder).
63
Chapter 1Developing Web Applications Each separate image in your animation should be saved as a PNG file with a file size limit of 32k. Using relatively small images, such as 100 x 70 pixels, stored using 256 colors will reduce the overall file size. The number of images in your animation is unlimited but each image you include will increase the size of orfc.dat and in turn the web client installer. To change the animated web client logo
Select the Tools>>Add-Ons>>Web Client Tools menu option and open the Image Compiler tool Select the Images>>Set Directory option to specify the location of your images Right-click on the Image list (on the right side of the dialog) and select the Add Line option Right-click on the new line that appears in the list and select the Set File option to select your first image Repeat this process for every image you want to include in your animation
You can specify the duration of each image or frame (in milliseconds) and the position or alignment of the animation itself. The Toggle Animation option lets you preview your animation.
When you have loaded your images and set the frame rate, you must select the Save Script option from the Script menu Name the script using the .scr extension
The script stores the location of the images for your animation and its other properties. Provided your images are present in the same location, you can reopen a script to reload the specification for an animation.
When you have saved the script you must select the Build Dat File option from the Script menu
A new orfc.dat file will be created in the same location as your image files. To test your new animation, place the new orfc.dat file in your local web client folder, such as c:\webclient under Windows (if you have more than one web client on your machine, make sure you replace the dat file in the web client that is currently registered). Open a remote form in one of your libraries to view the new animation in your web browser. You may need to create a delay in your code to see the animated logo; for example, you can execute an OK message in the $construct() method of your remote form, which will halt method execution in Omnis, and then switch to your web browser. You can add your own splash screen image using the Images>>Load Splash option. This is also stored in the orfc.dat and must not be bigger than 32k. 64
Image Compression
The Image Compressor allows you to reduce the size of images used in your web client applications, such as those placed on remote forms as background images or picture files stored in an Omnis data file. When you launch the Image Compressor library you first need to select the Omnis library and then the remote forms in which you want to compress the background images. Next you can select an Omnis data file in which you want to compress an image data. If you do not want to compress images for a data file then ignore this option. When the compression is complete a log window is opened.
65
The HTML file calls into a javascript file called omniswebclient.js, which is also located in the \html folder in the development version of Omnis. When you deploy your Omnis web application, both your HTML file and the Omnis javascript file must be placed in the same folder on your web server. If you need to edit the configuration of the Omnis Web Client plug-in or your remote form you will need to change the following parameters. The following table also shows how the parameters in the HTML file created by Omnis map to their corresponding ActiveX or Object parameters that are interpreted by the Omnis Server. HTML parameter oserver olibrary oclass ounicodeserver ActiveX/Object parameter OmnisServer OmnisLibrary OmnisClass OmnisUnicodeServer Description The Omnis server port number The name of your Omnis library The name of your Remote form class Whether or not the Omnis Server is Unicode compatible; will always be value=1 in Studio 5 onwards The URL or IP address of your web server: see Note below The location of the Omnis web server plug-in such as nph-omniscgi.exe The width of your remote form The height of your remote form
66
Deploying Your Omnis Web Application Note The WebServerURL should be a valid URL, and should not include a trailing / slash, otherwise the Omnis Server may hang. Test the URL in your browser before deploying your application in a live server environment. The omniswebclient.js file also performs platform and browser detection and creates either the <OBJECT> or <EMBED> tag with all the correct parameters as appropriate. Note that the ActiveX is only used for Internet Explorer under Windows. All other browsers and platforms use the Mozilla/Netscape type plug-in, including Internet Explorer on Mac OS.
The Omnis web client ActiveX has the following parameters. classid the id of the ActiveX object; this includes the height and width of the object which ought to be the same as the remote form; the plug-in size does not change if you change the size of your remote form, so you may need to edit these values.
67
Chapter 1Developing Web Applications OmnisServer the port number of the server, or service name, which is registered on the server, and specified in the $serverport preference in Omnis. The OmnisServer parameter can also be in the form IpAddress:port, if the Omnis Server is running on a different machine to your web server. For example, 111.222.333.444:5912 111.222.333.444:omnis ;; where omnis is a service name www.myhost.com:5912 www.myhost.com:omnis OmnisLibrary the internal name of the library on the Omnis Server; the default is the library file name minus the .lbs extension. OmnisClass the name of the remote form in the library OmnisLibrary. note that this is casesensitive. WebServerUrl the URL of your web server; the URL can be either an IP address, Domain name (for example www.myhost.com), or address:port. You can prefix the URL with http:// for standard http access, or https:// to enable a secure connection to the web server. You can use "address:port" to specify a port although this is not supported for secure socket connections. For local testing the WebServerURL can be set to 127.0.0.1 (i.e. the loopback address) or it can be the IP address of your local machine. Must be a valid URL without trailing / slash, otherwise the Omnis Server may hang WebServerScript the location of the Omnis web server plug-in, such as omnisapi.dll, on your web server; typically the /cgi-bin, /scripts, or /webapps folder. Param1 to Param9 specifies additional parameters, which can be sent to the Omnis Server. In the value clause you have to specify the parameter name and the data separated by an equal sign. Each of these parameters is optional. You can examine the template HTML pages in the HTML folder in the Omnis root directory, to see how the Omnis web client is embedded. The template pages have the port number/name, library name, and remote form class parameters filled in, but you will need to change or add the other parameters, such as WebServerUrl and WebServerScript, to allow remote access to the remote form.
68
Deploying Your Omnis Web Application Mozilla/Netscape Plug-in code and parameters The HTML code and parameters for the Netscape plug-in are as follows.
<EMBED type=application/OMNIS-RCC-plugin name="rcc1" width=500 height=500 OmnisServer="ServerPortNumber" OmnisLibrary="LibraryName" OmnisClass="RemoteFormName" webserverurl="www.yourdomainname.com" WebServerScript="/scripts/nph-omniscgi.exe" Param1=pOption1=dataParam9=pOption9=data>
Note that this includes the height and width of the object which ought to be the same as the remote form; the plug-in size does not change if you change the size of your remote form, so you may need to edit these values. For details of the parameter values, see the previous section about the ActiveX client.
69
70
Note the blocks of code delimited by <% and %>. These contain Active Server Page directives.
71
Note the directives prefixed with <!--#. These are the Server Side Include control directives.
Ultra-thin Omnis
In addition to the Omnis web client, Omnis Studio lets you interact with your Omnis application using standard HTML forms, without the web client plug-in. This approach is often referred to as Ultra-thin Omnis since the clients browser does not require the plugin, just HTML forms and the use of standard GET and POST methods are used. In the Ultra-thin Omnis environment, the HTML form sends parameters and data directly to the Omnis Server via the Omnis web server plug-in in the cgi-bin or scripts folder. When the Submit button in your HTML form is pressed, the Omnis web server plug -in is executed and passed all the forms parameters. The Omnis web server plug-in sends the request to the Omnis Server, which creates an instance of the specified Remote Task Class and calls its $construct() method.
The form has the special parameters: OmnisServer specifies the port number or service name of the Omnis Server, that is, the value specified in the $serverport preference in the Omnis Server. OmnisClass the name of the remote task class to which this form is to connect (not a remote form as is the case with web client based applications).
72
Ultra-thin Omnis OmnisLibrary the internal name of the library containing the remote task class on the Omnis Server; the default is the library file name minus the .lbs extension The following example HTML source code implements a feedback form. The Omnis specific parameters are marked in bold; the remainder of the source specifies the form fields and text labels in the form, including a standard Submit button.
<form method="GET" action="/cgi-bin/omnisapi.dll"> <input type="hidden" name="OmnisClass" value="tThinClientFeedback"> ;; the remote task name <input type="hidden" name="OmnisLibrary" value="Webclient"> ;; the library name <input type="hidden" name="OmnisServer" value="5912"> ;; the port number <table border="0" cellspacing="0" cellpadding="0" width="760"> <tr> <td width="788" valign="top"><div align="right"> <p><strong><font face="Arial">Developer Name:</font></strong></td> <td width="564" height="25"><font face="Arial"> <input type="text" name="Name" size="27"></font></td> </tr> <tr> <td width="788"><div align="right"> <p><strong><font face="Arial">Serial No:</font></strong></td> <td width="564" height="25"><font face="Arial"> <input type="text" name="Serial" size="27"></font></td> </tr> <tr> <td width="788" valign="top"><strong><font face="Arial"> <div align="right"> <p>Platform:</font></strong></td> <td width="564" height="23"><table border="0" cellspacing="0" cellpadding="0" width="520"> <tr> <td width="135"><font face="Arial"> <input type="checkbox" name="Macintosh" value="YES"> <strong>Macintosh</strong></font></td> <td width="385"><font face="Arial"> <strong><input type="checkbox" name="Windows" value="YES">Windows</strong></font></td> </tr> </table> </td> </tr> <tr> <td width="788" valign="top"><strong><font face="Arial">
73
In the above example, the HTML form uses the GET method. You can also use the POST method. The main difference lies in how the data is transmitted to the server, and this is reflected in cases where the URL generated by the form is displayed in the location bar of the users browser. A GET method is equivalent to requesting the URL
/cgi-bin/omnisapi.dll?OmnisClass=&OmnisLibrary=&
and sending content which specifies the parameters. If the URL is being displayed in the location bar, you might choose to use POST in order to hide the parameters from the user.
74
Ultra-thin Omnis
75
76
Ultra-thin Omnis
Break to end of switch Case 'WinNT' Calculate lUrl as iWinNTdownload Break to end of switch Case 'Ppc' Calculate lUrl as iPpcdownload Break to end of switch Case 'Linux' Calculate lUrl as iLinuxdownload Break to end of switch Case 'OSX' Calculate lUrl as iMacosxdownload Break to end of switch Default Calculate lUrl as iWin95download Break to end of switch End Switch End If End If If not(lCodeFound) Do $itasks.DOWNLOAD.$getUnsecuredUrl(lServerUrl) ; get the server path Calculate lUrl as con( lServerUrl,sys(9),'downloadhtml',sys(9), lFolder,sys(9),iUrl,'.htm') End If Quit method lUrl ;; return the path to the approp download
The final command in the $construct() method is the Quit method <url> which returns an URL to the clients browser. See the nex section for further details.
77
Chapter 1Developing Web Applications If you prefix it with http:// or https://, the users browser will be redirected to the specified URL. For example,
Quit method http://www.myhost.com/myfile.html
If you do not prefix the URL as above, the users browser will be redirected to the URL http://<web server address><url>. For example, if your web server is www.myhost.com
Quit method /omnishtml/00000001/myfile.html
If you do generate dynamic HTML files, perhaps by printing reports to HTML, you can use the oDirClean object to periodically check for expired files, and delete them. The HTML report task wizard contains an example of how to do this. You should also note that if you are generating new output for each request, you need to use a different file name or folder for each request. The oDirClean object provides a mechanism which allows this. Quit method <data> $construct() can generate content directly in memory, and return that content to the user. The content can be of any content type supported by a browser, typically HTML, or perhaps a JPEG image. You build the content in either an Omnis character or binary variable. The content must start with the text content-type:. This differentiates the data from a <url> or <error> (the other possible returns from $construct). The syntax of the data in the variable is: HTTP headers starting with content-type: and separated by carriage returnlinefeed pairs. There must also be a content-length header. An empty line terminated by a carriage return-linefeed pair. The content, for example HTML or JPEG data, the length of which must match that specified by the content-length header.
For example:
Begin text block Text: Content-type: text/html (Carriage return,Linefeed) Text: Content-length: 12 (Carriage return,Linefeed) Text: (Carriage return,Linefeed) Text: Some content End text block Get text block iReturn Quit method iReturn
78
Ultra-thin Omnis If you want to return binary content, you can build up the HTTP headers in a character variable, and then use the bytecon() function to combine the character variable and the binary content, storing the result in a binary variable. You can return the result as the return value of Quit method. In addition to the content type and length headers, you can specify other HTTP headers if you wish. However, note that Omnis will automatically generate Expires: and Pragma: nocache headers, so you should not generate these. The following extract of code is from the Omnis store (on www.omnis.net) which uses the Omnis Server to present the user with a store front containing many different HTML forms for logging in, choosing products, and so on, and heavily uses remote tasks to process user requests and compose HTML on-the-fly to display in the clients browser.
; $create_rtOrder1 method for composing the store login screen ; do some preparation... Begin text block Text: <html> (Platform newline) Text: (Platform newline) Text: <head> (Platform newline) Text: <title>Omnis Store - Login</title> (Platform newline) Do method getCSSHeader Do method getJSHelpHeader Do method getHeader (kTrue) ;; kTrue - wide table Text: <td width="262" ><span class="titletext">Login to the Omnis Store</span></td> (Platform newline) Text: <td width="220"></td> (Platform newline) Text: </tr> (Platform newline) Text: <tr> (Platform newline) Text: <td width="500" colspan="3"><span class="bodytext"> (Platform newline) Text: The Omnis Store lets you purchase the Omnis Studio rapid application (Platform newline) Text: development environment. Ordering is easy, just follow the step by step process.</span></td> (Platform newline) Text: </tr> (Platform newline) Text: <tr> (Platform newline) Text: <td width="500" colspan="3"> </td> (Platform newline) Text: </tr> (Platform newline) Text: <tr> (Platform newline) Text: <td width="500" colspan="3"><table border="0" width="100%" cellspacing="0" cellpadding="0"> (Platform newline) Text: <tr> (Platform newline)
79
The above code gives you some idea of how you can use the Text: command to build up complete HTML files and pass them back to the client. Note you can use Omnis variables enclosed in square brackets to fill in parameter values for form objects, such as:
<input type="hidden" name="OmnisServer" value="[iServerPort]">
80
Ultra-thin Omnis Quit method <error> $construct() can return an error to the browser. To do this, you use Quit method nnn The Error message, where nnn is a three digit error code followed by a single space before the error text.
HTTP Headers
When a request arrives at the web server from an HTML form, there are some HTTP headers sent from the client that may be of interest to the remote task instance. These include Cookie: and Referer. (Note that a discussion of how the various HTTP heade rs work is beyond the scope of this document; there are many good sources of information on the Web). You can gain access to these parameters using the following mechanism. In your HTML form, include an empty parameter with the name HTTP_<header name>, for example, HTTP_COOKIE. This is an instruction to the Omnis web server plug-in, telling it to insert the value of the corresponding HTTP header into the form parameter. This means that when $construct() runs, there is a column HTTP_<header name> in the row variable parameter, and its value is the value of the HTTP header. Note that the header value can be empty if it is either not present, or not available to the Omnis web server plug-in.
Each time Omnis receives a request from an HTML form, its default behavior is to destruct the remote task instance after returning the result. You can prevent this behavior, by implementing the $canclose method for the remote task instance, and returning kFalse if the task is to stay open. The remote task instance has a property $connectionid, which identifies the particular Omnis web client connection. The data you return to the user must contain $connectionid, so that the next request to the Omnis Server addresses the remote task instance. Typically, you return a new HTML form to the user. This must contain a parameter ConnectionID which contains the value of $connectionid.
evPost events
When an HTML form request arrives at the Omnis Server, Omnis looks for the ConnectionID parameter. If there is none, processing proceeds in the usual manner, calling $construct() for a new remote task instance. If there is a ConnectionID parameter, Omnis 81
Chapter 1Developing Web Applications tries to locate the existing remote task instance. If it is no longer present, Omnis returns an error to the user. Otherwise, Omnis sends an evPost event to the $event() method of the remote task instance. evPost works in exactly the same way as $construct(). In other words, there is a parameter which is a row variable containing the HTML form parameters, HTTP header processing occurs for the parameters, and the result is one of the three alternatives allowed for the result of $construct(). The only difference is that the parameters and return value are handled using event parameters. Event parameter pPostData is a row variable containing the form parameters from the client, and you use the field reference event parameter pPostResult to return the result to the client. After each call to evPost, Omnis calls $canclose, to see if the remote task instance can now be closed.
and use the file=type attribute to identify files to be uploaded. For example:
<FORM method="POST" action="/omnis_apache" enctype="multipart/form-data" accept-charset="utf-8"> <input type="hidden" name="OmnisServer" value="3012"> <input type="hidden" name="OmnisLibrary" value="LIB"> <input type="hidden" name="OmnisClass" value="rt"> <input type="text" name="test"> <input type="file" filename="myfilename" name="fileparam"> <input type="submit" value="Send"> </FORM>
Note that the get method restricts form data set values to ASCII characters. Only the post method (with enctype="multipart/form-data") will cover the entire character set. The form parameters are passed to the remote task using a row variable. Parameters without the filename attribute behave as in previous versions, that is, their contents is passed to the row variable. Parameters with the filename attribute are passed to the remote task via a column in the row variable, called MultiPartFileList. This column is a list, with a row for each filename parameter. The list has seven columns:
82
Direct Client Connections Column ParamName ReceivedFileName DataLength IsText CharData BinData TempFilePath Description the name of the filename parameter the pathname of the file as it was specified on the client machine the length of the file data in bytes if the length of the file is less than or equal to 16384 bytes, the data is in one of the following two cols, depending on the value of IsText if IsText is kTrue, this contains the character data read from the file. if IsText is kFalse, this contains the binary data read from the file. if the length of the file is greater than 16384 bytes, TempFilePath contains the pathname of a temporary file containing the file data; the temporary file is deleted after the remote task has returned from its $construct()
83
Chapter 1Developing Web Applications is the domain name or the IP address of the computer on which Omnis Studio is running. This is often 127.0.0.1 for your own local machine, but will be configured using a different address or server name on a remote server.
<Server>
is the port number which has been set in $serverport of Omnis Studio; this is 5912 by default, but you can change it to anything you wish, in the range 1-32767. The $serverport property is an Omnis preference ($root.$prefs).
<Serverport>
To try this out, create a library called "DirectHTTP" and add a remote task called "rtDirectHTTP". Then insert the following code into the $construct() method of the remote task:
; $construct() method ; create the following variables ; Parameter var: pParams (Row) ; Local vars: fullhtml (Char 100000000) & html (Char 100000000) Begin text block Text: <html> (Carriage return,Linefeed) Text: <body bgcolor="FFFFFF"> (Carriage return,Linefeed) Text: <title>Hello [pParams.User] </title> (Carriage return,Linefeed) Text: <H1>Hello [pParams.User] </H1> (Carriage return,Linefeed) Text: <a href="javascript:history.go(-1);">Go back</a> (Carriage return,Linefeed) Text: </BODY> (Carriage return,Linefeed) Text: </html> (Carriage return,Linefeed) End text block Get text block html Calculate fullhtml as con('content-type: text/html',chr(13,10),'content-length: ',len(html),chr(13,10,13,10),html) Quit method fullhtml
The Remote task can be called within an HTML form with the following source text:
<html> <form action="http://127.0.0.1:5912/ultra" method="Get"> What is your name? <input type="Text" name="User" size="30" maxlength="50"></br></br> <input type="Submit" name="Send" value="Send"> <input type="hidden" name="OmnisLibrary" value="DirectHTTP"> <input type="hidden" name="OmnisClass" value="rtDirectHTTP"> </form> </html>
You must change the IP address and the port according to your configuration, although the IP address and port number given above are the default values. 84
Direct Client Connections Then open the HTML form in a browser, enter a name in the field, and click Send. This will call the $construct method in the remote task "rtDirectHTTP", passing a parameter called "User" to it, which will contain the text you entered in the form. The full http call is like this:
http://127.0.0.1:5912/ultra?User=Username&Send=Send& OmnisLibrary=DirectHTTP&OmnisClass=rtDirectHTTP
The remote task processes the form values (and performs whatever other functions you like), and returns standard HTML text that is displayed in the browser.
85
Introduction
Computing is becoming more mobile with laptops and other handheld devices now outselling traditional desktop computers. The leading growth area in the handheld market is for so-called Smartphones, which have all the familiar features of mobile phones together with extended features like WiFi connectivity, satellite positioning and support for professional office applications like email, word processing, and spreadsheets. These mobile devices are becoming the must-have device for most business people, allowing them to communicate while out of the office, to have access to critical data, and to organize their work and family life more flexibly. In Omnis Studio 5, you can take advantage of this mobile revolution, by extending your new and existing Omnis applications to support these new mobile platforms and devices. Combined with all the other features in Studio 5, such as support for multiple languages (Studio 5 fully supports Unicode text and data), you can now reach new customers, in new markets, giving you greater success for your Omnis applications.
86
87
Make sure your library is selected in the Studio Browser, then click on the New Class option Click on the Windows Mobile option, name the class and press Return
The remote form created using this option is a standard remote form except that the $screensize property has been set to kSSZwindowsMobile240x320Portrait. In all other respects the remote form can be treated in exactly the same way as any other remote form. You can add fields and other web components to the form, and, if required, you can set the $screensize property to kSSZDesktop and rearrange the fields for the web version of the form. In this case, the same fields and instance variables are used for the different layouts of the remote form.
88
Creating Mobile Forms kSSZwindowsMobile320x320 For mobile devices with screens 320 x 320 px at 96dpi kSSZwindowsMobile480x800Portrait | kSSZwindowsMobile480x800Landscape For mobile devices with screens 480 x 800 px at 96dpi in Portrait/ Landscape orientation kSSZDesktop is for desktop (non-mobile) clients, that is, remote forms running in a desktop based web browser, as in previous versions of Omnis. The other sizes are for the Portrait and Landscape orientations of mobile devices with various screen sizes; the commonest screen size for smartphones is 240 x 320 pixels. The remote form stores an array of values for the left, top, width and height values for the form itself, and all of its objects, for each of the supported screen sizes. When you add an object to the class (either at design time, or at runtime using the notation), the coordinates are stored for the current value of $screensize. Obviously at this point, coordinates for other screen sizes are not set, so if you change $screensize, the coordinates returned will be obtained as follows: If the screen size has an opposite orientation (portrait/landscape), and the values are set for that orientation, use those values. If not, use the coordinates for the first screen size in the order of the list above that has values set. Similarly, if you change class object coordinates (either at design time or by using the notation), the values affected are for the current value of $screensize. When you open the form in design mode, the appearance of the design mode window depends on the current setting of $screensize. So for kSSZDesktop, the remote form will be displayed as in previous versions of Omnis Studio. For the Mobile screen sizes, the design window is of a fixed size, showing you the space available on the device, together with the menu and title bar areas of the Windows Mobile device screen.
Chapter 2Developing Mobile Applications these criteria for setting $width and $height, and assuming the title bar and menu bar are enabled, you can use the following coordinates for the supported screen sizes. Settings for remote form $screensize / orientation kSSZwindowsMobile240x320Portrait kSSZwindowsMobile240x320Landscape kSSZwindowsMobile240x240 kSSZwindowsMobile320x320 kSSZwindowsMobile480x800Portrait kSSZwindowsMobile480x800Landscape $width 240 320 240 320 480 800 $height 268 188 188 268 748 428
In addition, if you have set the $effect property of the remote form to any effect other than kBorderNone, you must subtract a further 2 pixels from the above coordinates to allow for a 1 pixel border around the form. When the client loads the remote form on the device, it takes the physical screen size of the device, and for rectangular screens it works out the coordinates for both portrait and landscape orientations. The client then looks at the width and the height of the form for each orientation. If the width and height of the form are different, the client will choose the appropriate form orientation. If the width and height of the form are the same, it treats the form as only having a single orientation, and the form will appear not to change when you flip the orientation of the mobile device.
Screen Events
When constructing a form, the Omnis Mobile Client uses the most appropriate screen size and orientation stored with the form, for the current screen size and orientation of the device. If the user swaps from portrait to landscape, or back again, the Omnis Mobile Client repositions the controls automatically, using the coordinates the new orientation stored in the remote form (assuming you have added a layout for each orientation). If for example, the user switches to landscape orientation, and you havent added a layout for this orientation to the form, the portrait layout is used by default. When the orientation changes, Omnis sends an evScreenOrientationChanged event to the top remote form. This allows the remote form to adjust the coordinates of any dynamically added objects. In addition, evFormToTop also receives the pScreenSize event parameter, allowing other forms to make adjustments if necessary when they come to the top. If you want to use any screen events in your code, such as evScreenOrientationChanged, you have to enable the events in the $events property of the remote form.
90
Connect your mobile device and development PC using a USB cable or cradle Check that the device can use the PCs Internet connection, for example, by running Mobile IE on the device Click on Studio 5.x in the Studio Browser and click Prefs to open the Property Manager In the Omnis preferences, click on the $webbrowser property and set it to Windows Mobile by clicking the button; wm: will be added to the text box which is a shortcut for the Windows Mobile client Right-click on your remote form or press Ctrl-T to open your form on the mobile device
When you press Ctrl-T, Omnis checks to see if the client is present and up-to-date on your mobile device, and if not, it installs the client automatically. Omnis also checks individual components within the form and updates them if required via the Omnis Component Manager. From there on, whenever you test the remote form from within the IDE, the form will open on your mobile device. You can change the form as much as you like and continue to test it using Ctrl-T.
Troubleshooting
If, for some reason, you have the Omnis Mobile Client (omwebcli) already running on your mobile device you may get an error when you try to open another instance. You need to open the Task Manager on your mobile device and stop the omwebcli application. To do this, tap on Start, then Settings, select the System tab, tap on the Task manager, check the Omnis Studio option and tap on Stop Selected. This applies to Windows Mobile 6.1; so the procedure for accessing the Task Manager for version 6.0 and 5.0 will be different.
91
92
Configuring the Mobile Client The WindowClass name attribute uniquely identifies the client program to the Windows Mobile operating system. This ensures that only one copy of the program with this class exists. The disable attribute of the TitleBar parameter can be set to yes, in order to remove the Windows Mobile title bar. The text attribute gives the application a name displayed on the device, which if omitted, defaults to Omnis Studio. The candefault attribute of the MenuBar parameter can be set to no if you do not want the client to provide a default menu on the Windows Mobile menu bar. The Application name is any name you want to give the Application entry in the configuration file, it can also have a desc. The ServerType unicode parameter should always be set to Yes. Webserver parameters The url and script parameters specify the web server url and location of the Omnis web server plug-in The OmnisServer address, library and class parameters specify the port number or IP address:port of the Omnis Server, the name of your Omnis library, and the remote form class name; these parameters are the same as the Web Client plug-in properties as in previous versions of Omnis. Note that the OmnisServer address attribute can be prefixed by an IP address, even when the WebServer url and script are empty (as they are for test form): this allows the client to connect directly to Omnis running on the PC when testing the form. The WebServerURL should be a valid URL otherwise the Omnis Server may hang. The URL should not include a trailing forward slash / since this may also cause the Omnis Server to hang. You can specify up to 9 parameters using Parameter tags to pass to the $construct() method of the remote task inside the Omnis application.
Chapter 2Developing Mobile Applications In addition to the client DLLs, you must also add the file omniswm.exe to the control manager data file.
Font table
The font table #WMWFONTS contains the fonts to be used for remote forms displayed in Windows Mobile; note that there is no Windows Mobile report font table, since Omnis reports are not possible on mobile devices. There is a column in the font table editor for Windows Mobile fonts. You can specify fonts for Desktop and Windows Mobile platforms, as follows: Desktop platforms For desktop platforms, the combo box list is either populated with the fonts available for the current platform, or a hard-coded list for other platforms (actually obtained from the resources used to initialize a new font table). Windows Mobile The combo box list for Windows Mobile is either hard-coded, or if possible, when running on Win32, Omnis will obtain the list of fonts for Windows Mobile from the device. This may result in Omnis attempting to install the client on the device: see the test form section for more details on client installation.
94
Style table
There is a style platform, kWindowsMobile, used for remote forms running on Windows Mobile. The initial values in kWindowsMobile are copied from kWindows.
Design DPI
The library property $designdpi has a fourth entry, which is the design DPI to be used for Windows Mobile. This defaults to 96, and for most purposes you wont need to change this value. Note that the scaling for 192dpi devices is not related to this property, rather the Omnis Mobile Client itself does the scaling to 192dpi automatically.
Scrollbars
The Omnis Mobile Client adds scrollbars to its client area automatically, if they are required to access all of the form. You should therefore avoid enabling scrollbars ($horzscroll and $vertscroll) for the remote form.
Keyboard Interface
Windows Mobile devices typically have only a SIP (Software Input Panel) accessed by the central button in the menu bar, and a few navigation keys. Left, right, up and down arrow keys perform tabs if the current context of the form control is appropriate, e.g. pressing up arrow when a list is at line one will perform a shift tab. In addition, the center button of the arrow keypad can be used to carry out selection actions, e.g. check a check box.
Control Appearance
Remote form fields and other controls generally have the correct appearance for Windows Mobile. This works in a similar manner to other platforms, where the theme or other property needs to be set to a specific value to obtain the standard system appearance. 95
Chapter 2Developing Mobile Applications However, the Formtbar component (tab bar with square tabs) has the standard Windows Mobile appearance.
Formflds
There is a new checkbox list control in the formflds component package. This is available on desktop as well as mobile platforms. The $statecolumn property works in a similar way to the fat client checkbox list. The headed list now supports $showcolumnlines and $linehtextra properties. This change applies on desktop as well as mobile platforms.
Hyplinks
The Hyplinks control cannot track while the mouse is over it on Windows Mobile, because there is no mouse pointer to move around. When you click on the link it highlights differently on Windows Mobile.
Unsupported Controls
The following controls are not available for Windows Mobile: Formhpic, Formroll, Formtran because they are too reliant on mouse tracking when the mouse is not pressed Formport because this is not useful on a mobile device Formpri because there is no printing API Formqt3 because there is no QuickTime API
96
Deployment
The Omnis Mobile Client (omwebcli) is packaged as a CAB file and is installed on your mobile device automatically when you test your remote forms during development (note it is placed in the \Program Files\omwebcli folder for development). For deployment, you need to create your own CAB file containing the Omnis Mobile Client and your configuration files. End users need to download your CAB file and run it on their mobile device. The CAB file should install the Omnis Mobile Client and other files into a subfolder of the \Program Files\<your-app-name> folder.
97
Chapter 2Developing Mobile Applications The parameters that relate to the Omnis Server (e.g. Omnis Server, Omnis Library, etc.) are identical to the parameters you set in your XML config file for your Mobile Client application during development or testing. The following options can be set in the Windows Mobile Deployment window: Load Settings button The Load Settings button allows you to load the settings from a CAB file you have previously created with this tool. Company name Your company name, which the user will see on their device. Abbreviated app name the name for your mobile application used on the client; up to 8 characters Programs folder app name the name used for the Programs folder shortcut for your mobile application Program icon the Windows icon file (.ico) for your client application. The icon file must contain icons for 16x16, 32x32, 48x48 formats. If omitted the Omnis icon is used. Window class name The class name for the client application window. This must be unique for the entire Windows Mobile system on the client device. Therefore, you are advised to use a combination of your company and application name to create a unique class name. You cannot use TIGERLOGICCORP_OMNISWM as it it reserved. Application title The title used in the client application window. Show title bar Displays the title bar in your client application window. Allow default menu If checked, the right menu button will use the default Omnis menu if you do not supply your own right menu Unicode server Specifies the Omnis server should be Unicode compatible; leave this checked since all Studio 5 servers are Unicode compatible. Web server URL The URL or server location of the Web Server through which your mobile client application connects to the Omnis Server; the URL must be a valid URL and should not include a trailing / slash, otherwise the Omnis Server may hang Web server script The path or location of the Omnis Web Server plug-in, usually located in your cgi-bin or scripts folder. 98
Deployment Omnis Server The port number or combination of IP-address and port number (ipaddress:port) of the Omnis Server containing your Omnis mobile application. Omnis Library The name of the Omnis library containing your Omnis mobile application. Omnis class The name of the remote form in your Omnis mobile application; this can be the name of your applications initial remote form if you have more than one remote form. Busy image DAT file The image to be used during communication between the client device and the server application. This defaults to a TigerLogic animation but can be changed using the Image Compiler available under the Web Client Tools option. Waiting for data connection message The message for when the application is waiting for a data connection. Parameters List of up to 9 parameters and their values that you can send to the $construct() method in the remote task in your Omnis application.
99
100
SSL Security
SSL Security
The external commands in Omnis Studio that allow low-level web communications have been enhanced to allow support for secure Internet-based connections using Secure Sockets Layer (SSL) technology. The FTP, HTTP, SMTP, POP3, and IMAP client commands that establish a connection to a server now allow you to control if and how a secure connection is used. The commands which allow secure connections are: FTPConnect HTTPGet HTTPOpen HTTPPost HTTPSetProxyServer IMAPConnect (new) POP3Connect POP3Recv POP3Stat SMTPSend
Two new parameters, called Secure and Verify, have been added to these commands to support secure connections. The new parameters behave as follows: Secure is an optional Boolean parameter which indicates if a secure connection is required to the server. Pass kFalse for non-secure (the default). Pass kTrue (value 1) for a secure connection; this enables the Verify option. In addition, you can pass value 2 to some of the commands to enable specific types of authentication. To use a secure connection, OpenSSL must be installed on the client system: see below.
101
Chapter 3Web Communications Verify is an optional Boolean parameter which is only significant when Secure is not kFalse. When Verify is kTrue, the command instructs OpenSSL to verify the server's identity using its certificate; if the verification fails, the connection will not be established. You can pass Verify as kFalse, to turn off the verification; in this case, the connection will still be encrypted, but there is a chance the server is an impostor. For example, the FTPConnect commands allows you to establish a secure connection to the specified FTP server; the full syntax of the command is:
FTPConnect ( serveraddr, username, password [,port, errorprotocoltext, secure {Default zero insecure;1 secure;2 use AUTH TLS}, verify {Default kTrue}]) Returns socket
where Secure is an optional Boolean parameter which indicates if a secure connection is required to the server. Pass kTrue for a secure connection. If you pass secure with the value 2, the connection is initially not secure, but after the initial exchange with the server, FTPConnect issues an AUTH TLS FTP command to make the connection secure if the server supports it (see RFC 4217 for details), followed by further commands necessary to set up the secure connection. Authentication occurs after a successful AUTH TLS command. Note that if you use either of the secure options, all data connections are also secure, and all data transfer uses passive FTP. See the Omnis Command Reference manual for full details about each updated web command and how to enable secure connections.
OpenSSL
Support for secure connections is enabled using the open source library called OpenSSL, which must be available on the client system. This is installed and enabled on Mac OS X and most Linux distributions by default. For Windows however, you or your end-users need to download and install the OpenSSL binaries, which are available from the OpenSSL organization at: http://www.openssl.org/related/binaries.html Note: The OpenSSL toolkit is licensed under an Apache-style licence, which means that you are free to use it for commercial and non-commercial purposes, but you must comply with certain license or legal conditions. See the OpenSSL website for further details.
102
IMAP
IMAP
There are a number of new external commands to support communications with IMAP mail servers. The new IMAP commands can use a secure connection. The new commands are prefixed with the letters IMAP and are summarized below, but are described in more detail in the Omnis Command Reference manual or the Omnis Help (F1). Command IMAPCheck Description Sends a CHECK command to the IMAP server which requests a checkpoint of the currently selected mailbox. You must select a mailbox using IMAPSelectMailbox before using this command Establishes a connection with an IMAP server, which must support IMAP4rev1; requires a server name, username, and password; if successful, it returns the socket opened which can be used with the other IMAP commands; you must call IMAPDisconnect when finished with the IMAP server Copies a message from the currently selected mailbox to another mailbox, using the UID COPY command. You must select a mailbox using IMAPSelectMailbox before using this command Creates a new mailbox on the IMAP server; requires a socket number created using IMAPConnect and a mailbox name Deletes a mailbox and the messages it contains; requires a socket number and a mailbox name Closes a connection to an IMAP server; requires a socket number Permanently removes all messages that have the \Deleted flag set from the currently selected mailbox; requires a socket number Returns a list of a subset of mailbox names from the complete set of all names available to the client by sending a LIST command to the IMAP server; requires socket, refname, mailboxname, list; the list must be predefined containing 7 columns Gets a list of messages in mailbox previously selected using IMAPSelectMailbox; requires socket, list; the list must be predefined containing 9 columns 103
IMAPConnect
IMAPCopyMessage
IMAPCreateMailbox
IMAPListMailboxes
IMAPListMessages
Chapter 3Web Communications Command IMAPListSubscribedMailboxes Description Returns a list of a subset of mailbox names from the complete set of all subscribed names available to the client by sending an LSUB command to the IMAP server; requires socket, refname, mailboxname, list; the list must be predefined containing 7 columns Sends a NOOP command to the IMAP server; you can use the command to poll the server to get status updates via untagged responses returned to the responselist parameter if present Receives the headers for a specified message in the currently selected mailbox; you can pass the received headers to the MailSplit command to parse them; requires socket, messageuid, headers Receives a specified message in the currently selected mailbox; you can pass the received message to the MailSplit command to parse it; requires socket, messageuid, headers Renames a mailbox; requires socket, oldmailboxname, newmailboxname Makes a mailbox the currently selected mailbox, allowing other IMAP commands to operate; requires socket, mailboxname, messages, recent, uidnext, uidvalidity, unseen Adds or removes flags for a message in the currently selected mailbox; requires socket and messageuid, plus the values for the flags: answered, deleted, draft, flagged, seen, where each flag value can be kTrue (adds the flag), kFalse (removes the flag) or kUnknown (leaves the flag unchanged) Adds a specified mailbox to the server's set of "active" or "subscribed" mailboxes as returned by IMAPListSubscribedMailboxes by issuing a SUBSCRIBE to the server; requires socket and mailboxname Removes a specified mailbox from the server's set of "active" or "subscribed" mailboxes as returned by IMAPListSubscribedMailboxes by issuing an UNSUBSCRIBE command to the server; requires socket and mailboxname
IMAPNoOp
IMAPRecvHeaders
IMAPRecvMessage
IMAPRenameMailbox IMAPSelectMailbox
IMAPSetMessageFlags
IMAPSubscribeMailbox
IMAPUnsubscribeMailbox
104
Multi-threading
Multi-threading
The Web commands are now multi-threaded, when running on a multi-threaded Omnis Server. The Web commands allow another thread to execute in the multi-threaded server while the current command runs. Note that the same socket cannot safely be used concurrently by more than one thread.
Email Headers
In addition to the above enhancements, the SMTPSend and MailSplit commands now support international characters in email headers (using RFC2047). See the updated commands in the Omnis Command Reference manual or the Omnis Help (F1).
105
Chart Types
XY Charts
XY charts can be one of several different minor types or subtypes.
Bar charts
Bar charts represent individual amounts, or compare individual amounts; you can change the graph orientation to show horizontal bars. There are several subtypes which you can select, including Line, Scatter, Area, and Box whisker.
106
Chart Types
Line charts
Line charts emphasize the rate of change rather than individual amounts.
Scatter charts
Scatter charts show the relationship of different groups of numerical data, and plot the data as xy coordinates.
Area charts
Area charts emphasize the amount or magnitude of change rather than the rate of change.
107
High/Low/Open/Close charts
High/Low/Open/Close (HLOC) charts are used to represent financial data; this type uses four data items to represent each element.
Candlestick charts
Candlestick charts are used to represent financial data; this type uses four data items to represent each element.
Pie Charts
The data in a pie chart is represented as sections, or slices of a pie. There are no minor types for this chart type, but pies have numerous visual effects.
108
Chart Types
Polar Charts
Polar charts represent data points on a radial axis with the values represented as the distance from the center; four minor types are available.
Polar Area
Polar Line
See later in this section for a description of how to draw the 2 graphs above
109
Meter Charts
Numeric amounts or measurements can be shown as a meter or gauge; angular (or dial) or linear styles are available.
A meter chart with the Linear subtype. In addition to changing the orientation of meter charts, you can add extra pointers for showing multiple data points, and colored zones to mark the scale or dial, for example. A Meter chart with Angular subtype providing a dial or gauge effect, shown here with rounded frame
110
The following common properties are found under the Prefs tab in the Property Manager. Property Name $deviceindependent Data Type Boolean Description If True report printing creates a device independent bitmap (DIB), used for printing in the Web client and cross-platform applications The path and folder name where the Graph component will search for images (on Mac OS X the property uses a standard HFS colonseparated pathname); if empty (the default), the component searches in the Omnis\Icons folder The legend background color The legend background effect: kG2colorSolid, kG2colorMetal, or kG2colorNotUsed The legend position: kG2legendNone, kG2legendLeft, kG2legendRight, kG2legendTop, kG2legendBottom, kG2legendManual ($legendx & legendy apply) The legend text color If True the legend is drawn vertically The X Position of the legend (only if $legendpos is kG2legendManual) The Y Position of the legend (only if $legendpos is kG2legendManual) The graph type, a constant: kG2xy, kG2pie, kG2polar, or kG2meter Minor type for XY, Polar, or Meter graphs only; there are no minor types for Pie charts If True the graph frame has rounded corners
$imagesearchpath
Char
Boolean
111
Chapter 4Omnis Graphs The following common properties are found under the Custom tab in the Property Manager for all graph types. Property Name $3d $backgroundborder $backgroundcolor $backgroundeffect $backgroundraised $columnheadings $labelfont Data Type Boolean RGB Color RGB Color Constant Integer List or row Character Description If true the graph is 3d The background border color The background color kG2colorSolid or kG2colorMetal The degree to which the background is raised (if positive) or sunken (if negative); 0 is not raised A list or row containing the column headings of the list. Name of the font for the graph label (appears under the main title); must be a font in the Omnis/fonts folder; see the Labels section later in this manual The main title of the graph The offset width for the graph Additional x offset for the graph Additional y offset for the graph Name of the font for the graph title; must be a font in the Omnis/fonts folder; see the Labels section later in this manual Height of the font for the graph title The path/filename of an image; leave blank for no image The angle of rotation, -1 is the default The title displayed on the X-Axis angle of rotation for X axis label, -1 is the default angle of rotation for Y2 axis label, -1 is the default angle of rotation for Y axis label, -1 is the default The title displayed on the Y axis
112
kG2polar
$minorpolartype
kG2meter kG2pie
When you have placed a Graph2 component on your window, you can set its $majortype in the Property Manager and select the appropriate minor type. As you change the major and minor type of the graph, several properties will be shown or hidden according to the graph type selected.
113
$addtext()
None
$addzone()
None
$convdate()
Integer
$dispose()
None
$findobject()
$formatvalue()
Char
$getcolors()
List
114
Common Graph Methods Method Name $getmainlayer() $redraw() $setcolors() Returns Object None kTrue for success None Description Returns the main layer object Redraws the graph $setcolors(lPaletteList) sets the colors for the graph using the specified list of RGB colors returned using $getcolors() $setlinearscale(iAxisid, nLowerlimit, nUpperlimit, [,nMajortick, nMinortick, lLabellist]) sets the linear scale for the specified axis $setlogscale(iAxisid, [cFormatstringORLowerlimit, nUpperlimit, ,cMajortick, nMinortick, nLabellist]) sets the log scale for the specified axis $snapshot([iWidth, iHeight]) captures a snapshot of the graph with the specified width & height in pixels; omitting the parameters will return an image with the same dimensions as the current graph; the $snapshot() method causes the evPrelayout event to occur which allows you to add layers; see Graph Layers section below
$setlinearscale()
$setlogscale()
None
$snapshot()
Picture
The following method is available for the non-visual graph object, that is, object variables based on the Graph2 object. Method Name $prelayout() Returns None Description Available for object variables based on Graph2 component only; called during construction of the graph enabling layers to be added; see Graph Layers section below
115
XY Charts
The XY chart type has several subtypes, which all share the following properties and methods.
XY chart properties
Property Name $datacombine Data Type Constant Description The combine method of the data for Bar, Area, and Line graphs, a constant: kG2dataSide, kG2dataStack, kG2dataOverlay, kG2dataPercentage; these constants can also be used in the $addarealayer(), $addbarlayer(), and $addlinelayer() XY chart methods Specifies the depth of a 3d XY chart; the default is 1 but can be set to a positive integer value to specify a custom depth which is useful for 3d line and area graphs with multiple series The horizontal grid color The minor type of a kG2xy graph; can be one of the following: kG2xyBar, kG2xyLine, kG2xyScatter, kG2xyArea, kG2xyBoxWhisker, kG2xyHLOC, kG2xyCandleStick The additional offset height of the graph The subtitle of the graph if true the X & Y axis are swapped if true the X axis is to be displayed on the top Width of the X axis in pixels Y2 axis title if true the Y axis is to be displayed on the right Width of the Y axis in pixels The effect for all layers, a constant: kG2effectNone, kG2effectGlass, kG2effectSoftLight The alignment or direction for the effect for all layers, as set by $layereffect; a constant: kG2alignTop, kG2alignBottom, kG2alignLeft, kG2alignCenter, kG2alignRight
$3ddepth
Integer
$hgridcolor $minorxytype
$layereffectalign
Constant
116
XY Charts Property Name $plotareacolorend $plotareacolorstart $vgridcolor Data Type RGB Color RGB Color RGB Color Description The end gradient color for the plot area The start gradient color for the plot area The vertical grid color
XY chart methods
All the following methods can only be executed during the evPreLayout event; see below for details. Method Name $addarealayer() $addbarlayer() $addboxwhiskerlayer() $addcandlesticklayer() $addhloclayer() $addlinelayer() $addscatterlayer() Returns Integer Integer Integer Integer Integer Integer Integer Description $addarealayer(pList [,iCombineType]) adds an area layer to the graph; pList is the area data* $addbarlayer(pList [,iCombineType]) adds a bar layer to the graph; pList is the bar data* $addboxwhiskerlayer(pList) adds a box whisker layer to the graph; pList is the box whisker data* $addcandlesticklayer(pList) adds candlestick layer to the graph; pList is the candlestick data* $addhloclayer(pList) adds a HLOC layer to the graph; pList is the HLOC data* $addlinelayer(pList [,iCombineType]) adds a line layer to the graph; pList contains the Line data* $addscatterlayer(pList [,pSymbol, pSymbolSize]) adds a scatter layer to the graph.; pList is the scatter data*; pSymbol is an optional symbol type (of type kG2symbolXXX, defaults is kG2symbolSquare); pSymbolSize is the symbol size, default is 10. $addtrendlayer(pList) adds a trend layer to the graph using the data in pList* $getxaxis([bSecondAxis]) returns the x-axis object, or the x2-axis object if bSecondAxis is true; only available during prelayout $getyaxis([bSecondAxis]) returns the y-axis object, or the y2-axis object if bSecondAxis is true; only available during prelayout
$addtrendlayer() $getxaxis()
Integer Object
$getyaxis()
Object
* See appropriate chart section below for the format of the data in pList. In addition, see $datacombine for details of the various data combine types available.
117
The list variable listGraph is specified as the $dataname of the graph field. The above method will create a graph of two groups each with four series:
Note you can use the Omnis 4GL commands to build the list data for the graph, either from an Omnis database, a SQL database, or on-the-fly, such as the following:
Set current Define list Add line to Add line to Add line to Add line to list listGraph {(Name,Sales,Expenses)} list {('Andy',85000,20000)} list {('Sam',80000,15000)} list {('Lisa',92000,34000)} list {('Harry',45000,15000)}
118
XY Charts
Line/Area Charts
The line and area chart in their data representation are very similar to the bar chart. So given the following data:
; define vars listGraph (List), colList (List), Name (Char), and use built-in #vars Do listGraph.$define(Name,#1,#2,#3,#4,#5,#6,#7,#8, #9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20) Do listGraph.$add('Andy',30,28,40,55,75,68, 54,60,50,62,75,65,75,91,60,55,53,35,50,66,56,48,52,65,62) Do listGraph.$add('Liza',48,52,65,62,30,68,54,60, 50,28,40,55,75,62,75,65,75,35,50,66,56,91,60,55,53) ; now build the column headings list Do colList.$define(#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12, #13,#14,#15,#16,#17,#18,#19,#20) Do colList.$add(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
Note the use of the colList list in the portion of code, which can be assigned to the $columnheadings property of the graph field, overriding the normal x-axis variable names. You should set the $majortype and minor type properties ($minorxytype or $minorpolartype) of the graph to specify its type and subtype. The above method will display the following line or area graph:
119
Scatter Charts
Each individual row in the chart list data represents a new plot (or series). The X & Y plot positions are then represented in two columns. Additional columns represent the other groups, so given the following data:
Do Do Do Do Do Do listGraph.$define(Name,#1,#2,#3,#4) listGraph.$add('Pt1',10,130,5,100) listGraph.$add('Pt2',15,150,12,95) listGraph.$add('Pt3',6,80,8,105) listGraph.$add('Pt4',12,110,7,82) listGraph.$add('Pt5',10.5,125,10.5,99)
There are two groups of five series which will result in the following chart:
Note that the symbols used to represent each series are in the order of square, diamond, triangle, right-triangle, left-triangle, inverted triangle, circle, cross, and cross #2.
120
XY Charts
Gantt Charts
You can create Gantt charts using a Box Whisker chart and setting the $swapxy property to kTrue so the bars are displayed horizontally. For Gantt charts you only need to provide two groups of data in your list. The example Graph2 library contains a simple Gantt chart, as follows:
121
Chapter 4Omnis Graphs The following method is executed in the $construct() of the Gantt chart window:
; define inst vars: iGraphList (List), Name (Char) Do iGraphList.$define(Name,#1,#2) Do method $addline ('Market Research',2004,8,16,14) Do method $addline ('Define Specifications',2004,8,30,14) Do method $addline ('Overall Architecture',2004,9,13,14) Do method $addline ('Project Planning',2004,9,20,14) Do method $addline ('Detail Design',2004,9,27,14) Do method $addline ('Software Development',2004,10,4,35) Do method $addline ('Test Plan',2004,10,25,14) Do method $addline ('Testing and QA',2004,11,1,21) Do method $addline ('User documentation',2004,11,8,14)
You can use the $convdate() method to convert a date/time variable to an integer equivalent which can be used in graph data.
122
XY Charts
Candlestick Charts
The candlestick chart is very similar to the HLOC chart and the list data is formatted in the same way. The difference in the graphical representation is that the area between the opening and closing price is shown as a filled rectangle; in the following example a black rectangle indicates that the closing price was lower than the opening price (a bad day). Both examples of the HLOC and Candlestick charts used the same data.
123
Trend Chart
A trend chart allows you to view and compare data values over a given period or within a group. The first column in the data list contains the name of item and the second column onwards contains the data values for the item. A trend chart will contain one line for each row of data in the list.
; iColList is a List var assigned to $columnheadings of the graph object Do lReturnList.$define( lName,#1,#2,#3,#4,#5,#6,#7,#8,#9,#10, #11,#12,#13,#14,#15,#16,#17,#18,#19,#20) Do lReturnList.$add( 0,50,55,47,34,42,49,63,62,73,59, 56,50,64,60,67,67,58,59,73,77) Do iColList.$define( #1,#2,#3,#4,#5,#6,#7,#8,#9,#10, #11,#12,#13,#14,#15,#16,#17,#18,#19,#20) Do iColList.$add(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
124
XY Charts
$datacombine = kG2dataSide: The data sets are shown as individual bars side-by-side (the default for XY bar charts)
$datacombine = kG2dataStack: The data sets are combined by stacking up the bar segments, therefore showing individual amounts in relation to the total amount for the data group
$datacombine = kG2dataOverlay: The data sets are overlayed each other providing a clearer comparison of data than the side-by-side type
$datacombine = kG2dataPercentage shows each individual amount as a percentage of the total for the data group
These different combine types can also be used when adding data layers to a graph using the $addarealayer(), $addbarlayer(), or $addlinelayer() XY chart methods; see the Graph Layers section.
125
Pie Charts
Pie charts have the following properties and methods, in addition to the Common graph properties and methods.
$donutradius
Integer
$drawclockwise $feelercolor $feelerwidth $framecolor $frameon $labelformat $labelpos $labelposon $rotate $shadow $showfeeler $sidelayout $tilt $tilton
Boolean RGB Integer RGB Boolean Character Integer Boolean Number Boolean Boolean Boolean Integer Boolean
126
Pie Charts
Note that some actions on a pie chart are controlled by setting a particular property, such as $tilt; see the previous section for pie chart properties. Note also that you cannot add layers to a pie chart using methods, such as those used on XY and Polar charts.
Pie charts have several properties that allow you to alter the appearance of the chart, such as $tilt and $rotate. These can be used together with a set of sliders to create a dynamic representation of the users data. See the Graph2 example in the Welcome screen when Omnis starts up (click the New Users button on the main Omnis toolbar) the Graph2 example application shows many effects for Pie charts.
127
The code behind the slider can change the appropriate property in the pie chart, such as the following, which allows the user to change the tilt of the pie chart:
; $event method for Tilt slider ; $min and $max of slider component are set to 0 and 100 On evNewValue Calculate $cinst.$objs.GR.$tilt as pNewVal
The following code for a slider component allows the user to change the rotation of the chart.
; $event method for Rotate slider ; $min and $max of slider component are set to 0 and 360 On evNewValue Calculate $cinst.$objs.GR.$rotate as pNewVal
In addition, the $slicemove(iDistance, iSlice) method lets you move or slice out one of the slices in the pie chart. For example, the Slice move slider in the above window has the following method:
; $event method for Slice-move slider ; $min and $max of slider component are set to 0 and 50 On evNewValue Do $cinst.$objs.GR.$slicemove(pNewVal,0,2) ;; items 1 and 3
Using a combination of properties you can create some good effects for Pie charts. The following pie chart uses $sidelayout set to kTrue, a custom $labelformat, and $slicemove is set to slice out the first and the third slices in the chart.
128
Polar Charts
Polar Charts
The Polar chart has the following properties and methods, in addition to the Common graph properties and methods.
129
$addsplinelinelayer()
None
$getradialaxis()
Object
* See appropriate chart section for the format of the data in pList. In addition, see $datacombine for details of the various data combine types available.
130
Note the following properties are set for the chart: $majortype = kG2polar, $minorpolartype = kG2polarArea, $legendpos = kG2legendManual, $legendx & $legendy = 10, $angularlabelson = kTrue, $offsetwidth = 30, $angularcolor = 187,187,255, $radialcolor = 153,153,255, $maintitle = Speed Reliability Test
The second data set is constructed during the evPrelayout event for the graph object and added as a line layer using the $addlinelayer() method.
131
132
Meter Charts
Meter Charts
You can create Linear or Angular (radial) meter charts, and change their appearance using a range of properties and methods. Meter charts have the following properties and methods, in addition to the common graph properties and methods.
$angulardegrees $angularpositionh
Integer Integer
$angularpositionv
Integer
133
$addring()
None
134
Meter Charts The example library uses the above data to create the following chart:
Note that this and the next meter chart has colored zones defined on the scale; these are described on the Adding Colored Zones section. When the minor type is set to kG2meterLinear, the following method:
Do Do Do Do iGraphList.$add(75.35) iGraphList.$add(0) iGraphList.$add(100) iGraphList.$add(10)
Adding Pointers
The standard meter chart represents a single data point, which is shown using the default pointer, but you can add one or more additional pointers to a chart to show other data. You can add extra pointers to a meter chart (angular or linear) using the $addpointer() method, which must be executed during the evPreLayout event for the graph object; see the Graph Layers section for information about evPreLayout. $addpointer(nValue, iColor [,nPointertype]) adds a pointer to an angular or linear meter chart with the specified value and color; this must be done during the evPreLayout event; the pointer type is a number in the range 0-5, as follows:
135
Chapter 4Omnis Graphs 0 1 2 3 4 5 Pencil pointer (the default pointer for linear charts) Diamond pointer (the default pointer for angular charts) Triangular pointer Arrow with square ends Arrow with sharp/pointed ends Line pointer
The different pointer styles are shown in the following linear chart:
136
Meter Charts
Adding Rings
A ring is the region in an Angular chart between two concentric circles. You can add rings to an Angular chart using the $addring() method, which is useful for adding circular borders and backgrounds to a meter; this must be done during the evPreLayout event. $addring(iStartradius, iEndradius, iFillcolor) adds a colored ring to an angular meter with the specified start and end radius in pixels The difference between the start and end radius is, in effect, the width or thickness of the ring in pixels. If you use a start radius of zero, the ring will be drawn starting from the center of the chart face and, depending on the value of the end radius, will draw a circle on the chart with the given radius. The example library demonstrates adding a ring to a radial meter chart, and uses the following method, which is added to the $event() method for the graph window object:
On evPreLayout Do $cinst.$objs.meterGraph.$addring( 173-abs(iBackgroundRaised), 174-abs(iBackgroundRaised), $cinst.$objs.ringColor.$contents) ; etc...
Which produces the following chart; note the ring has been changed to red using the color picker:
In the example library, the start and end radius settings for the $addring() method take account of the raised background, since when the background is raised or inset by any amount, the radius of the meter dial is reduced by the same amount. The color for the ring is
137
Chapter 4Omnis Graphs taken from the color picker, which is returned in the value of the $contents property of the color picker button. A ring must be added to a meter chart during the evPreLayout event, which is triggered following a $dispose() method for the graph object. For example, the method for the color picker in the example library is as follows:
On evClick Do $cinst.$objs.meterGraph.$dispose()
This causes the $event() method for the graph window object to be called and the evPreLayout event is triggered, which in this case runs the method to add the ring.
138
Graph Layers and the Prelayout Event For example, in the case of the High/Low/Open/Close charts, it is quite common in financial applications to draw a line between the open and close points. This can be achieved by adding a line layer during the evPreLayout event using the $addlinelayer() method, as follows:
; $event() method for graph window object ; define var: lineLayer (List) On evPreLayout Do lineLayer.$define(Name,#1,#2,#3) Do lineLayer.$add('',1950,1991,2026) ;; Closing prices Do $cinst.$objs.GraphObj.$addlinelayer(lineLayer, kG2dataOverlay)
Refer to the appropriate layers section for the exact format of the list. The above method will result in the following graph:
When using an object variable based on the Graph2 component you can use the $prelayout() method in the object to add layers in the same way as described above. Caution: A word of warning, evPreLayout events occur during the construction of a graph image which typically happens during the drawing of the graph control. This can make debugging the graph objects $event() method potentially troublesome.
139
For example, using the following method behind the $event() method of the graph object:
; the $event() for the graph object On evGraphClick OK message {Graph Click = // Item Number [pItem] (Name = [pItemname]) // Set Number [pSet] (Name = [pSetname])}
And clicking on the first item in the second set or group of the following graph
You can use the item and set number/name information to drilldown into the data by reformatting the list data and redrawing the graph. Note that pSet and pSetname are not valid for pie charts since they represent a single set of data only.
140
You can return the color palette for a graph by specifying one of the palette constants in the $getcolors([PaletteID]) method. The constants are: kG2paletteDefault, kG2paletteTransparent, or kG2paletteWhiteOnBlack (the latter inverts the black and white colors in the graph). The following method can be used to switch to a transparent color palette for a graph:
; define local var: lColorList (List) Do $cinst.$objs.polarGraph.$getcolors(kG2paletteTransparent) Returns lColorList Do $cinst.$objs.polarGraph.$setcolors(lColorList)
The following method can be used to switch the graph colors back to the default palette, perhaps after having colored individual elements or switching the whole graph palette to transparent or White-on-black:
Do $cinst.$objs.polarGraph.$getcolors(kG2paletteDefault) Returns lColorList Do $cinst.$objs.polarGraph.$setcolors(lColorList)
141
In drawing the sector labels, the graph component will replace "{label}" with the sector name, and "{percent}" with the sector percentage. So the label will be something like:
"ABC (34.56%)"
You can change the sector label format by changing the format string. For example, you can change it to:
"{label}: US${value}K ({percent}%)"
142
Parameter Substitution and Formatting Here is an example method that changes the $labelformat property in a pie chart.
Calculate $cinst.$objs.GROBJ.$labelformat as con("{label} ${value}K",chr(10),"({percent}%)")
For fields that are numbers, dates, or times, the Graph component supports a special syntax in parameter substitution to allow formatting of these values. Please refer to the Number Formatting and Date/Time Formatting sections below for details. The following tables describe the fields available for various chart objects.
143
Chapter 4Omnis Graphs because a stacked bar is composed of multiple data sets. It does not belong to any particular data set and hence does not have a data set name. Parameter x xLabel x2Label value accValue totalValue percent accPercent Description The x value of the data point. The bottom x-axis label of the data point. The top x-axis label of the data point. The value of the data point. The accumulative value of the data point. This is useful for stacked charts, such as stacked bar chart and stacked area chart. The total value of all data points. This is useful for stacked charts, such as stacked bar chart and stacked area chart. The percentage of the data point based on the total value of all data points. The accumulated percentage of the data point based on the total value of all data points. This is useful for stacked charts, such as stacked bar chart and stacked area chart. The data set number to which the data point belongs. The first data set is 1, the second is 2, and so on. The name of the data set to which the data point belongs. The data point number within the data set. The first data point is 1, the second is 2, and so on. The data group number to which the data point belongs. The first data group is 1, the second is 2, and so on. The name of the data group to which the data point belongs. The layer number to which the data point belongs. The first layer is 1, the second is 2, and so on.
144
145
The following method sets the label for the data points in a polar chart.
Do $cinst.$objs.GROBJ.$getmainlayer() Returns lLayer Do lLayer.$setdatalabelformat("({value},{angle})")
Number Formatting
For parameters that are numbers, the Graph component supports a number of formatting options in parameter substitution. For example, if you want a numeric field (value) to have a precision of two digits to the right of the decimal point, use ',' (comma) as the thousand separator, and use '.' (dot) as the decimal point, and you may use (value|2,.). The number 123456.789 will therefore be displayed as 123,456.79.
146
Parameter Substitution and Formatting For numbers, the formatting options are specified using the following syntax:
([param]|[a][b][c][d])
where: Parameter [param] [a] Description The name of the parameter An integer specifying the number of digits to the right of the decimal point. The default is automatic. To use the default, simply skip this parameter. The thousand separator. Should be a non-alphanumeric character (not 0-9, A-Z, a-z). Use '~' for no thousand separater. The decimal point character. The negative sign character. Use '~' for no negative sign character.
You may skip the trailing formatting options if they are needed. For example, (value|2) means formatting the value with two digits to the right, where the thousand separator, decimal point character, and negative sign character are all using the default settings of the chart.
Date/Time Formatting
For parameters that are dates & times, the formatting options can be specified using the following syntax:
([param]|[datetime_format_string])
where [datetime_format_string] must start with an alphabetic character (A-Z or a-z), and may contain any characters except ')'. Certain characters are substituted according to the following table:
Parameter Description
Year in 4 digits (e.g. 2005) Year showing only the least significant 3 digits (e.g. 007 for the year 2007) Year showing only the least significant 2 digits (e.g. 07 for the year 2007) Year showing only the least significant 1 digit (e.g. 7 for the year 2007) Month formatted as its name. The default is to use the first 3 characters of the English month name (Jan, Feb, Mar ...). Month formatted as 2 digits from 01 - 12, with leading zero if necessary. Month formatted using the minimum number of digits from 1 - 12. Day of month formatted as 2 digits from 01 - 31, with leading zero if
147
necessary. d w hh Day of month formatted using the minimum number of digits from 1 - 31. The name of the day of week. The default is to use the first 3 characters of the English day of week name (Sun, Mon, Tue ...). The hour of day formatted as 2 digits, adding leading zero if necessary. The 2 digits will be 00 - 23 if the 'a' option (see below) is not specified, otherwise it will be 00 - 12. The hour of day formatted using the minimum number of digits. The digits will be 0 - 23 if the 'a' option (see below) is not specified, otherwise it will be 0 - 12. The minute formatted as 2 digits from 00 - 59, adding leading zero if necessary. The minute formatted using the minimum number of digits from 00 - 59. The second formatted as 2 digits from 00 - 59, adding leading zero if necessary. The second formatted using the minimum number of digits from 00 - 59. Display either 'am' or 'pm', depending on whether the time is in the morning or afternoon.
nn n ss s a
For example, a parameter substitution format of (value|mm-dd-yyyy) will display a date as something similar to 09-15-2002. A format of (value|dd/mm/yy hh:nn:ss a) will display a date as something similar to 15/09/02 03:04:05 pm.
Font Styles
You can change the style of the text by using special tags. For example, the following code substitutes some of the parameters and formats the fonts using tags:
Calculate $cinst.$objs.GR.$labelformat as con("<*font=timesi.ttf,size=16,color=FF0000*>{label} ${value}K",chr(10), "<*font=arial.ttf,size=12,color=8000*>({percent}%)")
148
Parameter Substitution and Formatting In general, all tags in CDML are enclosed by <* and *>. Attributes within the tags determine the styles of the text following the tags within the same block. If you want to include <* in text without being interpreted as CDML tags, use <<* as the escape sequence. The following font style attributes can be used:
font
The font file name.
size
The font size.
width
The font width. This attribute is used to set the font width and height to different values. If the width and height are the same, use the size attribute.
height
The font height. This attribute is used to set the font width and height to different values. If the width and height are the same, use the size attribute.
color
The text color in hex format.
underline
The line width of the line used to underline the following characters. Set to 0 to disable underline.
Embedding Images
You can embed images in text using the <*img*> tag and the following syntax:
<*img=my_image_file.png*>
You can use the $imagesearchpath property (on the Preference tab) to specify the folder where the Graph component will search for images (on Mac OS X the property uses a standard HFS colon-separated pathname). If you leave the property blank (the default), the component sets the search path to the icons folder in the Studio tree, which means your image file must be located in this folder. Having set the image search path you can use the image file name only in the <*img*> tag. For example, the line:
; set $imagesearchpath to C:\Program Files\RainingData\OS43\images Calculate $cinst.$objs.GR.$labelformat as con( "{label} ${value}K",chr(10), "({percent}%)",chr(10),"<*img= sun_bullet.gif*>")
embeds the image file sun_bullet.gif which is located in the Omnis\images folder.
149
Labels
You can override the default fonts for the main title and labels in a graph by setting the $titlefont and $labelfont properties (found under the Custom tab in the Property Manager). You can specify any true type font (TTF) or True type collection (TTC) that is located in the Fonts folder in the main Omnis folder. If a folder called Fonts does not exist you can create one with this name. If you add fonts to this folder, you have to restart Omnis before the fonts become available in Omnis. The default value is set to (DEFAULT) which means the default font for your system will be used (e.g. Times Roman under Windows). You can adjust the height or size of the main graph title by setting the $titlefontheight property.
150
The following method is contained in the $construct() method of the report class, therefore the method is executed when the report is instantiated, and the graph object is created and transferred to the picture variable before the report is printed. The $snapshot() method is used to capture the graph image and returns it to the picture variable.
151
Note that the graph object will use all the default properties, so if you want to change the appearance, type or subtype of graph, you need to change the appropriate properties of the graph object at runtime using the notation. The above method sets the graph major type and assigns the list variable to the object. The report will look something like the following:
152
The Graph2 example library contains a Remote form example, showing all the main chart types. In this case, the remote form uses an object class based on the Graph2 component and uses $snapshot() to transfer the graph image to a picture field in the remote form. 153
; $event() method for remote form Picture field On evClick Do cGraphObj.$findobject(pMouseX,pMouseY, setno,itemno,setname,itemname) Returns ok ;; true if successful
154
Using Graphs in the Web client The mouse co-ordinates are returned in pMouseX and pMouseY in the evClick event. The $findobject() method uses the mouse co-ordinates to get the setno, itemno, setname, and itemname which contain information about the graph object clicked on. Clicking on the first bar in the second group of the above chart produces this data:
setno = 2, itemno = 1, setname = Expenses, itemname = Andy
You can use the item and set number/name information to drilldown into the data by reformatting the list data and redrawing the graph in the remote form. Note that the Set number and name are not valid for pie charts.
155
Introduction
The .NET Objects component for Omnis Studio allows you to integrate .NET functionality into your Omnis applications. You can create Omnis Objects based on .NET core functionality or third-party class libraries and call their methods in your Omnis code further extending the power and versatility of Omnis Studio. The Omnis .NET Objects component is available for the Microsoft Windows only at present.
156
Software Requirements
Software Requirements
Omnis Studio
To use the Omnis .NET Objects component, you need Omnis Studio 4.3, Studio 5.0 or higher. The component is not supported in older versions of Omnis Studio.
Windows
At present, the .NET Framework is available under Windows only - it is included as part of Windows Vista and Windows 2003 but can be installed for Windows XP. Therefore, the Omnis .NET Objects component is available for the Microsoft Windows only at present.
Windows XP/2000
The Microsoft .NET framework is not part of the standard Windows XP/2000 package so you will need to download it from the Microsoft web site and install it. In addition, you need to install the Win XP Service Pack 2 (SP2) to use the .NET framework. To run Omnis Studio under Windows 2000 you need to install SP4. When you have installed all of these products or updates, you will be able to install and run the Omnis .NET Objects component under Windows XP/2000.
Windows 98/ME
Although the Microsoft .NET framework is supported under Windows 98/ME, Omnis Studio 4.3/5.0 are not supported under Windows 98/ME, therefore the Omnis .NET Objects component is not available for these platforms.
157
Setting up
The Omnis .NET Objects component is installed as part of the standard Development version of Omnis Studio (Windows only). The component itself is comprised of two DLLs: OMDOTNET.DLL The Omnis .NET Objects component is located in the root of your Omnis Studio folder, but must be registered with .NET; see below. OMDNOBJS.DLL This is an Omnis Studio external component and is located in the XCOMP folder within the Omnis Studio development tree.
from a command line prompt (DOS box). If you have sufficient access rights you can run Regasm.exe from the Start>>Run command. Regasm.exe is an application provided with the .NET Framework and you may be required to locate it, if it isnt on your PATH. It normally resides in a folder called Microsoft.NET\Framework\<Version Number> which is held in the operating system folder, such as C:\WINNT or C:\Windows. You should enclose path name to the OMDOTNET.DLL file in quotes, especially if the pathname has spaces in it. For example:
C:\WINNT\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe "C:\Program Files\TigerLogic\OS50\OMDOTNET.DLL"
Failure to have the Microsoft .NET Framework installed or failing to register OMDOTNET.DLL will result in an error, which will be reported in the trace log. You can open the Trace log from the Omnis Tools menu if a component fails to load, it will be reported in the Omnis trace log.
Deployment
If you wish to deploy the Omnis .NET Objects component as part of your application, you must install both DLLs and register the OMDOTNET.DLL file on any client machine, as described above.
158
159
Chapter 5Omnis .NET Objects The following shows a .NET Object being defined from a .NET Class which resides in the SOAP module which has been loaded manually.
160
Creating .NET Objects The following shows both the lString object variable and the lStringRef Object Reference.
To allocate an Object to an Object Reference, you must use the notation. As notation strings for .NET Objects can be very long (due to the large hierarchies that are present in some .NET packages) the Notation Inspector can be displayed as a helper window when entering the notation for .NET Objects. You need to navigate the $extobjects.DNet.$objects group to find the .NET class you wish to reference. You can drag and drop the notation from the Notation Inspector to the Method Editor, and the full notation is created for you, such as the following:
161
Chapter 5Omnis .NET Objects Omnis will enclose the object string in double forward slashes since it does not recognize it as a variable or method name All .NET Object notation begins with $root.$extobjects.DNet.$objects (although you can omit $root and $extobjects), and the remainder of the notation string is dependant on the .NET class being used. The complete notation for a String object is as follows:
$root.$extobjects.DNet.$objects.//NET\mscorlib\System\String//
Now you have to add a call to the $newref() method manually. This method is responsible for allocating an Object to the Object Reference. Therefore, the complete method to allocate the String object would be as follows:
Calculate lStringRef as DNet.$objects.//NET\mscorlib\System\String//.$newref()
When the above method is executed, a String .NET Object will be created and assigned to the Object Reference lStringRef. It is your responsibility to ensure that this Object is deleted using the $deleteref() method once it has served its purpose. To de-allocate the variable, you can use:
Do lStringRef.$deleteref()
For further information about Object References, refer to Omnis Programming manual.
Other .NET Objects may have more than one $createobject() method. In this case, each $createobject() method corresponds directly to a .NET Constructor for the class that is being used. For example, the .NET.System.String class has the following constructors:
162
Creating .NET Objects String(char* value) String(char[] value) String(sbyte* bytes) String(char c,int count) String(char* value,int startindex,int length) String(char[] value,int startindex,int length) String(sbyte* value,int startindex,int length) String(sbyte* value,int startindex,int length, int Encoding) These are mirrored in Omnis by the following $createobject() methods:
Calling any of above $createobject() methods will invoke the corresponding Constructor in .NET and create the .NET Object in the Virtual Machine. For example, calling:
Do mystring1.$createobject(mystring)
163
In this case, the oString object class becomes a subclassed object of String and inherits all of its methods as follows:
164
Subclassed .NET Objects can be used to define Object and Object Reference variables in the same manner as .NET Objects. Defining .NET Object variables is described in the previous section.
165
As you can see from the above, most of the Data Types in Omnis can be coerced into multiple .NET Data Types. Although this coercion happens automatically, it is useful to be aware of Overloaded Types as they provide you with greater flexibility when programming with .NET Objects. For example, if you wish to construct a .NET.System.Byte object, you could define a Binary variable, load the byte into the variable and then call $createobject() with this variable. However, it is much quicker to simply call $createobject() using the integer value of the byte. For example:
Do mybyte.$createobject(65)
166
Using .NET Objects For a further explanation of Overloaded Types, see the Appendix.
Passing Parameters
In order to call .NET Objects effectively, it is necessary to know how Omnis Data Types are mapped to .NET Data Types when passing parameters. .NET Object Parameters can be categorized into two basic types: Simple Parameters Simple parameters are parameter types that are compatible with .NET base types Complex Parameters All other parameter types are considered to be Complex
167
List Types
Omnis lists must contain valid data before being passed to a .NET Object. Note that if you use a list that has more than one column, only the first column will be used. Omnis lists which do not contain valid data will cause .NET Objects to return an error. For a further explanation of error handling, see the Error Handling section.
168
Using .NET Objects Omnis converts Single Column Lists to .NET Arrays based on the type of the data that is stored in the list. This conversion can be described by the following table: Omnis List Omnis List containing Number Long integer Types Omnis List containing Number floating dp Types Omnis List containing Number Short integer Types Omnis List containing Boolean Types Omnis List containing Object References .NET Array Type int[] or long[] float[] or double[] short[] boolean[] Array of .NET Objects
As you can see from the table above, Overloaded Types are also supported by Omnis Lists. For an explanation of Overloaded Types, see the Appendix. It should also be noted that char[] and byte[] are absent from the above table. This is because .NET char[] and byte[] types are created directly from Omnis Character and Binary variables. Omnis will always attempt to determine the type of Array that you are trying to pass as a parameter by examining the data in the List. If a list contains .NET Objects, Omnis will attempt to determine the type of the objects in the list. If the type of all the objects is found to be the same, it is assumed that you are passing a parameter of that type. For example, if you create an Omnis list of .NET.System.String Objects, Omnis will assume that you are passing a String Array Parameter to .NET. However, if any of the Objects are found to be of different types, Omnis will assume that you are passing a generic Object Array (.NET.System.Object) to .NET. When calling .NET methods that take arrays as parameters, you should make sure that the Omnis list that you pass to the method in question contains appropriate data. Lists which do not contain appropriate data will cause the function call to fail with an error (see the Error Handling section). For example, if you create an Omnis List with 12 .NET.System.String Objects and add an extra .NET.System.Byte object by mistake, your method call will fail if you are attempting to call a .NET function that accepts a .NET.System.String Array as a parameter. Important Note: When creating a list of .NET Objects, Object References should be used. This is because standard objects cannot be used in Omnis Lists. Once you have finished using your list of Object References, remember to delete each reference in the list by calling $deleteref for each reference. Please refer to the Omnis Programming manual for further information about Object References.
Object Types
.NET Objects should be created using $createobject() before being passed a s parameters to other .NET Objects. Passing an uninitialized object to a .NET function will return an error.
169
As you can see from the table above, this is merely a reversal of the Omnis to .NET table shown in the previous section. To return a value from a .NET object method, use the Method Editor to specify the variable that will be used to hold the return value. You must ensure that the Omnis variable that you are using is of the correct type to accept the value that will be returned from .NET. If this is not the case, an error will occur and the hash variables #ERRCODE and #ERRTEXT will be set accordingly (see the Error Handling section later in this manual). Important: If a .NET object returns a base object type, such as String, this will be returned as a base Omnis type. For example, the string object has a method called $substring which returns a character variable and not an object string. This is due to the fact that it would be otherwise impossible to get the contents of a string object if only a string object was returned.
170
The first line of the method obtains the installation folder of the .NET framework and appends the soap filename. The second line adds the class (or classes if the string has more than one filename separated by commas) to the Omnis .NET classes which are available; the value returned is the number of files added, in this case 1. The .NET objects in the class are then available in the Select Object dialog when creating object variables.
Its not necessary to restart Omnis after adding classes, but remember that this information is not persistent between sessions, so you will need to add the classes into Omnis each time the application starts up or a window is opened.
Error Handling
.NET Objects makes full use of the #ERRCODE and #ERRTEXT variables in Omnis. If an error occurs while executing a .NET object method, these variables will report the error code and text on return from the method. #ERRCODE will produce the value 0 after a successful .NET method call. 171
The example library has a number of pre-defined feeds from world-wide news organizations. After selecting a feed from the droplist, double-click a story headline to view the story detail. If you have Microsoft Internet Explorer ActiveX installed, this will be shown within an Omnis window, otherwise your default browser is used. You can examine the code in the library to see how the .NET Objects component can be used in Omnis applications to access .NET functionality.
172
.NET Objects example library RSS feed. Lastly it retrieves a list of all the item or story XML nodes within the channel node itself. The property numberOfTags is derived from the number of item nodes within the XML source. The second method, getItemTags(), allows Omnis access to the nth story XmlNode determined by the function argument. Once again, calls to member functions can further extract XML from the XmlNode object and provide information such as Story Headline, Feed Description and Publish Date.
Note the DNet object is part of the $root.$extobjects group. The next part of the method loads the System.Xml library and adds this to Omnis. You can use the $basefolder() method to return the folder containing your .NET Framework:
Do DNet.$basefolder Returns lPath ; lPath is something like C:\WINNT\Microsoft.NET\Framework\<version> Calculate lPath as con(lPath,'\System.Xml.dll') Do DNet.$addclass(lPath) Returns #F
The next part sets up and builds a list containing the list of RSS feeds and loads the first one in the list:
Do Do Do Do iItemList.$define(iItemTitle,iItemDes,iItemLink,iItemPubDate) method $buildurllist iUrlList.$first() iUrlList.$loadcols()
The next part of the window $construct() method creates an instance of the getRssFeed object and constructs the object in .NET using the $createobject() method. Finally, a class method is called to retrieve the feed.
Do $root.$extobjects. DNet.$objects.//NET\rssreader\rssreader\getRssFeed//.$newref() Returns iFeedObject Do iFeedObject.$createobject() Do method $getfeed
173
Chapter 5Omnis .NET Objects You can use the Interface Manager to examine the properties and methods of a .NET object. For example, this is the iFeedObject object created in the RSS feed window.
The $buildurllist and $getfeed methods are contained in the window class and are called from the window $construct() method. The $buildurllist method builds a list containing a single column of RSS feed URLs which in this case are loaded from a static list of URLs, but could have been constructed from a database.
Do iUrlList.$define(iFeedLink) Do iUrlList.$add( 'http://feeds.foxnews.com/foxnews/latest?format=xml') ; and so on...
174
.NET Objects example library The $getfeed method retrieves the XML source file for the current RSS feed and extracts the relevant information to display in the window.
; $getfeed method Do iItemList.$clear() Calculate iFeedObject.$rssurl as iFeedLink Working message Waiting/-1073735814,-1073735810;50;0;60 {Retreiving RSS Feed} ;; message while object is retrieved Do iFeedObject.$getdocument() ;; the XML source is retrieved ; Get the channel XmlNode and extract the channel information Calculate lXmlNodeObject as iFeedObject.$channelnode Do method $getchannelinfo (lXmlNodeObject) For lItemNumber from 1 to iFeedObject.$numberofitemtags step 1 Do iFeedObject.$getitemtags(lItemNumber) Returns lXmlNodeObject Do method $getiteminfo (lXmlNodeObject) End For
The $getchannelinfo method retrieves the title, language, and description for the RSS document while the $getitemtags method returns the information about each news story listed in the RSS feed including the URL, title, description, and publication date.
; Local var: lSubNode (Object) subtype NET\Xml\System\Xml\XmlNode Do pRssItemNode.$selectsinglenode("link") Returns lSubNode Calculate iItemLink as lSubNode.$innertext Do pRssItemNode.$selectsinglenode("title") Returns lSubNode Calculate iItemTitle as lSubNode.$innertext Do pRssItemNode.$selectsinglenode("description") Returns lSubNode Calculate iItemDes as lSubNode.$innertext ; ignore all html tags If pos('<',iItemDes)<>0 Calculate iItemDes as left(iItemDes,pos('<',iItemDes)-1) End If Do pRssItemNode.$selectsinglenode("pubDate") Returns lSubNode Calculate iItemPubDate as lSubNode.$innertext Do iItemList.$add(iItemTitle,iItemDes,iItemLink,iItemPubDate) Calculate iItemPubDate as '' Calculate iItemDes as ''
When you double-click on a news story in the RSS feed window, Omnis uses the URL stored in iItemLink (loaded from the iItemList) to launch a browser window and display the news story.
175
Pattern Matching
Omnis uses pattern matching in order to determine the overloaded method that youre trying to call. In simple terms, Omnis examines the parameters that you pass to a method and attempts to call the method whose parameters most closely match the parameters that you are passing. For example, consider the following .NET methods:
myfunc(int p1) myfunc(float p1)
Calling myfunc from Omnis using an Omnis Number type set to Long Integer will call myfunc(int p1). Calling myfunc from Omnis using an Omnis Number type set to Floating dp will call myfunc(float p2).
176
Method Method Overloading and Pattern Matching 2. If a match is not found, Omnis searches for a method that has a matching number of long parameters, that is, Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of int and long types. Thus, if (int,boolean,int) is not found, Omnis will look for the following: (int,boolean,long) (long,boolean,int) (long,boolean,long) 3. Finally, if this fails, Omnis searches for a method that has a matching number of byte parameters, that is, Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of int and byte types. Thus, if 2 does not find a compatible method, Omnis will look for the following: (byte,boolean,int) (int,boolean,byte) (byte,boolean,byte) Note that any method that matches the int Parameter Search pattern will always be called if it is available. For example, consider the following .NET methods:
myfunc(int p1) myfunc(long p1) myfunc(byte p1) myfunc(boolean p1)
calling myfunc using a Long Integer type will always call myfunc(int p1) in .NET. If this method is removed:
myfunc(long p1) myfunc(byte p1) myfunc(boolean p1)
calling myfunc using a Long Integer type will always call myfunc(long p1), and so on.
Chapter 5Omnis .NET Objects 2. If a match is not found, Omnis searches for a method that has a matching number of float parameters, that is, Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of double and float types. Thus, if (double,boolean,double) is not found, Omnis will look for the following: (double,boolean,float) (float,boolean,double) (float,boolean,float) 3. Finally, if this fails, Omnis searches for a method that has a matching number of decimal parameters, that is, Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of double and decimal types. Thus, if 2 is not found, Omnis will look for the following: (double,boolean,decimal) (decimal,boolean,double) (decimal,boolean,decimal) Note that any method that matches the double Parameter Search pattern will always be called if it is available. For example, consider the following .NET methods:
myfunc(double p1) myfunc(float p1) myfunc(decimal p1) myfunc(boolean p1)
calling myfunc using a Number Floating dp type will always call myfunc(double p1) in .NET. If this method is removed:
myfunc(float p1) myfunc(decimal p1) myfunc(boolean p1)
calling myfunc using a Floating dp type will always call myfunc(float p1), and so on.
178
Method Method Overloading and Pattern Matching Omnis will look for (Object,boolean,String) followed by (String,boolean,Object) followed by (Object,boolean,Object). Note that any .NET method that has a parameter list which matches the Objects that you are using as parameters will always be called if it is available. For example, consider the following .NET methods:
myfunc(String p1) myfunc(Object p1) myfunc(boolean p1)
calling myfunc using an Omnis object whose subtype is set to .NETObjs\System\.NET\lang\String will always call myfunc(String p1) in .NET. If this function is removed:
myfunc(Object p1) myfunc(boolean p1)
calling myfunc using an Omnis object whose subtype is set to .NETObjs\System\.NET\lang\String will always call myfunc(Object p1).
As a result of these conversions, you should be aware that it is not possible for Omnis to call an overloaded .NET function that takes char[] as a parameter using a single character. This is demonstrated in the following example. Consider the following:
myfunc(char p1[]) myfunc(char p1)
Following the rules for data conversion, calling myfunc with a single character will call myfunc(char p1) while calling myfunc with a string of characters will call myfunc(char p1[]). Thus, in this situation it is not possible to call myfunc(char p1[]) with a single character as myfunc(char p1) will always be called if the length of the data that you are passing is 1. However, it is possible to force Omnis to call myfunc(p1[]) with a single character if you call the overloaded method directly. The procedure for doing this is discussed in the next section.
179
Chapter 5Omnis .NET Objects Note: If the length of an Omnis Character type is 0, it will be converted into a .NET char type whose value is 0. If the length of an Omnis Binary type is 0, it will be converted into a .NET byte type whose value is 0.
If you want to call a particular method directly, you can do so from the Omnis Interface Manager, by selecting the desired overloaded method that you wish to call and clicking on the description tab. This will display the real name of the overloaded method. The following screenshot shows the Omnis Interface Manager for the .NET.System.String class. If you were to call the $compareto() method using an Omnis object type, you must use the real name of this method which, in this case, is $valueof{o}.
180
Nested Object Arrays The naming convention for these parameters are as follows: .NET Type Char boolean Decimal Float Double Unsigned Byte Signed Byte Unsigned Short Signed Short Unsigned Int Signed Int Unsigned Long Signed Long Object Object of known type Enum Void Abbreviated to (Omnis type) c b d f4 f8 u1 i1 u2 i2 u4 i4 u8 i8 o <Object Name> <Enum Name> v
181
Overloaded Types
The following sections provide detailed descriptions of the Overloaded Types used by the .NET Objects component.
This allows you to call any .NET object that takes either a char or char[] as a parameter with an Omnis Character variable. You may also place .NET return values that are of type char or char[] into an Omnis Character variable. In the case of char[] parameters, the Omnis Character variable is automatically converted into a .NET char array (or vice versa if you are dealing with return values). This allows objects such as the .NET String to be created easily from Omnis. For example:
Calculate mychar as hello this is a test Do mystring.$createobject(mychar)
The above will invoke the .NET String Constructor String(char[] value) Note: If you attempt to call a .NET function that takes a single char as a parameter and the Omnis variable that you are passing contains more than one character, .NET will only receive the first character of the string.
This allows you to call any .NET object that takes either a byte or byte[] as a parameter with an Omnis Binary variable. You may also place .NET return values that are of type byte or byte[] into an Omnis Binary variable. In the case of byte[] parameters, the Omnis Binary Type is automatically converted into a .NET byte array (or vice versa if you are dealing with return values). This allows objects such as the .NET String to be created easily from Omnis. For example:
Do mystring.$createobject(mybinval) ; where mybinval is a binary Omnis Variable
The above will invoke the .NET String Constructor String(byte[] bytes)
182
Overloaded Types Note: If you attempt to call a .NET function that takes a single byte as a parameter and the Omnis variable that you are passing contains more than one byte, .NET will only receive the first byte of the data that you are passing.
This allows you to pass Omnis Number Long integer variables to .NET functions which accept these types. Note: When dealing with return values, .NET int and long types can be converted into the Omnis Number Long integer type. However, all byte return values are always converted to the Omnis Binary type.
This allows you to pass Omnis Number floating dp variables to .NET functions which accept these types.
183
Setting Up
To use Java Objects in Omnis, you must install the latest version of the Java SE environment (formerly known as J2SE) and define a number of environment variables.
Software Requirements
Omnis Java Objects support version 1.4.1 or above of the Java SE (J2SE) environment, including Java SE version 5 and 6. You can get information and downloads for the latest version of Java SE for Windows, Linux, and Solaris SPARC, from the Sun Java web site: http://java.sun.com/javase If you are a Solaris SPARC user you should contact your System Administrator to ensure that your Solaris platform is capable of running the latest version of Java SE. A list of available OS patches for running Java on Solaris SPARC platforms can be found at: http://java.sun.com/javase/downloads To use Java Objects under Mac OS X you must have OS X version 10.3 (Panther), or above.
184
Setting Up
Current Restrictions
There are currently a number of restrictions imposed on Java Objects as follows: Java Events are not supported. The Java Objects component is non-visual and the use of awt/swing is not supported. Java Interface classes cannot be used directly in Omnis. To use an interface class, create a custom class which implements the interface. J2SE/Java SE is currently supported, meaning that you will have access to a Java Virtual Machine and can run any Java Code on this virtual machine with respect to b. However J2EE is not supported. Java Objects under Mac OS X are supported under version OS X version 10.3 (Panther) and 10.4 (Tiger), or above only.
Environment Variables
The following assumes that you are the System Administrator of the platform on which you are working, or that you have a basic knowledge of setting environment variables on your respective platform. To use Java Objects in Omnis, you must define or edit a number of environment variables, including the CLASSPATH and OMNISJVM. These variables are slightly different for each platform and are described in the following sections. You do not need to add the Omnis Java folder, OS50\java\JavaCode, or any of its subfolders to the CLASSPATH environment variable since this folder is registered by Omnis automatically. You can place your own Java classes in this folder or any of its sub-folders to register them automatically. However if you want to use any Java classes anywhere on your system you need to include their location in the CLASSPATH.
Windows 2000/XP
The environment variable OMNISJVM should be defined to point to the installation of the Java Virtual Machine that you wish to use. The Java Virtual Machine is normally located in the bin\client folder of your J2SE installation. For example:
OMNISJVM= C:\j2sdk1.4.2\jre\bin\client\jvm.dll or OMNISJVM= C:\Program Files\Java\jre1.6.0_01\bin\client\jvm.dll
185
Chapter 6Java Objects The CLASSPATH environment variable should also be defined to point to folders that contain any custom classes that you wish to use with Omnis. For example:
CLASSPATH=c:\java\myclass;c:\java\myclass1
Setting environment variables under Windows In Windows, you can add or edit environment variables in the System Properties dialog in the Control Panel. On the Advanced tab, click the Environment Variables button, then click New to define a new variable, or select the name of the User or System variable you want to change and click Edit.
Mac OS X
The CLASSPATH environment variable should be defined to point to folders that contain any custom classes that you wish to use with Omnis. For example:
CLASSPATH=/Volumes/HD/classes/myclass:/Volumes/HD/classes/myclass1
Setting environment variables under Mac OS X Documentation on how to set environment variables on OS X is in the Apple tech note QA1067, located at http://developer.apple.com/qa/qa2001/qa1067.html
Linux
The environment variable OMNISJVM should be defined to point to the installation of the Java Virtual Machine that you wish to use. The Java Virtual Machine is normally located in the lib/i386/client folder of your J2SE/Java SE installation. For example:
OMNISJVM=/usr/java/jdk1.4.1_01/jre/lib/i386/client/libjvm.so export OMNISJVM
The CLASSPATH environment variable should also be defined to point to folders that contain any custom classes that you wish to use with Omnis. For example:
CLASSPATH=/classes/java/myclass:/classes/java/myclass1 export CLASSPATH
The PATH environment variable should be modified to include the path to the bin folder of your J2SE/Java SE installation. For example:
PATH=/usr/java/jdk1.4.1_01/bin:$PATH export PATH
The LD_LIBRARY_PATH environment variable should be modified to point to the lib/i386 and lib/i386/client folders of your J2SE/Java SE installation as follows:
LD_LIBRARY_PATH=/usr/java/j2sdk1.4.1_01/jre/lib/i386: /usr/java/j2sdk1.4.1_01/jre/lib/i386 /client:$LD_LIBRARY_PATH export LD_LIBRARY_PATH
Object parameters
Java reflection requires that parameter objects exist on the main classpath. To ensure that objects or object references can be passed to a Java method, place the path to the jar file in the CLASSPATH variable. 186
Setting Up
Setting an Environment Variable The putenv(name,value) function sets the Omnis process environment variable with the specified name to the specified value. Creates a new environment variable if necessary, and returns true for success, false for failure. For example:
Do putenv(OMNISCLASSPATH,C:\Program Files\TigerLogic\OS50\java) ; Creates the environment variable OMNISCLASSPATH and sets its value to C:\Program Files\ TigerLogic \OS50\java
Getting the value of an Environment Variable The getenv(name) function returns the value of the Omnis process environment variable with the specified name. For example:
Calculate lVar1 as getenv("OMNISJVM") ; Returns the location of the JVM, e.g. C:\j2sdk1.4.2_11\jre\bin\client\jvm.dll
187
Memory Allocation
There are some Omnis preferences that allow you to set the memory allocation for Java. You can set the properties on the Java tab of the main Omnis preferences, visible in the Property Manager. The properties are: $usejavaoptions (boolean) when kTrue, the Java Virtual Machine will use the options specified in $javaoptions Omnis preference; if set to kFalse, the JVM will use its own internal memory settings. $javaoptions You can use this property to specify any switches you wish to pass to the Java Virtual Machine, e.g. to set a system property value, specify -Dproperty=value You can add the following parameters to the $javaoptions property, assuming $usejavaoptions is set to true. Original heap size Maximum heap size Stack size To specify the original heap size for the JVM add "-Xms <heapsize>" to the $javaoptions property To specify the maximum heap size for the JVM add "-Xmx <maxheapsize>" to the $javaoptions property To specify the stack size for the JVM add "-Xss <stacksize>" to the $javaoptions property
Note: The above options are for advanced users only. If you are unsure of what the settings for the above properties should be, you should leave $usejavaoptions set to kFalse. Note to existing users: the above options replace the Omnis $root preferences $javainitialheap, $javamaxheap and $javathreadstack. The $javaother property was renamed to $javaoptions.
Quitting Omnis
When Omnis starts up, it scans all of the paths on the CLASSPATH environment variable and creates a cache of all available classes on your system. When Omnis exits, any classes that you have added are appended to the internal Omnis Java class cache. When Omnis is restarted, all classes are read from this class cache. 188
Reloading Classes
Omnis will detect that you are attempting to add an existing class and will not attempt to add the class a second time. This will not produce an error in your code, which means that you do not have to worry about implementing a first time flag when adding classes.
189
As you can see from the above, the Object Selection Tree has completed the notation string by adding JavaObjs\ClassPath\zipdemo\zipdemo. In addition to this, a call to the $newref() method has to be added manually. This method is responsible for allocating an Object to the Object Reference. The command reads as follows:
Calculate lzipreference as $extobjects.JavaObjs Library.$objects.//JavaObjs\ClassPath\zipdemo\zipdemo//.$newref()
When the above command is executed, a zipdemo Java Object will be created and assigned to the Object Reference lzipreference. It is your responsibility to ensure that this Object is deleted using the $deleteref() method once it has served its purpose. For example:
Do lzipreference.$deleteref()
Other Java Objects may have more than one $createobject() method. In this case, each $createobject() method corresponds directly to a Java Constructor for the class that is being used. For example, the java.lang.String class has the following constructors: String() String(String original) String(byte[] ascii, int hibyte) String(byte[] bytes) String(char[] value) String(byte[] bytes,int offset,int String(StringBuffer buffer) String(byte[] bytes,String enc) String(char[] value,int offset,int String(byte[] ascii,int hibyte,int String(byte[] bytes,int offset,int
length,String enc)
Calling any of above $createobject() methods will invoke the corresponding Constructor in Java and create the Java Object in the virtual machine. For example, calling:
Do mystring1.$createobject(mystring)
191
Chapter 6Java Objects will invoke the String(String original) java.lang.String Constructor if mystring is an Omnis Java Object with a java.lang.String subtype that has been previously declared and created.
As a result of the above, an object class called zipobject becomes a subclassed object of zipdemo and inherits all of its methods as follows:
Subclassed Java Objects can be used to define Object and Object Reference types in the same manner as Java Objects, described in the previous section.
192
Those marked * are known as Overloaded Types as they are compatible with more than one Java Data Type. As you can see from the above, most of the Data Types in Omnis can be coerced into multiple Java Data Types. Although this coercion happens automatically, it is useful to be aware of Overloaded Types as they provide you with greater flexibility when programming with Java Objects. For example, if you wish to construct a java.lang.Byte object, you could define a binary variable, load the byte into the variable and call $createobject() with this variable. However, it is much quicker to simply call $createobject() using the integer value of the byte. For example:
Do mybyte.$createobject(65)
193
Passing Parameters
Java Object Parameters can be categorized into two basic types. Simple Parameters and Complex Parameters. Simple parameters are parameter types that are compatible with java base types. All other parameter types are considered to be Complex.
194
Using Java Objects In the above example, the Simple Parameter Type lpos is passed to the java.lang.String charat() function. This function returns the character value o (the letter o) as this character resides at index 4 of the Java String.
List Types
Omnis lists must contain valid data before being passed to a Java Object. Note that if you use a list that has more than one column, only the first column will be used. Omnis lists which do not contain valid data will cause Java Objects to return an error. See the Error Handling section for more information. Omnis converts Single Column Lists to Java Arrays based on the type of the data that is stored in the list. This conversion can be described by the following table: Omnis List Omnis list containing Number Long integer c Omnis list containing Number floating dp types Omnis list containing Number Short integer types Omnis list containing Boolean types Omnis list containing Object Reference types Converts to (Java Array Type) int[] or long[] float[] or double[] short[] boolean[] Array of Java Objects
As you can see from the above, Overloaded Types are also supported by Omnis Lists. For an explanation of Overloaded Types, see the Parameter Data Types section. It should also be noted that char[] and byte[] are absent from the above. This is because Java char[] and byte[] types are created directly from Omnis Character and Binary Variables. Omnis will always attempt to determine the type of Array that you are trying to pass as a parameter by examining the data in the List. If a list contains Java Objects, Omnis will attempt to determine the type of the objects in the list. If the type of all the objects is found to be the same, it is assumed that you are passing a parameter of that type. For example, if you create an Omnis list of java.lang.String Objects, Omnis will assume that you are passing a String Array Parameter to Java. However, if any of the Objects are found to be of different types, Omnis will assume that you are passing a generic Object Array (java.lang.Object) to Java. When calling Java methods that take arrays as parameters, it is important to make sure that the Omnis list that you pass to the method in question contains appropriate data. Lists which 195
Chapter 6Java Objects do not contain appropriate data will cause the function call to fail with an error. (See the Error Handling section.) For example, if you create an Omnis List with 12 java.lang.String Objects and add an extra java.lang.Byte object by mistake, your method call will fail if you are attempting to call a Java Function that accepts a java.lang.String Array as a parameter. An example of how to use Omnis lists as parameters to Java can be found in the example.lbs Omnis library that accompanies Omnis (in the Java\JavaCode folder). The window class arrayparams, which is part of this library, demonstrates how to call a Java method that takes an Array of java.lang.String and an Array of int as parameters. Important Note: When creating a list of Java Objects, Object References should be used. This is because standard objects cannot be used in Omnis Lists. Once you have finished using your list of Object References, remember to delete each reference in the list by calling $deleteref() for each reference. Please refer to OO Programming chapter for further information about Object References.
Object Types
Java Objects should be created using $createobject() before being passed as parameters to other Java Objects. Passing an uninitialised object to a Java Function will return an error. (See the Error Handling section.) An example of how to use Java Objects as parameters to other Java methods can be found in the example.lbs Omnis library that accompanies Omnis (in the Java\JavaCode folder). The window class objectparams in the example library demonstrates how to call a Java method that takes a variety of Java Objects as parameters.
196
Using Java Objects To return a value from a Java Object method, use the Method Editor to specify the variable that will be used to hold the return value. You must ensure that the Omnis variable that you are using is of the correct type to accept the value that will be returned from Java. If this is not the case, an error will occur and the hash variables #ERRCODE and #ERRTEXT will be set accordingly (see Error Handling). The following shows a String object being returned from Java. The object is created via the use of the Java String substring function and is returned as an Object Reference.
Note: The $getobjectvalue method is used to retrieve the character value of the lstringref Object Reference. This method is described in the next section.
197
The above example creates a Java String Object with the value Hello there. The call to $getobjectvalue() extracts this value and assigns it to the local variable lchar. The local variable ljerr is a long integer which is used for error handling. If $getobjectvalue() fails to convert the Object value, ljerr will contain an error code, otherwise the value 1 (kJavaCoreOK) is returned. The $getobjectvalue() method will accept all of the Simple Parameter Types as parameters. Therefore, the format of the $getobjectvalue() method call is the same regardless of the type of data that is being returned. For example, the following is very similar to the previous example:
198
The $getobjectvalue() method uses the same process of data conversion that is used for Return Values. For a further explanation of this process, see the Returning Values From Java Methods section.
Chapter 6Java Objects 3. A fully qualified Jar filename. If a single class is specified, only that class is loaded. If a folder is specified, then all class files within the folder are loaded. If a Jar file is specified, all classes within the Jar file are loaded. Note: Any classes that are specified must already reside on the Java Classpath. To make the best use of $addclass(), your CLASSPATH environment variable should include any paths that you may want to load classes from while Omnis is running. If you are loading a Jar file that itself requires the use of other Jar files, you should ensure that these dependencies are also listed in your CLASSPATH environment variable.
Examples
The following code shows some examples of using the $addclass() method: To load the class zipdemo.class that resides on the classpath c:\classes, use:
Do JavaObjs Library.$addclass( kJavaObjsClassPathGroup, c:\classes\zipdemo\zipdemo.class, c:\classes)
The above will add zipdemo.class to the JavaObjs ClassPath group. To add the same class to the Web Services group, use the following:
Do JavaObjs Library.$addclass( kJavaObjsWebServicesGroup, c:\classes\zipdemo\zipdemo.class, c:\classes)
200
Using Java Objects To load the class example.class from the Omnis JavaCode folder, use:
Do JavaObjs Library.$addclass( kJavaObjsClassPathGroup, <insert your omnis installation folder pathname here>\Java\JavaCode\example\example.class)
To load all of the classes in the myclass folder on the classpath c:\classes use:
Do JavaObjs Library.$addclass( kJavaObjsClassPathGroup, c:\classes\myclass, c:\classes)
Error Handling
Java Objects makes full use of the #ERRCODE and #ERRTEXT Omnis variables. If an error occurs while executing a Java Object Method, the error variables identify the error on return from the method. In addition to this, each Java Object has an error status which you can examine using the $getlasterror() method. The following example, which is in the example Omnis library, shows how to use $getlasterror() to retrieve the error status of an object.
201
Both #ERRCODE and $getlasterror will produce the value 1 (kJavaCoreOK) after a successful Java method call. If an error occurs while calling a Java method, an error code is generated.
Error Codes
Java Objects inherits all of the error codes that are supported by the JavaCore. The JavaCore is the Omnis Java Engine which is responsible for managing calls to the Java Virtual Machine. Both Java Objects and the JDBC DAM are clients of the JavaCore. All the error codes supported by the JavaCore are listed in the Omnis Catalog (F9) under JavaCore. In addition, error codes specific to Java Objects are also listed.
Development Tips
The following information may be useful when developing with Java Objects in Omnis. Ensure that your Java Code is working correctly before calling it from Omnis. Java Exceptions can be very difficult to track down as it is not possible to use a Java Debugger once a Java object is embedded in Omnis. Java Objects will report exceptions in Java Code. However, because Java Objects uses introspection to call functions in your Java Class, it will only be able to tell you that an Exception occurred while executing your method and the actual nature of the Exception will not be known. Use Object References with care. Remember that any Java Object that is returned to Omnis is returned as an Object Reference and it is your responsibility to delete this reference using
202
Method Overloading and Pattern Matching the $deleteref() method. Also remember that arrays of Java Objects are returned to Omnis as lists of Object References which also need to be deleted once they have been used. It is possible to pass Nested Object Arrays to Java and have Java return Nested Object Arrays to Omnis. Nested Object Arrays are passed to Omnis as a list of Omnis lists which in turn contain Java Objects. Nested Object Arrays are returned from Java in the same format. See the Nested Object Arrays section for further information.
Pattern Matching
Omnis uses pattern matching in order to determine the overloaded method that you are trying to call. Put simply, Omnis examines the parameters that you pass to a method and attempts to call the method whose parameters most closely match the parameters that you are passing. For example, consider the following Java methods: myfunc(int p1) myfunc(float p1) Calling myfunc from Omnis using an Omnis number type set to Long Integer will call myfunc(int p1). Calling myfunc from Omnis using an Omnis number type set to Floating dp will call myfunc(float p2).
Chapter 6Java Objects If a Number Long Integer Omnis type is passed to an overloaded method, the following occurs: 1. Omnis attempts to find an overloaded method that has the same number of int parameters that you are passing, i.e. if you are calling a method with (int,boolean,int), Omnis will try to find an overloaded method which matches this Parameter Search Pattern. 2. If a match is not found, Omnis searches for a method that has a matching number of long parameters, i.e. Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of int and long types. Therefore, if (int,boolean,int) is not found, Omnis will look for the following: (int,boolean,long) (long,boolean,int) (long,boolean,long) 3. Finally, if this fails, Omnis searches for a method that has a matching number of byte parameters, i.e. Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of int and byte types. Therefore, if b does not find a compatible method, Omnis will look for the following: (byte,boolean,int) (int,boolean,byte) (byte,boolean,byte) Note that any method that matches the int Parameter Search pattern will always be called if it is available. For example, consider the following Java methods: myfunc(int p1) myfunc(long p1) myfunc(byte p1) myfunc(boolean p1) calling myfunc using a long integer type will always call myfunc(int p1) in Java. If we remove this method: myfunc(long p1) myfunc(byte p1) myfunc(boolean p1) calling myfunc using a Long Integer type will always call myfunc(long p1), and so on.
Method Overloading and Pattern Matching If a Number Floating dp Omnis type is passed to an overloaded method, the following occurs: 1. Omnis attempts to find an overloaded method that has the same number of float parameters that you are passing, i.e. if you are calling a method with (float,boolean,float), Omnis will try to find an overloaded method which matches this Parameter Search Pattern. 2. If a match is not found, Omnis searches for a method that has a matching number of double parameters, i.e. Omnis will modify the Parameter Search Pattern in an attempt to find a match using combinations of float and double types. Therefore, if (float,boolean,float) is not found, Omnis will look for the following: (float,boolean,double) (double,boolean,float) (double,boolean,double) Note that any method that matches the float Parameter Search pattern will always be called if it is available. For example, consider the following Java methods: myfunc(float p1) myfunc(double p1) myfunc(boolean p1) calling myfunc using a floating dp type will always call myfunc(float p1) in Java. If we remove this function: myfunc(double p1) myfunc(boolean p1) calling myfunc using a floating dp type will always call myfunc(double p1).
205
Chapter 6Java Objects Note that any Java method that has a parameter list which matches the Objects that you are using as parameters will always be called if it is available. For example, consider the following Java methods: myfunc(String p1) myfunc(Object p1) myfunc(boolean p1) calling myfunc using an Omnis object whose subtype is set to JavaObjs\System\java\lang\String will always call myfunc(String p1) in Java. If that function is removed: myfunc(Object p1) myfunc(boolean p1) calling myfunc using an Omnis object whose subtype is set to JavaObjs\System\java\lang\String will always call myfunc(Object p1).
As a result of the above, you should be aware that it is not possible for Omnis to call an overloaded Java function that takes char[] as a parameter using a single character. This is demonstrated in the following example. myfunc(char p1[]) myfunc(char p1) Following the rules for data conversion, calling myfunc with a single character will call myfunc(char p1) while calling myfunc with a string of characters will call myfunc(char p1[]). Thus, in this situation it is not possible to call myfunc(char p1[]) with a single character as myfunc(char p1) will always be called if the length of the data that you are passing is 1. However, it is possible to force Omnis to call myfunc(p1[]) with a single character if you call the overloaded method directly. The procedure for doing this is discussed in the next section.
206
Calling Overloaded Methods Directly Note: If the length of an Omnis character type is 0, it will be converted into a Java char type whose value is 0. If the length of an Omnis binary type is 0, it will be converted into a Java byte type whose value is 0.
207
The above shows the interface manager for the java.lang.String class. If you were to call the $valueof method using an Omnis Number floating dp type, Omnis would always call $valueof(nFloat) as this is the closest possible match to the type of data that you are passing to Java. If you wish to call $valueof(nDouble), you must use the real name of this method which in this case is $valueof{n1457061552}.
Modifying The System Package List Line 1 2 3 Content List of java.lang.String Objects java.lang.Float Object List of java.lang.Integer Objects
The above list is passed to the exnested Java method. This method copies the above list structure and adds another array of java.lang.String objects to the end of the list. The content of each element is displayed in the nestedobjects main window.
The above is a list of paths to Java System Class packages. Each path is separated with a semicolon. To add a package to the list, simply insert it at the beginning as follows: To add the java.net package to the list of available System Java Classes, replace the . with a \ and prefix with System\ so that java.net becomes
System\java\net
The above can then be added to the existing filters in the jfilter.txt file as follows:
209
Overloaded Types
The following sections provide detailed descriptions of the Overloaded Types used by Java Objects.
The above will invoke the Java String Constructor String(char[] value) If you attempt to call a Java function that takes a single character as a parameter and the Omnis variable that you are passing contains more than one character, Java will only receive the first character of the string.
Frequently Asked Questions In the case of byte[] parameters, the Omnis Binary Type is automatically converted into a Java byte array (or vice versa if you are dealing with return values). This allows objects such as the Java String to be created easily from Omnis. For example:
Do mystring.$createobject(mybinval) ; where mybinval is a binary Omnis variable
The above will invoke the Java String Constructor String(byte[] bytes) If you attempt to call a Java function that takes a single byte as a parameter and the Omnis variable that you are passing contains more than one byte, Java will only receive the first byte of the data that you are passing.
Chapter 6Java Objects setup your OMNISJVM environment variable. Also, if you are running under Linux or Solaris, make sure that you have modified both the PATH and the LD_LIBRARY_PATH environment variables. Further information on environment variable settings can be found at the beginning of this chapter. Q. I have my own Java Package which I have placed on the class path. I have been using this package successfully with Java Objects but I have just compiled and updated my code and Omnis has not recognized the changes. What could be wrong? A. Omnis Studio caches Java classes and method names to improve performance. Once a java class has been loaded, it will not be loaded again until Omnis is restarted. If you modify your Java Code while Omnis is running, the changes you make will not become apparent until you restart Omnis. Q. Does Omnis recognize jar files? A. Omnis will recognize and load any jar files that are located in a folder which has been specified in the CLASSPATH environment variable. All of the classes in your jar file will be available via the Object Selection Tree which is displayed when you create the object variable in the method editor.
212
213
Object Interfaces
Server Object methods & properties
Method Open Close ErrorId ErrorText Execute Description Opens the connection. Closes the connection Obtain the last error id (0 = Ok) Obtain the last error text string Execute the specified remote method Execute the specified remote method Helper method to create a variable with a string Helper method to create a variable with a integer Helper method to create a variable with a Boolean Helper method to create a variable Parameters None None None None Method Name, Parameter Array, Parameter Count Method Name String Integer Boolean None Return Value Error Code (0=Ok) None Integer String Variable Object (null if failure) Variable Object (null if failure) Variable Object Variable Object Variable Object Variable Object
Note: All the above methods affect the error code and error text. Methods ErrorId() and ErrorText() should be used to verify success. Property ServerURL OmnisClass OmnisLibrary OmnisServer ServerScript Description The URL of the server The name of the Omnis class The name of the Omnis library The name of the Omnis server The server script text Type String String String String String Assignable Yes Yes Yes Yes Yes
214
Object Interfaces
Clear GetChar SetChar GetBool SetBool GetLong SetLong GetNumber SetNumber GetDate SetDate GetBinary
None None String None Boolean None Integer None Double None Date Byte buffer, start from (0), buffer size. Byte buffer, start from (0), buffer size None Integer column count Integer row count, integer column count
None String None Boolean None Integer None Double None Date None Integer: Number of bytes copied None
SetBinary
GetBinaryLen SetRow
Integer None
SetList
Creates a list
None
215
Chapter 7Remote Studio Applet Method Name GetRowCount GetColumnCount GetElement Description Get the row count Get the column count Get the variable for the specified column & row (zero based). Note that this variable is a duplicate and you must use setElement if you wish to update the list/row contents. Set the variable for the specified column & row (zero based) Parameters Integer Integer Integer row, integer column Return Value None None Variable Object
SetElement
None
Note: Variable conversion between types will automatically occur, however if a variable cannot be converted then a data mismatch error will be called.
MessageType
At the end of the $construct() and $event() methods you need to return the row parameter to ensure that the values are returned to the server applet. 216
217
218
219
220
Chapter 8Automation
Automation, formerly called OLE Automation, is a technology that allows you to utilize an existing programs content and functionality, and to incorporate it into your own applications. Automation is based on the Component Object Model (COM). COM is a standard software architecture, based on interfaces, that is designed to separate code into self-contained objects, or components. Each component exposes a set of interfaces through which all communication to the component is handled. For example, with Automation you can use a Word processors mail merge feature to generate form letters from data in an Omnis database without the user being aware that Word processor is involved. Automation consists of a client and a server. The automation client (Omnis) attaches to the automation server so that it can use the content and functionality that the automation server provides. Omnis can only be an automation client, it cannot be a server. Automation servers consist of an object or a number of objects. For example, in the object hierarchy for Excel, the uppermost object in the Excel object model is the Application object. The Excel Application object has many children, two of which are Workbooks and CommandBars. Workbooks and CommandBars are collection objects that contain other objects. A Workbooks collection object contains Workbook objects and a CommandBars collection objects contain CommandBar objects. And, the list goes on, but understanding the object relationships in the automation server is fundamental to its use in Omnis and the third-party manufacturer can only provide the appropriate level of documentation for these relationships. See the Excel documentation for an illustration of the object hierarchy.
221
Chapter 8Automation
You may notice that the above example references a property called xcount whereas the Microsoft Excel automation documentation refers to the property as count. This is because, Omnis already has $count as a core internal notation attribute and has therefore appended x as a prefix. Unfortunately, other automation properties and methods also clash with Omnis internal notation but have not been renamed. To utilise the automation attributes simply add two colons before the name. So $xcount becomes $::xcount. Adding two colons even when they arent required will not have an effect, so it is a good habit to get into. Another example would be to enquire on a particular value in a worksheet:
CValue = objectApplication.$Workbooks(Book1.xls).$Worksheets(Sheet1).R ange(A1).Value
If you require a particular object often, it is beneficial to assign the automation object to a Omnis object variable. To do this simply, create an object variable, with an empty subtype, and then invoke the automation method/property and assign the results. For example:
Do objectApplication.$Workbooks(Book1.xls).$Worksheets(Sheet1) returns objWorkSheet Do objWorkSheet.$Range(A1).$value.$assign(Cell Value)
So, how exactly, do you know what automation objects have what properties and methods? Obviously the best source of documentation is the third-party, which developed the automation server. For example, for Microsoft Office software, you can refer to the vbaxl8 (Excel), vbagrp8 (Graph), vbaoff8 (Office), vbaoutl (Outlook), vbappt (Powerpoint), vbawrd8 (Word), help files. Use an automation object browser such as the OLE/COM Object viewer, which is included with Microsoft Studio. Use the Omnis Interface manager and Values list.
222
Automation Server Functionality And lastly, many Microsoft Applications come with a Macro recorder, which enables you to record user actions as a Visual Basic for Applications, or VBA, script. To illustrate this, follow these simple steps: -
Start Microsoft Word. On the Tools menu, click Macro, and then select Record New Macro. In the Store Macro In drop-down box, select the name of the active document. Make note of the new macros name, and then click OK to start recording. Start a new document. Type one and press ENTER. Type two and press ENTER. Type three. On the File menu, click Save, and save the document as C:\doc1.doc Click the Stop Recording button (or, on the Tools menu, click Macro and then Stop Recording).
To view the VBA code that the macro recorder generated from your actions, on the Tools menu, click Macro, and then click Macros. Select the name of the new macro in the list and click Edit. The Visual Basic Editor displays the recorded macro.
Documents.Add Selection.TypeText Text:="one" Selection.TypeParagraph Selection.TypeText Text:="two" Selection.TypeParagraph Selection.TypeText Text:="three" ActiveDocument.SaveAs FileName:="Doc1.doc", FileFormat:=wdFormatDocument, _ LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= False
Whilst, this isnt valid Omnis script code, it does illustrate the automation properties and methods, and usually it is simply a case of making a few minor modifications such as adding the $ prefix to the names and appending the parenteses to methods.
223
Chapter 8Automation
Built-in Methods
Along with the automation servers methods, Omnis provides additional methods to enable you to manage the server. These methods are: $createobject() creates an instance of the object and may be called before the automation server can be used. $getactiveobject() obtains an instance to a current automation object. $getobject(Filename,[class]) creates an instance of an object from the specified filename and class, if supplied. For example $getobject("C:\CAD\SCHEMA.CAD") $isavailable() returns kTrue if the object variable has a server instance, or kFalse otherwise. Whether these methods exist or not, will depend on the source of the object variable. For example, an object, which originated from an ActiveX, OLE2, or an automation collection, will not have these methods.
Create an instance of the object using $createobject, $getactiveobject or $getobject. And validate that an instance was created by calling $isavailable. Communicate with the object via properties and methods. Finally, terminate the object. Many automation servers provide a method called $quit which should be used to ensure that the instance is terminated.
224
Before you start Omnis, ensure that you have used regsvr32 (a DOS program which is distributed by Microsoft and used to register automation servers) to register the UrlReader server. Create a new object, which is subclassed from the automation object UrlReader.UrlReader.1. To do this either, use the Class Wizard New Sub -class object from the Studio Browser and select Automation>>UrlReader.UrlReader.1 from the list or create an object and change the superclass property to Automation>>UrlReader.UrlReader.1 using the superclass dialog. Now open the method editor for the new object. You will notice numerous methods for the UrlReader object. Two of which will have the suffix event. Automation events have the extension event appended by Omnis. Now override both event methods and add the code Send to tracelog Event triggered, then close the method editor. Create a new window and add a button. Open the method editor for the window and add an object variable called myObj with the subtype that you named your object (in the first stage). Add the following code:
Open the window and the tracelog. Then press the button. Notice that the tracelog will contain Event triggered text.
225
Chapter 8Automation
226
Automation Errors and Limitations Typically a server will return the error code of 80070057 (see Automation errors section) if the parameter wasnt of the correct type. You can coerce variables to another datatype, by preceding the parameter with a constant listed in the table below: Constant Name KAutoBOOL kAutoI1 / kAutoUI1 kAutoI2 / kAutoUI2 kAutoI4 / kAutoUI4 kAutoR4 kAutoR8 kAutoBSTR kAutoDISPATCH kAutoCY kAutoEMPTY The above constants+REF kAutoNULL For example:
Do object.$setvalue(kAutoI4,45)
Automation DataType VT_BOOL VT_I1 / VT_UI1 VT_I2 / VT_UI2 VT_I4 / VT_UI4 VT_R4 VT_R8 VT_BSTR VT_DISPATCH VT_CY VT_EMPTY VT_xxxREF VT_NULL
Datatype description Boolean Value (True or false) Signed / Unsigned Byte Signed / Unsigned short Signed / Unsigned Long 4 byte real 8 byte real Binary String IDispatch * Currency Empty By Reference Null
227
Chapter 8Automation HRESULT codes are difficult to document as they can be defined by both the server application and by the operating system. However, here are a few of the more common codes (which are in hexidecimal): 8000FFFF 80004001 8007000E 80070057 80004002 80004004 80004005 800401F3 Unexpected error Not implemented Out of memory Invalid argument No such interface supported Operation aborted Unspecified error Invalid class string
An automation limitation is Constants, or automation enums, which are not supported for COM objects and OLE2 objects.
Automation Examples
Some of the best examples of automation in Omnis are contained within the automation sample library, but the following illustrate the use of XML, DAO and Outlook in Omnis.
XML
This example requires the file books.xml, which is available from Microsoft. Ensure that you obtain the correct version, which have AUTHOR tags, in the correct case; otherwise you will have to subsitute the AUTHOR tag with another tag in the example code. The variables xml (type Object and subtype Microsoft.XMLDOM.1.0) and element (type Object, no subtype) need to be added to your code.
Do xml.$createobject() Do xml.$async.$assign(kFalse) Do xml.$load("c:\books.xml") Do xml.$getelementsbytagname("AUTHOR") Returns element For #1 from 0 to element.$length-1 step 1 Calculate #S1 as element.$item(#1).$xml OK message {[#S1]} End For Do xml.$quit()
This example loads the xml file and enumerates each AUTHOR tag.
228
Automation Examples
DAO
This example requires the Microsoft Office sample database northwind.mdb. The variables obj (type Object and subtype DAO.DBEngine.36) and database, recordset, both of type Object (no subtype).
Do obj.$createobject() Do obj.$Workspaces(0).$opendatabase("c:\office\northwind.mdb") Returns database Do database.$openrecordset("Select * from Products",4) Returns recordset Calculate #1 as recordset.$fields().$xcount For #2 from 1 to #1 step 1 Calculate #S1 as recordset.$fields(#2-1).$::value Calculate #S2 as recordset.$fields(#2-1).$::name Send to trace log {[#S2]=[#S1]} End For Do recordset.$close() Do database.$close() Do obj.$quit()
This example opens the database file and enumerates each product in the record set.
Outlook 2000
This examples requires variables ol (type Object and subtype Outlook.Application.9) and variables olns, objFolder, ocontacts, and ocontact (all of type Object and no subtype).
Do ol.$createobject() Do ol.$getnamespace("MAPI") Returns olns Do olns.$getdefaultfolder(10) Returns objFolder Do objFolder.$items() Returns ocontacts OK message {There are [ocontacts.$xcount] contacts} Do ocontacts.$getfirst() Returns ocontact For #1 from 1 to ocontacts.$xcount step 1 Calculate #S1 as ocontact.$xfullname OK message {[#S1]} Do ocontacts.$getnext Returns ocontact End For
229
Chapter 9Encryption
Chapter 9Encryption
You can use the following tools to integrate encryption into your Omnis Studio applications.
Blowfish Encryption
Omnis Studio supports the Blowfish encryption algorithm via a non-visual external object which you can use in code to provide a layer of security. Blowfish is a fast and freely available encryption algorithm created by Counterpane (www.counterpane.com). The Blowfish external object contains methods to encrypt and decrypt, as well as initialize the encryption object using an initial key. To create an encryption object, you should create an object variable and specify the Blowfish object as the subtype of the variable. You must initialize the blowfish object with a variable length key using the $initkey() method. For example:
; create Object var blowfish of Blowfish subtype Do blowfish.$initkey("MyKey")
The bIncludeHeader parameter is a boolean to indicate whether or not a header should be appended to the data. If set to kTrue, Omnis will bind the length of the original string to the encrypted data. The header is 8 bytes. You can also use the following methods to encrypt or decrypt Character data:
Do blowfish.$encryptchar("cData",bIncludeHeader) Return binData ; or visa-versa Do blowfish.$decryptchar("cData",bIncludeHeader) Return binData
230
Binary Encryption
Binary Encryption
You can use the encxtea() and decxtea() functions to encrypt and decrypt binary data. The functions are found in the Binary Field group and use the eXtended Tiny Encryption Algorithm (XTEA) to encrypt the data. encxtea(binary,key) Returns the binary result of encrypting binary using the eXtended Tiny Encryption Algorithm (XTEA) with the binary key; the key must be 128 bits long. decxtea(binary,key) Returns the binary result of decrypting binary (previously encoded using encxtea()) with the binary key; the key must be 128 bits long.
String Encoding
You can encode and decode a string using the encstr() and decstr() functions. You can supply a code or Omnis supplies a default key. The functions are found in the String group of functions. encstr(string[,key]) Encodes the string using the key. If omitted, Omnis uses its default value for the key. The return value of encstr() is a string that is difficult to decode without knowing the key. To decode the string, and return the original value, use the decstr() function. decstr(string[,key]) Decodes the string (previously encoded using encstr()) using the key. If omitted, Omnis uses its default value for the key. Note that decstr(encstr(string,key),key) = string.
Calculate lEncoded as encstr('Testing',10) Calculate lDecoded as decstr(lEncoded,10) ; returns the original string 'Testing'
231
Omnis RegAdmin
The Omnis RegAdmin component is a non-visual object that allows you to manage Keys and Values within the Windows Registry on the end-users computer. The Windows Registry provides a means for storing settings and options for the Windows Operating System and its applications. It consists of a number of what are termed Keys and Values. Keys are similar to the notion of folders and are used to structure the registry. Each Key can contain any number of sub-keys and values. Values consist of a name and data pair and are the means for storing settings. The Windows Registry structure is split into a number of logical sections including some default Keys, often termed as hives. These all are prefixed by HKEY, for example, HKEY_LOCAL_MACHINE, or HKEY_CURRENT_USER.
232
Omnis RegAdmin
Opening a Key
Once you have an instantiated object or object reference the next step is to point your object to a key in the registry. This is done using the $openkey() method. This method takes two parameters: the first can be either a kRegAdminKey constant (see below), or an existing RegAdmin object. The second parameter is optional and specifies the path to the key you want to open. For example, if you provide the constant kRegAdminKeyClassesRoot as the first parameter and Applications/omnis.exe as the second, you would open up the key HKEY_CLASSES_ROOT\Applications\omnis.exe. The method returns the flag indicating if the specified registry key was opened successfully, 1 for success. The following Omnis code creates an Object reference to the RegAdmin object and assigns it to iRegAdminRef Object Reference variable. The $openkey() method sets the Object Reference to point to a key in the Windows Registry. If this call fails the OK message reports the error. When youve finished using your RegAdmin object, you have to call the $closekey() method to free up the associated memory.
Do $extobjects.RegAdmin.$objects.RegAdmin.$newref() Returns iRegAdminRef Do iRegAdminRef.$openkey( kRegAdminKeyClassesRoot,'Applications\omnis.exe') Returns #F If flag false OK message Failed to open ... {[iRegAdminRef.$getlasterror]} End If
233
Reading Values
You can read values using the $getvalue() method, but the return value is dependent on the type of registry value you are retrieving. Therefore, to determine the type of the registry value, you can execute the $getvaluetype() method passing in the name of the parameter as the first argument. This returns a kRegAdminValue constant specifying the type of the registry value. Once you have returned the type of the value in the registry, you can call the $getvalue() method with a suitable variable return, as follows:
234
Omnis RegAdmin
Do iRegAdminObj.$getvaluetype(iValueName) Returns iValueType Switch iValueType Case kRegAdminValueMultiSz Do iRegAdminObj.$getvalue(iValueName) Returns lList Case kRegAdminValueBinary Do iRegAdminObj.$getvalue(iValueName) Returns lBinary Case kRegAdminValueNone Calculate lCharacter as '' Default Do iRegAdminObj.$getvalue(iValueName) Returns lCharacter End Switch
Error Handling
Most RegAdmin object methods return a flag to indicate whether or not the call was successful. In the event that the flag returned is false there are two error handling method calls which you can use to report the error. The $getlasterrorcode() method returns the Windows error code associated with the error, and $getlasterror() returns a description of the error provided by the Windows operating system.
235
Chapter 11DDE
Chapter 11DDE
Dynamic Data Exchange (DDE) is a Windows facility similar to OLE that lets Omnis exchange data and commands with other programs running under Windows. To set up a conversation as the client, Omnis uses the Open DDE channel command. An acknowledgment from the server confirms that the conversation can take place, and Omnis issues the transactions using commands such as Request field, Send command, and so on. Before Omnis can act as a server, the Set server mode command lets Omnis respond to certain requests and commands from a DDE client.
In your spreadsheet, copy a range of cells to the clipboard In Omnis, select a field such as a list From the Edit menu, select Paste Link
Omnis as Client
To set up a conversation with a DDE server, you must open a channel to the server and give it a number. You can have up to eight channels open at the same time.
Test if file exists {EXCEL.EXE} If flag true Start program normal (EXCEL) Set DDE channel number {1} Open DDE channel (EXCEL|SHEET1) If flag false Quit method kFalse End If End If
236
Omnis as Client The Open DDE channel command contains the name of the program, 'Excel', followed by the topic name. Note that the delimiter '|' must be entered as part of the parameter. You use the Send field command to send data and the Send command command to send a command to a DDE server. In this example, Omnis is sending monthly sales totals from n1 to column two in an Excel spreadsheet. The value of CUSTOMER is sent to column one; char1 contains a string that includes the row and column numbers to which the data goes.
While PRODUCT=char2 Calculate char1 as con('R',n2,'C',1) ;; Excel row [n2] Col 1 Send field CUSTOMER {[char1]} Calculate n1 as Jans Calculate n1 as n1+Febs Calculate n1 as n1+Mars .... Calculate n1 as n1+Decs ;; totaling the monthly sales Calculate char1 as con('R',n2,'C',2) ;; Excel row [n2] Col 2 Send field n1{[char1]} ;; send total month sales to row n2 col 2 Calculate n2 as n2+1 ;; Row number increased by 1 Next (Exact match) End While
DDE makes extensive use of square brackets, for example, you must include the commands you send inside square brackets. This can lead to confusion since Omnis tries to evaluate square bracket text as an expression. To solve this problem you can Put the text including brackets into a character field and send the contents of the field Use two initial square brackets
Calculate num2 as num2-1 ;; return to last row Calculate char3 as con('R',num2,'C',2) ;; last row column 2 Calculate char1 as con('[SELECT("R1C1:',char3,'")] [NEW(2)][GALLERY.PIE(5, TRUE)]') ; command to be sent to Excel to draw chart Send command {[char1]} Do method (wait) Calculate char1 as '[OPEN("\EXCEL\SALES.XLM",0,0)]' ; command to be sent to Excel to open macrosheet Send command {[char1]} Calculate char1 as '[RUN("SALES.XLM!mclose")]' ; command to be sent to Excel to execute a macro Send command {[char1]} Close DDE channel
237
Chapter 11DDE The DDEExecute message can contain one or more Omnis commands. A string of commands sent in this way constitutes a method. The commands must follow a certain syntax in order to be understood by Omnis. The best way to create the script is to Create the method Copy the method to the clipboard Paste it into a text editor Now you need only incorporate the method lines of the script in your application. Don't forget to edit out the title and error count lines. You can also print the method to a screen report and use the mouse to select the method script and copy in the usual way. This is a simple example written in Word for Windows:
DDEExecute ChanNum, "OK message {Word says Hi!}"
The script form for a method consists of a series of command lines separated by carriage return characters. '&' at the end of a line denotes that the next line is a continuation of the previous line. Each command line converts to a single Omnis command. The syntax for a command line is exactly the same as that in the right-hand list of the method editor. Case is not significant, and you can include extra spaces. The script cannot contain local, class or task variables since these must be already declared before using the variable. The method created from the script is in its own self-contained format that deletes as soon as the script finishes executing. When you convert the text to a method, you can get a syntax error. Omnis returns an error code of -1 plus an error string to the server. If there are multiple errors, Omnis only reports the first. If the Omnis debugger is available, Omnis still creates a method on the method stack, replacing the syntax error with a Breakpoint command. If there are no syntax errors, the created method is pushed onto the method stack and immediately executed. A reply is not returned to the sender of the Do Script event until the created method (and all its called methods) finishes executing, or an error occurs when executing the method (or any of its called methods), or until a command which returns control to the user is encountered (such as Enter data or any of the Prompt for... commands which open a non-modal window). If an error occurs and the debugger is available, the debugger is opened at the error in the usual way; otherwise, no error is reported to the user by Omnis. Methods which display an OK message or other modal windows do not count as returning control to the user, so the sender may be waiting for a reply for the period that the message is being displayed; this means that eventually the sender may receive a time-out reply to the DDEExecute message.
238
Omnis as Client
Requesting Data
You can request data from another program with the Request field command. It takes two parameters: the name of the data item in the server program and the Omnis field name into which the data is placed:
Request field S3 {CCNAME} Request field n5 {FEXCHANGE}
The control method traps each DDE event (evSent) caused by the incoming field values. The fields are sent in the order they were requested, that is, TEL, NAME, ADDRESS. When the ADDRESS field has been received, the control method updates the files and cancels Enter data mode. The example is an interesting way of transferring data from one Omnis library to another, and can be driven from the server library using Send advises now to specify when to send the field values.
239
Chapter 11DDE
241
Chapter 11DDE If Omnis is in Enter data, Prompted find or Import data mode, the appropriate status is returned. If the client requesting the status has DDE control, Omnis sends the status message You have control. If no program has DDE control, Omnis sends the status message No control. Alternatively, the data message contains an item indicating that Omnis status is busy.
Ack Bits
When Omnis sends a Data message as server, the fAck bit is set which requests the client to send an acknowledgment. When receiving Data messages as a client, Omnis sends an acknowledgment if requested to do so by the incoming fAck bit set in the incoming Data message from the server. These acknowledgment bits are used by Omnis to determine the value of the flag after DDE commands. Omnis as server returns a busy message when it is running methods, printing reports or running a menu option. This happens when field values are requested, poked or commands sent. As a client, Omnis returns a 'busy' Ack when running a method, printing a report, or executing a standard menu option. Omnis never returns a 'busy' Ack message in response to data which is the result of a Request message because Omnis waits for the response.
242
The client wishes to start a conversation with Omnis on the topic of PERSON.LBS. For Omnis to respond positively to an Initiate message, the name Omnis must be present in the message. It is possible to send an Initiate message to Omnis with the program name 'Omnis', and a null topic. 'Null' in this context means that no value has been given for the topic, i.e. no library name has been supplied. Omnis responds with a positive ACK message containing the name Omnis, and the name of a currently supported Omnis library. Omnis sends one positive ACK message for each library which it supports. If any parameter value sent to Omnis as part of an Initiate message is invalid, Omnis sends a TERMINATE message to the client. To request data from the Omnis CRB, the field name in the Request message must be a valid Omnis field name as defined in the Omnis file classes. The clipboard format required in the Request message must be CF_TEXT. To send data to Omnis via the Poke message, the field name must be currently valid in the Omnis file classes, and the text type must be one of the supported clipboard formats.
Start Omnis and switch on the server options with Accept advise requests (Accept) and Advise on Redraw (Advise) In your Word document, select the Insert>>Field menu item From the list of Word field types, choose DDE Auto Add the name of Omnis, the Omnis library and Omnis field to the parameter line for the Word field
243
Chapter 11DDE
ddeauto Omnis DDE2 C_COMPANY
With the Show field codes option turned off, Word displays the Omnis field and updates it when the value changes. This method uses Word as the client, and you need to enable Omnis as a DDE server. Word issues the 'advise request' when you create the field or when you open the document containing the field. You can use Word Basic to set up DDE links to Omnis, but remember to put Omnis in your PATH statement. Heres a simple example
Sub MAIN Shell "Omnis.EXE \Omnis\DDE\DDE2.LBS" ; Wait for Omnis to start For x = 1 to 1000 Next Beep ChanNum = DDEInitiate("Omnis", "DDE2") Print ChanNum Print DDERequest$(ChanNum, "C_FRSTNAME") DDEExecute ChanNum, "Next" Print DDERequest$(ChanNum, "C_FRSTNAME") DDETerminate ChanNum End Sub
244
245
Terminology
A number of Apple terms have been introduced into Omnis when dealing with Apple events; in error messages, for example. However, some Omnis terms have been used to replace System 7 terms, where these clash; the word 'attribute' is an example. Initially, the client application starts sending Apple events in order to use the services of the server application. Since Omnis can both send and receive Apple events, it can act as both client and server. Indeed, Omnis can send Apple events to itself, and in this case is both client and server. This is the default for many Omnis commands using Apple events; for example, Set event recipient without a parameter sends events from Omnis to itself. Source/target While the client is initially the source of Apple events, and the server the target, the server can, in fact, send its response to an event back to the client, in the form of a further event. When this happens the source and target are reversed. Recipient The recipient of an Apple event may be any object that can understand them; a named computer; a file in a server application; a field within that file. Note that Omnis can be the recipient of its own events; it can also be the recipient of Apple events created by other applications, such as Hypercard. Recipient tag This is a parameter that allows Omnis to store the path to a particular recipient with a name or tag, and so avoid constant re-prompting when using multiple recipients. Message/parameter Many commands include messages and parameters. For example:
Send DataBase event {Set Field ('THERE','HERE')}.
This Omnis command is a member of the Send DataBase event group; the message 'Set Field' is selected from an option list, and the parameters are added, if required, in the Message box, including the plain brackets ().
246
247
Chapter 12Apple Events The Send Database event {Use table ('TABLENAME)} command must be issued with a valid table name (file class name for Omnis) that is used for all subsequent record (row) operations. This Omnis command sends the Does Field Exist event before setting the current active table to ensure that there is such a valid table, and also resets the 'table index' to point to the first record in that table. Use Table may also be used to reset the table index to the first record in a table. The following example returns the type of the data in field CHARFIELD (Character, Boolean, etc.) and stores it in the Omnis field DATATYPE.
Send DataBase event {Does field exist ('CHARFIELD')} If flag true OK message (Sound bell) {Yes, CHARFIELD exists.} Else If flag false OK message (Sound bell) {CHARFIELD not found.} End If Send DataBase event {Get field type ('CHARFIELD','DATATYPE')}
This example returns the size of the field CHARFIELD (character, Boolean, etc.) and stores it in the Omnis field DATASIZE.
; mapping of Apple/Omnis data types? Send DataBase event {Get field type ('S5','DATATYPE')} OK message {field [S5] is of type: [DATATYPE].} Send DataBase event {Get field size ('CHARFIELD','DATASIZE')}
Get size CHARFIELD returns the size of the field/container in Bytes, e.g.
; create local var DATASIZE (Character) Send DataBase event {Get field size ('CHARFIELD','DATASIZE')} OK message {field 'CHARFIELD' has size of: [DATASIZE]} ; The next command: Send DataBase event {Set field ('S1', S5)}
Sets the value of the recipient field S1 to the value of the Omnis variable S5:
; This example sets S1 from S5 Send DataBase event {Set Field ('S1', S5)} Redraw (S1) ; and to get the value, use: Send DataBase event {Get field ('S1','CHAR_FIELD')}
Gets the value of the recipient field S1 and returns it to the Omnis variable CHAR_FIELD.
248
Scripts Similarly:
; Create local vars Nets (Char) and Message_date (Short date 1980) Set event recipient {('DocsCI:Q4O:V2:Contractors')} Send DataBase event {Get field ('NETWORKS','Nets')} Send DataBase event {Get field ('DATE','Message_date')} OK message {Number of networks is [Nets] on [Message_date]}
Note differences in use of quote marks in the Get field and Set field commands. If quotes are used for the second parameter of the Set command the actual string is sent; i.e., the characters 'S' and '5' in the example above. The Send Finder commands let you send many standard events to the Finder. However, only two of the events can also be sent and received over a network. Both are compulsory commands and can be received by libraries even when Disable receiving of Apple events has been run. These two commands are Send Finder event {Open Files Send Finder event {Print Files Sent without parameters, these commands prompt the user for filenames with a file open dialog. Note that the command Send Finder event {Empty Trash} permanently removes deleted files. The Are you sure? warning is not given. There is an error reporting mechanism within Omnis which uses two hash variables #ERRCODE and #ERRTEXT; these allow target programs to pass back errors into your library and allow your methods to analyze errors in more detail than a simple 'flag false'.
Scripts
You can send a series of commands to a target program in the form of an executable script using the Do script commands, such as Send Core event {Do Script (FIELDNAME)} and Send Core event returns ReturnField {Do Script (FIELDNAME)}. Omnis can send or receive scripts, and the format of the script depends on the particular program being used by the source. The syntax for Omnis scripts is defined simply by the form of the commands as displayed by Omnis in the method editor. A useful tip when creating scripts is to write and debug the method in Omnis in the method editor, copy the required method lines to the clipboard, and paste into the appropriate field. To split a command between two lines of script, you add '&' to the end of the line and continue the command after the carriage return character. When the script is read by Omnis, the two lines are concatenated with a space in the position of the &. When each script is
249
Chapter 12Apple Events received by Omnis, it is converted into method form and, if free from syntax errors, pushed onto the method stack and executed immediately. This is a simple example written in Hypercard:
on mouseUp Send "OK message {Hypercard says Hi}" to program "Omnis " end mouseUp
Variables used in the script must be hash variables or % local variables. To send this method:
Find first on CSEQ Do method Total Prepare for edit Calculate %TOTAL as %TOTAL*17.5+%TOTAL Update files Next
you would type the commands into the field as they appear in the Omnis method editor, one command per line, and send the value of the text field (LTEXT) to the target Omnis program:
Set event recipient Send Core event {Do script (LTEXT)} ; Sending to myself
This illustration assumes that you are sending events from Omnis to Hypercard. The Set event recipient command is first used to see if the target program is already in the Application menu; if not, it is launched.
250
Scripts
Set event recipient {Hypercard} ; Checks Application menu to see whether HC is running If flag false Send Finder event {Open files} ; prompts the user to locate Hypercard, add it to the App ; Menu and open the Hypercard stack 'SalesStack'. Alternatively, ; the file path could be given as a parameter: Send Finder ; event {Open files ('Mac OSHD:Apps:Hypercard:SalesStack')} ; in which case you could add the following condition: Set event recipient {Hypercard} If flag false OK message {Can't start Hypercard} Quit method flag false End If End If ; with 'SalesStack'open, and Hypercard the recipient ; you can send a HyperText message Send Core event {Do script ('Go Next')} OK message {Error handling: Code is [#ERRCODE], text is [#ERRTEXT]} ; This has opened a stack and advanced one card ; Now publish a field on this card Send Core event {Create publisher('Card Field TEXT','SalesStack-TEXT')} ; Second parameter not required here ; Next, send HC a value from Omnis Send Database event {Set field ('Card Field TEXT','Omnis Text')} ; And finally, get a value back from HC Send Core event returns S1 {Get data ('Card Field TEXT')}
Note the different uses made of the commands Send Core event and Send Core event returns. Clearly, the latter is capable of getting data from the target program. The data passing protocol uses either text or PICT and Omnis uses its usual character-to-number conversion routine when receiving numbers from another program such as Hypercard. If an event is sent which returns an error to Omnis, the hash variables #ERRCODE and #ERRTEXT are used to store the error code and message. The flag is set if the event evokes a positive response (no errors are returned). Omnis waits for a reply for the default timeout period and, while waiting, allows the user to cancel by pressing Cmnd-period or Cancel if a working message with a Cancel button is visible. If there is a syntax error when converting the text to a method, an error code of -1 together with an appropriate error string is returned in the reply message to the sender. If there are multiple errors, only the first is reported. If the Omnis debugger is available, a method is
251
Chapter 12Apple Events still created and pushed on the method stack. A syntax error is replaced by a Breakpoint command containing the error text. The debugger for a method created from a script is titled External Script; you can modify the method, but Save and Revert To Saved are not available. If there are no syntax errors, the created method is pushed onto the method stack and immediately executed. A reply is not returned to the sender of the Do Script event until one of the following occurs: The created method (and all its called methods) have finished executing An error occurs when executing the method (or any of its called methods) A command which returns control to the user is encountered (such as Enter data or any of the Prompt for commands which open a non-modal window) If an error occurs, an error code of -2 with the usual error string is returned in the reply message to the sender. If the debugger is available, the debugger is opened at the error in the usual way, but otherwise no error is reported to the Omnis user. Methods which display an OK message or other modal window do not count as returning control to the user, so the sender may be waiting for a reply for the period that the message is being displayed; this means that eventually the sender may receive a time-out reply to the Do Script message (the default time out period set by Apple is currently around a minute but the sender can override this). If the script contains a Quit method Returns Result command, Omnis returns this value to the caller as a keyDirectObject parameter in the return message. If the value is a picture, it is sent as typePict; else it is sent as typeChar (lists are converted into their tab-delimited forms). If, for example, there is an Enter data command in the script, the reply is returned to the sender when Enter data is encountered, and any return value which has been set at that stage is included in the reply. You can use Send Core event returns ReturnField {Do Script SCRIPTFIELD} if the result of running a script returns a value (for example, sent to Hypercard ), which is placed in the Omnis ReturnField.
252
Scripts The following methods illustrate some simple uses of Apple Events
Set event recipient {'MagicMac'} ; Send to MagicMac already on my Application Menu If flag false OK message {Error [#ERRTEXT], code [#ERRCODE]} Quit method flag false End If Send Finder event {Open files ('MagicMac:Sheet36')} ; This initializes MagicMac on my workstation .. deal with errors etc. Send Finder event {Print files} ;; prompts you for sheets to print Send event {Create publisher ('Work')} ;; Publishes document 'Work' Send event {Set data ('Spread1',LIST1)} ;; Sends LIST1 to spreadsheet
The following example method uses Apple events to open a remote library called 'Contractors' , which includes a file class (an Omnis file class is a 'table' in Apple terminology) called 'Site details'. The local library has a field, S4, that is used to test the link, in particular the existence and value of the field CO_NAME (Company name) in 'Site details'. If the script needs to use variables, as in this case, they must be ready-defined such as hash variables or % local variables.
; Open Library method, behind a pushbutton On evClick Send Finder event {Open Files('DocsCI:Docs:V2:Contractors')} Prompt for event recipient {REM} Use event recipient {REM} Send DataBase event {Does table exist ('Site details')} If flag false OK message {No file class of that name} Quit method End If Send DataBase event {Use table ('Site details')} Send DataBase event {Does field exist ('CO_NAME')} If flag false OK message {No such field as CO_NAME} Quit method End If Send DataBase event {Get field ('CO_NAME','%S4')} OK message {CO_NAME IS [%S4]} Send DataBase event {Define Returns ('%S1','%S2','%S3')}
253
compiles and executes AppleScript cScript. The method returns zero for success, or a nonzero error value. The result of script is returned to cResult. If the script fails, cError receives error text. If $runapplescript is called by a web client method in the Multi-threaded server, and the script executes for longer than $root.$prefs.$timeslice, Omnis schedules another thread to execute in parallel with the script.
254
Scripts When creating/using AppleScripts to be run in Omnis, any sub routines must be declared before the main process, otherwise you will receive an error -1753 in Omnis. So typically, you should construct your script as follows:
On ListToText(PartA,PartB) Set... Set ... Return .... End ListToText Tell application xyz Set myparts to ListToText(abc,def) End Tell
255
Index
Index
#ERRCODE, 170, 171 #ERRTEXT, 170, 171 #ICONS, 18, 27 $add() Remote form instances, 16 $addarealayer(), 117, 130 $addbarlayer(), 117 $addboxwhiskerlayer(), 117 $addcandlesticklayer(), 117 $addclass(), 171, 173 $addhloclayer(), 117 $addlinelayer(), 117, 130, 139 $addmark(), 114 $addpointer(), 134, 135 $addring(), 134, 137 $addscatterlayer(), 117 $addsplinearealayer(), 130 $addsplinelinelayer(), 130 $addtext(), 114, 150 $addtrendlayer(), 117 $addzone(), 114, 142 $canclose, 82 $clearcachedforms(), 27 $clientaddress, 37 $columnheadings, 119 $connectbytessent, 36 $connectionid, 37, 81 $connectiontime, 37 $construct(), 34, 99 $construct(), Remote tasks, 77 $convdate(), 114, 122 $createkey(), 234 $createobject(), 159, 162, 173, 224 $cursor, 25 $datacombine, 116, 124 $dataname Graph field, 118 Graphs, 111 $deletekey(), 235 $deleteref(), 190 $deletevalue(), 235 $designdpi, 95 $dispose(), 114 $enablesenddata, 20 $event(), 16, 97 Tasks, 35 $events, 97 Web components, 16 $findobject(), 114, 154 $formatvalue(), 114, 150 $getactiveobject(), 224 $getcolors(), 114, 141 $getmainlayer(), 115 $getobject(), 224 $getradialaxis(), 130 $getvalue(), 234 $getxaxis(), 117 $getyaxis(), 117 $iconpages, 18, 25 $imagesearchpath, 149 $isavailable(), 224 $issecure, 37, 52 $javaoptions, 188 $lastresponse, 37 $listsubkeynames(), 234 $majortype, 111, 113 $maxtime, 36 $maxusers, 35 $minormetertype, 111 $minorpolartype, 111, 129 $minortype, 113 $minorxytype, 111, 116 $multipleclasses, 26 $new(), 162 $newref(), 160, 190, 233 $openkey(), 233 $prelayout(), 115, 139 $redraw(), 21 Graphs, 115 in remote forms, 21 $reqcurbytesreceived, 36 $reqcurbytessent, 36 $reqmaxbytesreceived, 36 $reqmaxbytessent, 36 $reqtotbytesreceived, 36 $reqtotbytessent, 36 $requests, 36 $runapplescript(), 254
256
Index
$screensize, 88 $senddata(), 20 $serverport, 49 $serverstacks, 38, 49 $setcolors(), 115, 141 $setlinearscale(), 115 $setlogscale(), 115 $setvalue(), 234 $showmessage(), 21 Remote tasks, 35 $showurl(), 21 $slicemove(), 127 $snapshot(), 115, 151, 153 $startfield, 16 $superclass, 164 $swapxy, 121 $timeout, 37 $timeslice, 49 $tooltip, 25 $usejavaoptions, 188 .NET .NET Framework, 156, 157, 158 Data Types, 166 Why use .NET, 156 .NET Arrays, 169 .NET Classes Adding, 171 .NET Object types Overloading, 178 .NET Objects, 159 Constructing, 162 Defining, 159 Subclassing, 164 Using, 166 .NET Objects component, 158 80, port setting, 49 Accept advise requests command, 240 Accept commands command, 240 Accept field requests command, 240 Accept field values command, 240 ActiveX, 67 Amend Startup Task option, 33 Angular charts, 133 Apache Server Extension, 50 Apple event Commands, 245 Apple events, 245 Scripts, 249 Sending and receiving, 247 Terminology, 246 Apple Scripts, 254 Area charts, 107, 119 Arrays, 169 Object Arrays, 181 ASP, 62, 69 AUTH TLS FTP, 102 Automatic installation, 58 Automation, 221 Errors, 227 Events, 225 Examples, 228 Omnis variables, 226 Bar charts, 106, 107, 118 Begin critical block command, 41 Binary types, 182 Blowfish encryption, 230 Box whisker charts, 107, 121 Breakpoints Web client, 14 cacerts, 102 Caching Forms, 26 Candlestick charts, 108, 123 CDML, 148 Certificate Authority Certificates, 102 Character types, 182 Chart types, 106 ChartDirector, 106, 148 classid, 67 classname, 26 CLASSPATH, 185 Client connections, 37 Client form caching, 27 Client method debugging, 23 Client method execution, 22 Color palettes, 141 Colors Changing graph elements, 141 Complex Parameter types, 167 Component Download Manager, 62 Component Store, 15 Creating form controls, 15 Components Web client, 58 Components, Remote form, 15 Connections pane, Monitor, 33 Constants, 170 Context menus
257
Index
Remote forms, 30 Control Manager library, 63 Controls, Remote form, 15 Create New Monitor Task option, 33 ctrlmgr.df1, 63 ctrlmgr.lbs, 63 Cursors, 25 Web Client, 25 DAO, 229 Data handling Optimizing, 19 Data Types, 166 Date formatting, 147 DDE, 236 Ack bits, 242 Creating a DDE link, 236 Events, 242 Omnis as client, 236 Omnis as server, 240 Printing reports to a DDE channel, 240 Programming, 243 System topic, 241 Using Word, 243 DDEExecute message, 238 Debugging web client methods, 23 Deploying your Omnis web solution, 46 Deployment Web Client tools, 61 Disable receiving of Apple events command, 247 Do script commands, 249 Download Manager, 62 Drag and drop Web client, 25 Drag and Drop Web Client, 25 Drilldown, 140 Web client, 154 Dynamic Data Exchange, 236 Edit menu Creating a DDE link, 236 Enable receiving of Apple events command, 247 Encryption, 230 Encryption, Blowfish, 230 End critical block command, 41 Enter data command, 240 Enums, 170 Environment variables Java, 185 evAfter, 17 evBefore, 17 evBusy, 35, 36 evClick, 17 evDoubleClick, 17 Events, 16 Remote tasks, 35 evIconPicked, 17 evIdle, 35, 36 evPost, 81 evPreLayout, 138 evRejected, 35 evSetPicked, 17 Execute On Web Client, 22 Firefox, 57, 58 Floating numbers, 177 Form caching, 26 FTP, 101 FTPConnect, 102 Gantt charts, 121 GET method, 72 Graph layers, 138 Graph methods Common, 114 Graph properties Common, 111 Graph2 component, 106 Graphs Web client, 153 History pane, Monitor, 33 HLOC charts, 108, 122 Hosting ISP, 52 HTML forms, 72 HTML Pages Web client, 65 HTML Report task wizard, 33 HTTP, 101 HTTP headers, 81 https, 37 HTTPS, 52 Icon Editor, 19 Icon pages, 18, 27 Icons, 18 IIS, 69 Image Compiler, 63 Image Compressor, 65 Images
258
Index
Embedding images, 149 IMAP, 103 Inherit from Monitor task option, 32 Installation Automated installers, 58 Installers, 57 Creating your own, 59 Integers, 176 Interface Manager, 174 Internet Explorer, 57, 58 ISP web hosting, 52 Java Environment variables, 185 Java Class Cache, 188 Resetting, 189 Java Objects, 184 Java Servlet, 51 Javascript, 69 JavaScript, 62 Keys, Registry, 233 kG2meter, 113 kG2pie, 113 kG2polar, 113 kG2xy, 113 kSSZ (screensize) constants, 88 kSSZDesktop, 88 Labels, 150 Layers, 138 Line charts, 119 Linear charts Meter charts, 133 List Types, 168 listenv(), 187 Load sharing, 42 Load Sharing Enabling, 43 Load sharing mechanism, 44 localclient folder, 29 loopback address, 68 Major type, 113 Menus Remote form, 30 Message timeout command, 240 Messages, 21 Remote tasks, 35 Meter charts, 133 Methods, 134 Properties, 133 Meters, 110 Method Overloading, 176 Method stacks, 38 Methods Client method execution, 22 Minor type, 113 Mobile applications, 86 Deployment, 97 Mobile Client, 87 Mobile forms, 88 Monitor task wizard, 33 Monitor window , 33 Multipart form data, 82 Multi-threaded server, 38 Multi-threading Secure web commands, 105 NET Objects, 156 nobackground property, 26 np_orfc.dat, 58 np_orfc.dll, 58 NT Servers, 48 NTSERV.EXE, 48 Number Floating dp types, 177, 183 Number formatting, 146 Number Long Integer types, 176, 183 Object Arrays Nested, 181 oclass, 66 oheight, 66 OK message command, 20 olibrary, 66 OMDNOBJS.DLL, 158 OMDOTNET.DLL, 158 Omnis Data Types, 166 Omnis datafiles, 40 Omnis Mobile Client, 87, 97 Omnis preferences Server port, 49 Omnis server Load sharing, 42 Server usage, Monitor, 33 Omnis Server, 38 Commands, 40 Installation, 47 Multi-threaded, 38 Port number, 49 Omnis Web Client omniswebclient.js, 58, 66 Omnis web server plug-in Installation, 50
259
Index
OmnisClass, 66 OmnisClass parameter, 68 for direct access, 72 OMNISCLASSPATH, 187 OMNISJVM, 185 OmnisLibrary, 66 OmnisLibrary parameter, 68 for direct access, 73 Omnispic, 18 OmnisPIC, 27 OmnisServer, 66 OmnisServer parameter, 68 for direct access, 72 Load sharing, 42 OmnisUnicodeServer, 66 omniswebclient.js, 58, 66 omnisxi.so, 59 omupdate.exe, 59 omweb.exe, 57 omwebcli, 87 omwebie.cab, 58 Open DDE channel command, 236, 237 Open window command, 21 Open windows, 20 OpenSSL, 102 orfc.class, 58 orfc.dat, 63 Orfc.dat, 58 Orfc.dll, 58 orfcexec.dll, 59 Orfcgui.dll, 58 Orfcmain.dll, 58 Orientation for Mobile, 88 oserver, 66 ounicodeserver, 66 Outlook, 229 Overloaded Data Types, 176 Overloaded Methods, 180 Overloaded Types, 169, 182 owebserverscript, 66 owebserverurl, 66 owidth, 66 Param1 to Param9 parameters, 68 Parameter Data Types, 166 Parameters, 167 Substitution, 142 Pattern Matching, 176 Persistent remote tasks, 81 Pie charts, 108, 126 List structure, 127 Pie properties, 126 Plain Remote Task, 14 Plain task wizard, 32 Polar area charts, 109 Polar charts, 109, 129 List structure, 130 Methods, 130 Properties, 129 Polar line charts, 109 Polar Spline Line / Area charts, 109 POP3, 101 Port number, Omnis Server, 49 POST method, 74 pPostData, 82 pPostResult, 82 Prelayout event, 138 Prompt for data file command, 20 Prompt for input command, 20 Prompted find command, 240 Prompts, 20 putenv(), 187 Quit method <data>, 78 Quit method <error>, 81 Quit method <url>, 77 RdtaServlet, 51 RegAdmin, 232 Errors, 235 Keys and Values, 232 Object variable, 233 Regasm.exe, 158 Registering the component, 158 Remote form objects Events, 16 Remote forms, 12 Caching, 26 Changing forms, 27 Controls, 15 for Mobile, 88 Icons, 18 Mobile use, 87 Multiple forms, 28 Programming, 19 Subforms, 25 Testing, 14 Thick client, 29 Remote Forms Wizards, 12
260
Index
Remote menu class, 30 Remote menu classes, 30 Remote menus, 30 Remote task classes, 31 Creating new, 34 Remote task wizards, 32 HTML Report, 33 Monitor, 33 Plain, 32 Submit, 34 Remote tasks, 14 $construct(), 77 Client access, 36 Events, 35 Instances, 34 Persistant, 81 Reports Printing to a DDE channel, 240 Request field command, 236, 239 Scatter charts, 107, 120 Screen size, 88 for Mobile, 88 Secure sockets, 37, 52 Secure web commands, 101 Send advises now command, 240 Send command command, 236 Send Core event command, 245 Send Database event command, 245 Send field command, 237 Send Finder event command, 245 Send to DDE channel command, 240 Send Word Services event command, 246 Server configuration, 49 Server Side Includes, 71 Server Usage pane, Monitor, 33 Servers NT service, 48 Servlet, Java, 51 Session pools, 42 Set advise options command, 240 Set event recipient command, 246 Set server mode command, 236, 240 SHTML, 71 Simple Parameter types, 167 Smartphones, 86 SMTP, 101 SQL sessions, 42 SSI, 62, 71 SSL, 101 Start server command, 39, 40 Stop server command, 39, 40 Subclassing .NET Objects, 164 Subforms Web client, 25 Web Client, 25 Submit task wizard, 34 Task properties, 36 Tasks Remote tasks, 31 Threads, 40 Time formatting, 147 Timeouts, 36 Tooltips, 25 Web Client, 25 Trace log, 158 Trend charts, 124 Ultra-thin Omnis, 72 Use Existing Monitor Task option, 33 Userpic, 18, 27 Web applications, 11 Web client Database access, 39 Graphs, 153 Web Client Image Compiler, 63 Image Compressor, 65 Installers, 57 Web Client Components, 58 Web Client tools, 61 Web components, 15 Notation, 15 Web server plug-in Installation, 50 WebServerScript, 66 WebServerScript parameter, 68 WebServerUrl, 37 WebServerURL, 66 WebServerUrl parameter, 68 Windows 98, 157 Windows Mobile, 86 Create remote form, 88 Deployment tool, 97 Editions, 87 Windows Registry, 232 Windows Vista, 157 Windows XP, 157 Working message command, 20 XCOMP folder, 158
261
Index
XML, 228 XML config file for Mobile, 98 XY charts, 106, 116 List structure, 118 Yes/No message command, 20 Yield to other threads command, 41 Zones, 142
262