Hanya's MRI extension is an invaluable tool as an UNO object browser that will display properties, methods, interfaces and services relevant to any UNO object passed to it. It can readily be called by inserting a line into a macro. Often, however, I found I had a need to call MRI directly from a form document to check the properties, methods, interfaces and services applicable to a particular form or form control in that document.
To this end, and with essential help from Hanya, I have been using a routine that can be called whether the form document is in 'edit' or in 'direct' mode to display a form control tree similar to that used by the 'form navigator'. Double clicking the name of any form or form control shown in the list automatically runs MRI on the 'model' of that object and on its 'view' if the object has one. Unless the 'Auto close' box is checked the tree control remains open so that MRI can be run on other objects listed therein.
I store the module as a separate library under 'My Macros' and call its 'Main' routine from an icon added to the form document toolbar.
You use it at your own risk, but hopefully it should cause no damage as it only displays on the screen a tree control and one or more MRI results. Some routines at the end seem to be empty, but they must be included to prevent errors arising from the use of mouse and button event listeners. Please PM me if you find errors or have problems.
--------------------------------------------------------------
Edit 26 March 2011: Updated the code to include display of MRI scan of the 'View' of controls contained within a Grid control. Access to these View is only obtained through the View of the Grid Control and then using .GetByIndex to reach the View of the contained control, but never if the containing form document is in edit mode
--------------------------------------------------------------
Edit 26 Sep 2011: I have prepared a first draft of a User Guide for this macro that can be downloaded from https://www.dropbox.com/pri/get/Public/ ... c2nOMS5ORA.
--------------------------------------------------------------
Edits 11 Oct 2011, 30 June & 3 Jul 2012: Update code to access 'View' of columns in a Grid Control unless form document is in Edit Mode.
Code: Select all
REM ***** BASIC *****
REM Control Tree Code
REM ***** BASIC *****
REM I owe a debt of gratitude to Hanya for the Tree Control code as well as for the MRI extension.
REM All the remaining errors and bugs, however, are entirely my responsibility.
REM The Main macro can be run from a Form Document open (in either edit or run mode).
REM Best called from an icon added to the standard toolbar saved in the OOoBase:Form design
REM It displays a dialog similar to that of the Form Navigator. Double clicking any control on the
REM list will run MRI on that control's model and where available on its view. A single click will
REM select a control from the list and MRI can then be run by selecting the MRI button.
REM Unless the auto close check box has been selected, the dialog and Tree Control will remain
REM open to permit MRI to be run on further controls.
REM *******************************************************
Dim oDoc As Object
Dim oDocCtrl As Object
Dim oForms As Object
Dim oDialog As Object
Sub Main
oDoc = ThisComponent
oDocCtrl=oDoc.GetCurrentController()
If oDoc.supportsService("com.sun.star.text.TextDocument") Then
oForms = oDoc.getDrawPage().getForms()
ElseIf oDoc.supportsService("com.sun.star.sheet.SpreadsheetDocument") Then
' Spreadsheet needs problem about active sheet changing
oForms = oDoc.getCurrentController().getActiveSheet().getDrawPage().getForms()
Else MsgBox("This is neither a Writer nor a Calc document - Macro will abort",0) : Exit Sub
End If
' create dialog
oDialog = CreateUnoService("com.sun.star.awt.UnoControlDialog")
oDialogModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
oDialogModel.setPropertyValues( _
Array("Height", "PositionX", "PositionY", "Width","Title"), _
Array(200, 50, 50, 130, "Double Click to run MRI") )
oDialog.setModel(oDialogModel)
' AutoClose check box
oCheckModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlCheckBoxModel")
oCheckModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "State", "Width"), _
Array(13, "Auto Close", 1, 187, 1, 40))
oDialogModel.insertByName("AutoClose", oCheckModel)
' Close Button
oCloseBtnModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oCloseBtnModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "PushButtonType", "Width"), _
Array(13, "~Close", 94, 187, com.sun.star.awt.PushButtonType.CANCEL, 35))
oDialogModel.insertByName("CloseBtn", oCloseBtnModel)
' MRI Button
oMRIBtnModel = oDialogModel.createInstance("com.sun.star.awt.UnoControlButtonModel")
oMRIBtnModel.setPropertyValues(_
Array("Height", "Label", "PositionX", "PositionY", "PushButtonType", "Width"), _
Array(13, "~MRI", 58, 187, com.sun.star.awt.PushButtonType.STANDARD, 35))
oDialogModel.insertByName("MRIBtn", oMRIBtnModel)
' create tree control
oTreeModel = oDialogModel.createInstance("com.sun.star.awt.tree.TreeControlModel")
oTreeModel.setPropertyValues( _
Array("Height", "PositionX", "PositionY", "SelectionType", "ShowsRootHandles", "Width"), _
Array(186, 1, 1, com.sun.star.view.SelectionType.SINGLE, False, 128) )
oDialogModel.insertByName("Tree", oTreeModel)
oTree = oDialog.getControl("Tree")
oTreeDataModel = CreateUnoService("com.sun.star.awt.tree.MutableTreeDataModel")
' make new tree model structure
oTreeDataModel = CreateUnoService( _
"com.sun.star.awt.tree.MutableTreeDataModel")
' top node
oRootNode = oTreeDataModel.createNode("Forms", true)
oRootNode.setCollapsedGraphicURL("private:graphicrepository/res/sx18013.png")
oRootNode.setExpandedGraphicURL("private:graphicrepository/res/sx18013.png")
' set data to the root
oTreeDataModel.setRoot(oRootNode)
oTreeModel.DataModel = oTreeDataModel
AddChildren(oForms, oTreeDataModel, oRootNode)
oDialog.setVisible(True)
oButtonListener = CreateUnoListener("ButtonPush_", "com.sun.star.awt.XActionListener")
oMRIBtn = oDialog.getControl("MRIBtn").addActionListener(oButtonListener)
oTree.expandNode(oRootNode) ' expand after dialog visible
ExpandAllNodes(oTree, oRootNode)
oMouseListener = CreateUnoListener("Mouse_", "com.sun.star.awt.XMouseListener")
oTree.addMouseListener(oMouseListener)
oDialog.execute()
oTree.removeMouseListener(oMouseListener)
CloseDialog()
End Sub
Sub CloseDialog()
If oDialog.getControl("AutoClose").State = 1 Then
oDialog.endExecute()
Endif
End Sub
Function GetFormControl(oForms As Object, oNode As Object) As Object
Dim oControl As Object
Dim sNames() As String
While NOT IsNull(oNode)
n = UBound(sNames) +1
ReDim Preserve sNames(n)
sNames(n) = CStr(oNode.getDisplayValue())
oNode = oNode.getParent()
WEND
' find control
oControl = oForms
For i = UBound(sNames) -1 to 0 step -1
oControl = oControl.getByName(sNames(i))
Next
GetFormControl = oControl
End Function
Sub SelectControl(oForms As Object, oNode As Object) As Object
oControl = GetFormControl(oForms, oNode)
If IsNull(oControl) Then Exit Sub
oDoc.getCurrentController().select(oControl)
End Sub
Sub OpenWithMRI(oForms As Object, oControl As Object)
Globalscope.BasicLibraries.loadLibrary("MRILib")
oControl = GetFormControl(oForms, oControl)
If IsNull(oControl) Then Exit Sub
MRILib.Mri(oControl)
REM Routine to get view of controls within Grid control
if oControl.Parent.SupportsService("com.sun.star.form.component.GridControl") _
THEN GetView(oControl) : Exit Sub
REM Views not available for Hidden Controls, Forms or Sub-Forms
If oControl.SupportsService("com.sun.star.form.component.Form") OR _
oControl.SupportsService("com.sun.star.form.Forms") OR _
oControl.SupportsService("com.sun.star.form.component.HiddenControl") then Exit Sub
REM Document's Controller and Form Control's Model gives Form Control's View
oView = oDocCtrl.GetControl(oControl)
If NOT ISNULL(oView) then MRI oView
End Sub
Sub GetView(oControl) REM Required for controls within a Grid/Table control
IF oForms.Parent.CurrentController.isFormDesignMode() THEN Exit Sub REM Abort if Edit Mode
oGridView = oDocCtrl.GetControl(oControl.Parent).View
For i = 0 to oGridView.Count-1
If oGridView.GetByIndex(i).Model.Name = oControl.Name THEN
MRI oGridView.GetByIndex(i) REM MRI View of control in grid
End if
Next
End Sub
Sub Mouse_mousePressed(oEv As com.sun.star.awt.MouseEvent)
If oEv.Buttons = com.sun.star.awt.MouseButton.RIGHT Then
oTree = oEv.Source.getContext().getControl("Tree")
oNearNode = oTree.getClosestNodeForLocation(oEv.X,oEv.Y)
If IsNull(oNearNode) Then Exit Sub
aRect = CreateUnoStruct("com.sun.star.awt.Rectangle")
aRect.X = oEv.X + oTree.PosSize.X
aRect.Y = oEv.Y + oTree.PosSize.Y
oPopup = CreateUnoService("stardiv.vcl.PopupMenu")'"com.sun.star.awt.PopupMenu")
oPopup.insertItem(1, "Select", 0, 0)
oPopup.insertItem(2, "MRI", 0, 1)
oPopup.setCommand(1, "select")
oPopup.setCommand(2, "mri")
n = oPopup.execute(oTree.getContext().getPeer(), aRect, _
com.sun.star.awt.PopupMenuDirection.EXECUTE_DEFAULT)
If n > 0 Then
sCommand = oPopup.getCommand(n)
Select Case sCommand
Case "select"
SelectControl(oForms, oNearNode)
Case "mri"
OpenWithMRI(oForms, oNearNode)
End Select
CloseDialog()
End If
End If
End Sub
Sub Mouse_mouseReleased(oEv)
If oEv.Buttons = com.sun.star.awt.MouseButton.LEFT and oEv.ClickCount = 2 Then
oTree = oEv.Source.getContext().getControl("Tree")
oNearNode = oTree.getClosestNodeForLocation(oEv.X,oEv.Y)
If IsNull(oNearNode) Then Exit Sub
OpenWithMRI(oForms, oNearNode)
CloseDialog
End If
End Sub
Sub ButtonPush_actionPerformed(oEv As com.sun.star.awt.ActionEvent)
' get selected item
Dim oSelected() As Object
oTree = oEv.Source.getContext().getControl("Tree")
oSelected = oTree.getSelection()
If IsArray(oSelected) Then
Exit Sub
Else
OpenWithMRI(oForms, oSelected(0))
CloseDialog
End If
End Sub
Sub AddChildren( oContainer As Object, oDataModel As Object, oParent As Object )
For i = 0 To oContainer.getCount() - 1 step 1
oModel = oContainer.getByIndex(i)
sName = oModel.getName()
sImageURL = GetImageURL(oModel.getServiceName())
If HasUnoInterfaces(oModel, _
"com.sun.star.container.XContainer") Then
oChild = oDataModel.createNode(sName, true)
AddChildren(oContainer.getByName(sName), oDataModel, oChild)
Else
oChild = oDataModel.createNode(sName, false)
End If
oChild.setExpandedGraphicURL(sImageURL)
oChild.setCollapsedGraphicURL(sImageURL)
oParent.appendChild(oChild)
Next
End Sub
Sub ExpandAllNodes(oTree As Object, oParent)
For i = 0 To oParent.getChildCount() - 1 step 1
oChild = oParent.getChildAt(i)
oTree.expandNode(oChild)
If oChild.getChildCount() > 0 Then
ExpandAllNodes(oTree, oChild)
End If
Next
End Sub
Function GetImageURL(sServiceName As String) As String
Dim sName As String
sControlService = Mid(sServiceName, 28) 'stardiv.one.form.component.Form
sServices = Array(_
"CheckBox", "ComboBox", "CommandButton", _
"CurrencyField", "DateField", "Edit", "FileControl", _
"FixedText", "Form", "FormattedField", _
"Grid", "GroupBox", "HiddenControl", _
"ImageButton", "ImageControl", "ListBox", _
"NumericField", "PatternField", "RadioButton", _
"TextField", "TimeField", _
".NavigationToolBar", ".SpinButton", ".ScrollBar")
sNames = Array(_
"sx10596", "sx10601", "sx10594", _
"sx10707", "sx10704", "sx10599", "sx10605", _
"sx10597", "sx10593", "sx10728", _
"sx10603", "sx10598", "sx18022", _
"sx10604", "sx10710", "sx10600", _
"sx10706", "sx10708", "sx10595", _
"sx10599", "sx10705", _
"sx10607", "sx10769", "sx10768")
For i = 0 To UBound(sServices) step 1
If sServices(i) = sControlService Then
sName = sNames(i)
Exit For
End If
Next
GetImageURL = "private:graphicrepository/res/" & sName & ".png"
End Function
Sub Mouse_mouseEntered(ev)
End Sub
Sub Mouse_mouseExited(ev)
End Sub
Sub Mouse_disposing(ev)
End Sub
Sub ButtonPush_dispose(oEv)
End Sub