You are on page 1of 262

Extending Omnis

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

About This Manual

About This Manual


This manual describes all the features and capabilities in Omnis Studio that allow you to create full-featured enterprise, web and mobile applications. It contains information about extending your Omnis application to the web and mobile devices, as well as topics as diverse as graphs, .NET and Java objects. You should read the Omnis Programming manual before this one to learn about the general tasks and techniques required for creating Omnis applications, but if you are completely new to Omnis, you should start with the Introducing Omnis Studio manual which contains a short tutorial. In addition to these manuals, there are the Omnis Reference manuals, and a comprehensive Help system describing the Omnis Studio commands, functions, and the notation, available from within the Omnis Studio development environment using the F1 key.

10

Omnis Web Architecture

Chapter 1Developing Web Applications


This chapter describes how you can develop applications that can be accessed via the web using the Omnis Web Client (thin client), or standard HTML (ultra-thin) forms. Specifically, it describes how you create remote tasks and configure the Omnis Server to run your Omnis web applications. Creating remote forms using the Class Wizards is described in the Tutorial and the GUI Classes chapters in the Introducing Omnis Studio manual. The Tutorial provides a good introduction to creating remotes forms and building a simple web application. If you are developing applications for Windows Mobile based devices, you should read the whole of this chapter since many of the topics covered here, such as using remote tasks, remote forms and setting up the Omnis Server, are relevant to mobile applications. Note that some editions of Omnis Studio do not allow you to test Web Client based applications in design mode.

Omnis Web Architecture


Omnis Studio provides thin client and ultra-thin client access to your web application via the Omnis web client and standard HTML forms. The Omnis web client is a web browser plug-in, either an ActiveX or Mozilla based plug-in, that lets you embed visually rich and interactive forms into standard HTML pages placed on a web server. The web client allows some methods to be executed on the client machine, in order to optimize and enhance the user interface. The server side of your Omnis web application comprises a standard web server, the Omnis Server that runs your Omnis library, and your database server(s). All these parts need not run on the same machine, but typically would be on the same LAN or subnet, communicating via TCP/IP. The web server and the Omnis Server can be located on a Windows, Linux, or Mac OS X machine. The web server would store your entire web, including any HTML pages containing the Omnis web client and your remote forms. The Omnis library would contain all the form class definitions, business rules, and application logic, while the database server would be an industry-standard database server, such as Oracle, MySQL, PostgreSQL, Sybase, DB2, or any JDBC or ODBC compliant database such as MS SQL Server. You can use an Omnis database (data file) as your data 11

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.

Creating Remote Forms


You can create a remote form using one of the wizards or templates available in the Studio Browser: New Remote Form creates a new blank remote form class containing no web components and without a remote task class; if you create a new form using this template you need to create your own remote task class and set the $designtaskname property of the remote form yourself File Form creates a remote form based on an Omnis file class; the wizard creates a field for every data field in your file class and provides a Next and Previous button to view your data Multiform lets you create a complete web site containing a home page, navigation bar and any number of Omnis remote forms. The wizard creates an HTML page with a horizontal or vertical frame and navigation buttons linked to the different forms. In the wizard you can select existing remote forms to include in your web site, or create new remote forms from the available wizards and templates

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.

Testing Remote Forms


In order to run and debug a remote form, the development version of Omnis lets you open a remote form in your local web browser. You can press Ctrl/Cmnd-T while designing your remote form, or choose Test Form from the forms context menu, to display your form in your browser. The Omnis web client establishes a connection to your local copy of Omnis. Note you can debug methods that run on the Omnis Server as well as client methods. You can set breakpoints in the form code (such as in the $construct() of the form) and step through the code in the Omnis debugger as usual. When you test the remote form, and Omnis reaches a breakpoint in your code, operations will halt in your browser and you need to switch back to Omnis in order to view or step through your code.

14

Remote Forms

Remote Form Components


The Omnis Component Store contains over 50 different web components that let you create interactive, feature-rich environments for your web applications. The remote form wizards add components to your forms automatically, but if you are creating your own forms or adding fields to an existing form, you use the Component Store to add components. When you have created a component in your remote form, you can modify it by changing its properties in the Property Manager. Note that all data-bound components should use an instance variable for their data container; class variables should not be used in remote forms. All the remote form components are described in the Window and Form Components chapter in the Omnis Programming manual. To create a web component from the Component Store

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.

Web Component Variables


The majority of the web components have their own Custom tab in the Property Manager containing properties specific to the component. Where a component requires a $dataname, such as an entry field or list, you must assign an instance variable to the remote form field; you cannot use an Omnis file class field directly in a remote form field. You can however assign a file class field value to an instance variable and display this in your remote form. For example, you can load a list from file and assign it to an instance variable of list type and use the list instance variable to populate a sidebar component. In addition to using simple instance variables, you can also set $dataname to a column in an instance row variable, using the syntax <row variable name>.<column name>, such as iSqlRow.Pic_Name.

Web Component Notation


Web components are a special type of External component, and in general, their property names do not clash with built-in or standard field properties. However, when a web component property has the same name as a standard built-in field, you must access the web 15

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)

$add() method in Remote form instances


Note that, unlike window instances, the $add() and $remove() methods are not available for the $objs and $bobjs object groups in remote form instances, that is, you cannot add objects (or background objects for that matter) to a remote form once it is instantiated and opened in the client browser. If you want to add objects to a remote form using the notation, you must add the object to $objs and $bobjs object group in the remote form class and re-open the form in the client browser.

$startfield for remote form fields


The $startfield property is available for remote forms. The property specifies which field in a form will get the focus when the form is opened; it takes the field number as specified in the $order property of the field. For positive values, it is the order number of the initial enterable field of the remote form. If you specify a negative value, and a subform is created from the remote form class, the field specified in $startfield becomes the current enterable field on the form.

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.

Standard Field Events


Most web components report the evBefore and evAfter events, which are triggered when the user is about to enter or leave the field, respectively. You can use the On command to detect events in your event handling methods. For example, in the $event() method for a single-line edit field you could use the following commands to detect the evBefore or evAfter event.
On evBefore ; do something.. On evAfter ; do something else..

Pushbuttons and Lists


Pushbuttons, button areas, and all the list type components report the evClick event, as well as evBefore and evAfter; and some list types also report the evDoubleClick event. The Booklist in the Books example library (see the Examples section in the Welcome screen) is a Headed List field and has the following $event() method, which is executed when the user double-clicks on a line in the list:
On evDoubleClick Do method $findnow ; executes the $findnow method contained in the form. ; the method loads the details for the selected book and ; redraws the fields on the form

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

Chapter 1Developing Web Applications


On evIconPicked Set current list iSideBarList ; makes the list var behind the sidebar the current list Load from list {pLinenum} ; loads the line from the list using the line number ; pLinenum param is sent to the method Do method $ctask.$buildbooks (iBookGroup) ; executes the $buildbooks method in the current task using ; the current value of iBookGroup from the selected list line Calculate iBookList as tBookList ; transfers the data from tBookList to iBookList instance var ; contained in the remote form Do $cinst.$objs.BookList.$redraw() ; redraws the Booklist field on the form Do $cinst.$senddata(iBookList) ; sends the iBookList data to the client

Remote Form Events


Remote forms generate the evFormToTop event only, which you can detect in the $event() method for the remote form. See the Multiple Forms section later in this manual. Note that in addition, the $construct() method of the form is called by default when a form is opened on the client, but in this case no event is generated.

Icons and Icon Pages


You can add an icon to several of the remote form components, such as pushbuttons, transbuttons, the tile object, while some of the standard form objects, such as radio buttons, check boxes, and tree lists, also require icons to work correctly. To add icons to any of the components on your remote form, you have to add the icons Icon page to the $iconpages property of the form, shown under the General tab in the Property Manager. The icon pages for any web components in a remote form are sent to the client, together with the class data, when the form is opened. Omnis does not send individual icons to the client, but complete icon pages as defined in the #ICONS system table in the current library, or the Omnispic or Userpic icon datafile. The $iconpages property for a form specifies a list of icon pages which are to be sent to the client when the form in opened. In the Property Manager you can click on the droplist for the $iconpages property and select a page or a number of icon pages. The names of icon pages are stored in the $iconpages property separated by commas, and different pages from the #ICONS system table, the Omnispic, and Userpic icon data files (in that order) are further separated by semi-colons. For example, two pages called Books and General from the #ICONS table in the current library and one page called Embedded Colors from Userpic datafile are stored in the $iconpages property as:
Books,General;;Embedded Colors

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.

Creating your own Icons and Icon Pages


To optimize your web application, you could create a single icon page containing all the icons needed by a particular remote form, or set of forms, or your web application as a whole. In this case, the client would only need to fetch a single icon page, rather than multiple pages. You can create your own icons and icon pages using the Icon Editor and store them in either the #ICONS system table, or Userpic icon datafile (you should avoid adding to or changing the Omnispic icon file). You can copy and paste icons from existing icon pages, but you must be careful what icon id you give new or copied icons. See the Omnis Programming manual for more details about using the Icon Editor.

Programming Remote Forms


When writing methods for a remote form class or its components, you must consider that the class may be instantiated many times, depending on how many clients are connected simultaneously. Although you can use any Omnis command or notation and create methods of any length, you must choose carefully what commands you use and how you program certain operations. You can handle events by executing the event handling method on the client machine, or an event may call and execute a method on the Omnis Server. When you design your application, you have to decide which events are best handled on the client or the Omnis Server, and you need to consider what impact any programming will have on general performance of your application. You cannot modify a remote form instance at runtime, that is, you cannot add objects to the form instance, or remove them. The same applies to instance variables. Such changes must be made to the remote form class prior to opening an instance, if they are required. In addition, invalid notation will generate an error on the server and the client will be suspended.

Optimized Data Handling


When an event occurs triggering a server method, Omnis checks if the value of any instance variables has changed on the Omnis Server, and if any variables have changed their new values are sent back to the client automatically. This occurs for all variables that are changed on the server, and not for those variables that are unchanged. This data handling system ensures that only the data that has changed and needs to be updated on the client is sent to the client. This data handling system operates when the remote task property $enablesenddata is set to kFalse, which is the case for all new remote tasks. For the vast majority of cases, this mechanism can be used to handle the data between the client and the Omnis Server, but if you do need to control the data sent to the client you can override the default data handling mechanism.

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.

Open windows and User Prompts


You should not use any commands or programming in your library that would result in a prompt appearing on the Omnis Server. For example, if you use the standard OK message command in a server executed method, the message appears on the Omnis Server, not in the clients browser and the server is effectively halted since the message is not cleared until you click OK (imagine if the Omnis Server is in a remote location, clicking the OK box may be impossible); see below for how to show a message on the client from a server executed method. If a message or prompt remains open in the Omnis Server all client to server interaction is suspended and the clients browser is, in effect, locked up. This situation is not serious during development on your local machine, since you can switch back to Omnis and clear the message box or prompt, but for an application deployed on the web, this may be disastrous and would severely inhibit useability! There are many commands that you cannot use in server executed methods for the above reason, they include: OK message, Yes/No message, Working message, Prompt for input, Prompt for data file, and so on.

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')

Redrawing Remote forms


Window related method commands such as Redraw do not work in the web client and should not be used in a web application. In general, you should try to use notation, such as the $redraw() method for the current object; for example, in the case of redrawing an object, you can use the notation like $cinst.$objs.Object.$redraw(), or $cobj.$redraw() depending on the context of the current method. The $redraw() method of a remote form instance allows you to redraw the current remote form instance: $redraw([bSetcontents=kTrue ,bRefresh=kFalse ,bBobjs=kFalse]) redraws all objects on the form. If you pass bSetContents as kTrue, the data for each object is set using its $dataname. Note that this will use the data currently available on the client. If you pass bRefresh as kTrue, the client draws the form contents, for any objects requiring a screen update. Note that if you pass kFalse, the objects requiring a screen update will still be drawn, but not necessarily before $redraw() completes. Passing bBobjs as kTrue redraws background objects. You can also use $redraw() as a method of a remote form object, in which case it only affects that object.

Opening a Browser window on the Client


The $showurl() method of a remote form instance allows you to display an HTML page in a separate browser window or HTML frame on the client machine:
$showurl(cUrl[,cFrameName,cBrowserProperties])

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.

Client Method Execution


You can specify that a remote form method is to run on the client rather than the server. In particular, you can perform simple calculations or process events on the client, thus avoiding the overhead of sending events and messages between the client and server, and reducing the network traffic and workload on the server. Methods that run on the client can contain only a subset of the complete Omnis command language (the Omnis Help lists the commands you can run on the client; press F1 and navigate to the Command Index). In general, command groups that allow client execution include:
Calculations Constructs Methods Events Message boxes

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.

Calling methods from client methods


If you want to call a server method from a client method you should use the command Do method $cinst$servermethod rather than the Do $cinst$servermethod command.

Client Method Debugging


You can debug methods that have been specified to execute on the client as well as server executing methods. For example, you can set a breakpoint in a method that is to execute on the client, test the form using Ctrl/Cmnd-T, and Omnis will drop you into the debugger at the breakpoint. From thereon, debugging of a client method is the same as debugging any other method in Omnis with only a few minor restrictions, as listed below. You can only debug client methods in read-only mode. The Debug menu in the method editor has a new option called Kill Client to halt debugging and close the current browser.

Web client method commands


The following debug commands are supported in web client methods. Breakpoint Open trace log Trace on Trace off Send to trace log All these commands trigger a debug message to the Omnis Server and a debugger window is opened. The commands Variable menu command and Set break calculation do not work on the client.

23

Chapter 1Developing Web Applications

Stopping client debugging


To stop debugging, you can: Clear all breakpoints and select Go. Clear the method stack Kill the client by selecting the Kill Client option from the Debug menu. This disconnects the client and closes the browser.

Client debugger restrictions


The following lists the menus in the debugger window and what changes/restrictions there are when debugging client methods. Modify menu is not be available. View menu no change Debug menu Read-only mode is selected and disabled, plus the new Kill Client option. Client methods can only be debugged in read only mode. Options menu no change Breakpoint menu Clear field breakpoints is disabled. (not applicable) Instances menu no change Stack menu no change Kill Client Debug menu option The Debug menu in the debugger/method editor has a new option called Kill Client to halt debugging. This option disconnects the client and closes the browser, and is a convenient option since to stop debugging you would have to: clear all breakpoints, hit go, and than close the browser or clear the method stack and then close the browser Either of these would cause further calls to the server when the client disconnects, which may be undesirable since the client may have been left in an unknown state. The Kill Client option clears all current breakpoints, clears the method stack, disconnects the client, and closes the browser.

24

Remote Forms

Drag and Drop


The Omnis Web Client allows you to drag and drop data between fields in remote forms. The drag and drop functionality is the same as for window class fields, except that kDragObject or kDragDuplicate are not supported in remote form fields. The drop mode for remote form fields can be either kAcceptAll or kAcceptNone, that is, none of the other kAccept... constants are valid for remote form fields. Drag and drop events must be processed by a $event() method marked as 'Execute on client'. See the Omnis Programming manual for more information about drag and drop.

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

Chapter 1Developing Web Applications

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.

Client Form Caching


In addition to the server form caching, the Omnis web client caches any remote forms it has downloaded from the server on the clients hard disk (the formcache folder is in the local webclient folder). The client caches the remote form class data, the instance variable definitions, icon pages, and font tables. The client cache stores the modification dates of each item. When the client connects to the form at a later date, it passes these modification dates to the server, and the server returns only those items that have changed. Icon caching IMPORTANT NOTE: The icon pages receive their modified data from the #ICONS system table in the current Omnis library. If you include icons from the Omnispic or Userpic icon datafile and you update them, you must modify the #ICONS class to force all icons on the client to be updated; there is no other way for the Omnis Server to tell if icons in Omnispic.df1 or Userpic.df1 have changed, other than checking the modification date of the #ICONS system table.

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().

Opening Remote forms on the thick client


You can open a remote form in the thick client (runtime) as well as, or instead of, in the web client. In effect, Omnis displays a remote form on the local client by opening the web client plugin in a standard Omnis window. There is no network communication since all events and method execution will occur in the local Omnis runtime environment. This feature is currently available under Windows and Mac OS X only. Remote forms have a property called $openinwindow. If this is set to kTrue, the remote form will be opened in Omnis on the local machine, not in a web browser. If $openinwindow is set to kFalse in a remote form and its $open method is executed, it will be displayed in the clients browser using the web client. A folder called localclient is located in the Omnis Development and Runtime product trees containing a set of web client components that allow remote forms to be displayed on the local client. If you are going to deploy an application containing remote forms that are opened in the thick client only, you do not need to install the Omnis Server, or a web server, and no HTML pages are required, but the end user will require an Omnis Runtime as in all thick client applications. You may, however, create an application that uses remote forms locally and remotely, in which case end-users will require a copy of the Omnis Runtime as well as the web client, and you will need to install the Omnis Server, and so on, as with any other web based application. Remote forms opened in the thick client behave in more-or-less the same way as their web client counterparts, but you should consider the following: 1. The $showurl() method will not work in a remote form opened in the thick client, since in this case the remote form is not opened in a web browser. 2. A remote form opened on the thick client creates a window instance (which is added to $iwindows) as well as the usual remote form and remote task instances. 3. If you execute $cinst.$windowinst in a remote form instance (where $cinst is the remote form) a reference to the window instance will be returned if the remote form has been opened in the thick client. 4. If you execute $cinst.$rforminst in a window instance (where $cinst is the window instance created by opening a remote form locally) a reference to the remote form will be returned if the window is derived from a remote form.

29

Chapter 1Developing Web Applications

Features not supported in the Web Client


#MODIFIED
Note that the use of #MODIFIED is not supported for Remote Form components; this variable only works for window class fields.

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.

Creating Remote Menu Classes


The new remote menu is implemented using a different mechanism from existing menu classes and instances. The remote menu editor is very similar to the editor for existing menu classes, except that there is no access to methods, because the new remote menu class does not contain any methods. In addition, the properties of the new remote menu class and its objects are different from the existing desktop menu class. You can associate a remote menu with a remote form, or a remote form control, by setting the $contextmenu property of the form or individual control. In addition, you can add menus for the left and right menus of the Windows Mobile menu bar, by setting the $menunames property of the remote form. If you do not specify a menu for the right-hand menu, the client may supply its own default right menu, depending on the MenuBar setting in the configuration file for the Mobile Client. Objects have a $disabledefaultcontextmenu property. If true, the default context menu for the object will not be generated in response to a context click ($clib.$disabledefaultcontextmenu and $cobj.$disabledefaultcontextmenu must both be false for the default menu to be generated). The default menu could be the clipboard menu for the edit control. The key property of a remote menu line is $commandid. This allows you to execute the appropriate code when the menu line is selected; see the next section. There is a new group, $remotemenus in the library object, containing all remote menu classes for the library. There is no $iremotemenus group.

Remote Context Menu Events


Context menus for remote forms work in a similar way to context menus for windows, that is, if an object is clicked on and it does not have a context menu, the client will display the

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.

Creating Remote Task Classes using Wizards


You can create an Omnis remote task from scratch or by using one of the templates or wizards provided in the Studio Browser. To create a remote task using a wizard

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.

Plain Remote Task Wizard


The Plain Task wizard creates a basic template remote task that is suitable for linking to most simple remote forms. The Plain remote task also has an $event() method containing a template event handling method that detects evBusy and evIdle events in the task. You can add your own code to handle these events. The Plain remote task has a $construct() method containing a parameter variable called pParams of type Row Variable. This row variable can receive all the parameters of the ActiveX/plug-in, including the remote form name, task name, etc, and up to nine additional parameters which are embedded in the HTML page containing the form. When you create a task using the Plain Task wizard you can specify the Inherit from Monitor task option. This option adds a set of monitor classes to your libra ry which allows you to record client connections associated with the new plain task you are adding to your library. If you check the Monitor option, the wizard prompts you for details about the new monitor task. If your library does not contain a monitor task, you need to specify the

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.

Monitor Remote Task Wizard


The Monitor wizard creates a number of monitor classes, including a new task and monitor window, that allow you to record remote connections between clients using the Omnis web client and the Omnis Server. The wizard prompts you to enter the name of the new Monitor remote task and window, in most cases however, you can accept the default names. The Amend Startup Task option lets you add code to the Startup_Task in the current library to open the Monitor window at startup; this is checked by default. Monitor Window The Monitor window, called wMonitor by default, has three panes. The Connections pane shows the connections grouped by remote form name. The History and Server Usage panes let you monitor the traffic flow on your Omnis Server and provide some general information about server usage. You can print the server usage using the Print Report button.

HTML Report Task Wizard


The HTML report task wizard creates a remote task that generates an HTML report on-thefly and returns it to the client. The $construct() method contains code to print a report to HTML using the temp directory object, and return a URL or error message to the client. The wizard lets you base your HTML report on an existing Omnis report class. You can also specify the folder where the temporary report pages are placed, and you can add an object class to your library to clean out the contents of the temporary folder after a time period has elapsed. In addition, you can add the new HTML report task to the Monitor task. The HTML Report wizard creates an HTML file containing a Print Report button, using the name TaskName.htm, and places it in the Omnis HTML folder. When the button on the HTML form is pressed, the $construct() of the task creates a new HTML page in the webserver\omnishtml\[reportname] folder which contains the report. This page is then returned to the user. The Cleaner object sweeps the omnishtml folder in your webserver and deletes expired reports every minute.

33

Chapter 1Developing Web Applications

Submit Remote Task Wizard


The Submit wizard creates a remote task and HTML file containing a submit form. The HTML form created by this wizard allows direct access to your database, and does not use a remote form or the Omnis web client. See a later chapter for more details about using standard HTML forms for direct access. The $construct() method in the Submit task contains variables to handle the data from the form in the associated HTML file. The wizard places the Submit HTML file in your Omnis HTML folder. The Submit task can be inherited from the monitor task. The first pane in the wizard lets you define the fields to appear in your HTML Submit form. A Submit and Reset button are included on the form automatically. You will need to amend the $construct() code of the remote task to return the response you want to generate when the user has pressed the Submit button on the form. This is documented in the tasks $construct() method.

Creating a New Remote Task Class


The Remote Task wizards in the Studio Browser let you create many types of remote task, but you can create a completely empty task using the New Class>>Task option in the Studio Browser. You modify a remote task class in the method editor. You can place any code that you want to run when the remote task is instantiated in the $construct() method. You can add any other custom properties and methods to the task, as well as any type of variable including instance variables.

Remote Task Instances


When the Omnis web client first connects, Omnis first creates an instance of the Remote Task Class as specified by the Remote form class to which you are connecting (using the $designtaskname property of the form). Omnis passes a parameter variable of type Row to the $construct() method of the Remote Task Class.. This parameter contains a column for each parameter of the ActiveX or Netscape plug-in, meaning that there are columns for WebServerUrl and WebServerScript for example. In addition to these parameters, you can specify up to 9 user-defined parameters of the ActiveX or Netscape plug-in. You add these parameters in a similar way to the standard parameters such as WebServerUrl. The parameters are called Param1, Param2,, Param9. The value of each parameter has the form name=value. The row variable passed to $construct() has a column for each user defined parameter specified in the HTML for the ActiveX or plug-in, where the name and value of the column are set from the name=value value of the user defined parameter. For example, if Param1 has the value MyParameter=3, the row variable will have a column called MyParameter, which has value 3. When working with remote forms and the remote task $construct() method terminates, it should do so without returning a value if the connection is to go ahead, that is, Quit method without specifying a return value. If you need to pass an error back to the client, you can use 34

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.

Remote Task Events


For remote tasks, the evBusy and evIdle events are sent to the $event() method during the lifetime of a connection: evBusy is sent when Omnis receives a request from a client, evIdle is sent when Omnis is about to return the result of a request, i.e. the task instance is about to become idle. The following example, shows the code for the $event() method in the Monitor task created using the Monitor task wizard:
On evBusy If iMonitorOpen Do iMonitorRef.$setstatus($cinst,kTrue) Returns lServerBusyFlag If lServerBusyFlag Quit event handler (Discard event) ; server cannot handle request End If End If On evIdle If iMonitorOpen Do iMonitorRef.$setstatus($cinst,kFalse) End If On evRejected Do $cinst.$showmessage(pErrorText)

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.

Client Access Properties


Remote tasks instances have a number of properties that let you monitor connections to your Omnis application. $connectbytessent specifies the number of bytes which have been sent to the client during the connection. This property is set after $construct() has been executed. $requests specifies the number of events executed on the server. Excludes connect and disconnect messages. Updated prior to evBusy message. $reqtotbytesreceived the total number of bytes received from the client for all requests. To calculate an average per request, you can divide this value by $requests. Updated prior to evBusy message. $reqtotbytessent the total number of bytes sent to the client for all requests. To calculate an average per request, you can divide this value by $requests. Updated prior to evIdle message. $reqmaxbytesreceived The largest block in bytes received from the client for all requests. Updated prior to evBusy message. $reqmaxbytessent The largest block in bytes sent to the client for all requests. Updates prior to evIdle message. $reqcurbytesreceived The number of bytes received from the client for the current request. Updated prior to evBusy message for the current request. $reqcurbytessent The number of bytes sent to the client for the current request. Updated prior to evIdle message.

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

Chapter 1Developing Web Applications

The Omnis Server


The Omnis Server runs your application files (libraries) and provides the interface between your web or mobile based clients, the web server, the business rules and processes in your application and data located in your server database. In this sense, the Omnis Server is the central and most important component for all your web and mobile applications. The Omnis Server allows multiple requests to be processed concurrently, allowing smoother allocation of available processor time and avoiding any lengthy delays on the client. To handle these multiple requests, the Omnis Server is multi-threaded. By default, the Omnis Server is a standard single-threaded server handling client requests in a strictly first-come, first-serve basis; client requests are queued, with each request being handled only when the previous request has completed. You can however handle multiple client requests concurrently using the Omnis Multi-threaded Server, which you can enable by executing the Start server command on the Omnis Server. The Multi-threaded Server maintains a pool of method stacks that can process web client requests simultaneously. The pooling mechanism allows a balance to be struck between performance and server resources - the number of method stacks in the pool is configurable with the $root.$prefs.$serverstacks property.

Multiple Method Stacks


The standard single-threaded Omnis Server has only a single method stack to process methods. Broadly speaking, once a method call has been pushed onto the method stack no other method call can begin to execute until the first call has completed. For the majority of web client applications this is fine for processing events, particularly if some processing is performed on the client and your web server receives relatively few hits or requests for data. By contrast, the Omnis Multi-threaded Server contains a pool of method stacks which are available to process multiple client requests, and this is appropriate for more data intensive web applications where lengthy calls to a server database are required, or for web sites that receive higher volumes of traffic. When a request to execute a method is received from a web client, that method call is pushed onto any unused stack or, if there are no unused stacks, the message is queued until one becomes available. Each method stack runs in its own thread, which means that if a method stack is stalled (for example, it is waiting for the database server) the other stacks will continue to execute. Potentially, the Multi-threaded Server may have to cope with a very large number of simultaneous clients, each with their own remote form and remote task instances. Typically though, a small proportion of clients will require the use of the server at any one time. In fact, multi-threading does not increase the server processor time available, it just allows the available processor time to be allocated in a smoother way. The method stack pool mechanism allows a balance to be struck between performance and server resources - the number of method stacks in the pool is configurable with the $root.$prefs.$serverstacks property, which is set to 5 by default. 38

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).

Using the Server


When the Multi-threaded Server starts up, it opens the libraries, data files and SQL session pools required by the clients (see below for the description of a SQL session pool). You need to issue the Start server command to cause the method stacks and associated threads to be created. The Start server command can specify an optional stack initialization method; when specified, this method is pushed onto every client method stack and allowed to execute (so if $serverstacks is 5 it will execute five times), so it can be used to initialize the state of the method stacks. The Start server command generates a fatal error if, due to lack of resources or some other reason, it is unable to complete successfully. When you want to stop the server, you should issue the Stop server command, but quitting the Studio program achieves the same result. When the server is active, Omnis continues to be responsive to events on the server and could, for example, display a window with 'Start server' and 'Stop server' buttons. It is not recommended that the server program performs any substantial tasks while it is deployed and in use listening for client requests. Any runtime errors generated by client methods are reported in the trace log (using a similar mechanism as errors during library conversion), but you can override this default behavior by making sure each client method stack has an error handler. You can use the stack initialization method call for the Start server command to define an error handler for each method stack. Note that you cannot debug methods running in a remote form or task instance, after you have called the Start server command in a development version of Omnis.

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.

Omnis datafile access


You can access the built-in Omnis database (i.e. Omnis datafile) on the Multi-threaded Server. The list of open data files is shared amongst all the method stacks and all the data files that might be used by the clients should be opened before the Start server command is issued. Each method stack has its own set of CRBs for the read/write, read-only and memory-only files and also has its own main file, find tables, and the various modes used by the native data file commands. Since these belong to a method stack and not a client it is important that client methods do not make any assumptions about the modes, contents of the CRBs, etc. between method calls. In particular, there is no way that a client can assume that a find table exists between method calls. These restrictions apply equally to a single threaded Omnis Server when it is acting as a web client server.

Omnis Server Commands


There are some new commands that you can use to control the Multi-threaded Server which are contained in the Threads command group in the Omnis method editor.

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

The Omnis Server

Begin and End critical block


These commands are used to denote a section of code which needs to execute in single threaded mode without allowing other client methods to execute. For example:
Set current list cList Begin critical block Build list from file End critical block

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.

Yield to other threads


The Yield to other threads command is a hint that the executing thread is waiting for other threads and is prepared to yield its processor time. It can be used when waiting for semaphores (since with the Multi-threaded Server another client stack could be holding the semaphore), as follows:
Do not wait for semaphores Repeat Prepare for edit If flag true Break to end of loop End If Yield to other threads Until break

Commands which are not available to a client


The following commands are not available for methods running on the Multi-threaded Server. They usually generate a 'Command not available when executing a client method' fatal error but some (such as the Debugger group) simply do nothing:
Enter data Prompted find The Libraries group The Classes group Pre V30 SQL commands

41

Chapter 1Developing Web Applications


Open data file Prompt for data file Create data file Close data file Open lookup file Close lookup file The Data management group The Message boxes group The Debugger group Quit Omnis

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.

SQL Session Pools


Suppose the Multi-threaded Server has N method stacks, and therefore N threads capable of processing methods on behalf of clients. This means that at any one time, there can be at most N SQL sessions in use. However, the Multi-threaded server may have many more than N current users. If you are using SQL, you need a potentially large number of sessions to the database server. There is nothing wrong with this in itself, and there are occasions when you might want to use database access permissions, to control the tables and columns accessible to different users. If this is the case, you require a separate session for each user. However, if all users have the same access permissions, you really only need N SQL sessions. This can significantly reduce the resource usage of the server. SQL Session Pools provide a way to do this. A SQL Session Pool is a set of multi-threaded DAM sessions, which can be shared by clients. Typically, you would create a session pool with one session for each method stack. Details of how to use SQL Session Pools can be found in the Methods chapter of the manual Omnis Studio Reference.

Server Load Sharing


Load sharing allows a pool of Omnis Server processes, running on one or more machines, to serve clients. Once a client connects to an Omnis Server process, all subsequent requests for that client need to be handled by the same Omnis Server process, since the process contains the instance data for the client. Therefore, load sharing provides a mechanism that assigns a new client connection to an Omnis Server process. The OmnisServer parameter in an HTML page normally has the syntax: [(IP address|domain name):](service name|port number)

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.

Enabling Load Sharing


To enable the load sharing process you need place the LSP program on your web server, or a machine connected to your web server. It is a single executable called Omnislsp.exe (Windows) or omnislsp (Linux and Mac OS X). A configuration file (omnislsp.ini) must be made to accompany the Omnislsp program, and this takes the following format:
[Setup] Port=6001 QuietMode=0 BucketSize=100 LogLineThreshold=16 Pool1=Omnis [Omnis] PollTimer=10 Server1=123.145.71.123:7001 Server2=123.145.71.124:7002

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.

Using version 2.x and 3.x Web Clients


A 2.4 client or earlier will receive an error if it tries to connect to a 3.x Omnis Server, set up for load sharing. If you want 2.x clients to be able to connect to 3.x Omnis Servers using load sharing (perhaps to enable the 2.x client to be updated to 3.x), you can do so by specifying an additional server address in the OmnisServer property in your HTML page containing the web client plug-in. For example:
OmnisServer = "OMNIS,194.131.70.122:6000;194.131.70.122:5912" OmnisServer="OMNIS,6000;5912" or

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.

Deploying Your Omnis Web Application


Having designed your remote forms and tasks in your Omnis library, and tested your web application locally in the development version of Omnis, you are ready to deploy your application to the web using the Omnis Server. You need to place your Omnis library on a Windows, Linux, or Mac OS X server with the Omnis Server (which is an Omnis Runtime serialized with a special Web Deployment serial number, which you must purchase separately), and add your HTML pages to your web server. Note that the majority of the information in this section regarding the setup and configuration of the Omnis Server and the Omnis web server plug-in equally applies to deploying mobile applications; see the Mobile Development chapter for specific details about setting up mobile clients. Before end users can access your web application, they will need to download and install the Omnis web client. Under Windows, you can prompt the user to install the web client automatically using the cab files (supplied in the \clientserver\client\omnis\auto-installers folder in the main Omnis folder). Otherwise, users will need to download the web client installer and run it manually. You can use the installers supplied on the Omnis Studio CD and Omnis web site, or create your own, especially if you want to provide your end users with only a subset of the web components. This section describes how you: install the Omnis Server, and add your Omnis library to the Server tree install and configure your web server including the web server plug-in or Java Servlet supplied by Omnis copy your HTML files and web client installers to your web server set up your HTML pages containing the Omnis web client; this involves editing the HTML pages created for you by the form wizards in Omnis and incorporating the pages (or just the ActiveX/Object definition) into your web site pages as appropriate; alternatively, you can use the HTML wizard in the Web Client Tools option

46

Deploying Your Omnis Web Application

Installing the Omnis Server


This section deals with the configuration of the Omnis Server, installed from the Omnis Server folder on the Studio DVD. You need to install the Omnis Server on a Windows, Linux, or Mac OS X server and serialize it with a Web Deployment serial number. Note that you cannot use a standard multi-user Runtime serial number for your Omnis Server; in this case you must use a web serial number designed for Omnis web client access. The server does not need to be located on the same machine as your web server, but it must be a Windows, Linux, or Mac OS X server. For testing and debugging you can use the Omnis development version, but for deployment you should use the Omnis Server. You need to place any libraries containing your application in the Startup folder within the Omnis Server tree, so that Omnis automatically opens them when it starts up.

Linux Server Setup


You can install and run the Omnis Server under SuSE Linux 9.2 or Red Hat 9.2. The following installation guidelines are for SuSE Linux. In most Linux distributions, the access to /usr/local/ requires root privileges, so you need to login as root in order to install the Omnis Server on a Linux machine. You can install the Omnis Server using the omserver.rpm file; this will install Omnis into the folder:
/usr/local/tigerlogic/osxxweb/

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

Chapter 1Developing Web Applications

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.

Setting the Omnis Server Port Number


Having installed the Omnis Server, you need to set its port number or service name. The port number must be an available TCP/IP port number on the Omnis Server. The number can be between 1 and 32767, but you must not use 80 or any other number used for e-mail, FTP, or other services. During development, you can leave the $serverport preference set to zero and Omnis will choose a free port automatically. However, since youll be running your Omnis web application using the Omnis Server, you have to set its server port number. You should use a high number for the $serverport setting, preferably a four or five digit number, for example, 5912: choosing a port number in the range 5000-6000 should be fine. In the development version of Omnis, you can set the port number in the Omnis preferences by entering the port number in the $serverport preference. To edit the Omnis Preferences in the Omnis Server using the Property Manager, select the Tools>>Options/Preferences menu option, click on the Prefs option in the Studio Browser and the Omnis preferences will be displayed in the Property Manager. In the Omnis Server you can set the port number in the Server Configuration dialog, available under the File>>Server Configuration menu option (note this option is only available in the Omnis Server when it is serialized with a Web Deployment serial number). The Server Configuration dialog lets you enter the server port number. The Server stacks ($serverstacks) parameter lets you specify the number of method stacks (and therefore threads) on the Omnis Server, which will be created when you execute the Start server command. The Timeslice ($timeslice) parameter lets you specify the duration (in 1/60 th second units) of the execution time slice for a server thread. When you click OK in the Server Configuration dialog and if the Omnis Server is already listening, you are prompted to restart Omnis, otherwise the Omnis Server starts to listen on the specified port using the new parameters. You can set the Omnis Server port using the command Calculate $prefs.$serverport as 5912. 49

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.

Installing the Web Server Plug-in


You need to install the appropriate Omnis web server plug-in in the correct location on your web server, for example, in the /cgi-bin, /scripts, or /webapps folder. Typically a web server will have a place to store all executable code accessible via HTTP over the Internet. This is often the /cgi-bin or /scripts folder, but it can be any folder configured to allow execution. You need to place the web server plug-in, such as the omnisapi.dll (IIS) or mod_omnis.so (Apache), in this folder and ensure that the web server is set up correctly to enable it to be executed. The name and location of the plug-in should be specified in the WebServerScript parameter of your HTML files containing your remote forms.

Apache Server Plug-in


The Apache module for Linux is called mod_omnis.so and is located in the clientserver\server folder in the main Omnis tree. The Apache module works with Red Hat 9.x, and other Linux distributions. This module is faster than the nph-omniscgi server extension. Two versions of the Apache web server plug-in are provided in the clientserver\server folder, under the main Omnis folder, to upport Version 2 and Vesion 2.2 Apache web servers. To install the Apache module

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

Deploying Your Omnis Web Application

Installing the Java Servlet


Omnis Studio includes a Java Servlet web server plug-in that allows you to run your Omnis web applications with any web server that supports version 2.3 of the Servlet API. For more information about Java Servlets, see http://java.sun.com/products/servlet Web servers that comply with Java Servlet API 2.3 include the Apache TomCat and Jetty web servers, but there are several others. Some are listed here: http://java.sun.com/products/servlet/industry.html The Java Servlet allows Omnis remote forms to connect to an Omnis Server via a Java web server. In this respect, the Servlet is the Java equivalent of the ISAPI, CGI or the regular Apache plug-in available in Omnis Studio. The Java Servlet is called RdtaServlet and can be found in the Omnis Studio installed tree in the clientserver\server\servlet folder. Inside the Servlet folder, the servlet files are in the following folder structure:
servlet | - WEB-INF | - rdtaserv.dll (Platform dependant) | - web.xml | - classes | - com | - rdta | - RdtaServ.class

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>

ISP Web Hosting


If your web site is hosted by a third-party, such as an ISP, they will need to place the Omnis web server plug-in in their cgi-bin folder, and furthermore they need to provide you with a direct connection to the Internet. Your ISP may want to test the web server plug-in, usually the case for any files you place in their cgi-bin folder, and this is often very expensive. Alternatively, you may consider having your own local web server specifically for running your Omnis web application and, if necessary, link to it from your main web site hosted by your ISP. If your Omnis web application uses a web site hosted by an ISP you will need to adjust your port settings in the Omnis Server and HTML files. In this case you can use DomainName:Port or IPAddress:Port in your port setting.

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

Deploying Your Omnis Web Application

Web Server Plug-in Configuration


In Omnis Studio 5, you can configure the Web Server plug-in via a separate configuration file, allowing greater security and control over user access to your Omnis web or mobile application. It is not necessary to configure the web server plug-in in most circumstances, but this functionality provides added flexibility and security. The parameters specified in your configuration file can provide default connections for clients, simplifying the post command required to connect to the Omnis Server. The configuration file should be placed in the same directory as your Web Server plug-in. Access and Security Using the web server plug-in configuration file you can restrict access to an Omnis Server Configure Server parameters The configuration file allows you to override parameters for the Omnis Server, or in effect, provide default parameters if the oserver parameter is blank in your cgi parameters in your html; in this case the value would be taken from the configuration file. Post content to Remote tasks the configuration file allows you to pass HTTP Post content to the Omnis remote task.

Server plug-in activation


The new functionality in the Omnis Web Server plug-in is built into the plug-ins supplied with the Omnis Server installation, but you have to rename plug-in itself to activate the new functionality. mod_omnis.so If you are using mod_omnis.so under Linux or Windows, you need to change the value of the location in your http.conf or equivalent apache configuration script to /omnis_apacheini, for example:
<location /omnis_apacheini> SetHandler omnis-apache </location>

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

Chapter 1Developing Web Applications

Creating a Configuration file


The configuration file should be named omnissrv.ini and be placed in the same directory as your Web Server plug-in, for both Windows and Linux. The format of the configuration file mirrors that of a Windows .ini file and is defined as follows: Section names are contained in square brackets e.g. [SectionName]. A section ends when another section begins or at End Of File (EOF). Comments are lines beginning with a semicolon (;). All text following a comment is ignored until the line is terminated. Keys are of the form keyname=value where keyname is a unique identifier within the section and value is the value of the specified key. Section names, key names and key values must not contain white space. Section names and key names are case sensitive. The new functionality in the Web Server plug-in is controlled using specific named sections in the configuration file. The omnissrv.ini file can contain the AllowConnectionsTo section which controls access to the Omnis Server. The .ini file can also include either a DefaultConnection or OverrideConnection section (but not both), which either provide default parameters for the Omnis Server or override parameters posted to the Omnis Server from the http web server. Controlling Server Access You can control access to your Omnis Server by including the [AllowConnectionsTo] section in the configuration file. This section contains a list of key names of the form address<n> where n is a sequentially numbered character starting at 1. When this section is present, connections to Omnis Servers are limited to those defined in the specified key values. In the event that the oserver parameter is defined as a port number, only the port number is required. For example, in the following AllowConnectionsTo section connections are limited to Omnis servers running on the local machine on port 5920 and the remote machine 192.168.0.2 on port 5920.
[AllowConnectionsTo] address1=5920 address2=192.168.0.2:5920

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&param1=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

Chapter 1Developing Web Applications


/omnis_apacheini?OmnisClass=remoteTask&OmnisServer=192.168.0.1:5920& OmnisLibrary=TEST&param1=1234&param2=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. 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&param1=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&param1=value1&param2=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

Deploying Your Omnis Web Application

Web Client Plug-in Installers


To use your Omnis web application, an end user must first download and install the Omnis web client plug-in. You can provide a page on your web site to allow the user to download and/or Run the Web Client installer, with a link to each of the installers for each platform and browser type. Under Windows only, it is possible to allow users to download and install the web client plug-in automatically using the so-called smart web client installers; for Internet Explorer users these are Windows .cab files that will run automatically when the user first visits a web page containing a remote form, and for Firefox users a .xpi file is provided. Web client installers for most popular web browsers and platforms are provided on the Omnis Studio CD, and to download from the Omnis web site at http://www.omnis.net/downloads. If you want to ensure your users get the most up-to-date web client installers, you can link to the Omnis web client download page on our web site.

Windows Web Client installer


There is only one Web Client installer for Windows XP/Vista that supports all the most popular web browsers, including Internet Explorer, Firefox, Safari, Opera, and all other Netscape compatible browsers. Both the ActiveX plug-in (required for IE) and the Netscape-type plug-in (required for all other browsers) are installed into the same folder and the appropriate one is used when a Web Client based web page is displayed. The new Windows installer is called omweb.exe, and installs the Web Client plug-ins in a user defined directory, although a default directory is supplied. The default destination provided in the Web Client installer under Windows NT/XP is:
C:\webclient

Under Windows Vista, the default destination is:


C:\Users\<name>\AppData\LocalLow\TigerLogic\webclient

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

Chapter 1Developing Web Applications

Automatic Installation (Windows IE and Firefox only)


It is possible to allow users to download and fully install the web client automatically, when they first visit a web page containing the web client plug-in. This automatic installation of the web client is enabled using special installers that you have to place on your web server (or users can download automatically from the Omnis ftp server). The automatic installers are available for Windows only using the Internet Explorer or Firefox web browser. Configuring your Omnis Web Server to support Automatic Installers To take advantage of the automatic installers, you need to use the HTML template file created for you when you tested your remote form. The HTML file calls into a javascript file called omniswebclient.js, which is located in the omnis\html folder in the development version of Omnis Studio. This file must be placed in the same folder as your HTML files containing your remote forms. By default, the omniswebclient.js file uses URLs that point to the auto-installers located on the Omnis FTP site (ftp.omnis.net). If you wish to store these on your own server, you should edit the omniswebclient.js file, remembering to place it with your HTML files. The installer files are as follows: omwebie.cab the Internet Explorer ActiveX installer. omwebff.xpi the Firefox installer for Windows

Web Client Components


This section describes the web client itself (or Omnis remote form controller, Orfc, to give it its full name) and the various web components that comprise the Omnis web client. As explained previously, the Omnis web client is an ActiveX or Mozilla/Netscape type plug-in. These are small objects which dynamically link in further DLLs, or Shared Libraries under Linux and Mac OS. The following components make up the Omnis web client. Note that the names below use Windows naming conventions. The names for the other platforms use the appropriate conventions for the platform. Orfc.dll & Orfc.dat the ActiveX object (required) or np_orfc.dll,np_orfc.dat and orfc.class for the Netscape type plug-in (required) Orfcgui.dll library that provides the web client GUI (required) Orfcmain.dll the web client engine (required)

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.

Web Client Compatibility


Client machines should use a version of the Omnis web client that is compatible with the Omnis Server you are using to deploy your application. Different versions of the web client and the Omnis Server are not compatible. So for example, if a user has a version 5 web client they can only access a version 5 Omnis Server based application.

Creating your own Web Client Installers


In most cases, you can use the web client installers provided by Omnis since they will install the web client engine and all the web components needed to display most remote forms, and if the Control Manager is setup on your Server additional components are downloaded as required. This is the easiest and most desirable course of action for most types of web application. The web client installer is only 1.75mb under Windows and 3.3mb under Mac OS X so is very quick and easy for end users to download and install. However, you may want to create your own web client installer, either containing a subset of the components we provide, or if you want to add your own web components. For example, you may be deploying a remote form that contains only a few of the Omnis web components, so you may decide to create an installer containing only these components. You can use any industry-standard Installer package, such as Install Vise, to create your own web client installers. To create your own web client installer you must include all the orfc files and classes, together with the appropriate web components. You must use the client version of web components, not the development ones located in your \webcomp folder, or the ones in the \localclient folder used for opening remote forms on the fat client. The client web components are located in the clientserver\client\omnis\plugin folder under the main Omnis folder. A complete list of form components and their filenames is as follows:

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.

Web Client location


The Omnis Web client installers install the web client files into the following folders. Your web client installers can use the same locations unless you have specific or alternative requirements. Windows XP Under Windows XP the Omnis web client is installed into the folder:
C:\Webclient

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

Web Client Deployment tools


There are a number of tools available in the Tools>>Add-Ons>>Web Client Tools menu option in the main Omnis menubar that can help you with deploying Omnis web client applications. Image Compressor allows you to reduce the size of background images and any images used in an Omnis data file Download Manager allows you to manage new and updated web components from the Omnis Server Remote Form Deployment lets you create an HTML page for deploying your web client application Image Compiler lets you change the default animated image displayed when the web client is busy Windows Mobile Deployment lets you create a configuration file for mobile clients (described in the Mobile development chapter)

Creating an HTML file for deployment


Omnis creates an HTML page when you test your remote form that contains details of your web client application, including the remote form you wish to display, plus the details of

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.

Managing Web Components


If for some reason an end user does not have a particular component on their machine, and it is needed in a remote form they are accessing, the web client prompts them to download the component and install it automatically on their machine. This process is handled by the Web Component Download Manager which is a database of all web components located on the Omnis Server. The automatic download mechanism also handles the process of updating old versions of components, and the web client plug-in (the orfc files, except orfc.class). 62

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).

Changing the Web Client logo


The Web client Image Compiler allows you to change the animated image displayed in the web client when the Omnis Server is busy, such as when a remote form is requesting data from the server. The image currently displayed in the web client is an animated TigerLogic logo, but you can change this to your own logo if you wish. The images in the web client animation are stored in an Omnis data file called orfc.dat which is installed along with the web client plug-in. You can replace the default animated RD logo with your own which will a number of your own images. The Image Compiler will handle which images are displayed, in which order and at which frame rate. The Image Compiler creates a new orfc.dat which you must use to replace the default one in the users local Webclient folder (e.g. c: \webclient). Therefore if you replace the RD animated logo you will need to build your own Web client installer containing your copy of orfc.dat.

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

Deploying Your Omnis Web Application

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.

Editing your HTML Pages


Omnis creates an HTML page when you test your remote form that contains details of your remote form, web sever location, and so on. You can use this file for deploying your web application, but in practice you will need to edit this file, or copy the relevant parts to your own HTML pages. The template HTML file is located in the \html folder in the development version of Omnis Studio, under the main Omnis Studio folder. You can open the HTML file in a standard web page design tool or a text editor, such as Notepad under Windows. The HTML file should look similar to the following;
<!-- saved from url=(0014)about:internet --> <html> <head> <META http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Remote Form Test - REMOTEFORMNAME</title> </head> <body bgcolor="#FFFFFF"> <script type="text/javascript"> // Omnis replaces the text between $$Start and $$End, when it fills in the template // $$Start ounicodeserver="yes" // is the Server Unicode; always Yes owidth="561" // the width of your remote form oheight="336" // the height of your remote form oserver="1335" // the port number of the Omnis Server olibrary="PICS" // the Omnis library name containing your remote form oclass="PicsRemoteForm" // the remote form name // $$End // If you wish to use this page with a web server, set the following variables to the script and URL,e.g. // owebserverurl="www.myserver.com" // owebserverscript="/cgi-bin/nph-omniscgi.exe"

65

Chapter 1Developing Web Applications


owebserverurl="" // the URL or IP address of your web server owebserverscript="" // the location of the Omnis web server plug-in // To enable auto-download of the Omnis Web Client // Active X CAB file (providing support for Win32 // Internet Explorer, or Firefix XPI file), set odownload to "yes" odownload="no" // To pass parameters to the called Remote Task Instance set the following variables. omparam1name="" omparam1value="" // up to omparam9name & omparam9value </script> <script type="text/javascript" charset="utf-8" src="omniswebclient.js"> </script> </body> </html>

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

owebserverurl owebserverscript owidth oheight

WebServerURL WebServerScript width height

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.

Creating your own HTML pages


For most purposes you can use the HTML and omniswebclient.js files provided for you in the omnis\html folder. Alternatively, you can create your own HTML or server files, in which case the following sections are provided to help you construct your own server files. You can use Javascript, server side includes (SSIs), or an Active Server Page (ASP) to detect the client operating system and type of browser, and display the appropriate web client plug-in. ActiveX code and parameters The HTML code and parameters for the ActiveX are as follows.
<object classid=" clsid: 13510606-30FA-11D2-B383-444553540000\" width="500" height="250"> <param name="OmnisServer" value="ServerPortNumber"> <param name="OmnisLibrary" value="LibraryName"> <param name="OmnisClass" value="RemoteFormName"> <param name="WebServerUrl" value="www.yourwebserver.com"> <param name="WebServerScript" value="/cgi-bin/omnisapi.dll"> <param name="Param1" value="pOption1=Data"> ... <param name="Param9" value="pOption9=Data"> </object>

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.

Autodetecting Browser/Platform using Javascript


You can use Javascript to detect the clients browser and platform type and construct the appropriate code for displaying the web client plug-in. Using Javascript you can either detect the browser and platform type, and display one of two separate HTML files, or you can display the appropriate plug-in using a single HTML file. You can examine the contents of the omniswebclient.js file, which contains code for detecting the browser and platform type.

Autodetecting Browser/Platform using ASP


You can use an Active Server Pages (ASP) to detect the client platform and browser type, if your web server supports Active Server Pages. Microsoft Internet Information Server (IIS) is one such web server. An example of such a page, which has the suffix .asp to identify it as an Active Server Page, is as follows:
<% ' this is asp script that runs on the server when the page is requested Dim SvrVarCollection Set SvrVarCollection = Request.ServerVariables Dim ua, os Dim AnyIE, AnyNetscape '''''''''''''''''''' ' Server Variables ' '''''''''''''''''''' ua = SvrVarCollection("HTTP_USER_AGENT") os = SvrVarCollection("HTTP_UA_OS") '''''''''''''''''''''''''

69

Chapter 1Developing Web Applications


' Determine the Browser ' ''''''''''''''''''''''''' AnyIE = False AnyNetscape = False If Instr(ua, "MSIE") Then AnyIE = True ElseIf Instr(ua, "Mozilla") And Instr(ua, "compatible") = 0 Then AnyNetscape = True End If '''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Check for the Mac and change to Netscape in this case' '''''''''''''''''''''''''''''''''''''''''''''''''''''''' If InStr(ua, "Mac") Then If InStr(ua, "PowerPC") Or InStr(ua, "PPC") Then AnyNetscape = True AnyIE = False End If End If %> <html> <head> <title>Thin Client Example - Books</title> </head> <body bgcolor="#FFFFFF"> <p><%if AnyIE then%> <object classid="clsid:13510606-30FA-11D2-B383-444553540000" width="633" height="426"> <param name="_Version" value="65536"> <param name="_ExtentX" value="7161"> <param name="_ExtentY" value="7373"> <param name="_StockProps" value="0"> <param name="OmnisServer" value="5912"> <param name="OmnisLibrary" value="THIN"> <param name="OmnisClass" value="rfBooks"> <param name="WebServerUrl" value="mhthinserver.mh.rainingdata.com"> <param name="WebServerScript" value="/cgi-bin/omnisapi.dll"> </object> <%elseif AnyNetscape then%><embed type="application/OMNIS-RCCplugin" name="rcc1" width="633" height="426" OmnisServer="5912" OmnisLibrary="THIN" OmnisClass="rfBooks"

70

Deploying Your Omnis Web Application


WebServerUrl="mhthinserver.mh.rainingdata.com" WebServerScript="/cgi-bin/omnisapi.dll"> <% end if %></p> </body> </html>

Note the blocks of code delimited by <% and %>. These contain Active Server Page directives.

Autodetecting Browser/Platform using Server Side Includes


You can use Server Side Includes (SSI) to detect the client platform and browser type, if your web server supports Server Side Includes. Apache is one such web server. An example of such a page, which has the suffix .shtml to identify it as a Server Side Includes page, is as follows:
<html> <head> <title>OMNIS Web Client Gallery - FORMFLDS</title> </head> <body bgcolor="#FFFFFF"> <p> <!--#if expr="$HTTP_USER_AGENT = /.*[Mm][Aa][Cc].*/ || $HTTP_USER_AGENT !=/.*[Mm][Ss][Ii][Ee].*/" --> <embed type="application/OMNIS-RCC-plugin" name="rcc1" width="800" height="360" OmnisServer="5000" OmnisLibrary="formflds" OmnisClass="rfForm" WebServerUrl="mhlinux.mh.rainingdata.com" WebServerScript="/cgibin/nph-omniscgi"> <!--#else --> <object classid="clsid:13510606-30FA-11D2-B383-444553540000" width="800" height="360"> <param name="_Version" value="65536"> <param name="_ExtentX" value="7161"> <param name="_ExtentY" value="7373"> <param name="_StockProps" value="0"> <param name="OmnisServer" value="5000"> <param name="OmnisLibrary" value="formflds"> <param name="OmnisClass" value="rfForm"> <param name="WebServerURL" value="mhlinux.mh.omnis-software.com"> <param name="WebServerScript" value="/cgi-bin/nph-omniscgi"> </object> <!-- ActiveX object END--> <!--#endif --> </p> </body>

71

Chapter 1Developing Web Applications


</html>

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.

HTML Forms and Remote Tasks


The parameters required in the GET request in your HTML form contain the necessary criteria for interacting with the Omnis remote task on the Omnis Server: your HTML contains the location of the web server plug-in, the port number, the remote task name, the Omnis library name, as well as the specification for the fields in the form. For example, the following constructs a form with the GET method:
<form method="GET" action="/cgi-bin/omnisapi.dll"> <input type="hidden" name="OmnisServer" value="PortNumber"> <input type="hidden" name="OmnisClass" value="RemoteTaskName"> <input type="hidden" name="OmnisLibrary" value="LibraryName"> <p><input type="password" name="pPassword" size="20"></p> <p><input type="text" name="pQuery" size="80"></p> <p><input type="submit" value="Submit" name="B1"> <input type="reset" value="Reset" name="B2"></p> </form>

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

Chapter 1Developing Web Applications


<div align="right"><p>Client:</font></strong></td> <td width="564" height="23"> <table border="0" cellspacing="0" cellpadding="0" width="601"> <tr> <td width="136" height="13"><font face="Arial"> <input type="checkbox" name="ActiveX" value="YES"> <strong>ActiveX&nbsp;&nbsp; </strong></font></td> <td width="135" height="13"><font face="Arial"> <strong><input type="checkbox" name="Netscape" value="YES">Netscape </strong></font></td> <td width="330" height="13"><font face="Arial"><strong> <input type="checkbox" name="RAWHTML" value="YES">RawHTML</strong></font></td> </tr> </table> </td> </tr> <tr> <td width="788" valign="top"><strong><font face="Arial"> <div align="right"> <p>Comments:</font></strong></td> <td width="564" height="249" valign="top"> <font face="Arial"><textarea rows="11" name="Comments" cols="57"></textarea></font></td> </tr> </table> <div align="center"><center><p><font face="Arial"> <input type="submit" value="Send Comments" name="B1"></font></p> </center></div> </form>

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=&

whereas a POST method is equivalent to posting to the URL


/cgi-bin/omnisapi.dll

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

Using Task Methods to Process Requests


Omnis passes a single parameter to the $construct() method of a remote task instance created by a request from an HTML form. This parameter called pParams is a row variable, and it has a column for each parameter in the HTML form. The code contained in the $construct() method of your remote task could literally do anything you like and depends on the functionality of your application. Having passed in the row variable to your $construct() method you can use any type of Omnis programming to process the information submitted by the user and pass back whatever content or data you wish. Typically and with most complex web applications your library will contain many different methods that can be called from your remote tasks, most of which could be located in object classes to allow reuse of your code. See the Omnis Programming manual for information about programming Omnis methods and using object classes. The column names in the row variable are the same as the form parameter names, and the values are either the values of the parameters in the form (e.g. hidden fields may have default values), or the values entered by the user. You can use the columns values in the pParams row variable (i.e. values in the form parameters) as input to what you do in $construct(). The following $construct() method is contained in a remote task that handles Studio evaluation download form requests. The method contains a parameter variable called pParams of Row type that receives the values from the form. The row variable contains a column for each field in the form, including the fields Email, Country, Platfrom, and so on, that are referenced using the syntax pParams.Colname. The method also contains several calls to methods in object classes within the library handling the download requests. After registering the customer, the method sends the customer an email and redirects their browser to the appropriate download page.
; $construct() for processing download requests If len(pParams.Code) Do iObj.$getMagazine(pParams.Code,lMagazineRow) Returns lCodeFound ; get magazine data (esp. name and serial number) Else Calculate lCodeFound as kTrue ; default to true for straight downloads End If If not(lCodeFound) ;; invalid magazine code Do inherited If not(len(pParams.Folder)>0) Do method createFolderName Returns lFolder ; identify the folder name for this user Else Calculate lFolder as pParams.Folder

75

Chapter 1Developing Web Applications


End If Do iHTMLObj.$setFolder(lFolder) ; set the folder name for this instance of the html page Do iHTMLObj.$setUrl(iUrl) Do iHTMLObj.$createRegisterError(pParams,lFolder) Else Do iObj.$getDownloadCustID(pParams.Email,lCustID) ; see if this is an existing download customer Do lAdminObj.$getDistID(pParams.Country) Returns lDistID If not(lCustID) Do iSequence.$getNext('ECS_DownloadCustomers') Returns lNextSeq ; get the next sequence number Do iObj.$createDownloadCustRecord(lNextSeq,pParams,lDistID) Calculate lCustID as lNextSeq Else Do iObj.$getDownloadCustData(lCustID,lCustRow) ; get their data Calculate lCustRow.DistID as lDistID ; if the user has changed country their DistID may ; also have changed, so update it anyway Do iObj.$updateDownloadCustData(pParams,lCustRow) ; update their account data End If Do iObj.$getPlatformID(pParams.Platform,lPlatformID) ; get the platform Do iSequence.$getNext('ECS_Downloads') Returns lNextSeq ; get the next sequence number Do iObj.$createDownloadRecord( lNextSeq,lCustID,lPlatformID,,,,pParams.Code, pParams.ProductID,pParams.HowDidYouHear) If len(pParams.Code) ; if they have entered a magazine code, they need an ; email with a serial number ; send user email with the appropriate serial number Do iEmailObj.$sendEmail( 2,lCustID,lMagazineRow.SerialNumber,,kTrue) ; 4th parm is blank; 5th parm for using downloadcustomer table Calculate lUrl as 'http://www.omnis.net' Else Do iEmailObj.$sendEmail(1,lCustID,,,kTrue) ; 3rd & 4th parm are blank; 5th parm is for using ; downloadcustomer table Switch pParams.Platform Case 'Win95' Calculate lUrl as iWin95download

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.

Returning Content to the Client


After completing its processing, $construct() returns its results as the return value of the method, using the Quit method command. There are three possible types of return from such a remote task instance: <url>, <data>, and <error>. Quit method <url> $construct() can generate a file (typically HTML), and any files it references, and then return the URL of that file. For example, it can use the HTML report destination, and print a report to HTML. You return the <url> in one of two forms.

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

will result in the browser being redirected to


http://www.myhost.com/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

returns the 12 character string Some content to the browser.

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">&nbsp;&nbsp; </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

Chapter 1Developing Web Applications


Text: <td width="500" colspan="3"><form method="Get" action="[iOmnisDll]"> (Platform newline) Text: <input type="hidden" name="OmnisLibrary" value="[iLibName]"> (Platform newline) Text: <input type="hidden" name="OmnisClass" value="rtNewCustomer"> (Platform newline) Text: <input type="hidden" name="OmnisServer" value="[iServerPort]"> (Platform newline) Text: <input type="hidden" name="IEBrowser" value="[pParams.IEBrowser]"> (Platform newline) ;; store browser type Text: <input type="hidden" name="Folder" value="[pParams.Folder]"> (Platform newline) Text: <input type="hidden" name="BasketID" value="[pParams.BasketID]"> (Platform newline) ;; store basket id if there is one Text: <input type="hidden" name="AcctsCountry" value="[pParams.AcctsCountry]"> (Platform newline) ;; so we know the accounts country Text: <input type="hidden" name="InitialCountry" value="[pParams.InitialCountry]"> (Platform newline) ;; so we know the initla country Text: <input type="hidden" name="SessionID" value="[pParams.SessionID]"> (Platform newline) ;; so we know the session Text: <table border="0" width="100%" cellspacing="0" cellpadding="0" bordercolor="#FFFFFF"> (Platform newline) Text: <tr><td width="50%"> (Platform newline) ;; ### was <td> Text: <span class="subtitle">New Customers</span><br> (Platform newline) Text: <span class="bodytext">Click here to create a new account:</span><br> (Platform newline) Text: <input type=image src="../../images/buttons/newaccount/new1.gif" width="135" border="0" height="39" name="NewAccount" (Platform newline) Text: onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('NewAccount','','../../images/buttons/n ewaccount/new2.gif',1)"> (Platform newline) Text: </td></tr></table> (Platform newline) Text: </form> (Platform newline) ; etc etc etc...

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.

Persistent Remote Tasks


Normally, the remote task instance created to process an HTML form destructs, as soon as Omnis has called $construct(), and received the result to return to the user. It is possible that you may want to keep the remote task instance available, so that it can receive further requests. This mechanism is explained here. You should note: 1. 2. This mechanism does not work in conjunction with Load Sharing (Load Sharing is described in a later chapter). This mechanism does not detect use of the back button on the browser, meaning that remote task instances can build up; these only go away when they time-out.

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.

Multipart Form Data


You can pass data and upload files from HTML forms to the Omnis Server, using the Multipart form data type. The content type multipart/form-data can be used for submitting forms that contain files, non-ASCII data, and binary data files. To use multipart form data, add the following attribute to the form tag:
enctype=multipart/form-data

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()

Direct Client Connections


In addition to the technique of connecting web based clients to an Omnis Server via a standalone Web Server, the Web Client plug-in (omwebcli) can connect directly to Omnis, without the need to install a Web Server (in fact, Omnis has its own built-in web server). This capability is available for web and mobile applications and may be suitable for certain circumstances where a web server is not available or necessary within a private network. This direct access method would also enable you to test your web and mobile application without setting up a web server. It could also allow you to develop a Windows Mobile based application when running the Omnis Server on Mac OS X, without needing to set up a Web Server. To enable direct connections to the Omnis Server you need to make some modifications to the html file for web based clients or the config.xml for mobile clients. The WebServer script attribute needs to be set to /webclient The WebServer url attribute needs to be set to http://<ipaddress>:port In this case, the OmnisServer address attribute is not relevant when connecting directly to Omnis in this way. To enable direct access, Omnis Studio includes its own built-in web server, which means you can communicate with Omnis directly via HTTP. Using the built-in http server may be a convenient way to test an Omnis Ultra-thin application, where the only difference is the format of the http call itself to Omnis: in all other respects your application, including the code in your remote tasks, is the same. The diret http call to Omnis is structured like this:
http://<Server>:<Serverport>/Ultra

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

Chapter 2Developing Mobile Applications

Chapter 2Developing Mobile Applications


This chapter describes how you can develop applications that run on Windows Mobile based devices, such as Smartphones, PDAs and small-form tablet computers. In general, the process of creating applications for Windows Mobile is entirely the same as creating applications for the Web or desktop. In fact, applications for use on Windows Mobile can use the same Remote forms, Remote tasks and other objects as used for Web applications. The Omnis Server is setup and deployed in the same way as for Web applications, but Windows Mobile clients require a slightly different setup for deployment. Creating or adapting a Remote form for use on Windows Mobile is described in the Tutorial in the Introducing Omnis Studio manual, and in the Welcome start screen available when you start Omnis (click the New Users option on the main Omnis toolbar to open the Welcome screen). You are advised to work through the tutorial if you have never created an Omnis application for use on Windows Mobile based devices. Note that some editions of Omnis Studio do not allow you to test Mobile Client based applications in design mode.

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

The Omnis Mobile Client

The Omnis Mobile Client


Omnis Studio 5 introduced a new version of the Omnis Web Client plug-in that supports applications running on Microsoft Windows Mobile based devices. The new mobile enabled client is called the Omnis Mobile Client (omwebcli) and works in a very similar way as previous versions of Omnis in that it displays a remote form on the mobile device. The major difference with the mobile-enabled client is that it does not run inside a web browser, such as the mobile version of Internet Explorer, rather it runs inside a small, standalone program, which is downloaded to the mobile device along with the client. The remote forms that you can run in the Omnis Mobile Client have a specific size and format for mobile phones, but this is all taken care of in Omnis in design mode when you create the form. Beyond the size, designing a remote form for the mobile client is virtually the same as designing a remote form for an Omnis web application, and you can use most of the components available in remote forms. Your computer and mobile device are connected using Windows Mobile Device Center (previously called ActiveSync), and once set up, you can test your forms on the device itself by pressing Ctrl-T. The Omnis Mobile Client runs on version 5.0, 6.0 and 6.1 of Windows Mobile from Microsoft. Specifically, the mobile client has been tested on the new breed of smartphones which run Windows Mobile Professional edition. These phones have all the usual phone capabilities, touch sensitive screens, and PDA functions including the mobile version of Word, Excel and PowerPoint. Windows Mobile is available in various editions including Standard, Professional, and Classic. The Standard version is for mobile phones with only basic phone functionality and without touchscreens, while Professional is for Pocket PCs or PDAs with touchscreens and full phone functionality. The Classic version is for Pocket PCs without phone capabilities. The Omnis Mobile Client does not run on the Standard version of Windows Mobile.

87

Chapter 2Developing Mobile Applications

Creating Mobile Forms


Creating forms for mobile devices is very much the same as designing other forms in Omnis. You can design multiple layouts for the same remote form, catering for desktop and mobile clients in one single remote form. The remote form property $screensize can be set to Desktop monitors, as well as Portrait or Landscape for mobile screen sizes. The fields on your form can be arranged for the different layouts, but only one set of methods, for fields and the form itself, is required. When you are designing a remote form for mobile, the Windows Mobile titlebar and menubar are displayed in the design window to give an authentic look. To create a remote form for Windows Mobile

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.

Screen Size and Orientation


There are many different screen sizes and resolutions for smartphones and other mobile devices. The mobile client supports the most common screen sizes, including 240x320 screens that run at 96dpi, and 480x640 screens that run at 192dpi (the latter uses a 240x320 logical size after scaling in other words each application pixel is 4 device pixels). The $screensize property stores the current screensize and orientation of the screen and can be set to one of several values: kSSZDesktop For display on a desktop/PC based web browser kSSZwindowsMobile240x240 For mobile devices with screens 240 x 240 px at 96dpi kSSZwindowsMobile240x320Portrait | kSSZwindowsMobile240x320Landscape For mobile devices with screens 240 x 320 px at 96dpi, and 480 x 640 at 192dpi, in Portrait/ Landscape orientation

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.

Form Width and height


When $screensize is set to one of the mobile formats, changing $width and $height for the remote form changes the width and height of the client area of the design window (the area where you can place controls), rather than the size of the design window itself. The design window adds scrollbars to the client area when necessary, therefore you dont need to enable the $horzscroll or $vertscroll for the remote form. In addition, you can control whether the design window shows the Windows Mobile title bar, by setting the $designshowmobiletitle property for the form, although you may want to show this for most types of mobile applications. In most cases, you should set the $width and $height of the remote form to match the exact coordinates of each of the screen sizes you wish to support in your application, allowing for the Windows Mobile Title bar and Menu bar which are both 26 pixels each in height. Given 89

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

Testing Mobile Forms

Testing Mobile Forms


Omnis Studio 5 allows you to test a remote form on your mobile device during development, by connecting your PC running Omnis and your mobile device using the Windows Mobile Device Center (ActiveSync on older platforms). Assuming your mobile device is setup correctly:

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

Chapter 2Developing Mobile Applications

Configuring the Mobile Client


The mobile forms you build in Omnis are run inside the Omnis Web Client, which itself runs inside a small stand-alone program, called omniswm.exe, installed on the mobile device and configured using an XML file. In effect, the mobile client program and XML file replace the ActiveX and HTML file required for web browser based Omnis applications and available in previous versions of Omnis. The XML configuration file specifies the Omnis library name, remote form name, Omnis Server location, and any other additional parameters. The Omnis Mobile Client runs in two modes: test form mode, and normal client mode. In test form mode, the configuration is in the file testformconfig.xml; otherwise, it is in the file config.xml. There are two files to prevent test form from overwriting a configuration file you may want to keep: test form works by substituting placeholders in testformconfigtemplate.xml, copying the resulting file to testformconfig.xml on the client, and running the client. The configuration files are located in the same folder as the Omnis Mobile Client (omniswm.exe), usually in the \Program Files\omwebcli folder of your mobile device. You can navigate to this folder using the Windows File Manager on your desktop PC. The configuration file has the following syntax:
<?xml version="1.0" encoding="UTF-8"?> <OmnisMobileConfig> <WindowClass name="TIGERLOGICCORP_OMNISWM"/> <TitleBar disable="no" text="Application Name"/> <MenuBar candefault="yes"/> <!-- Message for when the application is waiting for a data connection --> <WaitingForDataConnection message="Waiting for a data connection"/> <Application name=" ApplicationName" desc="This is my app"> <ServerType unicode="yes"/> <WebServer url="http://www.myserver.com" script="/omnis_apache"/> <OmnisServer address="5920" library="MOBILE" class="NewRemoteForm1"/> <!-- Add up to nine parameters for the application here --> <Parameter name="p1" value="value1"/> ... <Parameter name="p9" value="value9"/> </Application> </OmnisMobileConfig>

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.

Mobile Client Updates


The Omnis Mobile Client itself and the various components available in the mobile client are updated on the end user device automatically via the Omnis Component Download Manager, as in previous versions of Omnis Studio. There is a control platform in the Component Download Manager for Windows Mobile, which can load Windows Mobile components into the control manager data file when running on Win32 platforms. It detects whether a DLL is for desktop Windows or for Windows Mobile. 93

Chapter 2Developing Mobile Applications In addition to the client DLLs, you must also add the file omniswm.exe to the control manager data file.

The End User Experience


End users need to install the Omnis Mobile Client onto their mobile device by downloading and running a cab file you have created and containing all the necessary components and the mobile client itself (see the Deployment section). When the end user displays a form in your application, the most appropriate screen size and orientation is chosen for the device, and they can switch between portrait and landscape orientation automatically (assuming you have designed the form with multiple layouts). Users can navigate the form using the standard left, right, up and down arrow keys on the device, or using the touchscreen or stylus, while data can be entered using the keypad. In addition, you can now add context menus to remote forms (using the new Remote menu class: see the Web Development chapter), which appear on Windows Mobile when the user taps and holds on the form.

Mobile Client Design considerations


There are various issues regarding the font table, styles, themes, borders, and so on, that you should consider when designing remote forms or applications for the mobile devices.

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

Mobile Client Design considerations

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.

Borders and Themes


Windows Mobile supports only simple borders for fields, and as a result so does the Omnis Mobile Client. Setting $effect to any value other than kBorderNone has no effect and results in a single pixel black border around fields when the form is displayed on the client. Remote forms now support the $backgroundtheme property. This change applies to desktop clients as well as mobile clients.

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.

Default context menu for lists


Lists in the formflds component group, such as the headed list, now have a default context menu allowing selection of lines when in multiple select mode.

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.

Icons on 192dpi devices


If you use a 16x16 icon from an Omnis icon file or #ICONS, when running on a 192dpi device with automatic scaling, the Omnis Mobile Client uses the 32x32 icon if there is an equivalent available. This provides a better result than stretching the 16x16 icon.

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

Client method execution


The Quit Omnis command quits the Mobile Client when executed in a client method. It has no effect in a desktop client.

96

Mobile Form Events

Mobile Form Events


The remote form event evFormToTop has the parameter pScreenSize. This is one of the kSSZ... constants that identifies the current screen size and orientation of the client in use. In addition, remote forms have the following events which are relevant to mobile devices: evScreenOrientationChanged This applies only to omwebcli, and it was described earlier. Event parameters are pEventCode and pScreenSize evOpenContextMenu and evExecuteContextMenu Events for Remote menu class You can detect these events in the $event() methods in your remote form. If you want to use any of these events in your code, such as evScreenOrientationChanged, you have to enable the events in the $events property of the remote form.

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.

Windows Mobile Deployment tool


The Omnis Windows Mobile Deployment tool, available in the Web Client Tools section on the Add-on menu, is for creating a CAB file for deploying your mobile application to end-user devices. The Windows Mobile Deployment tool allows you to create a CAB file for your application, containing your own values for information such as the application name, icon, shortcut link in the Programs folder, and the connection configuration for your Omnis Server. The CAB file created by this tool installs the client application in \Program Files on the mobile device, in a folder named with the abbreviated name of your application.

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.

Single Mobile Client


You should note that the Windows Mobile OS supports only a single version of the Omnis Mobile Client installed on a device. In practice, this is unlikely to cause you many problems since the majority of your end users will not have multiple versions of the Omnis Mobile Client on their mobile device. This is because the Windows Mobile OS only supports a single loaded DLL of each DLL module name over the entire system. This means that if you create a Windows Mobile based Omnis application installed in its own directory (e.g. using a CAB file created by our deployment mechanism), the application must use the identical Omnis Mobile Client to all other Windows Mobile based Omnis applications installed on the device. The consequence of using two different versions are that the first executed will load and run, but the second may not, as it could be using a mixture of DLLs from the first and the second, because Windows Mobile uses any loaded DLLs with the same name from the first installation when it loads the second. One solution is for the user to terminate the process for the first application before running the second, but this is not practical for end users. The best solution is to ensure that the end user has only one version of the Omnis Mobile Client installed on their mobile device.

99

Chapter 2Developing Mobile Applications

Server and Client Requirements


To deploy your mobile application, you need to install an Omnis Server, to host your Omnis library, database and other application files, and a standard Web Server. In this respect, the setup is very similar to previous versions of Omnis when deploying Web Client applications. Your mobile application can be hosted on a Windows, Mac OS X, or Linux based Omnis Server even though clients are currently supported only on Windows Mobile based devices. You will also need to install the Omnis web server plug-in into the Web Server, but you dont need to set up any html files to configure the client, since the XML configuration file configures the client. To use your mobile application, your end users need to download and install the CAB file you created containing the Omnis Mobile Client and your own XML configuration files. The Omnis Mobile Client is supported on Windows Mobile Professional version 5.0, 6.0 and 6.1. The latest version 6.1 is typically available on the new breed of smartphones with touchscreens, such as the Sony Ericsson Xperia X1, Samsung Omnia, and the HTC Touch range. The Omnis Mobile client does not work on the Standard version of Windows Mobile.

Direct Client Connections


In addition to the existing technique of connecting web based clients to an Omnis Server via a Web Server, the new Web Client plug-in (omwebcli) can connect directly to Omnis, without the need for a Web Server. This capability is available for the web browser based clients and new Windows Mobile based clients. The new direct way of connecting web and mobile clients to the Omnis Server may be useful in certain circumstances, and enables you to test your web and mobile application without setting up a web server. It also allows you to develop a Windows Mobile client when running the Omnis Server on Mac OS X or Linux, without needing to set up a Web Server. To enable direct connections to the Omnis Server you need to make some modifications to the html file for web based clients or the config.xml for mobile clients. The WebServer script attribute needs to be set to /webclient, and the WebServer url attribute needs to be set to http://<ipaddress>:port. In this case, the OmnisServer address attribute is not relevant when connecting directly to Omnis in this way.

100

SSL Security

Chapter 3Web Communications


Support for secure connections using SSL has been added to the existing package of web commands. In addition, there is a new set of commands that allow you to communicate with an IMAP email server. The HTTP, FTP, SMTP and POP3 client commands that establish a connection to a server all have two new arguments, which control if and how a secure connection is used. The new and updated Web Commands are summarized here and described in more detail, including useful code examples, in the Omnis Command Reference manual and in the Omnis Help (press F1).

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.

Certificate Authority Certificates


In order to perform the verification (when the Verify parameter is kTrue), OpenSSL uses the Certificate Authority Certificates in the cacerts sub-folder of the secure folder in the Omnis folder. If you use your own Certificate Authority to self-sign certificates, you can place its certificate in the cacerts folder, and OpenSSL will use it after you restart Omnis.

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

IMAPDeleteMailbox IMAPDisconnect IMAPExpungeMessages

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

Chapter 4Omnis Graphs

Chapter 4Omnis Graphs


You can create many different types of chart in Omnis using the Graph component (called Graph2) and display them in your windows, remote forms, or reports. The data and appearance of a chart is based on the data stored in an Omnis list variable. The different chart types require a different list data structure to represent their data points. The Graph2 component supports four main types of chart, XY charts, Pie charts, Polar charts and Meter charts, each of which has a number of subtypes (except Pie). The major and minor types of the graph are specified as properties of the graph window object (found under External Components in the Component Store) and the associated list variable is specified in the $dataname property of the object.

Note to existing Omnis developers


The Graph2 component is based on a new graphing engine (called ChartDirector from Advanced Software Engineering Ltd) and was introduced in order to simplify graphing functionality in Omnis. The new Graph2 component can produce many more types of chart and is easier to use than the old Graph component, which for backwards compatibility is still available in Omnis, but is no longer maintained or supported.

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.

Box whisker charts


Box whisker charts normally consist of five items of data to represent each element. Gantt charts are also constructed using the Box Whisker type, using three items of data per graph element.

107

Chapter 4Omnis Graphs

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

Polar Spline Line and Area

109

Chapter 4Omnis Graphs

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

The Graph2 Example Library


There is an example library showing how the Graph2 component works, which is located under the Examples link in the Welcome window when you first launch Omnis you can open this window by clicking on the New Users button in the main Omnis toolbar. Code from the example library is used later in this manual to show you how to use the component.

110

Common Graph Properties

Common Graph Properties


All the different graph types have the following properties; one of the most important properties is the $dataname which contains the name of the Omnis list variable containing the data for the graph; this is found under the General tab in the Property Manager. Property Name $dataname Data Type List Description The name of the Omnis list variable supplying the data to the graph; the structure of the data in the list must match the type of graph you wish to draw

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

$legendbackgroundcolor $legendbackgroundeffect $legendpos

RGB Color Constant Constant

$legendtextcolor $legendvert $legendx $legendy $majortype $minorxytype $minorpolartype $minormetertype $roundedframe

RGB Color Boolean Integer Integer Constant Constant

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

$maintitle $offsetwidth $offsetx $offsety $titlefont

Character Integer Integer Integer Character

$titlefontheight $wallpaper $xaxisfontangle $xaxistitle $xlabelfontangle $y2axisfontangle $yaxisfontangle $yaxistitle

Integer Character Integer Character Integer Integer Integer Character

112

Common Graph Properties

Setting the major and minor type


The different types of graph are specified using the $majortype and $minortype of the graph object. The following types are available, specified under the Prefs tab in the Property Manager: Major type ($majortype) kG2xy Minor type $minorxytype Minor type constants kG2xyBar kG2xyLine kG2xyScatter kG2xyArea kG2xyBoxwhisker kG2xyHLOC kG2xyCandlestick kG2xyTrend kG2polarArea kG2polarLine kG2polarSplineArea kG2polarSplineLine kG2meterAngular kG2meterLinear

kG2polar

$minorpolartype

kG2meter kG2pie

$minormetertype No minor types

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

Chapter 4Omnis Graphs

Common Graph Methods


All the graph types have the following methods under the Methods tab in the Property Manager. More details about each method is supplied later in this section. Note these methods apply to the window graph object; methods are also available for the non-visual graph object, described in the second table. Method Name $addmark() Returns None Description $addmark(iAxisID, nValue, iColor [,cText, cFontname, iFontsize]) adds a mark or separator at the specified axis, value and color; you can add text to the mark with the specified font name and size $addtext(cText, iX, iY [,cFontname, iFontsize, iColor, iAlign, iAngle, bVertical]) adds the specified text positioned according to the X & Y co-ordinates; this must be done during the evPreLayout event; the coordinates are taken from the top left of the graph object and the Y component is inverted so that as Y increases the text string will appear further down the object $addzone(iAxisID, iLowerlimit, iUpperlimit, iFillcolor) adds a zone from the lower and upper limits, in the color and on the axis specified $convdate(dDatetime) converts a date/time variable to an integer equivalent which can then be used in graph data Disposes the graph and rebuilds it. Useful if you need to change something other than a property on the graph which requires it to be rebuilt, such as adding more layers $findobject(iX, iY, iSetno, iItemno [,cSetname, cItemname]) obtains the set & item information for the graph object under the mouse given its position as the X & Y co-ordinates: see Drilldown $formatvalue(nValue, cFormatstring) formats a number/date using the formatting syntax described in the Parameter Substitution and Formatting section $getcolors([PaletteID]) returns a list of RGB colors used for the graph, or palette if specified, a constant: kG2paletteDefault, kG2paletteTransparent, or kG2paletteWhiteOnBlack

$addtext()

None

$addzone()

None

$convdate()

Integer

$dispose()

None

$findobject()

kTrue for success

$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

Chapter 4Omnis Graphs

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

RGB Color Constant

$offsetheight $subtitle $swapxy $xaxisontop $xaxiswidth $y2axistitle $yaxisonright $yaxiswidth $layereffect

Integer Character Boolean Character Integer Character Character Integer Constant

$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

Chapter 4Omnis Graphs

List data structure for XY charts


Bar Charts
The bar chart is one of the most common forms of chart. The list format is one row per series with the first column being the group name followed by the data for each group. You can build the list data for your graph from a database or construct it on the fly: you need to use the $define() method to specify the columns in your list, and you can use $add() (or the SQL database list methods) to build the list line by line. The following method will construct the list data for a simple bar chart.
; define vars listGraph (List), Name (Char), Sales (Long Int), Expenses (Long Int) Do listGraph.$define(Name,Sales,Expenses) Do listGraph.$add('Andy',85000,20000) Do listGraph.$add('Sam',80000,15000) Do listGraph.$add('Lisa',92000,34000) Do listGraph.$add('Harry',45000,15000)

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:

3d Line chart $majortype=kG2xy, $minorxytype=kG2xyLine

3d Area chart $majortype=kG2xy, $minorxytype=kG2xyArea

119

Chapter 4Omnis Graphs

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

Box Whisker Charts


Box whisker charts represent data ranges as boxes and/or marks. A common application is to represent the maximum, 3rd quartile, median, 1st quartile and minimum values of some statistics. Each individual row in the chart list data represents each series.
Do Do Do Do listGraph.$define(Name,#1,#2,#3,#4,#5) listGraph.$add('',55,70,80,40,62) listGraph.$add('',60,80,90,45,70) listGraph.$add('',50,65,75,40,60)

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)

The $addline() class method is:


; Params: p1 (Char) p2-p5 (Long Int) ; Local var: chartdate (Date time D m y) Calculate Name as p1 Calculate chartdate as dat(con(p2,"-",p3,"-",p4),"Y-M-D") Calculate #1 as $cinst.$objs.ganttChart.$convdate(chartdate) Calculate chartdate as dadd(kDay,p5,chartdate) Calculate #2 as $cinst.$objs.ganttChart.$convdate(chartdate) Add line to list

You can use the $convdate() method to convert a date/time variable to an integer equivalent which can be used in graph data.

High/Low/Open/Close (HLOC) Charts


The HLOC chart is often used to represent financial stock data. Each series consists of four pieces of information, the highest price, the lowest price, the open price, and the close price. The volatility is then shown as a vertical line, with the opening price as a horizontal line to the left and the closing price as a horizontal line to the right.
Do Do Do Do listGraph.$define(Name,#1,#2,#3,#4,#5) listGraph.$add('',2043,1931,2000,1950) listGraph.$add('',2039,1921,1957,1991) listGraph.$add('',2076,1985,1993,2026)

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

Chapter 4Omnis Graphs

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)

Data presentation in XY charts


You can change the way data is presented in Bar, Area, and Line graphs using the $datacombine property, which can be set to one of the following constants: kG2dataSide, kG2dataStack, kG2dataOverlay, or kG2dataPercentage. When $datacombine is changed the bars, areas, or lines, and the Y-axis, are redrawn to reflect the selected combine type. The following example graphs shown how the different combine types affect the presentation of the same set of data (these graphs are available in the Graph example library).

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

Chapter 4Omnis Graphs

Pie Charts
Pie charts have the following properties and methods, in addition to the Common graph properties and methods.

Pie chart properties


Property Name $depth $depthcolumn Data Type Integer Integer Description The depth of the pie (-1 is default) The column number (0 if not required) of the depth values in the list. This can be used to enable different slice depths The amount of cut out from the center of the pie, specified as the percentage of the total radius of the pie; the range is 0-100, with 0 being no donut (the default) if true the slices are drawn clockwise The feeler color The feeler width The color of frame around pie slices, if $frameon is true If true a frame is drawn around each pie slice Overrides the default formatting of labels; see section Parameter Substitution and formatting Position of the labels relative to the edge of the pie, only used if $labelposon is true If true $labelpos is enabled The pie rotation, in degrees If true a pie shadow is displayed if true feelers are shown If true the labels are displayed by the side of pie If $tilton is enabled this contains the degree of tilt if true the tilt is enabled (see $tilt); note $3d has to be enabled as well to display tilt

$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

Pie chart methods


Pie charts have the following method(s), in addition to the common methods. Method Name $slicemove() Returns None Description $slicemove(iDistance, iSlice [,iSliceend]) moves iSlice or range of slices (iSlice to iSliceend) the specified iDistance from the center of the pie; the first slice in the chart is value 0; to move non-adjacent slices, iSlice should be a comma-separated list of slices, e.g. .$slicemove(iDistance,0,2) to move slices 1 and 3

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.

List data structure for Pie charts


The following list data will result in the graph shown.
Do Do Do Do Do listGraph.$define(Name,Sales ) listGraph.$add('Andy',85) listGraph.$add('Sam',80) listGraph.$add('Liza',92) listGraph.$add('Harry',45)

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

Chapter 4Omnis Graphs

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.

Polar chart properties


Property Name $angularcolor $angularlabelson $angularwidth $circulargrid $minorpolartype Data Type RGB color Boolean Integer Boolean Constant Description Color of angular grid If true labels are shown on the angular axis Width of the angular grid If true the grid is circular, otherwise the default is polygonal The minor type for kG2polar type graphs; can be one of the following: kG2polarArea, kG2polarLine, kG2polarSplineArea, kG2polarSplineLine Color of radial grid If true labels are shown on the radial axis Width of the radial grid

$radialcolor $radiallabelson $radialwidth

RGB color Boolean Integer

129

Chapter 4Omnis Graphs

Polar chart methods


The following methods must only be executed during the evPreLayout event; see below for details. Method Name $addarealayer() $addlinelayer() $addsplinearealayer() Returns None None None Description $addarealayer(pList [,iCombineType]) adds an area layer to the graph; pList is the area data* $addlinelayer(pList [,iCombineType]) adds a line layer to the graph; pList contains the Line data* $addsplinearealayer(pList [,pSymbol, pSymbolSize]) adds a spline area layer to the graph; pList is the spline area data list (same format as all polar charts) $addsplinelinelayer(pList [,pSymbol, pSymbolSize]) adds a spline line layer to the graph; pList is the spline line data list (same format as all polar charts) $getradialaxis() returns the radial axis object

$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.

List data structure for Polar charts


The data points in a polar chart are plotted using polar co-ordinates (radius,angle) whereby radius is the distance or amount from the center of the chart and angle is the relative angle with reference to the "12 o'clock position" in the chart. The first three columns in the Omnis list for a polar chart should therefore be Name (Label), Amount, Angle. If the angle is omitted from the list data, then the data points are distributed evenly around the chart. For example, consider the following data:
; define listGraph (List), Name (Char), Score (Long int) Do listGraph.$define(Name,Score) Do listGraph.$add("Speed",90) Do listGraph.$add("Reliability",60) Do listGraph.$add("Comfort",65) Do listGraph.$add("Safety",75) Do listGraph.$add("Efficiency",40)

130

Polar Charts Will give the following polar chart:

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

Adding layers to a polar chart


To draw a second set of data in a polar chart, from a second list perhaps, you can add the additional data in a layer over the first set of data. You can add layers to charts during the evPrelayout event which is triggered as the graph component is instantiated. Consider the following example. The first set of data is constructed in the $construct() method of the graph window: the second set of data is added as a layer.
; $construct() method for graph window ; define listGraph (List), listNames (List), Name (Char) Do listGraph.$define(Name,#1,#3) Do listGraph.$add("",90,15) Do listGraph.$add("",25,60) Do listGraph.$add("",40,110) Do listGraph.$add("",55,180) Do listGraph.$add("",68,230) Do listGraph.$add("",44,260) Do listGraph.$add("",79,260) Do listGraph.$add("",85,310) Do listGraph.$add("",50,340) ; $columnheadings of graph is set to listNames Do listNames.$define(#S1) Do listNames.$add("Closed loop")

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

Chapter 4Omnis Graphs


; $event() method for graph window object ; define listLayer2 (List), local vars lLayer and OpenLoop On evPreLayout Do listLayer2.$define(Name,OpenLoop,#1) Do listLayer2.$add("",80,40) Do listLayer2.$add("",91,65) Do listLayer2.$add("",66,88) Do listLayer2.$add("",80,110) Do listLayer2.$add("",92,150) Do listLayer2.$add("",87,200) Do $cinst.$objs.GROBJ.$getmainlayer() Returns lLayer Do lLayer.$setlinewidth(2) Do lLayer.$setsymbol(kG2symbolTriangle,11) Do lLayer.$setdatalabelformat("({value},{angle})") Do listNames.$define(#S1) Do listNames.$add("Open loop") Do $cinst.$objs.GROBJ.$addlinelayer(listLayer2) Returns lLayer Do $cinst.$objs.GROBJ.$setlinearscale(kG2axisAngular,0,360,30) Do lLayer.$setlinewidth(2) Do lLayer.$setcloseloop(kFalse) Do lLayer.$setsymbol(kG2symbolDiamond,11) Do lLayer.$setDataLabelFormat("({value},{angle})")

The above code produces the following graph:

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.

Meter chart properties


Property Name $minormetertype $linearalignment Data Type Constant Constant Description The minor type for meter charts, a constant: kG2meterLinear, kG2meterAngular The alignment for linear meter charts, a constant: kG2alignTop, kG2alignBottom, kG2alignLeft, kG2alignRight, kG2alignCenter The start and end degrees for an angular chart in the form n,n, the default is 0,360 The horizontal position of the center (start) of an angular meter chart; the default is 50 which centers the chart horizontally The vertical position of the center (start) of an angular meter chart; the default is 50 which centers the chart vertically The width of the major tick in pixels; the default is 1 The width of the micro tick in pixels; the default is 1 The width of the minor tick in pixels; the default is 1 The color of the pointer for a meter chart

$angulardegrees $angularpositionh

Integer Integer

$angularpositionv

Integer

$majortickwidth $microtickwidth $minortickwidth $pointercolor

Integer Integer Integer RGB color

Changing the minor type for Meter charts


You can change the minor type of a meter graph using the following method:
Do $cinst.$objs.meterGraph.$minormetertype.$assign(kG2meterAngular) or Do $cinst.$objs.meterGraph.$minormetertype.$assign(kG2meterLinear)

133

Chapter 4Omnis Graphs

Meter chart methods


Meter charts have the following methods in addition to the common methods. Method Name $addpointer() Returns None Description $addpointer(nValue, iColor [,nPointertype]) adds a pointer to a 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; see the Adding Pointers section below $addring(iStartradius, iEndradius, iFillcolor) adds a colored ring to an angular meter with the specified start and end radius in pixels; this must be done during the evPreLayout event; you can use this to add a colored band or a number of bands around a standard meter dial; you can color the entire face by setting the start radius to zero and the end radius to beyond the meter ticks

$addring()

None

List data structure for Meter charts


The Meter chart type (kG2meter) lets you create Angular and Linear meters to represent single data points. The properties of the meter type let you specify analog and digital read outs, colored backgrounds, multiple pointers per chart, pointers of different shapes, and so on. The example library demonstrates angular/radial and linear charts. The data in the list associated with the graph object is used to specify the data point and various properties of the graph, as follows:
Do Do Do Do Do Do iGraphList.$add(45.17) iGraphList.$add(0) iGraphList.$add(100) iGraphList.$add(10) iGraphList.$add(5) iGraphList.$add(1) ;; ;; ;; ;; ;; ;; the data point scale start scale end major tick interval minor tick interval micro tick interval

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)

Can be used to build the following linear chart:

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:

The following method adds two pointers to an angular chart:


On evPreLayout If iAddpointer ;; var behind checkbox on window Do $cinst.$objs.meterGraph.$addpointer(30,kGreen,2) ;; triangle Do $cinst.$objs.meterGraph.$addpointer(10,kMagenta,5) ;; line End If ;; etc

The method produces the following 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.

Graph Layers and the Prelayout Event


You can add multiple layers to certain types of XY and Polar graph using the $add<layertype> methods during the Prelayout event (evPreLayout) event, which is triggered just before the graph instance is created in a window. Note you cannot add layers to Pie charts. You can add layers to any type of XY or Polar chart using one of the $add<layertype> methods. In theory, any combination of chart type and layer is possible within the major XY and Polar types, but not all combinations are that meaningful. It largely depends on what type of data you are trying to represent or what data sets you might want to compare by showing the data sets as different layers.

Adding layers to charts


You can specify how the layer data is combined with or added to the graph using one of the data combine type constants as follows: kG2dataOverlay kG2dataPercentage kG2dataSide kG2dataStack The additional data layer is added on top of the existing graph data The existing and additional data sets are combined and scaled so each adds up to 100 The existing and additional data sets are shown side by side The additional data set is stacked on top of the existing graph data

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

Chapter 4Omnis Graphs

Graph Clicks and Drilldown


The Graph2 window component reports an evGraphClick event when the user clicks on the object. The event returns the following event parameters: pItem The number of the item or data point clicked on within the current data set or group; the first item or data point is 1, the second is 2, and so on. The name of the data point clicked on. The number of the data set or group clicked on; the first set or group is 1, the second is 2, and so on. The name of the data set or group clicked on.

pItemname pSet pSetname

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

Will give the following message:


Graph Click = Item Number 1 (Name = Andy) Set Number 2 (Name = Expenses)

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

Changing the Color of Graph elements

Changing the Color of Graph elements


The methods $getcolors() and $setcolors() allow you to get and set the color of elements within a graph at runtime. $getcolors() returns a list containing the RGB color of each element in the current graph. The first eight color values in the color list have special significance. The first three palette colors are the background color, default line color, and the default text color of the chart. The fourth to seventh palette colors are reserved for future use. The eighth color is a special dynamic color indicating the current data set. The ninth color (index = 8) and subsequent colors in the list represent the elements in the graph, such as lines and text objects. In a pie chart, Omnis will automatically use the ninth color for the first slice, the tenth color for the second slice, and so on. Similarly, for a multi-line chart, Omnis will use the ninth color for the first line, the tenth color for the second line, and so on. The $setcolors() method allows you to set the color of any element in the graph. For example, the following method will set the color of the first data element in the chart to black (value 0):
; define local var: lColorList (List) Do $cinst.$objs.GR.$getcolors() Returns lColorList Calculate lColorList.9.1 as 0 ;; 0 = black Do $cinst.$objs.GR.$setcolors(lColorList)

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

Chapter 4Omnis Graphs

Adding Colored Zones


A zone is a color band on the back of the plot area. Like marks, zones can be horizontal or vertical. They are particularly useful for marking different parts of the scale on a meter chart, or adding bands of color behind a bar, area or line chart. You can add zones to the background of a chart using the $addzone() method; this must be done in the evPreLayout event. For example, the following method can be used to set the color for different parts of the scale on a linear meter.
On evPreLayout Do $cinst.$objs.meterGraph.$addzone(0,50,kGreen) Do $cinst.$objs.meterGraph.$addzone(50,80,kYellow) Do $cinst.$objs.meterGraph.$addzone(80,100,kRed) ; etc

This method produces the following chart.

Parameter Substitution and Formatting


Charts often contain a lot of text strings, such as sector labels in pie charts, axis labels for XY charts, data labels for the data points, graph titles, and so on. You can substitute many of these parameters to allow you to configure precisely the information contained in the text and their format. For example, when drawing a pie chart with side label layout, the default sector label format is:
"{label} ({percent}%)"

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}%)"

The sector value will then be something like:


"ABC: US$123 (34.56%)"

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}%)")

Pie chart with default labels

Same pie chart with modified labels

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.

Parameters for Pie charts


Parameter sector dataSet label dataSetName value percent Description The sector number. The first sector is 1, the second is 2, and so on. Same as {sector}. See above. The text label of the sector. Same as {label}. See above. The data value of the sector. The percentage value of the sector.

Parameters for all XY Chart Layers


The following are parameters that apply to all XY Chart layers in general. Some layer types may have additional parameters (see below). Note that some parameters do not apply in certain cases. For example, when specifying the aggregate label of a stacked bar chart, the {dataSetName} parameter does not apply,

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.

dataSet dataSetName dataItem dataGroup dataGroupName layerId

144

Parameter Substitution and Formatting

Additional Parameters for HLOC and CandleStick Layers


The following are in addition to the parameters for all XY Chart layers. Parameter high low open close Description The high value of the data representation. The low value of the data representation. The open value of the data representation. The close value of the data representation.

Additional Parameters for Box Whisker Layers


The following are in addition to the parameters for all XY Chart layers. Parameter top bottom max min med Description The value of the top edge of the box-whisker symbol. The value of the bottom edge of the box-whisker symbol. The value of the maximum mark of the box-whisker symbol. The value of the minimum mark of the box-whisker symbol. The value of the median mark of the box-whisker symbol.

Additional Parameters for Trend Layers


The following are in addition to the parameters for all XY Chart layers. Parameter slope intercept corr stderr Description The slope of the trend line. The y-intercept of the trend line. The correlation coefficient in linear regression analysis. The standard error in linear regression analysis.

145

Chapter 4Omnis Graphs

Parameters for Polar Charts


Parameter radius value angle x label xLabel name dataSetName i dataItem Description The radial value of the data point. Same as {radius}. See above. The angular value of the data point. Same as {angle}. See above. The angular label of the data point. Same as {label}. See above. The name of the layer to which the data point belongs. Same as {name}. See above. The data point number. The first data point is 1, the second is 2, and so on. Same as {i}. See above.

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})")

Parameters for Axis


Parameter value Description The axis value at the tick position.

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.

[b] [c] [d]

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

yyyy yyy yy y mmm mm m dd

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

Chapter 4Omnis Graphs


Parameter Description

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.

Further formatting options


You can use a type of Mark Up Language (supported in the underlying graph engine and called ChartDirector Mark Up Language or CDML) to include formatting information in text strings by marking up the text with tags. This Mark Up Language allows a single text string to be rendered using multiple fonts, with different colors, and even embed images in the text. CDML is supported in all text objects including chart titles, legend keys, axis labels, data labels, and so on.

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

Chapter 4Omnis Graphs

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.

Adding Text to a Chart


You can add text to a chart using the $addtext() method, but this must be done during the evPreLayout event. $addtext(cText, iX, iY [,cFontname, iFontsize, iColor, iAlign, iAngle, bVertical]) adds the specified text positioned according to the X & Y co-ordinates The X & Y co-ordinates are taken from the top left of the graph object, but the Y component is inverted, so that as Y increases the text string will appear further down the chart. The following method adds some text to a Linear meter chart. Note the $formatvalue() method is used to format a number before it is added.
On evPreLayout Calculate lTextToAdd as $cinst.$objs.meterGraph.$formatvalue(75.35,"2") Do $cinst.$objs.meterGraph.$addtext( lTextToAdd,345,70, "arialbd.ttf",8,kBlack,kG2alignBottomRight) Do $cinst.$objs.meterGraph.$addtext( "Temperature C",10,68, "arialbd.ttf",8,kBlack,kG2alignBottomLeft)

This method produces the following chart:

150

Using Graphs in Reports

Using Graphs in Reports


You can use the Graph2 component on Omnis reports in much the same way as you can for windows for displaying data contained in an Omnis list. That is, you can place a graph component on a report class, assign a list variable to it, print the report and the data will be displayed in a chart as expected, depending on the properties you have set in the graph object. However, if you wish to manipulate a graph using any of the graph methods, this must be done within the report instance itself and before the report is printed. Therefore to do this, you must instantiate an object variable based on the Graph2 component, execute any methods against the graph object and transfer the image of the graph to an Omnis picture variable using the $snapshot() method. The graph image contained in the picture variable can be displayed in the report using a standard Omnis Picture field. For example, the following report class has a single picture field with its $dataname set to the variable iPicture. The $height and $width properties are set to 7.9cm and 10.5cm respectively, which corresponds the height and width of the graph image created in the report instance.

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

Chapter 4Omnis Graphs


; ; ; Do Do Do Do Do Do Do Do Do Define class var: cGraphObj (Object), subtype Graph2 Define instance var: iList1 (List), iPicture (Picture) Define instance var: iCol1, iCol2 (Char) iList1.$define(iCol1,iCol2) iList1.$add('Col1',10) iList1.$add('Col2',60) iList1.$add('Col3',30) cGraphObj.$majortype.$assign(kG2xy) cGraphObj.$dataname.$assign(iList1) cGraphObj.$snapshot(400,300) Returns iPicture $cinst.$printrecord() $cinst.$endprint()

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

Using Graphs in the Web client

Using Graphs in the Web client


If you wish to display a chart in a remote form you have to use a similar technique to displaying graphs in a report this is because there is no visual graph component for use with remote forms. Instead, you can use the graph component as an object variable and construct the graph image in memory on the Omnis Server and save and display it as a picture in the remote form. When the graph is constructed in memory, the $snapshot() method lets you transfer the graph image to an image variable suitable for displaying in an Omnis picture field in a remote form. You have to create an Object variable in your remote form with the Graph object specified as the object subtype. The following method will do this:
; cGraphObj is an Object variable with Subtype of Graph2 Do listGraph.$define(Name,Sales) Do listGraph.$add('Andy',85) Do listGraph.$add('Sam',80) Do listGraph.$add('Liza',92) Do listGraph.$add('Harry',45) Do cGraphObj.$majortype.$assign(kG2pie) Do cGraphObj.$dataname.$assign(listGraph) Do cGraphObj.$maintitle.$assign("WebClient Pie Example") Do cGraphObj.$snapshot(640,400) Returns iWebImage

This will result in this image:

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

Chapter 4Omnis Graphs

Drilldown in Web Client graphs


The remote form Picture field type reports the mouse X and Y co-ordinates when an evClick event is triggered. This allows you to pinpoint where in the image the user has clicked. You can use this information to find out which active graph element has been clicked, such as a bar, line or pie slice. Having captured the graph image using the $snapshot() method you can use the $findobject() method to return the item and set information for the selected object. For example:
; do code to construct the graph object, such as Do listGraph.$define(Name,Sales,Expenses) Do listGraph.$add('Andy',850,400) Do listGraph.$add('Sam',800,600) Do listGraph.$add('Liza',920,560) Do listGraph.$add('Harry',450,230) Do cGraphObj.$majortype.$assign(kG2xy) Do cGraphObj.$minorxytype.$assign(kG2xyBar) Do cGraphObj.$dataname.$assign(listGraph) Do cGraphObj.$maintitle.$assign("Web Client Bar Chart") Do cGraphObj.$snapshot(640,400) Returns iWebImage Do $cinst.$objs.pic.$redraw ; graph image is transferred to remote form picture field and redrawn

The bar chart would look something like the following:

; $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

Chapter 5Omnis .NET Objects

Chapter 5Omnis .NET Objects


This chapter describes how you can access .NET Objects using the .NET Objects component available in some editions of Omnis Studio. It assumes that you have both a basic knowledge of Omnis Studio notation, creating Object references, and a basic knowledge of the .NET Language.

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.

Why use .NET


The Microsoft .NET Framework provides a library of prepackaged functionality, including base classes and various APIs, that can be reused and integrated into your Omnis applications. The base classes provide standard functionality such as input/output, string manipulation, security management, and network communications. In addition to the base classes provided in the .NET Framework, there are thousands of class libraries available from third-party developers providing a broad range of functionality, available to Omnis developers via the .NET Objects component. These can be located in your .NET Framework folder and added into Omnis using a $addclass() method call.

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.

Microsoft .NET Framework


In order to use the .NET Objects component in Omnis Studio, you must install the Microsoft .NET framework 2.0 or higher. The .NET framework requires IE 6.0 (SP2) or higher. See the Microsoft web site for further details on system requirements for the .NET framework. You can download the .NET framework from the Microsoft web site; see below for details.

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 Vista & Server 2003


The Microsoft .NET framework is included in Windows Vista and Windows Server 2003 (although it may not be part of the default installation for Windows Server 2003).

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

Chapter 5Omnis .NET Objects

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.

Registering the component


The Omnis .NET Objects component (OMDOTNET.DLL) is installed into the root of your Omnis Studio folder, but it must be registered with .NET in order to work. This can be done using the Regasm program and the following command:
REGASM <Installation Folder>\OMDOTNET.DLL

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

Creating .NET Objects

The .NET Example Library


There is an example library showing how the .NET Objects component works. The example library, which monitors RSS feeds from news web sites, is available under the Examples link in the Welcome window when you first launch Omnis you can open this window by clicking on the New Users button in the main Omnis toolbar. Code from the example library is used later in this manual to show you how to use the component.

Creating .NET Objects


Creating .NET Objects is a two-stage process that is similar to the process of creating Automation Objects or Java Objects in Omnis. A .NET Object is first declared and then constructed using the $createobject() method. This process is described in the following sections.

Defining .NET Objects


.NET Objects can be manipulated in a similar manner to other Omnis Objects. A .NET Object can be defined in a variety of ways: 1. Declaring an Omnis Object variable in the Method Editor and setting the object subtype to a .NET Object class. 2. Declaring an Omnis Object Reference variable and initializing it to point to a .NET Object class using notation. 3. Declaring an Object variable in the Method Editor that does not have a subtype and initializing it to a .NET Object class using notation.

Defining .NET Objects via the Method Editor


To create a .NET Object in the Omnis Method Editor, simply declare an Object variable (e.g. an instance variable) and set its subtype to the desired .NET Objects Class. To do this, click the Subtype dropdown menu to open the Select Object dialog, navigate the Object Selection Tree, highlight the class your require and click OK. The Object Selection Tree is split into one or more sections under the NET heading. These are mscorlib (basic .NET objects) and any classes that you have manually loaded (using $addclass).

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.

Defining .NET Objects using Object References


Object Reference variables are a relatively new feature, introduced in Omnis Studio 4.0. Object Reference variables are similar to Object variables, but you are responsible for the allocation and de-allocation of the object concerned. Object References are declared in the Method Editor, but do not have a subtype. To declare an Object Reference, simply declare a variable in the Method Editor and set its type to Object Reference. You can set a subtype in order to view the objects me thods in the Interface Manager, but the object associated with the reference has to be allocated using the $newref() method.

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.

Defining .NET Objects via Notation


.NET Objects can be defined using the Object type via notation. To define a .NET Object via notation, simply follow the instructions in the previous section but use an Object type variable instead of an Object Reference type and call the $new() method instead of the $newref method.

Constructing .NET Objects


Once a .NET Object has been declared, it needs to be constructed. Declaring a .NET Object simply tells Omnis that the Object exists. Constructing a .NET Object using the $createobject() method actually performs the work of constructing the Object inside the .NET Virtual Machine. By default all .NET Objects will have at least one $createobject() method which takes no parameters. This method can be used to create a .NET Object as follows:
Do lStringRef.$createobject()

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)

will invoke the String(char[] value).

163

Chapter 5Omnis .NET Objects

Subclassing .NET Objects


.NET Objects can be subclassed by creating an Object class (using the New Empty Class option in the Studio Browser followed by the Object option) and setting its Super Class property ($superclass) via the Property Manager and the Object Selection Tree. For example, you can create an Object class and set its $superclass property to .DNet.NET\mscorlib\System\String via the Select Object dialog, as follows:

In this case, the oString object class becomes a subclassed object of String and inherits all of its methods as follows:

164

Subclassing .NET Objects

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

Chapter 5Omnis .NET Objects

Using .NET Objects


The following sections describe how Omnis Data Types are converted to .NET Data Types, how you can pass parameters from Omnis to .NET, how you handle Return Values, and how you can retrieve data from .NET Objects. Other topics, such as Error Handling and Cache Control, are discussed later. Please check the Tech Notes on the Omnis web site (www.omnis.net) for supplementary information about using the .NET Objects component with complex data types.

Parameter Data Types


The following table shows how Omnis Data Types are converted to .NET Data Types when used as parameters to .NET Object methods. The Omnis Data Types marked with a * are known as Overloaded Types as they are compatible with more than one .NET Data Type. Omnis Type Simple types *Character *Binary *Number Long integer Number Short integer *Number floating dp or Number <n> dp Boolean Complex types List Object Object Reference .NET Array .NET Object .NET Object char or char[] byte or byte[] int, long or byte short float or double boolean .NET Type

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)

will create a .NET Byte object whose value is 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

Simple Parameter Types


Character converts to .NET base type char/char[] Binary converts to .NET base type byte/byte[] Number Long integer converts to .NET base type int/long/byte Number Short integer converts to .NET base type short Number floating dp or Number <n> dp converts to .NET base type float/double Boolean converts to .NET base type boolean

Complex Parameter Types


List can be converted to an array of any .NET type depending on list content Object can be converted to an Object of any .NET type depending on content Object Reference can be converted to an Object of any .NET Type depending on the content of the referenced Object

167

Chapter 5Omnis .NET Objects

Passing Simple Parameter Types


Passing simple parameter types is relatively easy. You can call the .NET Object method with parameter(s), as you would call any method in Omnis. In the following example, the simple parameter type lpos is passed to the .NET.System.String charAt() function. This function returns the character value l as this character resides at index 3 of the .NET String.

Passing Complex Parameter Types


Complex Parameter types such as lists and Objects can be passed to .NET, however these Parameter types must be initialised before being used.

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

Chapter 5Omnis .NET Objects

Returning Values From .NET Methods


The following table shows how .NET Return types are converted to Omnis data types. .NET Type char[] or char byte[] or byte int or long float or double short Boolean .NET Arrays (except char[] and byte[]) Objects Omnis Type Character Binary Number Long integer Number Floating dp or Number <n> dp Number Short Integer Boolean List Object References

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.

Obtaining constant (or Enum) values


Due to the numerous .NET classes available, constants (enums) are not added to the Omnis constants as shown in the Catalog (F9). To obtain the value of a particular constant, you can call the $getenum function with the fully qualified .NET class. For example, to open an existing stream object you can call:
Do oStream.$createobject( myFile,DNet.$getenum("System.IO.FileMode.Open"))

170

Using .NET Objects

Adding .NET Classes


Additional .NET classes can be added by calling DNET.$addclass() with the location of the filename. For example, to add SOAP classes you can execute:
Calculate #S1 as con( DNet.$basefolder(),sys(9), "System.Runtime.Serialization.Formatters.Soap.dll") Do DNet.$addclass(#S1) Returns #1

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

Chapter 5Omnis .NET Objects

.NET Objects example library


There is an example library showing how the .NET Objects component works. The example library, which monitors RSS feeds from news web sites, is available under the Examples link in the Welcome window when you first launch Omnis you can open this window by clicking on the New Users button in the main Omnis toolbar.

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.

The RSS feed component


The RSS feed application comprises an Omnis library and a DLL which are located in the \welcome\examples folder under the main Omnis folder. The rssreader.dll contains the compiled C# code and provides Omnis with a single .NET object with three properties and two methods. The first method in the RSS feed object, getdocument(), retrieves the XML source from the specified address in the rssUrl property. Thereafter it parses out the XML in the channel node and sets it to the channelNode property. This is of type System.Xml.XmlNode and allows Omnis to call its member functions to determine title, language, and so on, of the

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.

The RSS feed library


To discover how Omnis uses the .NET object you should examine the code in the RSS feed library. The Startup_Task in the library opens the RSS window and creates the object. The code for the $construct() method of the RSS window is as follows. The first part of the method loads the rssreader.dll and adds its .NET classes to Omnis using the $addclass() method.
Do FileOps.$splitpathname(sys(10),lDrive,lPath,,) Calculate lPath as con(lDrive,lPath,'rssreader.dll') Do DNet.$addclass(lPath)

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

Chapter 5Omnis .NET Objects

Method Method Overloading and Pattern Matching


Although Omnis Studio does not normally support the overloading of method names, the .NET Objects component is an exception as method overloading is usually unavoidable when dealing with even the most basic of .NET classes. The following sections discuss how Omnis deals with overloaded methods and how it is possible to manually call an overloaded method directly from Omnis.

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).

Overloaded Data Types


An extra level of complexity is added to Pattern Matching with the support of Overloaded Data Types. An Overloaded Data Type is an Omnis data type that has more than one matching data type in .NET. Overloaded Data Types are split into three groups, described in the following sections.

Number Long Integer types


The Omnis Number Long Integer type can be translated to the following .NET types: int long byte If a Number Long Integer 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. Therefore, if you are calling a method with (int,boolean,int), Omnis will try to find an overloaded method which matches this Parameter Search Pattern.

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.

Number Floating dp types


The Omnis Number Floating dp type can be translated to the following .NET types: double float decimal 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 double parameters that you are passing. Therefore, if you are calling a method with (double,boolean,double), Omnis will try to find an overloaded method which matches this Parameter Search Pattern. 177

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.

.NET Object types


The Omnis .NET Object type can be translated to the following .NET Types: < The object that you are attempting to pass as a parameter, e.g. .NET.System.String > .NET.System.Object When matching objects, Omnis will always try to find a method which takes an object parameter that matches the type of the object that you are passing. So if you pass a .NET.System.String object to an overloaded method, Omnis will look for a match using .NET.System.String as a search pattern. If Omnis fails to find a matching method, then Omnis will call a method which takes the generic type .NET.System.Object as a parameter, if such a method is available. Therefore, if Omnis searches for a method using the Parameter Search Pattern (String,boolean,String) and a matching method is not found,

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).

Char and Byte Pattern Matching


The following table shows how Omnis converts Character and Binary data types to .NET data types when dealing with overloaded methods. Omnis character types (length > 1) binary types (length > 1) character types (length <= 1) binary types (length <= 1) .NET char[] byte[] char byte

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.

Calling Overloaded Methods Directly


In some rare cases, it may be necessary to call overloaded methods directly. Consider the following example: you may be trying to call overloaded functions in the .NET.System.String Class. The functions are defined in .NET as follows:
compareto(Character c) compareto(Object o) (

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}.

Note: Each parameter is separated by an underscore (_).

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

An additional p character means pointer (or *) and an a character means an array.

Nested Object Arrays


The .NET Objects component supports Nested Object Arrays as parameters to .NET methods, and it can also interpret Nested Object Arrays returned from .NET. A Nested Object Array is an array of type .NET.System.Object that is capable of storing any .NET Object or Array of .NET Objects. To use a Nested Object Array, you must create an Omnis List variable and define it using a Binary variable. You can then add .NET Objects and lists of .NET Objects to the list. Once your list is complete, you can pass it to any .NET method that accepts .NET.System.Object array as a parameter. Nested Object Arrays can also be returned by .NET methods. A Nested Object Array is returned to Omnis as a Binary list. This list may contain both Object References and embedded Lists.

181

Chapter 5Omnis .NET Objects

Overloaded Types
The following sections provide detailed descriptions of the Overloaded Types used by the .NET Objects component.

Omnis Character types


The Omnis Character type can be converted into the following .NET types:
char char[]

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.

Omnis Binary types


The Omnis Binary type can be converted into the following .NET types:
byte byte[]

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.

Omnis Number Long Integer types


The Omnis Number Long Integer type can be converted into the following .NET types:
int long byte

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.

Omnis Number Floating dp types


The Omnis Number Floating type can be converted into the following .NET types:
float double

This allows you to pass Omnis Number floating dp variables to .NET functions which accept these types.

183

Chapter 6Java Objects

Chapter 6Java Objects


Java Objects allow you to use Java Objects from Omnis code. Once a Java Object has been created in Omnis, its methods can be called in the same manner as any Omnis object. A separate document describing the Omnis Java API that provides an interface to Java for Omnis External Component developers is available on the website at: http://www.omnis.net/download/components/index.html This chapter assumes that you have both a basic knowledge of Omnis Studio notation and a good knowledge of the Java Language. Note: The hyperlinks in this section were valid at the time of writing. However, these links are subject to change without notice by Sun Microsystems.

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.

Java Naming and Backwards compatibility


Note that following version 1.4.x, Sun renamed the J2SE environment to Java SE, so rather than naming the next version 1.5.x, it was called Java SE version 5. Omnis Java Objects implementation is backwards compatible so J2SE version 1.4.1 should still work. Search the Sun website for more information about the different versions of the Java SE environment and the Java SDK which they now call JDK.

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.

Java Example Library


Omnis Studio includes an example library called example.lbs that demonstrates the use of Java Objects. This library is referred to throughout this chapter and is designed to be used in conjunction with the Java Package called example. Both the Omnis library and the Java Package can be found in the \Java\JavaCode\example in the main Omnis folder.

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

OMNISCLASSPATH environment variable


You can use the OMNISCLASSPATH environment variable to specify Java classes instead of CLASSPATH. This can increase performance in situations where you have multiple Java applications installed that are not being used with Omnis. Under normal circumstances, the classes for these applications will be added to the Omnis Class Cache, even though they are not being used. By using OMNISCLASSPATH, you will be able to specify only the classes that you wish to use with Omnis. If OMNISCLASSPATH is not defined, CLASSPATH will be used.

Getting and Setting Environment Variables in Omnis


There are three functions in Omnis that you can use to for manipulate environment variables. Listing Environment Variables The listenv() function returns a 2 column list of the Omnis process environment variables. Column 1 contains the variable name and column 2 the variable value. The list is sorted by the variable name column, and is case insensitive. There is no need to define the list first; the returned list has 2 character columns, name and value. For example:
Calculate lList as listenv() ; returns a list of environment variables on the current system

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

Chapter 6Java Objects

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.

The Java Class Cache


Starting Omnis
Once you have configured your platform to run J2SE/Java SE, start Omnis. There may be a brief pause during startup. This is because Omnis is starting the Java Virtual Machine and collecting information on Java System Classes. This procedure does not occur every time you start Omnis as Java Class information is cached. However, this procedure will occur again if you reset the Omnis Class Cache (see the Advanced Topics section for further details on resetting the Omnis Class Cache).

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

Creating Java Objects

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.

Resetting the Java Class Cache


To reset the Java class cache, you can either delete the cache file manually or use the Reset class cache option in the Studio Browser (click on the Studio option in the treelist of the Studio Browser, then click on the Java option to show the Reset class cache option). The cache file is called jcache1.dat and can be found in the omnis\java folder.

Creating Java Objects


Creating Java Objects is a two-stage process that is similar to the process of creating Automation Objects in Omnis. A Java Object is first declared and then constructed using the $createobject() method. This process is described in the following sections.

Defining Java Objects


Java Objects can be manipulated in a similar manner to other Omnis Objects. A Java Object can be defined in a variety of ways: Declaring an object in the method editor and setting the object subtype to JavaObjs. or Declaring an object reference and initializing it to point to a Java Object using notation. or Declaring an object in the method editor that does not have a subtype and initializing it to a Java Object using notation. It is not possible to use a Java Class that contains either the string 'omnis' or 'javacore' in its name.

Defining Java Objects via the Method Editor


To create a Java Object in the method editor, simply declare an object variable and set its subtype to the desired Java Objects Class. The Java Class can be chosen from the Select Object dialog. To select a Class, navigate the Object Selection Tree until the desired class is found, highlight the class and click OK. The Object Selection Tree is split into two sections under the JavaObjs heading. These are ClassPath and System. Any classes that have been placed in any of the folders that are specified in the CLASSPATH environment variable will appear in the ClassPath section. All other available classes will appear in the System section.

189

Chapter 6Java Objects

Defining Java Objects using Object References


Object References are similar to object variables but you are responsible for the allocation and de-allocation of the object. Object References are declared in the Method Editor but do not have a subtype. The Object that is associated with an Object Reference is determined at runtime when it is allocated via notation: To declare an Object Reference, simply declare a variable in the Method Editor and set its type to Object Reference. To allocate an Object to an Object Reference, you must use notation. As notation strings for Java Objects can be very long (due to the large hierarchies that are present in some Java Packages) the Object Selection Tree is displayed as a helper window when entering Java Objects notation. If a class is selected from this tree then a large portion of the notation is created for you. All Java Object notation begins with $extobjects.JavaObjs Library.$objects. The remainder of the notation string is dependant on the Java Class that is being used. For example:
$extobjects.JavaObjs Library.$objects.//JavaObjs\ClassPath\zipdemo\zipdemo//

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()

Defining Java Objects via Notation


Java Objects can also be defined using the object type via notation. To define a Java Object via notation, simply follow the instructions in the previous section but use an Object type instead of an Object Reference type and call the $new() method instead of the $newerf() method.

Constructing Java Objects


Once a Java Object has been declared, it needs to be constructed. Declaring a Java Object simply tells Omnis that the Object exists. Constructing a Java Object using $createobject() actually performs the work of constructing the Object inside the Java Virtual Machine. By default all Java Objects will have at least one $createobject() method which takes no parameters. This method can be used to create a Java Object as follows: 190

Creating Java Objects


Do lzipdemo.$createobject()

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)

count) offset,int count) length)

These are mirrored in Omnis by the following $createobject() methods:

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.

Subclassing Java Objects


Java Objects can be subclassed by creating an Omnis Object class (using the New Class>>Object option in the Studio Browser) and setting its $superclass property to the name of a Java Class using the Object Selection Tree.

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

Using Java Objects

Using Java Objects


The following sections describe how Omnis Data Types are converted to Java Data Types, how to pass parameters from Omnis to Java, how to handle Return Values and how to retrieve data from Java Objects. Other topics such as Error Handling and Cache Control are also discussed.

Parameter Data Types


To call Java Objects effectively, you need to know how Omnis Data Types are mapped to Java Data Types when passing parameters. The following table shows how Omnis Data Types are converted to Java Data Types when used as parameters to Java Object Methods. Omnis Type Character* Binary* Number Long integer* Number Short integer Number floating dp* or Number <n> dp Boolean List Object Object Reference Converts to {Java Type) char or char[] byte or byte[] Int, long or byte short float or double Boolean Java Array Java Object Java Object

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)

will create a Java Byte object whose value is 65.

193

Chapter 6Java Objects

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.

Java Object Simple Parameter Types


Omnis data type Character Binary Number Long integer Number Short integer Number floating dp or Number <n> dp Boolean converts to (Java base type) char/char[] byte/byte[] int/long/byte short float/double Boolean

Java Object Complex Parameter Types


Omnis data type List Object Object Reference Can be converted to (Java type) an array of any Java type depending on list content an Object of any Java type depending on content an Object of any Java Type depending on the content of the referenced Object

Passing Simple Parameter Types


Passing Simple Parameter types to a Java Object is relatively simple. You call the Java Object method with the parameter(s), as you would call any object method in Omnis.

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.

Passing Complex Parameter Types


Complex Parameter types such as lists and Objects can be passed to Java Objects as well. However, these Parameter types must be initialized before being used.

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.

Returning Values From Java Methods


The following table shows how Java Return Types are converted to Omnis Data Types. Java Type char[] or char byte[] or byte int or long float or double short Boolean Java Arrays (except char[] and byte[]) Objects Converts to (Omnis Type) Character Binary Number Long integer Number floating dp or Number <n> dp Number Short integer Boolean List Object references

Note: this is a reversal of the table shown in the previous section.

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.

Data type mapping and performance


There is a Boolean library preference called $javareturnsnative that effects the way in which arrays of Java data types are returned from Java to Omnis. When the property is set to kTrue, Java object methods called from the library return native Omnis types if a suitable conversion exists, rather than an object reference to a Java object. For example, a method returning a Java String object returns an Omnis Character value. Setting the value to kTrue also benefits from the improved performance. Existing libraries have the $javareturnsnative property set to kFalse for backwards compatibility, but all new libraries will have a default value of kTrue. Note: If you wish to set the $javareturnsnative property to kTrue in an existing library, you must change the types of the Omnis variables used to return values from Java. For example, when a Java method that returns a java.lang.String is called from an Omnis library with $javareturnsnative set as kFalse, the Omnis return type will be Object reference. Changing the $javareturnsnative property to kTrue means that the return types for these methods need to be changed to the Omnis Character type.

197

Chapter 6Java Objects

Getting Values From Java Objects


All Java Objects in Omnis have the $getobjectvalue() method. The purpose of this method is to attempt to get the content of the current Java Object and to convert this content into a format that Omnis understands. This is not always possible as many Java Objects do not have a corresponding type in Omnis. However, most of the Objects in Java can usually be coerced into an object type that can, in turn, be converted into an Omnis Data type using $getobjectvalue(). In addition to this, some Objects in Java have their own versions of $getobjectvalue which are designed to convert object content. For example, the java.lang.Float class has functions such as byteValue() and intValue() to coerce the float content to byte and int types. $getobjectvalue can be used in the following manner:

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

Using Java Objects

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.

Adding Java Classes at Runtime


When Omnis is started for the first time, it will create a cache file for all Java System and Class Path classes automatically. This cache improves performance, as it removes the necessity to interrogate the Java Virtual Machine to find out which classes are available every time Omnis starts up. Once Omnis has started up, and loaded all the Java classes in your Omnis\Java folder and on your CLASSPATH and System, you can load Java classes while Omnis is running using the $addclass() method. The syntax of this method is as follows:
Do JavaObjs Library.$addclass( classgroup, classfilename [,classpath])

The classgroup parameter


The classgroup parameter specifies the Java Objects category or group in the Java Objects class list that the loaded class will be added to. The group is one of the following constants: kJavaObjsClassPathGroup: kJavaObjsWebServicesGroup: kJavaObjsWebServicesClientGroup: Specifies the classpath category. Specifies the webservices category. Specifies the webservices client category.

The classfilename parameter


The classfilename parameter can contain one of the following: 1. A fully qualified pathname of the class file to be loaded. 2. A fully qualified folder name that contains one or more class files. 199

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.

The classpath parameter


The classpath parameter specifies the particular classpath that your class resides on. You do not have to specify the entire contents of the CLASSPATH environment variable in this parameter, it is only necessary to specify the classpath that contains the class that you are adding. For example, if your CLASSPATH environment variable contains the path C:\classes and you are attempting to add the class c:\classes\zipdemo\zipdemo.class, you only need to specify c:\classes as your classpath parameter. If you do not specify a classpath parameter, the default classpath is used for the group that you have specified. For example, if you have specified a group constant of kJavaObjsWebServicesGroup, Omnis will use the path of the Omnis Web services directory as the classpath. The built-in classpath definitions for each group are represented by Omnis constants as follows: kJavaObjsClassPathGroup: kJavaObjsWebServicesGroup: kJavaObjsWebServicesClientGroup: <Omnis Folder>\Java\JavaCode <Omnis Folder>\Java\WebServices <Omnis Folder>\Java\WebServices\client

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

Chapter 6Java Objects #ERRCODE and #ERRTEXT can be used as follows:

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.

Method Overloading and Pattern Matching


Although Omnis Studio does not normally support the overloading of method names, Java Objects are an exception as method overloading is usually unavoidable when dealing with even the most basic of Java Classes. The following sections discuss how Omnis deals with overloaded methods and how it is possible to manually call an overloaded method directly from Omnis.

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).

Overloaded Data Types


An extra level of complexity is added to Pattern Matching with the support of Overloaded Data Types. An Overloaded Data Type is an Omnis Data Type that has more than one matching data type in Java. Overloaded Data Types are split into three groups as follows.

The Number Long Integer Type


The Omnis Number Long Integer type can be translated to the following Java Types. int long byte 203

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.

The Number Floating dp Type


The Omnis Number Floating dp type can be translated to the following Java Types. float double 204

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).

The Java Object Type


The Omnis Java Object type can be translated to the following Java Types. < The object that you are attempting to pass as a parameter (e.g. java.lang.String)> java.lang.Object When matching objects, Omnis will always try to find a method which takes an object parameter that matches the type of the object that you are passing. So if you pass a java.lang.String object to an overloaded method, Omnis will look for a match using java.lang.String as a search pattern. If Omnis fails to find a matching method, a method which takes the generic type java.lang.Object as a parameter will be called, if such a method is available, i.e. if Omnis searches for a method using the Parameter Search Pattern (String,boolean,String) and a matching method is not found, Omnis will look for (Object,boolean,String) followed by (String,boolean,Object) followed by (Object,boolean,Object).

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).

Char and Byte Pattern Matching


The following shows how Omnis converts Character and Binary data types to Java Data types when dealing with overloaded methods. Omnis character types (length > 1) binary types (length > 1) character types (length <= 1) binary types (length <= 1) are converted to are converted to are converted to are converted to Java char[] byte[] char byte

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.

Calling Overloaded Methods Directly


In some rare cases, it may be necessary to call overloaded methods directly. Consider the following example. You are trying to call overloaded functions in the java.lang.String Class. The functions are defined in Java as follows: valueof(float f) valueof(double d) etc.. You have created an Omnis Object for the String class and you are attempting to call valueof(double d) by passing an Omnis Floating dp type as a parameter. However, because of the Pattern Matching and Data Type Matching rules previously discussed, valueof(float f) is always called. In situations such as this, it is necessary to call valueof(double d) directly. In order to do this, the method can be called by its real name. All overloaded methods have an associated real name. This consists of the method name followed by a string of alpha numeric characters and is used internally by Omnis for pattern matching purposes. The real name of an overloaded method can be found by opening the Interface Manager for the Java Object (o open the Interface Manager, right-click on the object in the method editor and select Interface Manager). From the Interface Manager, select the required overloaded method that you wish to call and click on the description tab. This will display the real name of the overloaded method as follows:

207

Chapter 6Java Objects

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}.

Nested Object Arrays


Java Objects support Nested Object Arrays as parameters to Java methods and can also interpret Nested Object Arrays that are returned from Java. A Nested Object Array is an array of type java.lang.Object that is capable of storing any Java Object or Array of Java Objects. To use a nested Object array you must create an Omnis List variable and define it using a Binary variable. You can then add Java Objects and Lists of Java Objects to the list. Once your list is complete, you may pass it to any Java method that accepts java.lang.Object array as a parameter. Nested Object Arrays can also be returned by Java methods. A Nested Object Array is returned to Omnis as a Binary list. This list may contain both object references and embedded lists. An example of how to use Nested Object Arrays can be found in the example.lbs Omnis library that accompanies Omnis (in the Java\JavaCode folder). The window class nestedobjects demonstrates how to call a Java method using a Nested Object Array. The example begins by creating an Omnis list that has the following structure: 208

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.

Modifying The System Package List


Before attempting the following, the Java Object Cache should be cleared and Omnis should be shutdown if it is running. Modifying the Omnis Studio System Package list may cause unpredictable behavior and is not supported by TigerLogic. The following is simply provided for those readers who wish to experiment with extra functionality. Users attempting the following procedure should make a copy of the jfilter.txt file before proceeding. This file can be found in the Java folder under the main Omnis folder.

Adding Extra System Packages


When Omnis starts up, the following default System Class packages are available for use with Java Objects: java.lang java.io java.util java.math This list can be increased by editing the jfilter.txt file that can be found in the Java folder under the main Omnis folder. The default content of this file is as follows:
System\java\lang;System\java\io;System\java\util;System\java\math

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

Chapter 6Java Objects


System\java\net;System\java\lang;System\java\io ;System\java\util;System\java\math

Removing System Packages


To remove a package, delete the relevant path from the path list. Note that deleting the jfilter.txt file completely will make all Java System packages available. However, this will significantly worsen performance and is not recommended.

Overloaded Types
The following sections provide detailed descriptions of the Overloaded Types used by Java Objects.

The Omnis Character Type


The Omnis Character type can be converted into the following java types: char char[] This allows you to call any Java object that takes either a char or char[] as a parameter with an Omnis Character variable. You may also place Java 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 Java char 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:
Calculate mychar as hello this is a test Do mystring.$createobject(mychar)

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.

The Omnis Binary Type


The Omnis Binary type can be converted into the following java types: byte byte[] This allows you to call any Java object that takes either a byte or byte[] as a parameter with an Omnis Binary Variable. You may also place Java return values that are of type byte or byte[] into an Omnis Binary variable. 210

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.

The Omnis Number Long Integer Type


The Omnis Number Long Integer type can be converted into the following java types: Int long byte This allows you to pass Omnis Number Long integer variables to Java functions which accept these types. When dealing with return values, Java 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.

The Omnis Number Floating dp Type


The Omnis Number Floating dp type can be converted into the following Java types: Float double This allows you to pass Omnis Number floating dp variables to Java functions which accept these types.

Frequently Asked Questions


This section aims to answer some common questions about the Java installation and use with Omnis Studio. Q. I have created an Omnis library which uses Java Objects and have moved this library to another machine. Now when I examine Objects in the method editor using the interface manager, no methods are displayed. Why is this? A. The Java Virtual Machine has failed to start on the machine that you are now using. This can be confirmed by looking at Omnis Studio Trace Log. Make sure that you have correctly 211

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

How does it work?

Chapter 7Remote Studio Applet


Remote Studio is an applet, which provides an equivalent of remote procedure calls to an Omnis server in order to provide functionality. The applet may reside either on the client or the server and can be utilized from many languages. For example, you could invoke it on your server from PERL or PHP, or invoke it on your client from VBScript, Delphi or .NET(C#, C or Visual Basic). Remote Studio is available as COM, Java or PHP objects so the possibilities are endless. For example, you could write a Web Service using .NET, which uses the Remote Studio applet to provide functionality via SOAP requests; or you could simply use it from VBScript embedded in an HTML page.

How does it work?


The Remote Studio applet consists of two objects, both of which provide various methods and properties. The main object, the server object, lets you set up connection information; this information is very similar to the information required for an Omnis web client connection. The second object, the variable object, provides functionality to get and set the variable information using variable types, which are native to the language. This object ensures that when the applet is translated to another language, such as Java, your code is virtually identical to all the other languages. To use the applet, follow these steps: Create the server object Configure the connection information parameters (URL address, task name, etc.) Call the server object Destroy the server object During the calling of the server object, the specified Omnis task will be constructed and the $event() method will be called with the method name and the parameters. Note that if the parameters are altered during the call, they will be updated in the calling code so in that sense they can be referred to as being passed by reference.

213

Chapter 7Remote Studio Applet

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

ExecuteNoParams NewChar NewLong NewBool NewVar

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

Variable Object methods


Method Name GetType Description Get the variable type. The following types exist: varNone(0), varChar(1), varBinary(2), varPicture(3), varBool(4), varNumber(5), varList(6), varRow(7), varLong(8), varDateTime(9). Clears/empties the variable content resulting in its type being varNone. Get the character data Set the character data Get the Boolean data Set the Boolean data Get the long integer data (32 bits) Set the long integer data (32 bits) Get the number data Set the number data Get the date / time data Set the date / time data Get the binary data Parameters None Return Value Integer

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

Set the binary data

GetBinaryLen SetRow

Get the length of the binary data Creates a row

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

Integer row, integer column, Variable Object

None

Note: Variable conversion between types will automatically occur, however if a variable cannot be converted then a data mismatch error will be called.

Studio Remote Tasks


You need to create an Omnis remote task class on the server to process the method requests. You should consider whether or not you need an instance of the remote task class to be constructed and destructed for each method call (most of the time you will not), therefore you will need to add a $canclose() method (see examples section) to the task. The Remote Studio applet will add the following variables to the row parameter which is passed to the remote task instance during $construct() and $event() methods. Parameter vars RSrval RSname RSparmNN Description RSrval is the row column, which contains the return value. Populate this value with the data that you wish to return to the caller. RSname is the name of the method that should be invoked by the task instance. Where NN is the number of the parameter from 1 to N. RSparmNN are the parameters for the method. If these are modified then the variables in the server applet will also be modified. MessageType contains an integer to indicate the reason for the call. Currently the only valid values are: 0 = Object is being closed by the caller 1 = Method call

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

Remote Studio Examples

Remote Studio Examples


Studio server remote task format
An example of a remote task class:
Instance Var: iCanClose (Boolean) ; $construct method ; Parameter 1: pParams (Row) Quit method $processmsg(pParams) ; $canclose method Quit Method iCanClose ; $event method ; Parameter 1: pParams (Row) On evPost Quit method $processmsg(pParams) ; $processmsg method ; Parameter 1: pParams (Row) Switch pParams.MessageType Case 0 ;; Object being closed by server Calculate iCanClose as kTrue Case 1 ;; Method call ;; Use values in pParams to call method. ;; Note that this is a simple example and more work ;; is required for the parameters. Calculate iCanClose as kFalse Do method [pParams.RSname] Returns pParams.RSrval End Switch Quit method pParams ; TestRoutine method ; Sample method which can be called by server applet ; You should add more methods as required Quit method Test Return Value

217

Chapter 7Remote Studio Applet

Use of the Server applet in Visual Basic


The following is an example of use in Visual Basic. To use this code in other languages such as .NET, VBA, Delphi you will need to change the syntax, but the structure should remain similar or unchanged.
Private Sub Command1_Click() Dim rsapp As RemoteStudio.Application Dim args(1) As RSvar Dim result As RSvar Rem Create applet & connect Set rsapp = New RemoteStudio.Application rsapp.omnisLibrary = MyLibrary rsapp.omnisClass = rtMyTask rsapp.omnisServer = 5000 rsapp.serverURL = http://000.000.000.000 ;; IP of your server rsapp.serverScript = /cgi-bin/nph-omniscgi.exe If (rsapp.open()) then MsgBox (Error +rsapp.errorText()) End If Rem Setup parameters and call routine Set args(0) = New RSvar args(0).setChar (Parameter 1) Set result = rsapp.execute(TestRoutine,args,1) If ( rsapp.errorId()) Then MsgBox (Error +Str(rsapp.errorId()) + : + rsapp.errorText() ) Else MsgBox (Method returned +result.getChar()) End If Rem Close applet rsapp.Close End Sub

218

Remote Studio Examples

Use of the complex variables and Server applet in Omnis Studio


The following is an example of returning a complex variable type, in this case a list, in Omnis Studio. To use this code in other languages such as Visual Basic, .NET, VBA, Delphi you will need to change the syntax, but the structure should remain similar or unchanged.
; Server rtnVarList Method Set current list myList Define list {myCol1,myCol2} Add line to list {("Row1 Col1","Row1 Col2")} Add line to list {("Row2 Col1","Row2 Col2")} Add line to list {("Row3 Col1","Row3 Col2")} Do pParams.$cols.RSrval.$coltype.$assign(kList) Calculate pParams.RSrval as myList ; Client Method Do rsapp.$createobject() Calculate rsapp.$omnislibrary as "RSTUDIO" Calculate rsapp.$omnisclass as "rtRStudio" Calculate rsapp.$omnisserver as "5112" Calculate rsapp.$serverurl as "http://127.0.0.1" Calculate rsapp.$serverscript as "/cgi-bin/nph-omniscgi.exe" Do rsapp.$open() Do rsapp.$executeNoParams("rtnVarList") Returns result Calculate rcnt as result.$getrowcount() Calculate ccnt as result.$getcolumncount() For row from 1 to rcnt step 1 For col from 1 to ccnt step 1 ; To confirm with Visual Basic, offsets are zero based Calculate parm1 as result.$getelement(row-1,col-1) Send to trace log {[parm1.$getchar()]} End For End For

219

Chapter 7Remote Studio Applet

Use of the Server applet in PHP


The following is an example of use in PHP.
Server rtnVarList Method See previous example for the server method code Client Method <?php include_once("rstudio.php"); $rsapp = new RemoteStudio; $rsapp->mOmnisLibrary = "RSTUDIO"; $rsapp->mOmnisClass = "rtRStudio"; $rsapp->mOmnisServer = "5112"; $rsapp->mServerURL = "127.0.0.1"; $rsapp->mServerScript = "/cgi-bin/nph-omniscgi.exe"; if ( $rsapp->open() ) { echo "Port opened\r\n"; $result = $rsapp->executeNoParams("rtnVarList"); $lst = $result->getList(); for ( $r=1; $r<=$lst->rowCount(); $r++ ) { echo " Row $r = "; for ( $c=1; $c<=$lst->colCount(); $c++ ) { $var = $lst->getElement($r,$c); echo $var->getCString() . " "; } echo "\r\n"; } echo "Port closed\r\n"; $rsapp->close(); } if ( $rsapp->getErrorID() ) { echo " Error ID :" . $rsapp->getErrorID() . "\r\n"; echo " Error Message:" . $rsapp->getErrorText() . "\r\n"; } ?>

220

Instantiating an Automation Server

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.

Instantiating an Automation Server


In Omnis, before you can utilize automation servers, you need to get an object (in Excels case you need to obtain an Application object). You can obtain an automation object by: Creating an object variable with subtype set to the automation server that you require. Once created, you will have to invoke a standard method, such as $createobject(), to instantiate the server. Calling the OLE picture control $getobject() method and using the returned object variable. Querying an ActiveX controls property, or calling a method, which returns an object variable.

221

Chapter 8Automation

Automation Server Functionality


An object by itself does nothing unless you can do something with that object. To programmatically examine or control an object, you can use the properties and methods that the object supports. A property is a function that sets or retrieves an attribute for an object. A method is a function that performs some action on an object. For example, in Omnis, you can navigate to an object by starting at the uppermost object and working your way down to your target. Consider Excel and its Workbooks collection object, which represents all the open workbooks. You could use its Count property to acquire the count of workbooks open in Excel:
lNum = objectApplication.$Workbooks().$xcount

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.

Lifetime of an Automation Server Instance


The lifetime of an automation instance typically follows these steps:

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

Automation Event Handling

Automation Event Handling


Some automation servers fire events, for example, an email application may fire an email alert event to signify new emails. In Omnis, it is possible to intercept COM automation events (ActiveX and OLE2 events are handled differently). To intercept events, you simply sub-class the automation server object and override the desired events. The event method name will have the suffix event added. For example, the following steps illustrate the trapping of events for an automation server called UrlReader, which is available from Microsoft.

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:

$construct Do myObj.$createobject() $destruct Do myObj.$quit() Button evClick Do myObj.$readurl(http://www.microsoft.com/,c:\mscom.txt)

Open the window and the tracelog. Then press the button. Notice that the tracelog will contain Event triggered text.

225

Chapter 8Automation

Automation to Omnis Variable Conversion


An advanced topic is the differences between variable types in automation and in Omnis. This topic becomes less and less relevant as the automation servers become more and more flexible; unfortunately, some of the older automation servers are rather inflexible when it comes to the type of variables used. Automation has a parameter type called VARIANT; this type can hold any type of data. Unfortunately with this flexibility comes a price. Namely that some objects, Excel for example, state that they handle any type of data (ie VARIANT) in theory, but in fact they may be expecting data passed by reference or of a limit subset of the VARIANT types. The Omnis automation component takes the same approach as Visual Basic, in that everything is passed by VARIANT, and depending on the Omnis data type used, certain assumptions are made. All these assumptions can be over-ridden; the table below shows the default conversion. Omnis DataType Boolean Integer (0 to 255) Integer (Long) Number Character List Row Binary Automation DataType VT_BOOL VT_I1 VT_I4 VT_R8 VT_BSTR VT_ARRAY VT_ARRAY VT_ARRAY | VT_UI1

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

Automation Errors and Limitations


Should an automation error occur, then the contents of #ERRCODE and #ERRTEXT can be used to isolate the problem. On an error, #ERRCODE will be set to the automation error code type, HRESULT, which is a 32bit unsigned integer. A value of 1 indicates that the error occurred in the automation component rather than in the automation server, for example, Automation method not found. #ERRTEXT will contain a string representation of the error.

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

This example enumerates the contacts in your Outlook application.

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")

To encrypt or decrypt data use the following methods:


Do blowfish.$encrypt("MyData",bIncludeHeader) Return binData ; or visa-versa Do blowfish.$decrypt("MyData",bIncludeHeader) Return binData

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

Chapter 10Accessing the Windows Registry

Chapter 10Accessing the Windows Registry


The Omnis RegAdmin component is a non-visual object that gives you access to the Windows Registry allowing you to manage system information on the client machine. As the Windows Registry is applicable to the Windows platform only, all the functions return an error message on Mac OS X and Linux. WARNING: The registry contains system information that is vital to your computer, and an incorrect change to your computer's registry could render your computer inoperable. We therefore strongly recommend that you back up the registry before making any changes to it, especially if you are creating and testing code that will modify your registry or your customers registry settings. Alternatively, you can create a restore point using System Restore which will allow you to undo changes to your system settings if required. For further information about the registry, backing up and creating restore points, refer to the Windows Help. Note that under Windows Vista access to files in the Windows Registry is limited, unless you turn off User Account Control (UAC), which may not be possible or permissible on end user PCs.

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

Creating a RegAdmin Object


To access the functions within RegAdmin, you will need to define a RegAdmin object. You can do this using any of the following methods: Declare an Omnis Object variable in the Method Editor and set the subtype to the RegAdmin object. Declare an Object variable in the Method Editor and initialize it to point to a RegAdmin object via notation. Define an Object Reference variable in the Method Editor and initialize it to a RegAdmin object via notation and the $newref() function.

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

Navigating the Registry


You can open a registry key providing a Root Key handle (kRegAdminKey constant) or by providing an existing open key. The only caveat is that you cant pass in the calling object as the first parameter to the object.

233

Chapter 10Accessing the Windows Registry

Creating new Keys and Values


To create a new key you must execute the $createkey() method. It takes one parameter and a second optional parameter. The first parameter can be either an existing RegAdmin object, or a root key handle constant (kRegAdminKey). The second optional parameter can specify a path to a subkey, separating keys via the \ separator. This call will create and open a new key if not present in the registry. In the event that the key specified by the first and second parameters does exist, that key will be opened. You can add additional values to keys using the $setvalue() method, which takes two parameters and accepts an additional optional third parameter. The first parameter specifies the name of the value you wish to create. The second takes a kRegAdminValue constant and specifies the type of value you wish to add to the key. The third and optional parameter lets you set an initial value. The format of this value will be dependent upon the type of value youre adding to the registry and is as follows: Binary Value Multi String Value String Value Expandable String DWORD Value Omnis Binary Omnis List of Omnis Characters Omnis Character Omnis Character Omnis Long Integer

Retrieving Key and Value names


Once you have opened a key successfully, you can use the $listsubkeynames() method to query the register and return a list of subkeys within your existing key. This method takes no arguments and returns a list of Key Names in the opened key as an Omnis list of characters. To retrieve a list of Value names, the $listvaluenames() method can be used. This method is similar to $listsubkeynames() except that is returns a list of Value names rather than Key names.

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

Deleting Keys and Values


To delete a key within the registry you can execute the $deletekey() method. This takes a single parameter, which is the name of the key you want to delete. This either has the name of a sub-key or the path to the key relative to the currently open key. For example, if you want to delete the HKEY_CLASSES_ROOT\Applications\omnis.exe key, you can either open HKEY_CLASSES_ROOT and execute $deletekey(Applications\omnis.exe) or open HKEY_CLASSES_ROOT\Applications and call $deletekey(omnis.exe). If the key you're attempting to delete contains any number of sub-keys, an error is returned and the key is not deleted. WARNING: When you delete a Windows registry key, the key itself and its values are permanently deleted. To delete a value from a key, you can use the $deletevalue() method. This takes a single parameter, which specifies either a value name or the path to the value name. The path is relative to the current open key. WARNING: Deleting a key value is permanent.

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.

Creating a DDE Link


Using the Edit menu, you can link data from programs such as Excel and Word to Omnis entry fields and vice versa. In particular, you can link the data in an Omnis list to a spreadsheet, so that it updates automatically when the values in the list change. Similarly, you can copy a spreadsheet to the clipboard and paste it into an Omnis list field. To create a DDE link to a spreadsheet

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 data returned to Omnis is read into the CRB.

Requesting Advise Messages


You can also ask a server to advise Omnis whenever the value of a data item changes. If the request is accepted, the flag is set. From there on, if the requested item changes value, the server sends it to the CRB. The following method sets up a channel to another Omnis library and requests advise messages for three fields NAME, ADDRESS and TEL. The values are read into the fields CNAME, CADDRESS and CTEL in the client.
Set channel number {2} Open DDE channel {Omnis|COUNTRY} If flag false OK message {Country library not running} Quit method End If Request advises TEL {CTEL} Request advises NAME {CNAME} Request advises ADDRESS {CADDRESS} Prepare for insert Enter data ; $event() method for the window On evSent If $ctarget='ADDRESS' ;; Last field has been sent Update files Queue cancel Redraw WindowName End If

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

Omnis as the Server


When you want to run Omnis as the server, you must specify the mode using the Set server mode command. By default, Omnis accepts all commands and data from a DDE client. Omnis accepts the following DDE commands: Accept advise requests lets Omnis respond to a client program with values of requested advise messages. Accept field requests sends the field value to the client program response to a Request message specifying a valid field name. Accept field values responds to a Poke message specifying a valid field name by setting the value of that field to the value transmitted by the client program. Values are stored in the CRB and if the relevant field is on the top window, Omnis redraws it. Accept commands executes a command string sent by the client program. Whenever Accept field values or Accept commands is enabled, either as an option under Set server mode or by the appropriate command, Omnis processes the Take control command from the client. All conversations are terminated when the Omnis library is closed. Send advises now advises the client programs of all the values for all the fields for which it has received Advise requests, in the order that the client requested them. Message timeout waits a specified length of time for responses to messages sent to other programs: default 30 seconds. You use Set advise options to specify events that cause Omnis to send values to a client (in addition to an active request, as above): Find/next/previous sends the requested advise values on Find, Next, Previous, or Clear OK sends the requested advise values when an Enter data or Prompted Find command ends with an OK event Redraw sends the requested advise values when Omnis redraws

Printing Reports to a DDE Channel


You can send reports to an open channel either by selecting Channel in the Print destination hierarchical menu or by issuing a Send to DDE channel command. Each use of the command adds a field name to an internal list so that when you print the report, each field in the record section goes to a corresponding field in the server. This method exports a report to a DDE channel using the tab-delimited format. 240

The System Topic


Set DDE channel number {2} Open DDE channel {Omnis|CLIENTS} ; Check flag etc. Send to DDE channel Set export format {Delimited (tabs)} Set report name DDEReport Clear DDE channel item names Set DDE channel item name {Name} Set DDE channel item name {Address} Set DDE channel item name {Telephone} Set DDE channel item name {Town} Print report Close DDE channel

The System Topic


You must set up the server mode to enable Omnis to respond as a server. DDE has however a special feature, the system topic, that is an exception to this. This is a tab-delimited CF_TEXT document containing several generic items. Whatever server mode Omnis is in, when an Initiate message contains the name of the system topic, Omnis always accepts requests to act as server. Omnis responds to any one of the four following items under the system topic: SysItems Omnis returns a list containing the three items below in a Data message Topics Omnis returns the name of the current library if there is one, otherwise a blank is returned Formats Omnis returns a list of the clipboard format numbers which can be implemented Status Omnis returns a DDE data item with one of the following strings, indicating the current status Topic open You have control status message No control status message Enter data Prompted find Import data

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.

Events during DDE


The message evSent is sent to the window control method to indicate that data has been updated via a DDE link. The parameter pChannelNumber provides the number of the DDE channel. If the Data or Poke message does not contain a valid Omnis field name, Omnis rejects the message. The data item name need not correspond to an Omnis field name on the enter data window for the message to succeed, but if the field is visible on the window there is an automatic redraw. This example control method detects the arrival of a particular field and triggers an Update:
On evSent If $ctarget ='C_FIRSTNAME' OK message {Got first name} Update files Queue Cancel End If

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

Programming with DDE

Programming with DDE


This section has some tips for programming DDE calls to Omnis. Any client wishing to initiate a conversation with Omnis must send a WM_DDE_INITIATE message with the Program name given as Omnis. The topic name given in the message must be that of an Omnis library without the .LBS extension. So, for example, an Initiate message addressed to Omnis to open a conversation might read:
WM_DDE_INITIATE 'Omnis' 'PERSON'

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.

Using DDE with Word


Under Windows, Microsoft Word has good support for DDE as a client through its DDE Field facility and its macro programming language. The easiest way to get a field value from Omnis into Word is

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

Apple Event Groups

Chapter 12Apple Events


Apple Events is an event messaging system defined by Apple that allows applications, including Omnis, to send commands and data to each other. For example, your Omnis library can launch a spreadsheet, open a document and spellcheck it. Similarly, a Hypercard stack can send a method script to Omnis, execute it and print it.

Apple Event Groups


Apple events are divided by Apple into several categories, or 'suites', and this is followed closely by the Omnis grouping; see Apple events in the Omnis command list in the method editor. All applications that claim to handle Apple events must support the four 'required' events, Open Application, Open Documents, Print Documents and Quit. In addition to these compulsory events, Omnis supports events in the following suites (Omnis command in brackets, detailed in the Omnis Help): Core events (Send Core event) Database suite (Send Database event) Finder suite (Send Finder event) Note: The following Apple events are not supported by the Mac OS X version of Omnis. They are only supported by the Mac OS Classic version: About Get Info Selection Duplicate Selection Alias Selection Open Selection Print Selection Reveal Selection Get Privilege Selection Empty Trash Restart Show Clipboard Shutdown

245

Chapter 12Apple Events Sleep

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

Sending and Receiving Apple Events

Sending and Receiving Apple Events


This section discusses in general the way Omnis handles Apple events as both client and server. The technique of sending and receiving events using procedural text is given later in the Scripts section. Except for the four 'required' events, Omnis only accepts Apple events if the Enable receiving of Apple events command has been run in the library that is to receive them. When opened, an Omnis library has reception of Apple events disabled by default, and so Enable receiving of Apple events must be added to the library and run if all events are to be received. Once enabled in this way, Disable receiving of Apple events must be run within the library to return to the default. However, the four compulsory events are still accepted. Omnis must always respond to the four required Apple events, which may be created by another Omnis library, or by another Mac OS application. The actual way they are created depends on the client application. When received by Omnis the compulsory events do the following: the 'Open application' event launches Omnis, the 'Close application' event quits Omnis, the 'Open documents' event prompts the user to load a library or Ad hoc report, the 'Print documents' event prompts the user to open a library, and print a report or opens and prints the Ad hoc reports. With reception enabled, Omnis can respond to events in the following suites: Core events (usually sent from Finder to Omnis), Database events. Error messages when receiving events When an event is not accepted, the Apple message errAEEventNotHandled is returned to the sender. There is a default timeout period when an event sender is waiting for acknowledgment. This period is set by Apple and is not altered by Omnis. Numeric values are accepted as character strings and data conversion to numbers takes place. A table is simply described as a collection of rows and columns in a database or spreadsheet. For Omnis, this equates to the combination of an Omnis file class and corresponding data file, and takes the name of the file class as a parameter. Omnis keeps a table index (record pointer) for the table that is currently being used for database events in order that record (row) operations can be performed.

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

Chapter 12Apple Events


Send DataBase event {Next} OK message {%S1 is [%S1], %S2 is [%S2], %S3 is [%S3]} Calculate %S1 as 'Holland & Duke Inc.' Calculate %S2 as 'The Old School House' Calculate %S3 as 'Benhall' ; Instead of calculating values you could use data entry windows Send DataBase event {Insert} ; Takes values in %S1, %S2 and %S3 and inserts new row/record If flag false OK message {Insert event failed} End If OK message {%S1 is [%S1], %S2 is [%S2], %S3 is [%S3]} Calculate %S1 as 'Beta Productions Plc' Calculate %S2 as '56 Lion's Road' Calculate %S3 as 'Ipswich' Send DataBase event {Update} ; Takes values in %S1, %S2 and %S3 and updates current record If flag false OK message {Update event failed} End If OK message {%S1 is [%S1], %S2 is [%S2], %S3 is [%S3]} End If

Running Apple Scripts directly from Omnis


You can use the $runapplescript() root method ($root.$runapplescript()) to run an Apple Script directly from within Omnis. This method works under Mac OS X only, and has the following syntax:
Do $root.$runapplescript(cScript[,&cResult,&cError])

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

You might also like