[ Previous document | Content Table | Next document ]

11    OpenOffice.org Basic and Dialogs

OpenOffice.org provides functionality to create and manage Basic macros and dialogs. The following sections examine the usage of the OpenOffice.org Basic programming environment.

11.1    First Steps with OpenOffice.org Basic

Step By Step Tutorial

This section provides a tutorial to enable developers to use the Basic IDE. It describes the necessary steps to write and debug a program in the Basic IDE, and to design a Basic dialog. A comprehensive reference of all tools and options can be found at 11.2 Basic and Dialogs - OpenOffice.org Basic IDE.

Creating a Module in a Standard Library
  1. Create a new Writer document and save the document, for example, FirstStepsBasic.sxw.

  2. Click Tools – Macro.

The Macro dialog appears. The Macro from list shows macro containers where Basic source code (macros) can come from. There is always an soffice container for Basic libraries. Additionally each loaded document can contain Basic libraries.


Illustration 11.1: Macro dialog

The illustration above shows that the document FirstStepsBasic.sxw is the only document loaded. Therefore, the soffice and FirstStepsBasic.sxw containers are displayed in the illustration above. Both containers, soffice and FirstStepsBasic.sxw, contain a library named Standard. There are a number of other libraries in the soffice container that come with a default OpenOffice.org installation – most of them are AutoPilots. The Standard libraries of the application and for all open documents are always loaded. They appear enabled in the dialog. Other libraries have to be loaded before they can be used.

The libraries contain modules with the actual Basic source code. Our next step will create a new module for source code in the Standard library of our FirstStepsBasic.sxw document.

  1. Scroll to the document node FirstStepsBasic.sxw in the Macro from.

  2. Select the Standard entry below the document node and click New.

OpenOffice.org shows a small dialog that suggests creating a new module named Module1.

  1. Click OK to confirm.

The Basic source editor window () appears containing a Sub (subroutine) Main.


Illustration 11.2: Basic source editor window

The status bar of the Basic editor window shows that the Sub Main is part of FirstStepsBasic.Standard.Module1. If you click Tools – Macro in the Basic editor, you will see that OpenOffice.org created a module Module1 below the Standard library in FirstStepsBasic.sxw.


Illustration 11.3

When a module is selected, the Macro name list box on the left shows the Subs and Functions in the that module. In this case, Sub Main. If you click Edit while a Sub or Function is selected, the Basic editor opens and scrolls to the selected Sub or Function.

Writing and Debugging a Basic UNO program

Enter the following source code in the Basic editor window. The example shown asks the user for the location of a graphics file and inserts it at the current cursor position of our document. Later, the example will be extend to create a small insert graphics autopilot. (BasicAndDialogs/FirstStepsBasic.sxw)

Sub Main

    ' ask the user for a graphics file

    sGraphicUrl = InputBox("Please enter the URL of a graphic file", _

        "Import Graphics", _

        "file:///"

    if sGraphicURL = "" then  ' User clicked Cancel

        exit sub

    endif

    ' access the document model

    oDoc = ThisComponent

    ' get the Text service of the document

    oText = oDoc.getText()

    ' create an instance of a graphic object using the document service factory

    oGraphicObject = oDoc.createInstance("com.sun.star.text.GraphicObject")

    ' set the URL of the graphic

    oGraphicObject.GraphicURL = sGraphicURL

    ' get the current cursor position in the GUI and create a text cursor from it

    oViewCursor = oDoc.getCurrentController().getViewCursor()

    oCursor = oText.createTextCursorByRange(oViewCursor.getStart())

    ' insert the graphical object at the cursor position

    oText.insertTextContent(oCursor.getStart(), oGraphicObject, false)       

End Sub

If help is required on Basic keywords, press F1 while the text cursor is on a keyword. The OpenOffice.org online help contains descriptions of the Basic language as supported by OpenOffice.org.

Starting with the line oDoc = ThisComponent, where the document model is accessed, we use the UNO integration of OpenOffice.org Basic. ThisComponent is a shortcut to access a document model from the Basic code contained in it. Earlier, you created Module1 in FirstStepsBasic.sxw, that is, your Basic code is embedded in the document FirstStepsBasic.sxw, not in a global library below the soffice container. The property ThisComponent therefore contains the document model of FirstStepsBasic.sxw.


Outside document libraries use ThisComponent or StarDesktop.CurrentComponent to retrieve the current document. If access to an open document is required, even if it is not the current document, you have to view the components in StarDesktop.Components, checking their URL property with code similar to the following:

oComps = StarDesktop.Components

oCompsEnum = oComps.createEnumeration()

while oCompsEnum.hasMoreElements()

    oComp = oCompsEnum.nextElement()

    ' not all desktop components are necessarily models with a URL

    if HasUnoInterfaces(oComp, "com.sun.star.frame.XModel") then

        print oComp.getURL()

    endif

wend


To debug the program, put the cursor into the line oDoc = ThisComponent and click the Breakpoint icon in the macro bar.


The Run icon launches the first Sub in the current module. Execution stops with the first breakpoint.


Now step through the program by clicking the Single Step icon.


Click the Macros icon if you need to run a Sub other than the first Sub in the module.. In the Macros dialog, navigate to the appropriate module, select the Sub to run and press the Run button.

To observe the values of simple type Basic variables during debugging, enter a variable name in the Watch field of the Basic editor and press the Enter key to add the watch, or point at a variable name with the mouse cursor without clicking it. In our example, observe the variable sGraphicUrl:


Illustration 11.4

Currently you can not inspect the values of UNO objects in the Basic debugger during runtime.

Calling a Sub from the User Interface

A Sub can be called from customized icons, menu entries, upon keyboard shortcuts and on certain application or document events. The entry point for all these settings is the Configuration dialog accessible through the Assign... button in the Macro dialog or the Tools – Configure command.

To assign the Sub Main to a toolbar icon, select Tools – Configure, click the Toolbars tab and click the Customize button. The Customize Toolbars dialog is displayed.


Illustration 11.5

Scroll down the Customize Toolbars Dialog until you see the Basic libraries. Expand the FirstStepsBasic.sxw node. Navigate and select to the FirstStepsBasic.Standard.Module1. When Module1 is selected, the Icons section shows a button with the caption "Main" for the Sub Main in Module1. The "Main" button can be dragged to a toolbar of your choice. If you want, assign a pictogram before by clicking Buttons...

The section 11.2.3 Basic and Dialogs - OpenOffice.org Basic IDE - Assigning Macros To GUI Events describes other options available to make your Sub accessible from the user interface.

A Simple Dialog

Creating Dialogs

To create a dialog in the Basic IDE, right-click the Module1 tab at the bottom of the Basic source editor and select Insert – Basic Dialog. The IDE creates a new page named Dialog1:


Illustration 11.6


To add controls to the dialog, we require design tools. Click the Controls icon to pop up the design tools window. The title bar of the tools window is used to drag the window away from the toolbar to keep it open permanently.

Our dialog offers a convenient way to select a file different than the simple input box of our first example. We want the user to control how the picture is anchored in the text after inserting it. We will create a wizard dialog with two steps.


In the design tools window, select File Selection and use the left mouse button to define the space where the file selection field will appear.


The Properties icon displays the Properties Dialog that is used to edit controls and hook up event handling code to events occurring at dialog controls.


Next, we will add << Back and Next >> Buttons to move between the dialog steps, and a Finish and Cancel button. Select the Button icon and define the size of the buttons by dragging a rectangle in the dialog using the left-mouse button. Buttons are labeled with a default text, such as CommandButton1. If the Properties Dialog is not open, double click the buttons to display it. Enter new labels in the Label field as suggested, and name the dialog step buttons Back and Next. Set the property Enabled for the << Back button to false.


Use the Label tool to create a label "Select Graphics File:" in the same manner.

Now the dialog looks similar to the illustration below:


Illustration 11.7


Test the dialog using the Activate Test Mode icon from the design tool window. After you have finished the test, click the Close button of the test dialog window.

To edit the dialog, such as setting the title and changing thesize, select it by clicking the outer border of the dialog. Green handles appear around the dialog. The green handles can be used to alter the dialog size.The Properties Dialog is used to define a dialog title.

Adding Event Handlers

Now we will write code to open the dialog and add functionality to the buttons. To show a dialog, create a dialog object using createUnoDialog() and call its execute() method. A dialog can be closed while it is shown by calling endExecute().


It is possible to set the Finish button with the PushButtonType property, and the Cancel button to OK and Cancel respectively. The method execute() returns 0 for Cancel and 1 for OK.

To add functionality to the buttons, the Subs have to be developed to handle the GUI events, then hook them to GUI elements. Click the Module1 tab in the lower part of the Basic IDE and enter the following Subs above the previous Sub Main to open, close and process the dialog. Note that a Private variable oDialog is defined outside of the Subs. After loading the dialog, this variable is visible from all Subs and Functions of Module1. (BasicAndDialogs/FirstStepsBasic.sxw)

Private oDialog as Variant  ' private, module-wide variable

Sub RunGraphicsWizard

    oDialog = createUnoDialog(DialogLibraries.Standard.Dialog1)

    oDialog.execute

End Sub

Sub CancelGraphicsDialog

    oDialog.endExecute()

End Sub

Sub FinishGraphicsDialog

    Dim sFile as String, sGraphicURL as String

    oDialog.endExecute()

    sFile = oDialog.Model.FileControl1.Text

    ' the FileControl contains a system path, we have to transform it to a file URL

    ' We use the built-in Basic runtime function ConvertToURL for this purpose

    sGraphicURL = ConvertToURL(sFile)

    ' insert the graphics

    ' access the document model

    oDoc = ThisComponent

    ' get the Text service of the document

    oText = oDoc.getText()

    ' create an instance of a graphic object using the document service factory

    oGraphicObject = oDoc.createInstance("com.sun.star.text.GraphicObject")

    ' set the URL of the graphic

    oGraphicObject.GraphicURL = sGraphicURL

    ' get the current cursor position in the GUI and create a text cursor from it

    oViewCursor = oDoc.getCurrentController().getViewCursor()

    oCursor = oText.createTextCursorByRange(oViewCursor.getStart())

    ' insert the graphical object at the cursor position

    oText.insertTextContent(oCursor.getStart(), oGraphicObject, false)       

End Sub

Sub Main

        ...

End Sub

Select the Cancel button in our dialog in the dialog editor, and click the Events tab of the Properties Dialog, the click the ellipsis... button on the right-hand side of the Event When Initiating. In the Assign Macro dialog, navigate to FirstStepsBasic.sxw.Standard.Module1, select the Sub CancelGraphicsDialog and click the Assign button to link this Sub to the Cancel button.


Illustration 11.8

Using the same method, hook the Finish button to FinishGraphicsDialog.


If the Run icon is selected now, the dialog is displayed, and the Finish and Cancel buttons are functional.

AutoPilot Dialogs

The final step is to create a small AutoPilot with two pages. The OpenOffice.org Dialogs have a simple concept for AutoPilot pages. Each dialog and each control in a dialog has a property Page (Step) to control the pages of a dialog. Normally, dialogs are on page 0, but they can be set to a different page, for example, to page 1. All controls having 1 in their Page property are visible as long as the dialog is on page 1. All controls having 2 in their page property are only displayed on page 2 and so forth. If the dialog is on Page 0, all controls are visible at once. If a control has its Page property set to 0, it is visible on all dialog pages.

This feature is used to create a second page in our dialog. Hold down the Control key, and click the label and file control in the dialog to select. In the Properties Dialog, fill in 1 for the Page property and press Enter to apply the change. Next, select the dialog by clicking the outer rim of the dialog in the dialog editor, enter 2 for the Page property and press the Enter key. The label and file control disappear, because we are on page 2 now. Only the buttons are visible since they are on page 0.

On page 2, add a label "Anchor" and two option buttons "at Paragraph" and "as Character". Name the option buttons AtParagraph and AsCharacter, and toggle the State property of the AtParagraph button, so that it is the default. The new controls automatically receive 2 in their Page property. When page 2 is finished, set the dialog to page 1 again, because it will start with the current page number.


Illustration 11.9

The Subs below handle the << Back and Next >> buttons, and the FinishGraphicsDialog has been extended to anchor the new graphics selected by the user. Note that the property thatis called Page (Step) in the GUI, is called Step in the API. (BasicAndDialogs/FirstStepsBasic.sxw)

Sub BackGraphicsDialog

    oDialog.Model.Step = 1

    oDialog.Model.Back.Enabled = false

    oDialog.Model.Next.Enabled = true

End Sub

Sub NextGraphicsDialog

    oDialog.Model.Step = 2

    oDialog.Model.Back.Enabled = true

    oDialog.Model.Next.Enabled = false

End Sub

Sub FinishGraphicsDialog

    Dim sGraphicURL as String, iAnchor as Long

    oDialog.endExecute()

    sFile = oDialog.Model.FileControl1.Text

    ' State = Selected corresponds to 1 in the API

    if oDialog.Model.AsCharacter.State = 1 then

        iAnchor = com.sun.star.text.TextContentAnchorType.AS_CHARACTER

    elseif oDialog.Model.AtParagraph.State = 1 then

        iAnchor = com.sun.star.text.TextContentAnchorType.AT_PARAGRAPH

    endif

    ' the File Selection control returns a system path, we have to transform it to a File URL

    ' We use a small helper function MakeFileURL for this purpose (see below)

    sGraphicURL = MakeFileURL(sFile)

    ' access the document model

    oDoc = ThisComponent

    ' get the Text service of the document

    oText = oDoc.getText()

    ' create an instance of a graphic object using the document service factory

    oGraphicObject = oDoc.createInstance("com.sun.star.text.GraphicObject")

    ' set the URL of the graphic

    oGraphicObject.GraphicURL = sGraphicURL

    oGraphicObject.AnchorType = iAnchor

    ' get the current cursor position in the GUI and create a text cursor from it

    oViewCursor = oDoc.getCurrentController().getViewCursor()

    oCursor = oText.createTextCursorByRange(oViewCursor.getStart())

    ' insert the graphical object at the beginning of the text

    oText.insertTextContent(oCursor.getStart(), oGraphicObject, false)               

End Sub

11.2    OpenOffice.org Basic IDE

This section discusses all features of the Integrated Development Environment (IDE) for OpenOffice.org Basic. It shows how to manage Basic and dialog libraries, discusses the tools of the Basic IDE used to create Basic macros and dialogs, and it treats the various possibilities to assign Basic macros to events.

11.2.1    Managing Basic and Dialog Libraries

The main entry point to the library management UI is the Tools - Macro... menu item. This item activates the Macro dialog where the user can manage all operations related to Basic and dialog libraries.

Macro Dialog

The following picture shows an example macro dialog. From here you can run, create, edit and delete macros, assign macros to UI events, and administer Basic libraries and modules.


Illustration 11.10

Displayed Information

The tree titled with Macro from shows the complete library hierarchy that is available the moment the dialog is opened. See 11.4 Basic and Dialogs - Advanced Library Organization for details about the library organization in OpenOffice.org..

Unlike the library organization API, this dialog does not distinguish between Basic and dialog libraries. Usually the libraries displayed in the tree are both Basic and dialog libraries.


Although it is possible to create Basic-only or dialog-only libraries using the APIthis is not the normal case, because the graphical user interface (see 11.2.1 Basic and Dialogs - OpenOffice.org Basic IDE - Managing Basic and Dialog Libraries - Macro Organizer Dialog below) only allows the creation of Basic and dialog libraries simultaneously. Nevertheless, the dialog can also deal with Basic-only or dialog-only libraries, but they are not marked in any way.

The tree titled Macro from represents a structure consisting of three levels:

Library container -> library -> library element

If a library is password-protected and a user double-clicks it to load it, a dialog is displayed requesting a password. The library is only loaded and expanded if the user enters the correct password. If a password-protected library is loaded using the API, for example, through a call to BasicLibraries.loadLibrary("Library1"), it is displayed as loaded, not grayed out, but it remains condensed until the correct password is entered (see 11.4 Basic and Dialogs - Advanced Library Organization).

Initially all root nodes, the soffice and document nodes, are condensed and the contained libraries are displayed. Similar to expanding and condensing libraries, a complete root node can be expanded and condensed as well.

The left column contains information about the macros, that is, the Subs and Functions, in the libraries. In the list box at the bottom, all Subs and Functions belonging to the module selected in the tree are listed. In the edit field titled Macro name, the Sub or Function currently selected in the list box is displayed. If there is no module selected in the tree, the edit field and list are empty. You can type in a desired name in the edit field.

Buttons

On the right-hand side of the Macro dialog, there are several buttons. The following list describes the buttons:

Macro Organizer Dialog

This dialog is opened by clicking the Button Organizer... in the Macro dialog. The dialog contains the two tab pages Modules and Libraries. While the Macro dialog refers to Subs and Functions inside Basic modules, such as run Subs, delete Subs, and insert new Subs, this dialog accesses the library system on module/dialog (tab page Modules) and library (tab page Libraries) level.

Modules

shows the Macro Organizer dialog with the Modules tab page activated. The list titled Module/Dialog is similar to the Macro from list in the Macro dialog, but it contains the complete library hierarchy for the OpenOffice.org application libraries and the document libraries. The libraries are loaded, and condensed or expaned by double-clicking the library. The only difference is that the dialogs are listed together with the Basic modules in the Macro Organizer. The illustration shows the application library Standard containing two modules, Module1 and Module2, and three dialogs, Dialog1, Dialog2 and Dialog3.


Illustration 11.11

presents the same dialog with the Module/Dialog listbox that has been scrolled down to show the documents and their libraries.


Illustration 11.12

The illustration above shows that two documents are loaded. The illustration shows a library Standard in document Calculation.sxc containing a dialog named Dialog1, and another library Standard in document Description.sxw containing a Basic module.

The following list describes the buttons on the right side of the dialog:

Libraries

The following illustrations show the Macro Organizer dialog with the Libraries tab page activated. In this dialog, the application and document libraries are listed separately. The Library list only contains the libraries of the library container currently selected in the Application/Document listbox. The second illustration is dropped down showing the soffice entry and the two open documents.


Illustration 11.13


Illustration 11.14

The libraries are displayed in the following manner:

Clicking a library twice (notdouble-click) allows the user to rename it.

The following list describes the buttons on the right side of the dialog:


Illustration 11.15


Illustration 11.16


Illustration 11.17

11.2.2    Basic IDE Window

The OpenOffice.org IDE is mainly represented by the Basic IDE window. The IDE window has two different modes:

Basic source code and dialogs are never displayed at the same time. The IDE window is in Basic editor or debugger, or in dialog editor mode. The following illustration shows the Basic IDE window in the Basic editor mode displaying Module2 of the application Standard library.


Illustration 11.18

The IDE window control elements common to the Basic editor and dialog editor mode are described below. The mode specific control elements are described in the corresponding subchapters 11.2.2 Basic and Dialogs - OpenOffice.org Basic IDE - Basic IDE Window - Basic Source Editor and Debugger and 11.2.2 Basic and Dialogs - OpenOffice.org Basic IDE - Basic IDE Window - Dialog Editor:

Basic Source Editor and Debugger

The Basic editor and debugger of the IDE window is shown when the user edits a Sub or Function from the Tools-Macro dialog (see ). In this mode, the window contains the actual editor main window, debugger Watch window to display variable values and the debugger Calls window to display the Basic call stack. The Watch and Calls windows are only used when a Basic program is running and halted by the debugger.

The editor supports common editor features. Since the editor is only used for the OpenOffice.org Basic programming language, it supports a Basic syntax specific highlighting and F1 help for Basic keywords.


Illustration 11.19: Basic Editor and Debugger

The following list explains the functionality of the macro toolbar buttons.


Compile: Compiles the active module and displays an error message, if necessary. This button is disabled if a Basic program is running. Always compile libraries before distributing them.


Run: Executes the active module, starting with the first Sub in the module, before all modified modules of the active library are compiled. Clicking this button can also result in compiler errors before the program is started. This button resumes the execution if the program is halted by the debugger.


Stop: Stops the Basic program execution. This button is disabled if a program is not running.


Procedure Step: Executes one Basic statement without stepping into Subs or Functions called in the statement. The execution is halted after the statement has been executed. If the Basic program not is running the execution is started and halted at the first statement of the first Sub in the current module.


Single Step: Executes one Basic statement. If the statement contains another Sub, execution is halted at the first statement of the called Sub. If no Subs or Functions are called in the statement, this button has the same functionality as the Step over button (key command F8).


Step back: Steps out of the current executed Sub or Function and halts at the next statement of the caller Sub or Function. If the currently executed Sub or Function was not called by another Sub or Function or if the Basic program is not running, this button has the same effect as the Run button.


Breakpoint: Toggles a breakpoint at the current cursor line in the Basic editor. If a breakpoint can not be set at this line a beep warns the user and the action is ignored (key command F9). A breakpoint is displayed as a red dot in the left column of the editor window.


Add watch: Adds the identifier currently touched by the cursor in the Basic editor to the watch window (key command F7).


Object Catalog: Opens the Objects dialog. This dialog displays the complete library hierarchy including dialogs, modules and the Subs inside the modules.


Macros: Opens the Macro Dialog.


Modules: Opens the Macro Organizer dialog


Find Parentheses: If the cursor in the Basic editor is placed before a parenthesis, the matching parenthesis is searched. If a matching parenthesis is found, the code between the two parentheses is selected, otherwise the user is warned by a beep.


Controls: Opens the dialog editing tools in the dialog editor. In Basic editor mode this button is disabled.


Insert Source File: Displays a file open dialog and inserts the selected text file (*.bas is the standard extension) at the current cursor position into the active module.


Save Source As: Displays a file Save As dialog to save the active module as a text file (*.bas is the standard extension).

shows how the IDE window looks while a Basic program is executed in debugging mode.

Dialog Editor

This section provides an overview of the Dialog editor functionality. The controls that are used to design a dialog are not explained. See 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls for details on programming these controls. The dialog editor is activated by creating a new dialog, clicking a dialog tab at the bottom of the IDE window, or selecting a dialog in the Macro Organizer dialog and clicking the Edit button.

Initially, a new dialog consists of an empty dialog frame. The next illustration shows Dialog2 of the application Standard library in this state.


Illustration 11.20

In the dialog editor mode, the Controls button is enabled and the illustration shows the result by clicking this button. A small toolbar with dialog specific tools is displayed. The buttons in this toolbar represent the types of controls that can be inserted into the dialog. The user clicks the desired button, then draws a frame with the mouse at the position to insert the corresponding control type.

The following three buttons in the dialog tools window do not represent controls:


The Select button at the lower right of the dialog tools window switches the mouse cursor to selection mode. In this mode, controls are selected by clicking the control with the cursor. If the Shift key is held down simultaneously, the selection is extended by each control the user clicks. Controls can also be selected by drawing a rubberband frame with the mouse. All controls that are completely inside the frame will be selected. To select the dialog frame the user clicks its border or includes it in a selection frame completely.


The Activate Test Mode button switches on the test mode for dialogs. In this mode, the dialog is displayed as if it was a Basic script (see 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls). However, the macros assigned to the controls do not work in this mode. They are thereto help the user design the look and feel of the dialog.


The Properties button at the lower left of the dialog tools window opens and closes the Properties dialog. This dialog is used to edit all properties of the selected control(s). The next illustration shows the Properties dialog for a selected button control.


Illustration 11.21

The illustration above shows that the dialog tool window can be pulled from the main toolbar by dragging the window at its caption bar after opening it.

The Properties dialog has two tabs. The General tab, visible in , contains a list of properties. Their values are represented by a control. For most properties this is a listbox, such as color and enum types, or an edit field, such as numeric or text properties. For more complex properties, such as fonts or colors, an additional ellipsis button... opens another type of dialog, for example, to select a font. When the user changes a property value in an edit field this value is not applied to the control until the edit field has lost the focus. This is forced with the tab key. Alternatively, the user can commit a change by pressing the Enter key.

The Events tab page displays the macros assigned to the events supported by the selected control:


Illustration 11.22

In the example above, a macro is assigned to the Key pressed event: When this event occurs, the displayed Sub doNothing in Module2 of the application Basic library Standard is called. The events that are available depend on the type of control selected.

To change the event assignment the user has to click one of the ellipsis... buttons to open the Assign Macro dialog displayed in .


Illustration 11.23: Assign Macro Dialog

The listbox in the upper left of the dialog titled Event displays the same information as the Events tab of the Properties dialog. The Assign Macro dialog is always the same, that is only the selected event in its Event list changes according to the ellipsis button the user selected on the Events tab of the Properties dialog.

To assign a macro to an event, the user selects the event in the Event listbox. In the Macro section at the bottom of the dialog, the user navigates through the library hierarchy. If a module is selected in the left listbox, the contained Subs are displayed in the listbox on the right side. The Assign button hooks the Sub or Function selected in this listbox to the selected event. If another macro is already assigned to an event, this macro is replaced. If no Sub is selected, the Assign button is disabled.

The library hierarchy displayed in the Macros listbox contains the application library container and the library container of the document that the edited dialog belongs. If the dialog belongs to an application dialog library, documents are not displayed. Document macros can not be assigned to the controls of application dialogs. Event definition can not depend on a document that is not necessarily loaded when the event occurs.

The Remove button is enabled if an event with an assigned macro is selected. Clicking this button removes the macro from the event, therefore the event will have no macro binding.

The listbox below the Remove button is used to select different macro languages. Currently, only OpenOffice.org Basic is available.

The OK button closes the Assign Macro dialog, and applies all event assignments and removals to the control. The changes are reflected on the Events tab of the Properties dialog.

The Cancel button also closes the Assign Macro, but all assignment and removal operations are discarded.

As previously explained, it is also possible to select several controls simultaneously. The next picture shows the situation if the user selects both CommandButton1 and CheckBox1.For the Properties dialog such a multi selection has some important effects.


Illustration 11.24

Here the caption of the Properties contains the string Multiselection to point out the special situation. The two important differences compared to the single selection situation are:

11.2.3    Assigning Macros to GUI Events

The functionality to assign macros to control events in the dialog editor was discussed earlier. There is also a general functionality to assign macros or other actions to events. This functionality can be accessed through the Configuration dialog that is opened using Tools – Configure... or by clicking the Assign... button in the Macro dialog. In this section, only the assignment of macros is discussed. For more information about this dialog, refer to the OpenOffice.org documentation.

The next illustration shows the Menu tab of the Configuration dialog:


Illustration 11.25

The illustration above shows how a macro is assigned to a new menu item. The listbox at the top titled Menu entries represents the OpenOffice.org menu hierarchy. The Category listbox in the lower left corner contains an entry OpenOffice.org BASIC Macros that represents the root of the OpenOffice.org application Basic. Other categories not related to macros are also displayed.–. The user navigates through the Basic libraries. When a module is selected, its Subs and Functions are displayed in the Function listbox at the lower right.

The Modify button assigns the Sub or Function selected in the Function listbox to the menu item selected in the Menu entries listbox. This button is disabled if a Sub or Function is not selected..

The New button creates a new menu item that is connected to the Sub or Function. The other buttons are used for menu design:

The next illustration shows the Events tab of the Configuration dialog:


Illustration 11.26

On this tab, macros can be assigned to general events in OpenOffice.org. The events are listed in the listbox titled Event. At the bottom of the dialog the macros can be selected, then be assigned to the selected event with the Assign button. This button is disabled if a Sub or Function is not selected. The Remove button removes the assigned macro from the selected event. It is disabled if a macro is not assigned to the selected event.

The OpenOffice.org radio button is active when the event assignment for the OpenOffice.org application is displayed. This assignment is stored in the OpenOffice.org configuration. The Document radio button is active when the event assignment for the current document is displayed. This assignment is made persistent in the document file. If the Configuration was not opened from a document, for example, from the Basic IDE, the Document radio button is not displayed.

The Keyboard tab is similar to the Menu and Events tabs. Macros are accessed in Category and Function listboxes, then assigned to a shortcut key that can be specified in the Shortcut keys listbox. There are also Load..., Save... and Reset buttons with the same function as the corresponding buttons on the Menu tab.

The Keyboard tab contains a OpenOffice.org and a Document radio button with the same functionality as the corresponding radio buttons on the Events tab.

11.3    Features of OpenOffice.org Basic

This section provides a general description of the Basic programming language integrated in OpenOffice.org.

11.3.1    Functional Range Overview

This section outlines the functionality provided by OpenOffice.org Basic. The available runtime library functions are also described. The functionality is based upon the Basic online help integrated in OpenOffice.org, but limited to particular functions. Use the Basic online help to obtain further information about the complete Basic functionality.

Apart from the OpenOffice.org API, OpenOffice.org Basic is compatible to Visual Basic.

Screen I/O Functions

Basic provides statements and functions to display information on the screen or to get information from the user:

        e = 2.718

        Print e                        ' displays "2.718"

        Print "e =" ; e                ' displays "e = 2.718"

        Print "e =" , e                ' displays "e = 2.718"

        ' display a message box with an exclamation mark and OK and Cancel buttons

        ret& = Msgbox ("Changes will be lost. Proceed?", 48 + 1, "Warning")

        ' show user's selection. 1 = OK, 2 = Cancel

        Print ret&

        ' display a dialog with "Please enter a phrase:" and "Dear User" as caption

        ' the dialog contains an edit control and the text entered by the user

        ' is stored in UserText$ when the dialog is closed with OK. Cancel returns ""

        UserText$ = InputBox( "Please enter a phrase:", "Dear User" )

File I/O

OpenOffice.org Basic has a complete set of statements and runtime functions to access the operating system's file system that are compatible to Visual Basic. For platform independence, the ability to handle file names in file:// URL notation has been added.

It is not recommended to use this classic Basic file interface in the UNO context, because many interfaces in the OpenOffice.org API expect file I/O specific parameters whose types, for example, com.sun.star.io.XInputStream are not compatible to the classic Basic file API.

For programming, the file I/O in OpenOffice.org API context with the service com.sun.star.ucb.SimpleFileAccess should be used. This service supports the interface com.sun.star.ucb.XSimpleFileAccess2, including the main interface com.sun.star.ucb.XSimpleFileAccess that provides fundamental methods to access the file system. The methods are explained in detail in the corresponding interface documentation. The following list provides an overview about the operations supported by this service:

Two more services are instantiated at the global service manager that extends the service com.sun.star.ucb.SimpleFileAccess by functionality specific to text files:

Date and Time Functions

OpenOffice.org Basic supports several Visual Basic compatible statements and functions to perform date and time calculations. The functions are DateSerial, DateValue, Day, Month, WeekDay, Year, Hour, Now, Second, TimeSerial, TimeValue, Date, Time, and Timer.

The function Date returns the current system date as a string and the function Time returns the current system time as a string. The other functions are not explained.

In the UNO/toolkit controls context there are two other functions. The date field control method com.sun.star.awt.XDateField:setDate() expects the date to be passed as a long value in a special ISO format and the com.sun.star.awt.XDateField:getDate() returns the date in this format.

The Basic runtime function CDateToIso converts a date from the internal Basic date format to the required ISO date format. Since the string date format returned by the Date function is converted to the internal Basic date format automatically, Date can be used directly as an input parameter for CDateToIso:

    IsoDate = CDateToIso(Date)

    oTextField.setDate(IsoDate)

The runtime function CDateToIso represents the reverse operation and converts a date from the ISO date format to the internal Basic date format.

        Dim aDate as date

        aDate = CDateFromIso(IsoDate)

Please see also 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls in this context.

Numeric Functions

OpenOffice.org Basic supports standard numeric functions, such as:

String Functions

OpenOffice.org Basic supports several runtime functions for string manipulation. Some of the functions are explained briefly in the following:

Specific UNO Functions

The UNO specific runtime functions CreateUnoListener, CreateUnoService, GetProcessServiceManager, HasUnoInterfaces, IsUnoStruct, EqualUnoObjects are described in 3.4.3 Professional UNO - UNO Language Bindings - OpenOffice.org Basic.

11.3.2    Accessing the UNO API

In 3.4.3 Professional UNO - UNO Language Bindings - OpenOffice.org Basic, the interaction between Basic and UNO is described on an elementary level. This section describes the interface between Basic and the UNO API at the level of the OpenOffice.org application.

This is realized by two predefined Basic properties:

The property StarDesktop gives access to the global OpenOffice.org application API while the property ThisComponent accesses the document related API.

StarDesktop

The property StarDesktop is a shortcut for the service com.sun.star.frame.Desktop.

Example:

        MsgBox StarDesktop.Dbg_SupportedInterfaces

        ' is the same as

        Dim oDesktop

        oDesktop = CreateUnoService( "com.sun.star.frame.Desktop" )

        MsgBox oDesktop.Dbg_SupportedInterfaces

The displayed message box differs slightly because Dbg_SupportedInterfaces displays "StarDesktop" as an object type of the desktop object in the first case and "com.sun.star.frame.Desktop" in the second. But the two objects are the same.

ThisComponent

The property ThisComponent is used from document Basic, where it represents the document the Basic belongs to. The type of object accessed by ThisComponent depends on the document type. The following example shows the differences.

Basic module in a OpenOffice.org document:

    Sub Main

        MsgBox ThisComponent.Dbg_SupportedInterfaces

    End Sub

The execution of this Basic routine shows different results for a Text, Spreadsheet and Presentation document. Depending on the document type, a different set of interfaces are supported by the object. A portion of the interfaces are common to all these document types representing the general functionality that documents of any type offer. In particular, all OpenOffice.org documents support the com.sun.star.document.OfficeDocument service, including the interfaces com.sun.star.frame.XStorable and com.sun.star.view.XPrintable. Another interface is com.sun.star.frame.XModel.

The following list shows the interfaces supported by all document types:

        com.sun.star.beans.XPropertySet

        com.sun.star.container.XChild

        com.sun.star.document.XDocumentInfoSupplier

        com.sun.star.document.XEventBroadcaster

        com.sun.star.document.XViewDataSupplier

        com.sun.star.document.XEventsSupplier

        com.sun.star.document.XLinkTargetSupplier

        com.sun.star.frame.XModel

        com.sun.star.frame.XStorable

        com.sun.star.lang.XServiceInfo

        com.sun.star.lang.XMultiServiceFactory

        com.sun.star.lang.XEventListener

        com.sun.star.style.XStyleFamiliesSupplier

        com.sun.star.util.XModifiable

        com.sun.star.view.XPrintable

For more information about the functionality of these interfaces, see 6.1.1 Office Development - OpenOffice.org Application Environment - Overview - Framework API - Frame-Controller-Model Paradigm. This section alsogoes into detail about the general document API.

In addition to the common services or interfaces, each document type supports specific services or interfaces. The following list outlines the supported services and important interfaces:

A Text document supports:

A Spreadsheet document supports:

Presentation and Drawing documents support:

The usage of these services and interfaces is explained in the document type specific chapters 7 Text Documents, 8 Spreadsheet Documents and 9 Drawing.

As previously mentioned, ThisComponent is used from document Basic, but it is also possible to use it from application Basic. In an application wide Bais module, ThisComponent is identical to the current component that can also be accessed through StarDesktop.CurrentComponent. The only difference between the two is that if the BasicIDE is active, StarDesktop.CurrentComponent refers to the BasicIDE itself while ThisComponent always refers to the component that was active before the BasicIDE became the top window.

11.3.3    Special Behavior of OpenOffice.org Basic

Threading and rescheduling of OpenOffice.org Basic differs from other languages which must be taken into consideration.

Threads

OpenOffice.org Basic does not support threads:

Rescheduling

The OpenOffice.org Basic runtime system reschedules regularly. It allows system messages to be dispatched continuously that have been sent to the OpenOffice.org process during the runtime of a Basic module. This is necessary to allow repainting operations, and access to controls and menus during the runtime of a Basic script as Basic runs in the OpenOffice.org main thread. Otherwise, it would not be possible to stop a running Basic script by clicking the corresponding button on the toolbar.

This behavior has an important consequence. Any system message, for example, clicking a push button control, can result in a callback into Basic if an corresponding event is specified. The Basic programmer must be aware of the fact that this can take place at any point of time when a script is running.

The following example shows how this effects the state of the Basic runtime system:

    Dim EndLoop As Boolean

    Dim AllowBreak As Boolean

    ' Main sub, the execution starts here

    Sub Main

        ' Initialize flags

        EndLoop = FALSE

        AllowBreak = FALSE

        Macro1        ' calls sub Macro1

    End Sub

    ' Sub called by main

    Sub Macro1

        Dim a

        While Not EndLoop

            ' Toggle flags permanently

            AllowBreak = TRUE

            AllowBreak = FALSE

        Wend

        Print "Ready!"

    End Sub

    ' Sub assigned to a bush button in a writer document

    Sub Break

    If AllowBreak = TRUE Then

        EndLoop = TRUE

        EndIf

    End Sub

When Sub Main in this Basic module is executed, the two Boolean variables EndLoop and AllowBreak are initialized. Then Sub Macro1 is called where the execution runs into a loop. The loop is executed until the EndLoop flag is set to TRUE. This is done in Sub Break that is assigned to a push button in a writer document, but the EndLoop flag can only be set to TRUE if the AllowBreak flag is also TRUE. This flag is permanently toggled in the loop in Sub Macro1.

The program execution may or may not be stopped if the push button is clicked. It depends on the point of time the push button is clicked. If the Basic runtime system has just executed the AllowBreak = TRUE statement, the execution is stopped because the If condition in Sub Break is TRUE and the EndLoop flag can be set to TRUE. If the push button is clicked when the AllowBreak variable is FALSE, the execution is not stopped. The Basic runtime system reschedules permanently, therefore it is unpredictable. This is an example to show what problems may result from the Basic rescheduling mechanism.

Callbacks to Basic that result from rescheduling have the same effect as if the Sub specified in the event had been called directly from the position in the Basic code that is executed in the moment the rescheduling action leading to the callback takes place. In this example, the Basic call stack looks like this if a breakpoint is placed in the Sub Break:

    Basic                Native code

    0: Break  <---   Callback due to push button event

    1: Macro1  --->  Reschedule()

    2: Main

With the call to the native Reschedule method, the Basic runtime system is left and reentered when the push button events in a Callback to Basic. On the Basic stack this looks like a direct call from Sub Macro1 to Sub Break.

A similar situation occurs when a program raises a dialog using the execute method of the dialog object returned by CreateUnoDialog(). See 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls. In this case, the Basic runtime system does not reschedule, but messages are processed by the dialog's message loop that also result in callbacks to Basic. When the Basic runtime system is called back due to an event at a dialog control, the resulting Basic stack looks analogous. For example:

    Sub Main

        Dim oDialog

        oDialog = CreateUnoDialog( ... )

        oDialog.execute()

    End Sub

    Sub DoIt

          ...

    End Sub

If Sub Doit is specified to be executed if an event occurs for one of the dialog controls, the Basic call stack looks like this if a breakpoint is placed in Sub DoIt:

    Basic                Native code

    0: DoIt   <---   Callback due to control event

    1: Main    --->  execute() ---> Reschedule()

There is also a difference to the rescheduling done directly by the Basic runtime system. The rescheduling done by the dialog's message loop can not result in unpredictable behavior, because the Basic runtime system has called the dialog's execute method and waits for its return. It is in a well-defined state.

11.4    Advanced Library Organization

Basic source code and Dialogs are organized in libraries. This section describes the structure and usage of the library system.

11.4.1    General Structure

The library system that is used to store Basic source code modules and Dialogs has three levels:

Library container

Library

Library elements

The hierarchy is separated for Basic source code and dialogs, that is, a Basic library container only contains Basic libraries containing Basic source code modules and a dialog library container only contains dialog libraries containing dialogs.

Basic source code and dialogs are stored globally for the whole office application and locally in documents. For the application, there is one Basic library container and one dialog library container. Every document has one Basic library container and one dialog library container as well. By including the application or document level, the library system actually has four levels. depicts this structure.

As shown in the library hierarchy for Document 1, the Basic and dialog library containers do not have the same structure. The Basic library container has a library named Library1 and the dialog library container has a library named Library2. The library containers are separated for Basic and dialogs in the API.

It is not recommended to create a structure as described above because the library and dialog containers are not separated in the GUI, for example, in the Tools - Macro... dialog. When a user creates or deletes a new library through Tools - Macro – Organizer..., the library is created or deleted in the Basic and the dialog library containers.


Illustration 11.27: Sample module structure

11.4.2    Accessing Libraries from Basic

Library Container Properties in Basic

Currently, the library system is implemented using UNO interfaces, not as a UNO service. Therefore, the library system cannot be accessed by instantiating an UNO service. The library system has to be accessed directly from Basic using the built-in properties BasicLibraries and DialogLibraries.

The BasicLibraries property refers to the Basic library container that belongs to the library container that the BasicLibraries property is accessed. In an application-wide Basic module, the property BasicLibraries accesses the application Basic library containerand in a document Basic module, the property BasicLibraries contains the document Basic library container. The same applies to the DialogLibraries property.

Loading Libraries

Initially, most Basic libraries are not loaded. All the libraries in the application library container are known after starting OpenOffice.org, and all the library elements in a document are known when it is loaded, most of them are disabled until they are loaded explicitly. This mechanism saves time during the Basic initialization. When a Basic library is initialized, the source code modules are inserted into the Basic engine and compiled. If there are many libraries with big modules, it is tim consuming, especially if the libraries are not required.

The exception to this is that every library container contains a library named "Standard" that is always loaded. This library is used as a standard location for Basic programs and dialogs that do not need a complex structure. All other libraries have to be loaded explicitly. For example:

When Library1, Module1 looks like

    Sub doSomething

        MsgBox "doSomething"

    End Sub

the following code in library Standard, Module1

    Sub Main

        doSomething()

    End Sub

fails, unless the user loaded Library1 before using the Tools - Macro dialog. A runtime error "Property or method not found" occurs. To avoid this, load library Library1 before calling doSomething():

    Sub Main

        BasicLibraries.loadLibrary( "Library1" )

        doSomething()

    End Sub

Accordingly in the dialog container, all the libraries besides the Standard library have to be loaded before the dialogs inside the library can be accessed. For example:

    Sub Main

        ' If this line was missing the following code would fail

        DialogLibraries.loadLibrary( "Library1" )

        ' Code to instantiate and display a dialog

        ' Details will be explained in a later chapter

        oDlg = createUnoDialog( DialogLibraries.Library1.Dialog1 )

        oDlg.execute()

    End Sub

The code to instantiate and display the dialog is described in 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls. The library representing DialogLibraries.Library1.Dialog1 is only valid once Library1 has been loaded.

The properties BasicLibraries and DialogLibraries refer to the container that includes the Basic source accessing these properties. Therefore in a document module Basic the properties BasicLibraries and DialogLibraries refer to the Basic and Dialog library container of the document. In most cases, libraries in the document have to be loaded. In other cases it might be necessary to access application-wide libraries from document Basic. This can be done using the GlobalScope property. The GlobalScope property represents the root scope of the application Basic, therefore the application library containers can be accessed as properties of GlobalScope.

Example module in a Document Basic in library Standard:

    Sub Main

       ' This code loads Library1 of the

    ...' Document Basic library container

       BasicLibraries.loadLibrary( "Library1" )

       ' This code loads Library1 of the

    ...' Document dialog library container

       DialogLibraries.loadLibrary( "Library1" )

       ' This code loads Library1 of the

    ...' Application Basic library container

       GlobalScope.BasicLibraries.loadLibrary( "Library1" )

       ' This code loads Library1 of the

    ...'  Application  dialog library container

       GlobalScope.DialogLibraries.loadLibrary( "Library1" )

       ' This code displays the source code of the

    ...' Application Basic module Library1/Module1

       MsgBox GlobalScope.BasicLibraries.Library1.Module1

    End Sub


Application library containers can be accessed from document-embedded Basic libraries using the GlobalScope property, for example, GlobalScope.BasicLibraries.Library1.

Library Container API

The BasicLibraries and DialogLibraries support com.sun.star.script.XLibraryContainer2 that inherits from com.sun.star.script.XLibraryContainer, which is a com.sun.star.container.XNameContainer. Basic developers do not require the location of the interface to use a method, but a basic understanding is helpful when looking up the methods in the API reference.

The XLibraryContainer2 handles existing library links and the write protection for libraries. It is also used to rename libraries:

boolean isLibraryLink( [in] string Name)

string getLibraryLinkURL( [in] string Name)

boolean isLibraryReadOnly( [in] string Name)

void setLibraryReadOnly( [in] string Name,

                         [in] boolean bReadOnly)

void renameLibrary( [in] string Name, [in] string NewName)

The XLibraryContainer creates and removes libraries and library links. Furthermore, it can test if a library has been loaded or, if necessary, load it.

com::sun::star::script::XNameContainer createLibrary( [in] string Name)

com::sun::star::script::XNameAccess createLibraryLink( [in] string Name,

                                        [in] string StorageURL, [in] boolean ReadOnly)

void removeLibrary( [in] string Name)

boolean isLibraryLoaded( [in] string Name)

void loadLibrary( [in] string Name)

The methods of XNameContainer access and manage the libraries in the container:

void insertByName( [in] string name, [in] any element)

void removeByName( [in] string name)

any getByName( [in] string name)

void replaceByName( [in] string name, [in] any element)

sequence < string > getElementNames()

boolean hasByName( [in] string name)

type getElementType()

boolean hasElements()

These methods are accessed using the UNO API as described in 3.4.3 Professional UNO - UNO Language Bindings - OpenOffice.org Basic. Note however, these interfaces can only be used from OpenOffice.org Basic, not from other environments.

Libraries can be added to library containers in two different ways:

Creating a New Library

Creating a new library is done using the createLibrary() method. A library created with this method belongs to the library container where createLibrary() has been called. The implementation of the library container is responsible for saving and loading this library. This functionality is not currently covered by the interfaces, therefore the implementation determines how and where this is done. The method createLibrary() returns a standard com.sun.star.container.XNameContainer interface to access the library elements and modify the library.

Initially, such a library is empty and new library elements are inserted. It is also possible to protect a library from changes using the setLibraryReadOnly() method. In a read-only library, no elements can be inserted or removed, and the modules or dialogs inside cannot be modified in the BasicIDE. For additional information, see 11.2 Basic and Dialogs - OpenOffice.org Basic IDE. Currently, the read-only status can only be changed through API.

Creating a Link to an Existing Library

Creating a link to an existing library is accomplished using the method createLibraryLink(). Its StorageURL parameter describes the location where the library .xlb file is stored. For additional information about this topic, see the section on 11.7 Basic and Dialogs - Library File Structure). A library link is only referenced by the library container and is not owned, therefore the library container is not responsible for the location to store the library. This is only described by the StorageURL parameter.

The ReadOnly parameter sets the read-only status of the library link. This status is independent of the read-only status of the linked library. A linked library is only modified when the library and link to the library are not read only. For example, this mechanism provides read-only access to a library located on a network drive without forcing the library to be read-only, thus the library can be modified easily by an authorized person without changing its read-only status.

The following tables provides a brief overview about other methods supported by the library containers:

 Selected Methods of com.sun.star.script.XLibraryContainer2

isLibraryLink()

boolean. Can be used to ask if a library was added to the library container as a link.

getLibraryLinkURL()

string. Returns the StorageURL for a linked library. This corresponds to the StorageURL parameter of the createLibraryLink(...) method and is primarily meant to be displayed to the users through the graphical user interface.

isLibraryReadOnly()

boolean. Retrieves the read-only status of a library. In case of a library link, the method returns only false, that is, the library can be modified, when the link or the linked library are not read only.

renameLibrary()

Assigns a new name to a library. If the library was added to the library container as a link, only the link is renamed.

 Selected Methods of com.sun.star.script.XLibraryContainer

loadLibrary()

void. Loads a library. This is explained in detail in section 11.4 Basic and Dialogs - Advanced Library Organization

isLibraryLoaded()

boolean. Allows the user to find out if a library has already been loaded.

removeLibrary()

void. Removes the library from the library container. If the library was added to the library container as a link, only the link is removed, because the library addressed by the link is not considered to be owned by the library container.

11.4.3    Variable Scopes

Some aspects of scoping in Basic depend on the library structure. This section describes which variables declared in a Basic source code module are seen from what libraries or modules. Generally, only variables declared outside Subs are affected by this issue. Variables declared inside Subs are local to the Sub and not accessible from outside of the Sub. For example:

    Option Explicit        ' Forces declaration of variables

    Sub Main

        Dim a%

        a% = 42        ' Ok

        NotMain()

    End Sub

    Sub NotMain

          a% = 42        ' Runtime Error "Variable not defined"

    End Sub

Variables can also be declared outside of Subs. Then their scope includes at least the module they are declared in. To declare variables outside of the Subs, the commands Private, Public/Dim and Global are used.

The Private command is used to declare variables that can only be used locally in a module. If the same variable is declared as Private in two different modules, they are used independently in each module. For example:

Library Standard, Module1:

    Private x As Double

    Sub Main

        x = 47.11                ' Initialize x of Module1

        Module2_InitX                ' Initialize x of Module2

        MsgBox x                        ' Displays the x of Module1

        Module2_ShowX                ' Displays the x of Module2

    End Sub

Library Standard, Module2:

    Private x As Double

    Sub Module2_InitX

        x = 47.12                ' Initialize x of Module2

    End Sub

    Sub Module2_ShowX

        MsgBox x                        ' Displays the x of Module2

    End Sub

When Main in Module1 is executed, 47.11 is displayed (x of Module1) and then 47.12 (x of Module2).

The Public and Dim commands declare variables that can also be accessed from outside the module. They are identical in this context. Variables declared with Public and Dim can be accessed from all modules that belong to the same library container. For example, based on the library structure shown in , any variable declared with Public and Dim in the Application Basic Modules Standard/Module1, Standard/Module2, Library1/Module1, Library1/Module2 can also be accessed from all of these modules, therefore the library container represents the logical root scope.

11.5    Programming Dialogs and Dialog Controls

The dialogs and dialog controls are UNO components that provide a graphical user interface belonging to the module com.sun.star.awt. The Toolkit controls follow the Model-View-Controller (MVC) paradigm, which separates the component into three logical units, the model, view, and controller. The model represents the data and the low-level behavior of the component. It has no specific knowledge of its controllers or its views. The view manages the visual display of the state represented by the model. The controller manages the user interaction with the model.


Note, that the Toolkit controls combine the view and the controller into one logical unit, which forms the user interface for the component.

The following example of a text field illustrates the separation into model, view and controller. The model contains the data which describes the text field, for example, the text to be displayed, text color and maximum text length. The text field model is implemented by the com.sun.star.awt.UnoControlEditModel service that extends the com.sun.star.awt.UnoControlModel service. All aspects of the model are described as a set of properties which are accessible through the com.sun.star.beans.XPropertySet interface. The view is responsible for the display of the text field and its content. It is possible to have multiple views for the same model, but not for Toolkit dialogs. The view is notified about model changes, for example, changes to the text color property causes the text field to be repainted. The controller handles the user input provided through thekeyboard and mouse. If the user changes the text in the text field, the controller updates the corresponding model property. In addition, the controller updates the view, for example, if the user presses the delete button on the keyboard, the marked text in the text field is deleted. A more detailed description of the MVC paradigm can be found in the chapter about forms 13 Forms.

The base for all the Toolkit controls is the com.sun.star.awt.UnoControl service that exports the following interfaces:

11.5.1    Dialog Handling

Showing a Dialog

After a dialog has been designed using the dialog editor, a developer wants to show the dialog from within the program code. The necessary steps are shown in the following example: (BasicAndDialogs/ToolkitControls)

Sub ShowDialog()

    Dim oLibContainer As Object, oLib As Object

    Dim oInputStreamProvider As Object

    Dim oDialog As Object

    Const sLibName = "Library1"

    Const sDialogName = "Dialog1"

    REM library container

    oLibContainer = DialogLibraries

    REM load the library

    oLibContainer.loadLibrary( sLibName )

    REM get library

    oLib = oLibContainer.getByName( sLibName )

    REM get input stream provider

    oInputStreamProvider = oLib.getByName( sDialogName )

    REM create dialog control

    oDialog = CreateUnoDialog( oInputStreamProvider )

    REM show the dialog

    oDialog.execute()

End Sub

The dialog control is created by calling the runtime function CreateUnoDialog() which takes an object as parameter that supports the com.sun.star.io.XInputStreamProvider interface. This object provides an input stream that represents an XML description of the dialog. The section 11.4 Basic and Dialogs - Advanced Library Organization explains the accessing to the object inside the library hierarchy. The dialog control is shown by calling the execute() method of the com.sun.star.awt.XDialog interface. It can be closed by calling endExecute(), or by offering a Cancel or OK Button on the dialog. For additional information, see 11.5 Basic and Dialogs - Programming Dialogs and Dialog Controls.

Getting the Dialog Model

If a developer wants to modify any properties of a dialog or a control, it is necessary to have access to the dialog model. From a dialog, the model can be obtained by the getModel method of the com.sun.star.awt.XControl interface

oDialogModel = oDialog.getModel()

or shorter

oDialogModel = oDialog.Model

Dialog as Control Container

All controls belonging to a dialog are grouped together logically. This hierarchy concept is reflected by the fact that a dialog control is a container for other controls. The corresponding service com.sun.star.awt.UnoControlDialog therefore supports the com.sun.star.awt.XControlContainer interface thatoffers container functionality, namely access to its elements by name. Since in OpenOffice.org Basic, every method of every supported interface is called directly at the object without querying for the appropriate interface, a control with the name TextField1 can be obtained from a dialog object oDialog simply by:

oControl = oDialog.getControl("TextField1")

See 3.4.3 Professional UNO - UNO Language Bindings - OpenOffice.org Basic for additional information. The hierarchy between a dialog and its controls can be seen in the dialog model com.sun.star.awt.UnoControlDialogModel, which is a container for control models and therefore supports the com.sun.star.container.XNameContainer interface. A control model is obtained from a dialog model by:

oDialogModel = oDialog.getModel()

oControlModel = oDialogModel.getByName("TextField1")

or shorter

oControlModel = oDialog.Model.TextField1

Dialog Properties

It is possible to make some modifications before a dialog is shown. An example is to set the dialog title that is shown in the title bar of a dialog window. This can be achieved by setting the Title property at the dialog model vthrough the com.sun.star.beans.XPropertySet interface:

oDialogModel = oDialog.getModel()

oDialogModel.setPropertyValue("Title", "My Title")

or shorter

oDialog.Model.Title = "My Title"

Another approach is to use the setTitle method of the com.sun.star.awt.XDialog interface:

oDialog.setTitle("My Title")

or

oDialog.Title = "My Title"

Another property is the BackgroundColor property that sets a different background color for the dialog.

Common Properties

All Toolkit control models have a set of identical properties referred as the common properties. These are the properties PositionX, PositionY, Width, Height, Name, TabIndex, Step and Tag.


Note that a Toolkit control model has those common properties only if it belongs to a dialog model. This has also some consequences for the creation of dialogs and controls at runtime. See 11.6 Basic and Dialogs - Creating Dialogs at Runtime.

The PositionX, PositionY, Width and Height properties change the position and size of a dialog, and control at runtime. When designing a dialog in the dialog editor, these properties are set automatically.

The Name property is required, because all dialogs and controls are referenced by their name. In the dialog editor this name is created from the object name and a number, for example, TextField1.

The TabIndex property defines the order of focussing a control in a dialog when pressing the tabulator key. The index of the first element has the value 0. In the dialog editor the TabIndex property is set automatically when inserting a control. The order can also be changed through the property browser. Take care when setting this property at runtime.

The Tag property adds additional information to a control, such as a remark or number.

The Step property is described in detail in the next section.

Multi-Page Dialogs

A dialog may have several pages that can be traversed by the user step by step. This feature is used in the OpenOffice.org autopilots. The dialog property Step defines which page of the dialog is active. At runtime the next page of a dialog is displayed by increasing the step value by 1.

The Step property of a control defines the page of the dialog the control is visible. For example, if a control has a step value of 1, it is only visible on page 1 of the dialog. If the step value of the dialog is increased from 1 to 2, then all controls with a step value of 1 are faded out and all controls with a step value of 2 are visible.

A special role has the step value 0. For a control a step value of 0, the control is displayed on all dialog pages. If a dialog has a step value of 0, all controls of the dialog are displayed, independent of the step value of the single controls.

11.5.2    Dialog Controls

Command Button

The command button com.sun.star.awt.UnoControlButton allows the user to perform an action by clicking the button. Usually a button carries a label that is set through the Label property of the control model:

oDialogModel = oDialog.getModel()

oButtonModel = oDialogModel.getByName("CommandButton1")

oButtonModel.setPropertyValue("Label", "My Label")

or in short:

oDialog.Model.CommandButton1.Label = "My Label"

The label can also be set using the setLabel method of the com.sun.star.awt.XButton interface:

oButton = oDialog.getControl("CommandButton1")

oButton.setLabel("My Label")

During runtime, you may want to enable or disable a button. This is achieved by setting the Enabled property to True or False. The PushButtonType property defines the default action of a button where 0 is the Default, 1 is OK, 2 is Cancel, and 3 is Help. If a button has a PushButtonType value of 2, it behaves like a cancel button, that is, pressing the button closes the dialog. In this case, the method execute() of the dialog returns with a value of 0. An OK button of PushButtonType 1 returns 1 on execute(). The property DefaultButton specifies that the command button is the default button on the dialog, that is, pressing the ENTER key chooses the button even if another control has the focus. The Tabstop property defines if a control can be reached with the TAB key.

The command button has the feature, to display an image by setting the ImageURL property, which contains the path to the graphics file.

oButtonModel = oDialog.Model.CommandButton1

oButtonModel.ImageURL = "file:///D:/Office60/share/gallery/bullets/bluball.gif"

oButtonModel.ImageAlign = 2

All standard graphics formats are supported, such as .gif, .jpg, .tif, .wmf and .bmp. The property ImageAlign defines the alignment of the image inside the button where 0 is Left, 1 is Top, 2 is Right, and 3 is the Bottom. If the size of the image exceeds the size of the button, the image is not scaled automatically, but cut off. In this respect, the image control offers more functionality.

Image Control

If the user wants to display an image without the button functionality, the image control com.sun.star.awt.UnoControlImageControl is selected. The location of the graphic for the command button is set by the ImageURL property. Usually, the size of the image does not match the size of the control, therefore the image control automatically scales the image to the size of the control by setting the ScaleImage property to True.

oImageControlModel = oDialog.Model.ImageControl1

oImageControlModel.ImageURL = "file:///D:/Office60/share/gallery/photos/beach.jpg"

oImageControlModel.ScaleImage = True

Check Box

The check box control com.sun.star.awt.UnoControlCheckBox is used in groups to display multiple choices so that the user can select one or more choices. When a check box is selected it displays a check mark. Check boxes work independently of each other, thus different from option buttons. A user can select any number of check boxes at the same time.

The property State, where 0 is not checked, 1 is checked, 2 is don't know, accessesand changes the state of a checkbox. The tri-state mode of a check box is enabled by setting the TriState property to True. A tri-state check box provides the additional state "don't know", that is used to give the user the option of setting or unsetting an option.

oCheckBoxModel = oDialog.Model.CheckBox3

oCheckBoxModel.TriState = True

oCheckBoxModel.State = 2

The same result is achieved by using the com.sun.star.awt.XCheckBox interface:

oCheckBox = oDialog.getControl("CheckBox3")

oCheckBox.enableTriState( True )

oCheckBox.setState( 2 )

Option Button

An option button control com.sun.star.awt.UnoControlRadioButton is a simple switch with two states, that is selected by the user. Usually option buttons are used in groups to display several options, that the user may select. While option buttons and check boxes seem to be similar, selecting one option button deselects all the other option buttons in the same group.


Note, that option buttons thatbelong to the same group must have consecutive tab indices. Two groups of option buttons can be separated by any control with a tab index that is between the tab indices of the two groups.

Usually a group box, or horizontal and vertical lines are used, because those controls visually group the option buttons together, but in principal this can be any control. There is no functional relationship between an option button and a group box. Option buttons are grouped through consecutive tab indices only.

The state of an option button is accessed by the State property, where 0 is not checked and 1 is checked.

Function IsChecked( oOptionButtonModel As Object ) As Boolean

    Dim bChecked As Boolean

    If oOptionButtonModel.State = 1 Then

        bChecked = True

    Else

        bChecked = False

    End If

    IsChecked = bChecked

End Function

Label Field

A label field control com.sun.star.awt.UnoControlFixedText displays text that the user can no edit on the screen. For example, the label field is used to add descriptive labels to text fields, list boxes, and combo boxes. The actual text displayed in the label field is controlled by the Label property. The Align property allows the user to set the alignment of the text in the control to the left (0), center (1) or right (2). By default, the label field displays the text from the Label property in a single line. If the text exceeds the width of the control, the text is truncated. This behavior is changed by setting the MultiLine property to True, so that the text is displayed on more than one line, if necessary. By default, the label field control is drawn without any border. However, the label field appears with a border if the Border property is set, where 0 is no border, 1 is a 3D border, and 2 is a simple border. The font attributes of the text in the label field are specified by the FontDescriptor property. It is recommended to set this property with the property browser in the dialog editor.

Label fields are used to define shortcut keys for controls without labels. A shortcut key can be defined for any control with a label by adding a tilde (~) before the character that will be used as a shortcut. When the user presses the character key simultaneously with the ALT key, the control automatically gets the focus. To assign a shortcut key to a control without a label, for example, a text field, the label field is used. The tilde prefixes the corresponding character in the Label property of the label field. As the label field cannot receive focus, the focus automatically moves to the next control in the tab order. Therefore, it is important that the label field and the text field have consecutive tab indices.

oLabelModel = oDialog.Model.Label1

oLabelModel.Label = "Enter ~Text"

Text Field

The text field control com.sun.star.awt.UnoControlEdit is used to get input from the user at runtime. In general, the text field is used for editable text, but it can also be made read-only by setting the ReadOnly property to True. The actual text displayed in a text field is controlled by the Text property. The maximum number of characters that can be entered by the user is specified with the MaxTextLen property. A value of 0 means that there is no limitation. By default, a text field displays a single line of text. This behavior is changed by setting the property MultiLine to True. The properties HScroll and VScroll displays a horizontal and vertical scroll bar.

When a text field receives the focus by pressing the TAB key the displayed text is selected and highlighted by default. The default cursor position within the text field is to the right of the existing text. If the user starts typing while a block of text is selected, the selected text is replaced. In some cases, the user may change the default selection behavior and set the selection manually. This is done using the com.sun.star.awt.XTextComponent interface:

Dim sText As String

Dim oSelection As New com.sun.star.awt.Selection

REM get control

oTextField = oDialog.getControl("TextField1")

REM set displayed text

sText = "Displayed Text"

oTextField.setText( sText )

REM set selection

oSelection.Min = 0

oSelection.Max = Len( sText )

oTextField.setSelection( oSelection )

The text field control is also used for entering passwords. The property EchoChar specifies the character that is displayed in the text field while the user enters the password. In this context, the MaxTextLen property is used to limit the number of characters that are typed in:

oTextFieldModel = oDialog.Model.TextField1

oTextFieldModel.EchoChar = Asc("*")

oTextFieldModel.MaxTextLen = 8

A user can enter any kind of data into a text field, such as numerical values and dates. These values are always stored as a string in the Text property, thus leadingto problems when evaluating the user input. Therefore, consider using a date field, time field, numeric field, currency field or formatted field instead.

List Box

The list box control com.sun.star.awt.UnoControlListBox displays a list of items that the user can select one or more of. If the number of items exceeds what can be displayed in the list box, scroll bars automatically appear on the control. If the Dropdown property is set to True, the list of items is displayed in a drop-down box. In this case, the maximum number of line counts in the drop-down box are specified with the LineCount property. The actual list of items is controlled by the StringItemList property. All selected items are controlled by the SelectedItems property. If the MultiSelection property is set to True, more than one entry can be selected.

It may be easier to use the com.sun.star.awt.XListBox interface when working with list boxes, because an item can be added to a list at a specific position with the addItem method. For example, an item is added at the end of the list by:

Dim nCount As Integer

oListBox = oDialog.getControl("ListBox1")

nCount = oListBox.getItemCount()

oListBox.addItem( "New Item", nCount )

Multiple items are added with the help of the addItems method. The removeItems method is used to remove items from a list. For example, the first entry in a list is removed by:

Dim nPos As Integer, nCount As Integer

nPos = 0

nCount = 1

oListBox.removeItems( nPos, nCount )

A list box item can be preselected with the selectItemPos, selectItemsPos and selectItem methods. For example, the first entry in a list box can be selected by:

oListBox.selectItemPos( 0, True )

The currently selected item is obtained with the getSelectedItem method:

Dim sSelectedItem As String

sSelectedItem = oListBox.getSelectedItem()

Combo Box

The combo box control com.sun.star.awt.UnoControlComboBox presents a list of choices to the user. Additionally, it contains a text field allowing the user to input a selection that is not on the list. A combo box is used when there is only a list of suggested choices, whereas a list box is used when the user input is limited only to the list.

The features and properties of a combo box and a list box are similar. Also in a combo box the list of items can be displayed in a drop-down box by setting the Dropdown property to True. The actual list of items is accessible through the StringItemList property. The text displayed in the text field of the combo box is controlled by the Text property. For example, if a user selects an item from the list, the selected item is displayed in the text field and is obtained from the Text property:

Function GetSelectedItem( oComboBoxModel As Object ) As String

    GetSelectedItem = oComboBoxModel.Text

End Function

When a user types text into the text field of the combo box, the automatic word completion is a useful feature and is enabled by setting the Autocomplete property to True. It is recommended to use the com.sun.star.awt.XComboBox interface when accessing the items of a combo box:

Dim nCount As Integer

Dim sItems As Variant

REM get control

oComboBox = oDialog.getControl("ComboBox1")

REM first remove all old items from the list

nCount = oComboBox.getItemCount()

oComboBox.removeItems( 0, nCount )

REM add new items to the list

sItems = Array( "Item1", "Item2", "Item3", "Item4", "Item5" )

oComboBox.addItems( sItems, 0 )

Horizontal/Vertical Scroll Bar

If the visible area in a dialog is smaller than the displayable content, the scroll bar control com.sun.star.awt.UnoControlScrollBar provides navigation through the content by scrolling horizontally or vertically. In addition, the scroll bar control is used to provide scrolling to controls that do not have a built-in scroll bar.

The orientation of a scroll bar is specified by the Orientation property and can be horizontal or vertical. A scroll bar has a thumb (scroll box) that the user can drag with the mouse to any position along the scroll bar. The position of the thumb is controlled by the ScrollValue property. For a horizontal scroll bar, the left-most position corresponds to the minimum scroll value of 0 and the right-most position to the maximum scroll value defined by the ScrollValueMax property. A scroll bar also has arrows at its end that when clicked or held, incrementally moves the thumb along the scroll bar to increase or decrease the scroll value. The change of the scroll value per mouse click on an arrow is specified by the LineIncrement property. When clicking in a scroll bar in the region between the thumb and the arrows, the scroll value increases or decreases by the value set for the BlockIncrement property. The thumb position represents the portion of the displayable content that is currently visible in a dialog. The visible size of the thumb is set by the VisibleSize property and represents the percentage of the currently visible content and the total displayable content.

oScrollBarModel = oDialog.Model.ScrollBar1

oScrollBarModel.ScrollValueMax = 100

oScrollBarModel.BlockIncrement = 20

oScrollBarModel.LineIncrement = 5

oScrollBarModel.VisibleSize = 20

The scroll bar control uses the adjustment event com.sun.star.awt.AdjustmentEvent to monitor the movement of the thumb along the scroll bar. In an event handler for adjustment events the developer may change the position of the visible content on the dialog as a function of the ScrollValue property. In the following example, the size of a label field exceeds the size of the dialog. Each time the user clicks on the scrollbar, the macro AdjustmentHandler() is called and the position of the label field in the dialog is changed according to the scroll value. (BasicAndDialogs/ToolkitControls/ScrollBar)

Sub AdjustmentHandler()

    Dim oLabelModel As Object

    Dim oScrollBarModel As Object       

    Dim ScrollValue As Long, ScrollValueMax As Long

    Dim VisibleSize As Long

    Dim Factor As Double

    Static bInit As Boolean

    Static PositionX0 As Long

    Static Offset As Long

    REM get the model of the label control

    oLabelModel = oDialog.Model.Label1

    REM on initialization remember the position of the label control and calculate offset

    If bInit = False Then

        bInit = True

        PositionX0 = oLabelModel.PositionX

        OffSet = PositionX0 + oLabelModel.Width - (oDialog.Model.Width - Border)

    End If

    REM get the model of the scroll bar control

    oScrollBarModel = oDialog.Model.ScrollBar1

    REM get the actual scroll value

    ScrollValue = oScrollBarModel.ScrollValue

    REM calculate and set new position of the label control

    ScrollValueMax = oScrollBarModel.ScrollValueMax

    VisibleSize = oScrollBarModel.VisibleSize

    Factor = Offset / (ScrollValueMax - VisibleSize)

    oLabelModel.PositionX = PositionX0 - Factor * ScrollValue

End Sub

Group Box

The group box control com.sun.star.awt.UnoControlGroupBox creates a frame to visually group other controls together, such as option buttons and check boxes. Note that the group box control does not provide any container functionality for other controls, it only has visual functionality. For more details, see 11.5.2 Basic and Dialogs - Programming Dialogs and Dialog Controls - Dialog Controls - Option Button.

The group box contains a label embedded within the border and is set by the Label property. In most cases, the group box control is only used passively.

Progress Bar

The progress bar control com.sun.star.awt.UnoControlProgressBar displays a growing or shrinking bar to give the user feedback during an operation, for example, the completion of a lengthy task. The minimum and the maximum progress value of the control is set by the ProgressValueMin and the ProgressValueMax properties. The progress value is controlled by the ProgressValue property. By default, the progress bar is blue, but the fill color can be changed by setting the FillColor property. The functionality of a progress bar is demonstrated in the following example: (BasicAndDialogs/ToolkitControls/ProgressBar)

Sub ProgressBarDemo()

    Dim oProgressBar As Object, oProgressBarModel As Object

    Dim oCancelButtonModel As Object

    Dim oStartButtonModel As Object

    Dim ProgressValue As Long

    REM progress bar settings

    Const ProgressValueMin = 0

    Const ProgressValueMax = 40

    Const ProgressStep = 4

    REM set minimum and maximum progress value

    oProgressBarModel = oDialog.Model.ProgressBar1
   oProgressBarModel.ProgressValueMin = ProgressValueMin

    oProgressBarModel.ProgressValueMax = ProgressValueMax

    REM disable cancel and start button

    oCancelButtonModel = oDialog.Model.CommandButton1

    oCancelButtonModel.Enabled = False

    oStartButtonModel = oDialog.Model.CommandButton2

    oStartButtonModel.Enabled = False

    REM show progress bar

    oProgressBar = oDialog.getControl("ProgressBar1")

    oProgressBar.setVisible( True )

    REM increase progress value every second

    For ProgressValue = ProgressValueMin To ProgressValueMax Step ProgressStep

        oProgressBarModel.ProgressValue = ProgressValue

        Wait 1000

    Next ProgressValue

    REM hide progress bar

    oProgressBar.setVisible( False )

    REM enable cancel and start button

    oCancelButtonModel.Enabled = True

    oStartButtonModel.Enabled = True

End Sub

Horizontal/Vertical Line

The line control com.sun.star.awt.UnoControlFixedLine creates simple lines in a dialog. In most cases, the line control is used to visually subdivide a dialog. The line control can have horizontal or vertical orientation that is specified by the Orientation property. The label of a line control is set by the Label property. Note that the label is only displayed if the control has a horizontal orientation.

Date Field

The date field control com.sun.star.awt.UnoControlDateField extends the text field control and is used for displaying and entering dates. The date displayed in the date field is controlled by the Date property. The date value is of type Long and must be specified in the format YYYYMMDD, for example, the date September 30th, 2002 is set in the following format:

oDateFieldModel = oDialog.Model.DateField1

oDateFieldModel.Date = 20020930

The current date is set by using the Date and CDateToIso runtime functions:

oDateFieldModel.Date = CDateToIso( Date() )

The minimum and the maximum date that the user can enter is defined by the DateMin and the DateMax property. The format of the displayed date is specified by the DateFormat and the DateShowCentury property, but the usage of DateShowCentury is deprecated. Some formats are dependent on the system settings. If the StrictFormat property is set to True, the date entered by the user is checked during input. The Dropdown property enables a calendar that the user can drop down to select a date.

Dropdown is currently not working.

Time Field

The time field control com.sun.star.awt.UnoControlDateField displays and enters time values. The time value are set and retrieved by the Time property. The time value is of type Long and is specified in the format HHMMSShh, where HH are hours, MM are minutes, SS are seconds and hh are hundredth seconds. For example, the time 15:18:23 is set by:

oTimeFieldModel = oDialog.Model.TimeField1

oTimeFieldModel.Time = 15182300

The minimum and maximum time value that can be entered is given by the TimeMin and TimeMax property. The format of the displayed time is specified by the TimeFormat property.

The time value is checked during input by setting the StrictFormat property to True.

Short time format is currently not working.

Numeric Field

It is recommended to use the numeric field control com.sun.star.awt.UnoControlNumericField if the user input is limited to numeric values. The numeric value is controlled by the Value property, which is of type Double. A minimum and maximum value for user input is defined by the ValueMin and the ValueMax property. The decimal accuracy of the numeric value is specified by the DecimalAccuracy property, for example, a value of 6 corresponds to 6 decimal places. If the ShowThousandsSeparator property is set to True, a thousands separator is displayed. The numeric field also has a built-in spin button, enabled by the Spin property. The spin button is used to increment and decrement the displayed numeric value by clicking with the mouse, whereas the step is set by the ValueStep property.

oNumericFieldModel = oDialog.Model.NumericField1

oNumericFieldModel.Value = 25.40

oNumericFieldModel.DecimalAccuracy = 2

Currency Field

The currency field control com.sun.star.awt.UnoControlCurrencyField is used for entering and displaying currency values. In addition to the currency value, a currency symbol is displayed, that is set by the CurrencySymbol property. If the PrependCurrencySymbol property is set to True, the currency symbol is displayed in front of the currency value.

oCurrencyFieldModel = oDialog.Model.CurrencyField1

oCurrencyFieldModel.Value = 500.00

oCurrencyFieldModel.CurrencySymbol = "€"

oCurrencyFieldModel.PrependCurrencySymbol = True

Formatted Field

The formatted field control com.sun.star.awt.UnoControlFormattedField specifies a format that is used for formatting the entered and displayed data. A number formats supplier must be set in the FormatsSupplier property and a format key for the used format must be specified in the FormatKey property. It is recommended to use the property browser in the dialog editor for setting these properties. Supported number formats are number, percent, currency, date, time, scientific, fraction and boolean values. Therefore, the formatted field can be used instead of a date field, time field, numeric field or currency field. The NumberFormatsSupplier is described in 6 Office Development.

Pattern Field

The pattern field control com.sun.star.awt.UnoControlPatternField displays and enters a string according to a specified pattern. The entries that the user enters in the pattern field are defined in the EditMask property as a special character code. The length of the edit mask determines the number of the possible input positions. If a character is entered that does not correspond to the edit mask, the input is rejected. For example, in the edit mask "NNLNNLLLLL" the character L has the meaning of a text constant and the character N means that only the digits 0 to 9 can be entered. A complete list of valid characters can be found in the OpenOffice.org online help. The LiteralMask property contains the initial values that are displayed in the pattern field. The length of the literal mask should always correspond to the length of the edit mask. An example of a literal mask which fits to the above mentioned edit mask would be "__.__.2002". In this case, the user enters only 4 digits when entering a date.

oPatternFieldModel = oDialog.Model.PatternField1

oPatternFieldModel.EditMask    = "NNLNNLLLLL"

oPatternFieldModel.LiteralMask = "__.__.2002"

File Control

The file control com.sun.star.awt.UnoControlFileControl has all the properties of a text field control, with the additional feature of a built-in command button. When the button is clicked, the file dialog shows up. The directory that the file dialog initially displays is set by the Text property.

The directory must be given as a system path, file URLs do not work at the moment. In Basic you can use the runtime function ConvertToURL() to convert system paths to URLs.

oFileControl = oDialog.Model.FileControl1

oFileControl.Text = "D:\Programme\Office60"

Filters for the file dialog can not be set or appended for the file control. An alternative way is to use a text field and a command button instead of a file control and assign a macro to the button which instantiates the file dialog com.sun.star.ui.dialogs.FilePicker at runtime. An example is provided below. (BasicAndDialogs/ToolkitControls/FileDialog)

Sub OpenFileDialog()

    Dim oFilePicker As Object, oSimpleFileAccess As Object

    Dim oSettings As Object, oPathSettings As Object

    Dim oTextField As Object, oTextFieldModel As Object

    Dim sFileURL As String

    Dim sFiles As Variant

    REM file dialog

    oFilePicker = CreateUnoService( "com.sun.star.ui.dialogs.FilePicker" )

    REM set filter

    oFilePicker.AppendFilter( "All files (*.*)", "*.*" )

    oFilePicker.AppendFilter( "StarOffice 6.0 Text Text Document", "*.sxw" )

    oFilePicker.AppendFilter( "StarOffice 6.0 Spreadsheet", "*.sxc" )

    oFilePicker.SetCurrentFilter( "All files (*.*)" )

    REM if no file URL is set, get path settings from configuration

    oTextFieldModel = oDialog.Model.TextField1

    sFileURL = ConvertToURL( oTextFieldModel.Text )

    If sFileURL = "" Then

        oSettings = CreateUnoService( "com.sun.star.frame.Settings" )

        oPathSettings = oSettings.getByName( "PathSettings" )

        sFileURL = oPathSettings.getPropertyValue( "Work" )

    End If

    REM set display directory

    oSimpleFileAccess = CreateUnoService( "com.sun.star.ucb.SimpleFileAccess" )

    If oSimpleFileAccess.exists( sFileURL ) And oSimpleFileAccess.isFolder( sFileURL ) Then

        oFilePicker.setDisplayDirectory( sFileURL )

    End If

    REM execute file dialog

    If oFilePicker.execute() Then

        sFiles = oFilePicker.getFiles()

        sFileURL = sFiles(0)

        If oSimpleFileAccess.exists( sFileURL ) Then

            REM set file path in text field

            oTextField = oDialog.GetControl("TextField1")

            oTextField.SetText( ConvertFromURL( sFileURL ) )

        End If

    End If

End Sub

11.6    Creating Dialogs at Runtime

When using OpenOffice.org Basic, the dialog editor is a tool for designing dialogs. Refer to 11.2 Basic and Dialogs - OpenOffice.org Basic IDE for additional information. When using Java, a different approach is used, because Java is not supported as scripting language. Dialogs are created at runtime in a similar method as Java Swing components are created. Also, the event listeners are registered at runtime at the appropriate controls.


Illustration 11.28

In the example described in this section, a simple modal dialog is created at runtime containing a command button and label field. Each time the user clicks on the button, the label field is updated and the total number of button clicks is displayed.

The dialog is implemented as a UNO component in Java that is instantiated with the service name com.sun.star.examples.SampleDialog. For details about writing a Java component and the implementation of the UNO core interfaces, refer to 4.5.6 Writing UNO Components - Simple Component in Java - Storing the Service Manager for Further Use. The method that creates and executes the dialog is shown below.

/** method for creating a dialog at runtime

 */

private void createDialog() throws com.sun.star.uno.Exception {

    // get the service manager from the component context

    XMultiComponentFactory xMultiComponentFactory = _xComponentContext.getServiceManager();

    // create the dialog model and set the properties

    Object dialogModel = xMultiComponentFactory.createInstanceWithContext(

        "com.sun.star.awt.UnoControlDialogModel", _xComponentContext);

    XPropertySet xPSetDialog = (XPropertySet)UnoRuntime.queryInterface(

        XPropertySet.class, dialogModel);      

    xPSetDialog.setPropertyValue("PositionX", new Integer(100));

    xPSetDialog.setPropertyValue("PositionY", new Integer(100));

    xPSetDialog.setPropertyValue("Width", new Integer(150));

    xPSetDialog.setPropertyValue("Height", new Integer(100));

    xPSetDialog.setPropertyValue("Title", new String("Runtime Dialog Demo"));

    // get the service manager from the dialog model

    XMultiServiceFactory xMultiServiceFactory = (XMultiServiceFactory)UnoRuntime.queryInterface(

        XMultiServiceFactory.class, dialogModel);

    // create the button model and set the properties

    Object buttonModel = xMultiServiceFactory.createInstance(

        "com.sun.star.awt.UnoControlButtonModel" );

    XPropertySet xPSetButton = (XPropertySet)UnoRuntime.queryInterface(

        XPropertySet.class, buttonModel);

    xPSetButton.setPropertyValue("PositionX", new Integer(50));

    xPSetButton.setPropertyValue("PositionY", new Integer(30));

    xPSetButton.setPropertyValue("Width", new Integer(50));

    xPSetButton.setPropertyValue("Height", new Integer(14));

    xPSetButton.setPropertyValue("Name", _buttonName);

    xPSetButton.setPropertyValue("TabIndex", new Short((short)0));        

    xPSetButton.setPropertyValue("Label", new String("Click Me"));

    // create the label model and set the properties

    Object labelModel = xMultiServiceFactory.createInstance(

        "com.sun.star.awt.UnoControlFixedTextModel" );

    XPropertySet xPSetLabel = ( XPropertySet )UnoRuntime.queryInterface(

        XPropertySet.class, labelModel );

    xPSetLabel.setPropertyValue("PositionX", new Integer(40));

    xPSetLabel.setPropertyValue("PositionY", new Integer(60));

    xPSetLabel.setPropertyValue("Width", new Integer(100));

    xPSetLabel.setPropertyValue("Height", new Integer(14));

    xPSetLabel.setPropertyValue("Name", _labelName);

    xPSetLabel.setPropertyValue("TabIndex", new Short((short)1));        

    xPSetLabel.setPropertyValue("Label", _labelPrefix);

    // insert the control models into the dialog model

    XNameContainer xNameCont = (XNameContainer)UnoRuntime.queryInterface(

        XNameContainer.class, dialogModel);

    xNameCont.insertByName(_buttonName, buttonModel);

    xNameCont.insertByName(_labelName, labelModel);

    // create the dialog control and set the model

    Object dialog = xMultiComponentFactory.createInstanceWithContext(

        "com.sun.star.awt.UnoControlDialog", _xComponentContext);

    XControl xControl = (XControl)UnoRuntime.queryInterface(

        XControl.class, dialog );

    XControlModel xControlModel = (XControlModel)UnoRuntime.queryInterface(

        XControlModel.class, dialogModel);      

    xControl.setModel(xControlModel);

    // add an action listener to the button control

    XControlContainer xControlCont = (XControlContainer)UnoRuntime.queryInterface(

        XControlContainer.class, dialog);      

    Object objectButton = xControlCont.getControl("Button1");

    XButton xButton = (XButton)UnoRuntime.queryInterface(XButton.class, objectButton);

    xButton.addActionListener(new ActionListenerImpl(xControlCont));

    // create a peer

    Object toolkit = xMultiComponentFactory.createInstanceWithContext(

        "com.sun.star.awt.ExtToolkit", _xComponentContext);      

    XToolkit xToolkit = (XToolkit)UnoRuntime.queryInterface(XToolkit.class, toolkit);

    XWindow xWindow = (XWindow)UnoRuntime.queryInterface(XWindow.class, xControl);

    xWindow.setVisible(false);      

    xControl.createPeer(xToolkit, null);

    // execute the dialog

    XDialog xDialog = (XDialog)UnoRuntime.queryInterface(XDialog.class, dialog);

    xDialog.execute();

    // dispose the dialog

    XComponent xComponent = (XComponent)UnoRuntime.queryInterface(XComponent.class, dialog);

    xComponent.dispose();

}

First, a dialog model is created by prompting the ServiceManager for the com.sun.star.awt.UnoControlDialogModel service. Then, the position, size and title of the dialog are set using the com.sun.star.beans.XPropertySet interface. In performance critical applications, the use of the com.sun.star.beans.XMultiPropertySet interface is recommended. At this point, the dialog model describes an empty dialog, which does not contain any control models.

All control models in a dialog container have the common properties “PositionX”, “PositionY”, “Width”, “Height”, “Name”, “TabIndex”, “Step” and “Tag”. These properties are optional and only added if the control model is created by a special object factory, namely the dialog model. Therefore, a dialog model also supports the com.sun.star.lang.XMultiServiceFactory interface. If the control model is created by the ServiceManager, these common properties are missing.


Note that control models have the common properties “PositionX”, “PositionY”, “Width”, “Height”, “Name”, “TabIndex”, “Step” and “Tag” only if they were created by the dialog model that they belong to.

After the control models for the command button and label field are created, their position, size, name, tab index and label are set. Then, the control models are inserted into the dialog model using the com.sun.star.container.XNameContainer interface. The model of the dialog has been fully described.

To display the dialog on the screen, a dialog control com.sun.star.awt.UnoControlDialog is created and the corresponding model is set. An action listener is added to the button control, because the label field is updated whenever the user clicks on the command button. The listener is explained below. Before the dialog is shown, a window or a peer is created on the screen. Finally, the dialog is displayed on the screen using the execute method of the com.sun.star.awt.XDialog interface.

The implementation of the action listener is shown in the following example.

/** action listener

 */

public class ActionListenerImpl implements com.sun.star.awt.XActionListener {

    private int _nCounts = 0;

    private XControlContainer _xControlCont;

    public ActionListenerImpl(XControlContainer xControlCont) {

        _xControlCont = xControlCont;

    }

   

    // XEventListener

    public void disposing(EventObject eventObject) {

        _xControlCont = null;

    }

   

    // XActionListener

    public void actionPerformed(ActionEvent actionEvent) {

        // increase click counter

        _nCounts++;

       

        // set label text

        Object label = _xControlCont.getControl("Label1");

        XFixedText xLabel = (XFixedText)UnoRuntime.queryInterface(XFixedText.class, label);            

        xLabel.setText(_labelPrefix + _nCounts);

    }    

}

The action listener is fired each time the user clicks on the command button. In the actionPerformed method of the com.sun.star.awt.XActionListener interface, an internal counter for the number of button clicks is increased. Then, this number is updated in the label field. In addition, the disposing method of the parent interface com.sun.star.lang.XEventListener is implemented.

Our sample component executes the dialog from within the office by implementing the trigger method of the com.sun.star.task.XJobExecutor interface:

public void trigger(String sEvent) {

    if (sEvent.compareTo("execute") == 0) {

        try {

            createDialog();

        }

        catch (Exception e) {

            throw new com.sun.star.lang.WrappedTargetRuntimeException(e.getMessage(), this, e);

        }

    }

}

A simple OpenOffice.org Basic macro that instantiates the service of our sample component and executes the dialog is shown below.

Sub Main

    Dim oJobExecutor

    oJobExecutor = CreateUnoService("com.sun.star.examples.SampleDialog")

    oJobExecutor.trigger("execute")

End Sub

In future versions of OpenOffice.org, a method for executing dialogs created at runtime will be provided.

11.7    Library File Structure

This section describes how libraries are stored. Generally all data is stored in XML format. Four different XML document types that arespecified in the DTD files installed in <OfficePath>/share/dtd/officedocument are used:

Additionally, a binary format is used to store compiled Basic code for password protected Basic libraries. This is described in more detail in 11.7 Basic and Dialogs - Library File Structure.


In a password protected Basic library, the password is used to scramble the source code using the Blowfish algorithm. The password itself is not stored, so when the password for a Basic library is lost, the corresponding Basic source code is lost also. There is no retrieval method if this happens.

Besides the XML format of the library description files, it is necessary to understand the structure in which these files are stored. This is different for application and document libraries. Application libraries are stored directly in the system file system and document libraries are stored inside the document's package file. For information abuot package files, see 6.2.9 Office Development - Common Application Features - Package File Formats. The following sections describe the structure and combination of library container and library structures.

11.7.1    Application Library Container

In an OpenOffice.org installation the application library containers for Basic and dialogs are located in the directory <OfficePath>/user/basic. The library container index files are named script.xlc for the Basic and dialog.xlc for the Dialog library container. The "lc" in .xlc stands for library container.

The same directory contains the libraries created by the user. Initially only the library Standard exists for Basic and dialogs using the same directory. The structure of the library inside the directory is explained in the next section.

The user/basic directory is not the only place in the OpenOffice.org installation where libraries are stored. Most of the autopilots integrated in OpenOffice.org are realized in Basic, and the corresponding Basic and dialog libraries are installed in the directory <OfficePath>/share/basic. These libraries are listed in the library container index file as read-only links.

It is necessary to distinguish between libraries created by the user and the autopilot libraries. The autopilot libraries are installed in a directory that is shared between different users. In a network installation, the share directory is located somewhere on a server, so that the autopilot libraries cannot be owned directly by the user-specific library containers.

In the file system, a library is represented by a directory. The directory's name is the same as the library name. The directory contains all files that are necessary for the library.

Basic libraries can be protected with a password, so that the source code cannot be read by unauthorized persons. Dialog libraries cannot be protected with a password. This can be handled using the Tools - Macro - Organizer... dialog that is explained in 11.2.1 Basic and Dialogs - OpenOffice.org Basic IDE - Managing Basic and Dialog Libraries. The password protection of a Basic library also affects the file format.

Libraries without Password Protection

Every library element is represented by an XML file named like the element in the directory representing the library. For Basic modules these files, following the specification in module.dtd, have the extension .xba. For dialogs these files, following the specification in dialog.dtd, have the extension .xdl. Additionally, the directory contains a library index file (library.dtd). These index files are named script.xlb for Basic and dialog.xlb for dialog libraries.

In the following example, an Application Basic library Standard containing two modules Module1 and Module2 is represented by the following directory:

        <DIR> Standard

        |

        |--script.xlb

        |--Module1.xba

        |--Module2.xba

An application dialog library Standard containing two dialogs SmallDialog and BigDialog is represented by the following directory:

    <DIR> Standard

    |

    |--dialog.xlb

    |--SmallDialog.xba

    |--BigDialog.xba

It is also possible that the same directory represents a Basic and a Dialog library. This is the standard case in the OpenOffice.org, See the chapter Library organization in OpenOffice.org. When the two example libraries above are stored in the same directory, the files from both libraries are together in the same directory:

    <DIR> Standard

    |

    |--dialog.xlb

    |--script.xlb

    |--Module1.xba

    |--Module2.xba

    |--SmallDialog.xba

    |--BigDialog.xba

The two libraries do not affect each other, because all file names are different. This is also the case if a Basic module and a dialog are named equally, due the different file extensions..

Libraries with Password Protection

Only Basic libraries can be password protected. The password protection of a Basic library affects the file format, because binary data has to be stored. In plain XML format, the source code would be readable in the file even if it was not displayed in the Basic IDE. Also, the compiled Basic code has to be stored for each module together with the encrypted sources. This is necessary because, Basic could not access the source code and compile it as long as the password is unknown in contrast to libraries without password protection. Without storing the compiled code, Basic could only execute password-protected libraries once the user supplied the correct password. The whole purpose of the password feature is to distribute programs without giving away the password and source code, therefore this would not be feasible.

The followig example shows a password-protected application Basic library Library1, containing three modules Module1, Module1 and Module3, is represented by the following directory:

    <DIR> Library1

    |

    |--script.xlb

    |--Module1.pba

    |--Module2.pba

    |--Module3.pba

The file script.xlb does not differ from the case without a password, except for the fact that the password protected status of the library is reflected by the corresponding flag.

Each module is represented by a .pba file. Like OpenOffice.org documents, these files are package files ("pba" stands for package basic) and contain a sub structure that can be viewed with any zip tool. For detailed information about package files, see 6.2.9 Office Development - Common Application Features - Package File Formats).

A module package file has the following content:

    <PACKAGE> Module1.pba

    |

    |--<DIR> Meta-Inf                ' Content is not displayed here

    |--code.bin

    |--source.xml

The Meta-Inf directory is part of every package file and will not be explained in this document. The file code.bin contains the compiled Basic code and the file source.xml contains the Basic source code encrypted with the password.

11.7.2    Document Library Container

While application libraries are stored directly in the file system, document libraries are stored inside the document's package file. For more informatin about package files, see 6.2.9 Office Development - Common Application Features - Package File Formats. In documents, the Basic library container and dialog library container are stored separately:

The libraries are stored as sub folders in these library container folders. The structure inside the libraries is basically the same as in an application. One difference relates to the stream - "files" inside the package or package folders – names. In documents, all XML stream or file names have the extension .xml. Special extensions like .xba, .xdl are not used. Instead of different extensions, the names are extended for the library and library container index files. In documents they are named script-lc.xml (Basic library container index file), script-lb.xml (Basic library index file), dialog-lc.xml (dialog library container index file) and dialog-lb.xml (dialog library index file).

In example 1, the package structure for a document with one Basic Standard library containing three modules:

    <Package> ExampleDocument1

    |

    |--<DIR> Basic

    |  |

    |  |--<DIR> Standard                ' Folder: Contains library "Standard"

    |  |  |

    |  |  |--Module1.xml                ' Stream: Basic module file

    |  |  |--Module2.xml                ' Stream: Basic module file

    |  |  |--Module3.xml                ' Stream: Basic module file

    |  |  |--script-lb.xml        ' Stream: Basic library index file

    |  |

    |  |--script-lc.xml                ' Stream: Basic library container index file

    |

    |  ' From here the folders and streams have nothing to do with libraries

    |--<DIR> Meta-Inf

    |--content.xml

    |--settings.xml

    |--styles.xml

In example 2, package structure for a document with two Basic and one dialog libraries:

    <Package> ExampleDocument2

    |

    |--<DIR> Basic

    |  |

    |  |--<DIR> Standard                ' Folder: Contains library "Standard"

    |  |  |

    |  |  |--Module1.xml                ' Stream: Basic module file

    |  |  |--Module2.xml                ' Stream: Basic module file

    |  |  |--script-lb.xml        ' Stream: Basic library index file

    |  |

    |  |--<DIR> Library1                ' Folder: Contains library "Library1"

    |  |  |

    |  |  |--Module1.xml                ' Stream: Basic module file

    |  |  |--script-lb.xml        ' Stream: Basic library index file

    |  |

    |  |--script-lc.xml                ' Stream: Basic library container index file

    |

    |--<DIR> Dialogs

    |  |

    |  |--<DIR> Standard                ' Folder: Contains library "Standard"

    |  |  |

    |  |  |--Dialog1.xml                ' Stream: Dialog file

    |  |  |--dialog-lb.xml        ' Stream: Dialog library index file

    |  |

    |  |--<DIR> Library1                ' Folder: Contains library "Library1"

    |  |  |

    |  |  |--Dialog1.xml                ' Stream: Dialog file

    |  |  |--Dialog2.xml                ' Stream: Dialog file

    |  |  |--dialog-lb.xml        ' Stream: Dialog library index file

    |  |

    |  |--dialog-lc.xml                ' Stream: Dialog library container index file

    |

    |  ' From here the folders and streams have nothing to do with libraries

    |--<DIR> Meta-Inf

    |--content.xml

    |--settings.xml

    |--styles.xml

If a document Basic library is password protected, the file structure does not differ as much from an unprotected library as in the Application Basic case. The differences are:

The following example shows the package structure for a document with two Basic and one dialog libraries where only the Basic library Library1 contains any of the modules:

    <Package> ExampleDocument3

    |

    |--<DIR> Basic

    |  |

    |  |--<DIR> Standard                ' Folder: Contains library "Standard"

    |  |  |

    |  |  |--script-lb.xml        ' Stream: Basic library index file

    |  |

    |  |--<DIR> Library1                ' Folder: Contains library "Library1"

    |  |  |

    |  |  |--Module1.xml                ' Stream: Scrambled Basic module source file

    |  |  |--Module1.bin                ' Stream: Basic module compiled code file

    |  |  |--Module2.xml                ' Stream: Scrambled Basic module source file

    |  |  |--Module2.bin                ' Stream: Basic module compiled code file

    |  |  |--Module3.xml                ' Stream: Scrambled Basic module source file

    |  |  |--Module3.bin                ' Stream: Basic module compiled code file

    |  |  |--script-lb.xml        ' Stream: Basic library index file

    |  |

    |  |--script-lc.xml                ' Stream: Basic library container index file

    |

    |--<DIR> Dialogs

    |  |

    |  |--<DIR> Standard                ' Folder: Contains library "Standard"

    |  |  |

    |  |  |--dialog-lb.xml        ' Stream: Dialog library index file

    |  |

    |  |--<DIR> Library1                ' Folder: Contains library "Library1"

    |  |  |

    |  |  |--dialog-lb.xml        ' Stream: Dialog library index file

    |  |

    |  |--dialog-lc.xml                ' Stream: Dialog library container index file

    |

    |  ' From here the folders and streams have nothing to do with libraries

    |--<DIR> Meta-Inf

    |--content.xml

    |--settings.xml

    |--styles.xml

This example also shows that a Dialogs folder is created in the document package file although the library Standard and the library Library1 do not contain dialogs. This is done because the Dialog library Library1 would be lost after reloading the document. Only a single empty library Standard is assumed to exist, even if it is not stored explicitly.

11.8    Library Deployment

OpenOffice.org has a simple concept to add Basic libraries to an existing installation. Bringing Basic libraries into a OpenOffice.org installation involves the following steps:

[<OfficePath>/program] $ pkgchk my_package.zip

The opposite steps are necessary to remove a package from your OpenOffice.org installation:

You can run pkgchk with the option '--help' or '-h' to get a comprehensive overview of all the switches.


Be careful not to run the pkgchk deployment tool while there are running instances of OpenOffice.org. For ordinary users, this case is recognized by the pkgchk process and leads to abortion, b is not reognized for shared network installationsusing option '--shared' or '-s'. If any user of a network installation has open processes, data inconsistencies may occur and [PRODUCT] processes may crash.

Package Structure

A UNO package is a zip file containing Basic libraries, or UNO components and type libraries. The pkgchk tool unzips all the packages found in the package directory into the cache directory, preserving the file structure of the zip file.

After the cache directory is ready, pkgchk traverses the cache directory recursively. Depending on the extension of the files it detects, it carries out the necessary registration steps. Unknown file types are ignored.

Basic libraries

The pkgchk tool links Basic library files (.xlb) into OpenOffice.org by adding them to the Basic library container files (.xlc) that reside in the following paths:

Library File

User Installation

Shared Installation

script.xlb

<OfficePath>/user/basic/script.xlc

<OfficePath>/share/basic/script.xlc

dialog.xlb

<OfficePath>/user/basic/dialog.xlc

<OfficePath>/share/basic/dialog.xlc

The files share/basic/*.xlc are created when new libraries are shared among all users using the pkgchk option -s (--shared) in a network installation.

The name of a Basic library is determined by the name of its parent directory. Therefore, package complete library folders, including the parent folders into the UNO Basic package. For example, if your library is named MyLib, there has to be a corresponding folder /MyLib in your development environment. This folder must be packaged completely into the UNO package, so that the zip file contains a structure similar to the following:

my_package.zip:

    MyLib/

        script.xlb

        dialog.xlb

        Module1.xba

        Dialog1.xba

Other package components

Pkgchk automatically registers shared libraries, Java archives and type libraries found in a UNO package. For details, see 4.7.1 Writing UNO Components - Deployment Options for Components - UNO Package Installation


The autopilot .xlb libraries are registered in the user/basic/*.xlc files, but located in share/basic. This makes it is possible to delete and disable the autopilots for certain users even in a network installation. This is impossible for libraries deployed with the pkgchk tooland libraries deployed with the share option are always shared among all users.

Path Settings

The package directories are called uno-packages by default. There can be one in <OfficePath>/share for shared installations and another one in <OfficePath>/user for single users. The cache directories are created automatically within the respective uno-packages directory. OpenOffice.org has to be configured to look for these paths in the uno.ini file (on Windows, unorc on Unix) in <OfficePath>/program. When pkgchk is launched, it checks this file for package entries. If they do not exist, the following default values are added to uno(.ini|rc).

[Bootstrap]
UNO_SHARED_PACKAGES=${$SYSBINDIR/bootstrap.ini::BaseInstallation}/share/uno_packages
UNO_SHARED_PACKAGES_CACHE=$UNO_SHARED_PACKAGES/cache
UNO_USER_PACKAGES=${$SYSBINDIR/bootstrap.ini::UserInstallation}/user/uno_packages
UNO_USER_PACKAGES_CACHE=$UNO_USER_PACKAGES/cache

The settings reflect the default values for the shared package and cache directory, and the user package and cache directory as described above.

In a network installation, all users start the office from a common directory on a file server. The administrator puts the packages for all the users of the network installation into the <OfficePath>/share/uno_packages folder of the shared installation. If a user wants to install packages locally so that only a single installation is affected, the user must copy the packages to <OfficePath>/user/uno_packages.

Pkgchk has to be run differently for a shared and a user installation. To install shared packages, run pkgchk with the -s (-shared) option which causes pkgchk to process only the shared packages. If pkgchk is run without command-line parameters, the user packages will be registered.

Additional Options

By default, the tool logs all actions into the <cache-dir>/log.txt file. You can switch to another log file through the -l (–log) <file name> option. Option -v (–verbose) logs to stdout, in addition to the log file.

The tool handles errors loosely. It continues after errors even if a package cannot be inflated or a shared library cannot be registered. The tool logs these errors and proceeds silently. If you want the tool to stop on every error, switch on the –strict_error handling.

If there is some inconsistency with the cache and you want to renew it from the ground up, repeating the installation using the option -r (–renewal).

[ Previous document | Content Table | Next document ]