Programmatic Assignment of Scripts to Events

From Apache OpenOffice Wiki
Jump to: navigation, search



Sometimes, you want to create a document programmatically, including form controls, and assigning certain scripts to certain events for those controls. In the user interface, this is done by using the property browser. Programmatically, this is somewhat more difficult.

As an example, if you want to programmatically create a document containing radio buttons. When those radio buttons change their state (i.e. are selected), a certain StarBasic script should be called.

One possibility is to make use of the OnLoad event of the document as a whole. Using this event, you can create a listener of the desired type (in our sample case: com.sun.star.awt.XItemListener), and register it at the control in question.

Tip.png In StarBasic, you can create an UNO listener using the procedure CreateUnoListener.


This approach has three disadvantages: First, it is expensive. The scripting environment is loaded every time the document is loaded, which is too early. It should be loaded as late as possible, which is when the radio buttons really change their state.

Second, it is error prone. There are certain circumstances where StarBasic listeners are automatically revoked, without the document being closed. In those cases, you need to manually reload the document, or re-run your OnLoad script for re-creating the listener.

Third, it is complex. You would, in your OnLoad initialization script, need to manually obtain the control in questions, which can involve a large amount of code.

A better solution is to use the event attacher manager mechanism described in Scripting and Events.

The following example creates a text document with three radio buttons, all three calling the same script when being selected.

Documentation note.png When you try the following code, you may need to adjust the location of the script being called. At the moment, it assumes a module name macro_assignment in the application-wide library named Standard.
 REM ***** BASIC *****
 
 Option Explicit
 
 Sub Main
     ' create a new writer document
     Dim oDocument as Object
     Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
     oDocument = StarDesktop.LoadComponentFromURL( "private:factory/swriter", "_blank", 0,
         oEmptyArgs )
     Erase oEmptyArgs
     
     ' create a new logical form
     Dim oFormsCollection as Object
     oFormsCollection = oDocument.DrawPage.Forms
     Dim oSampleForm as Object
     oSampleForm = createUnoService( "com.sun.star.form.component.DataForm" )
     oFormsCollection.insertByName( "sample form", oSampleForm )
     
     ' create three radio buttons associated with three colors
     Dim oControlShape as Object
     Dim oControlModel as Object
     
     ' we want to add the equivalent of an com.sun.star.awt.XItemListener
     Dim sListenerInterfaceName as String
     sListenerInterfaceName = "com.sun.star.awt.XItemListener"
     Dim sListenerMethodName as String
     sListenerMethodName = "itemStateChanged"
     
     ' we want the onColorChange function in this module to be called
     Dim sMacroLocation as String
     sMacroLocation = "application:Standard.macro_assignment.onColorChange"
         ' note that this assumes that the module is called macro_assignment, and
         ' resides in the "Standard" library of the application-wide Basic macros
     
     Dim sColors(2) as String
     sColors(0) = "red"
     sColors(1) = "green"
     sColors(2) = "blue"
     Dim i as Integer
     For i = 0 To 2
         ' a shape
         oControlShape = oDocument.createInstance( "com.sun.star.drawing.ControlShape" )
         positionShape( oControlShape, 1000, 1000 + i * 800, 5000, 600 )
         
         ' a control model
         oControlModel = createUnoService( "com.sun.star.form.component.RadioButton" )
         oControlModel.Name = "colors"
         oControlModel.Label = "make it " & UCase( sColors( i ) )
         oControlModel.Tag = sColors( i )
         oSampleForm.insertByIndex( i, oControlModel )
         
         ' knit both
         oControlShape.Control = oControlModel
             ' yes, unfortunately the terminology is inconsistent here ...
         
         ' add the shape to the DrawPage
         oDocument.DrawPage.add( oControlShape )
         
         ' bind a macro to the "stateChanged" event
         Dim oEvent as new com.sun.star.script.ScriptEventDescriptor
         oEvent.ListenerType = sListenerInterfaceName
         oEvent.EventMethod = sListenerMethodName
         oEvent.ScriptType = "StarBasic"
         oEvent.ScriptCode = sMacroLocation
         oSampleForm.registerScriptEvent( i, oEvent )
     Next i
     
     ' switch the document (view) to alive mode
     Dim oURL as new com.sun.star.util.URL
     oURL.Complete = ".uno:SwitchControlDesignMode"
     createUnoService( "com.sun.star.util.URLTransformer" ).parseStrict( oURL )
     Dim oDispatcher as Object
     oDispatcher = oDocument.CurrentController.Frame.queryDispatch( oURL, "", 63 )
     oDispatcher.dispatch( oURL, oEmptyArgs() )
     Erase oURL
     
     ' set the focus to the first control
     oDocument.CurrentController.getControl( oSampleForm.getByIndex( 0 ) ).setFocus
 End Sub
 
 ' this sets the size and position of a given shape
 ' Additionally, it anchors this shape at a paragraph
 Sub positionShape( oShape as Object, X as Integer, Y as Integer, Width as Integer, Height as Integer )
     oShape.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PARAGRAPH
         ' Not that this implies that you can use it for text documents only.
         ' The rest of the function also works for shapes in other documents
 
     Dim oPos as new com.sun.star.awt.Point
     oPos.X = X
     oPos.Y = Y
     oShape.setPosition( oPos )
     Erase oPos
 
     Dim oSize as new com.sun.star.awt.Size
     oSize.Width = Width
     oSize.Height = Height
     oShape.setSize( oSize )
     Erase oSize
 End Sub
 
 ' This will be bound to the radio button's state changes
 ' At the moment, it simply changes their text color, but of course
 ' you could do more than this here ...
 Sub onColorChange( oClickEvent as Object )
     If ( oClickEvent.Selected > 0 ) Then
         Dim nColor as Long
         Select Case oClickEvent.Source.Model.Tag
             Case "red"
                 nColor = CLng( "&HFF0000" )
             case "green"
                 nColor = CLng( "&H00FF00" )
             case "blue"
                 nColor = CLng( "&H0000FF" )
         End Select
 
         Dim oControlParent as Object
         oControlParent = oClickEvent.Source.Model.Parent
         Dim i as Integer
         For i = 0 to oControlParent.getCount() - 1
             oControlParent.getByIndex( i ).TextColor = nColor
         Next i
     End If
 End Sub
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages