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 userinterface, 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 Basic 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 Apache OpenOffice Basic, 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 Apache OpenOffice Basic 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