rglover General User


Joined: 06 Mar 2006 Posts: 26 Location: Victoria, B.C., Canada
|
Posted: Thu Mar 16, 2006 2:30 pm Post subject: improved approach to event listeners for dialog controls |
|
|
This is a continuation of my earlier post in this forum on the same subject: http://www.oooforum.org/forum/viewtopic.phtml?p=132658#132658
I recently discovered by chance (actually, from the slides for a presentation by Andrew Pitonyak) that it is possible to define structs in OOo Basic. That is what is required to do an elegant job of making the routines for assigning event listeners to dialog controls fully general. I couldn't resist.
What follows is in 3 parts:
library elements
example application
comments
Comments in the code below, especially at the head of the library routines, should explain the purpose and usage of each element.
Library Elements
(Actually, a the contents of a module.) Install this somewhere all your macros can access it (i.e., My Macros & Dialogs).
| Code: | '=============================================================================
' Utilities to support event listener assignment for controls in dialogs
' Author: Rod Glover
' Date: March 2006
'------------------------------------------------------------------------------
' Structure for holding a record of an event listener assignment to a control
'
Type ControlEventListenerAssignment
Control as Variant
ListenerType as String
Listener as Variant
End Type
'------------------------------------------------------------------------------
' Return a list (implemented as a 0-based array) of empty event listener assignments
'
Function newEventListenerAssignmentList (n as Integer)
Dim newArray(0 to n-1) as ControlEventListenerAssignment
Dim i as Integer
For i = 0 to n-1
With newArray(i)
.Control = Null
.ListenerType = ""
.Listener = Null
End With
Next
newEventListenerAssignmentList = newArray()
End Function
'------------------------------------------------------------------------------
' Add an event listener of specified type to a control in a dialog, recording the assignment in the list of
' event listener assignments
'
' Arguments
' oDialog Dialog containing control
' sNamePrefix Prefix for event handler names; see below
' sControlName Name of control in dialog
' sListenerType Type of listener to be created and added to control, in standard form
' "com.sun.star.awt.X<type>Listener"; see below
' oListenerAssignments List of event listener assignments in which the requested assignment will be
' recorded (for later removal)
'
' Each listener requires one or more specially named event handler routines to be created.
' Generically, each event handler name is composed of:
' - listener identifier (usually the control name + "_") specified when the listener is created +
' - a listener-specific handler name, as noted below for selected listeners
'
' In this routine, event handler names for a control are constructed using a listener identifier =
' sNamePrefix + sControlName.
' sNamePrefix is most useful when the caller sets it to the dotted qualifier for the library and
' module in which the event handler routines are stored, e.g., "My_Library.My_Module.".
'
' See the SDK documentation for each listener interface (e.g., XActionListener) for details
' about the event specifier object passed to each type of handler routine. Briefly, the handlers
' required for selected event listeners are:
'
' Listener Handler names
' -------- -------------
' XActionListener actionPerformed
' XItemListener itemStateChanged
' XTextListener textChanged
' XFocusListener focusGained
' focusLost
'
Sub addListenerToControlInDialog ( _
oDialog as Variant, sNamePrefix as String, sControlName as String, sListenerType as String, _
oListenerAssignments() as ControlEventListenerAssignment)
Dim oDialogModel as Variant
Dim oControl as Variant
Dim oControlModel as Variant
Dim sListenerName as String
oDialogModel = oDialog.getModel()
oControl = oDialog.getControl(sControlName)
sListenerName = sNamePrefix + oControl.Model.Name + "_"
addListenerToControl (oControl, sListenerName, sListenerType, oListenerAssignments() )
End Sub
'----------------------------------------------------
' Create a listener of the specified type and name, and add it to the control.
' Record the listener in the oListenerAssignments list so that it can later be removed.
' Return the created listener.
'
' The Select Case statement below determines the listener types supported. If additional
' types are required, add them there, and correspondingly in routine removeListenersFromControls.
'
Function addListenerToControl ( _
oControl as Variant, sListenerName as String, sListenerType as String, _
oListenerAssignments() as ControlEventListenerAssignment)
Dim free as Integer
Dim oListener as Variant
' Extend listener assignments array by 1
' Dim L as Integer, U as Integer
' L = LBound(oListenerAssignments())
' U = UBound(oListenerAssignments()) + 1
' ReDim Preserve oListenerAssignments (L to U) as ControlEventListenerAssignment
' Dim oNewListenerAssignments (L to U) as ControlEventListenerAssignment
' For i = L to U-1
' oNewListenerAssignments(i) = oListenerAssignments(i)
' Next
' oListenerAssignments() = oNewListenerAssignments()
' Locate a free listener assignment, denoted by empty string for ListenerType
free = LBound(oListenerAssignments())
Do While free <= UBound(oListenerAssignments())
If oListenerAssignments(free).ListenerType = "" Then
Exit Do
End If
free = free + 1
Loop
If free > UBound(oListenerAssignments()) Then
MsgBox ("No free listener assignments when attempting to add listener ", sListenerName)
Exit Function
End If
' Create listener, record it in the free listener assignment slot, and add it to the control.
oListener = CreateUnoListener(sListenerName, sListenerType)
With oListenerAssignments(free)
.Control = oControl
.ListenerType = sListenerType
.Listener = oListener
End With
Select Case sListenerType
Case "com.sun.star.awt.XActionListener":
oControl.addActionListener(oListener)
Case "com.sun.star.awt.XFocusListener":
oControl.addFocusListener(oListener)
Case "com.sun.star.awt.XItemListener":
oControl.addItemListener(oListener)
Case "com.sun.star.awt.XTextListener":
oControl.addTextListener(oListener)
Case Else:
MsgBox ("addListenerToControl: " + sListenerType + " not supported")
End Select
addListenerToControl = oListener
End Function
'----------------------------------------------------
' Remove action listeners from controls.
'
' This appears to be required to prevent errors after the dialog is closed.
'
Sub removeListenersFromControls (oListenerAssignments() as ControlEventListenerAssignment)
Dim c as Integer
for c = LBound(oListenerAssignments) to UBound(oListenerAssignments)
With oListenerAssignments(c)
Select Case .ListenerType
Case "":
' Already removed
Case "com.sun.star.awt.XActionListener":
.Control.removeActionListener(.Listener)
Case "com.sun.star.awt.XFocusListener":
.Control.removeFocusListener(.Listener)
Case "com.sun.star.awt.XItemListener":
.Control.removeItemListener(.Listener)
Case "com.sun.star.awt.XTextListener":
.Control.removeTextListener(.Listener)
Case Else:
MsgBox ("removeListenersFromControls: " + .ListenerType + " not supported")
End Select
' .Control = Null ' For some reason mysterious to me, this causes an error
.ListenerType = ""
.Listener = Null
End With
next
End Sub |
Example Application
To run the following example, you need to create a dialog named "TestDialog" in a library named "TestLibrary". It must include the following controls:
Button named CommandButton1
Textbox named TextField1
Label named Label1
With the example code below, this dialog will pop up a message box when the button is clicked, and will set the text in the label to the text entered in the textbox. Woo-hoo.
Install the following code in a module "TestLibrary.Test" (or change the addListenerToControlInDialog calls to refer to wherever you put it).
| Code: | Dim oTestDialog as Variant
Dim oTestListenerAssignments
Sub StartTestDialog
oTestDialog = CreateUnoDialog (DialogLibraries.TestLibrary.TestDialog)
oTestListenerAssignments = newEventListenerAssignmentList(3)
addListenerToControlInDialog (oTestDialog, "TestLibrary.Test.", _
"CommandButton1", "com.sun.star.awt.XActionListener", oTestListenerAssignments)
addListenerToControlInDialog (oTestDialog, "TestLibrary.Test.", _
"TextField1", "com.sun.star.awt.XTextListener", oTestListenerAssignments)
oTestDialog.execute()
removeListenersFromControls (oTestListenerAssignments)
End Sub
Sub CommandButton1_actionPerformed (oEvent as Variant)
MsgBox("CommandButton1")
End Sub
Sub TextField1_textChanged (oEvent as Variant)
oTestDialog.Model.Label1.Label = oTestDialog.Model.TextField1.Text
End Sub |
Comments
As you may discover in the code, I initially wanted to automatically extend the list (array) of event listener records as each listener was added. But OOo Basic wasn't cooperating, and I had to fall back on pre-allocating an array and finding and using the first empty slot in it. (I couldn't be bothered to implement this as a linked list.) Hence the routine newEventListenerAssignmentList(), which you must call first to allocate a sufficiently long list to hold your listener assignments. It will complain if you exceed its size. Imperfect, but quite usable.
I invite comments or improvements to this. _________________ Rod Glover |
|