Create fancy custom toolbars with OOo Basic
Posted: Sat Apr 05, 2008 4:48 pm
Hi,
this code shows two examples for custom designed toolbars. These are just very simple examples, the methods shown allow you to have complete control over your toolbar items and make them as fancy as you want. You only need to know OO Basic.
The first example generates a toolbar with a simple drop down box, very similar e.g. to the standard font selection drop down box. Whenever the user changes the selection, a listener is called (CBOX_itemStateChanged). In its current version, it only adds a line to the first sheet in the calc document. Overwrite this method to implement your own needs.
The second example uses the standard OO dialog capabilities to show a non modal dialog in the toolbar. I use it with a simple dialog created on the fly, but it should also work with dialogs defined by the OO Basic dialog editor capabilities. With this technique, you can transform all OO dialogs into non modal toolbar dialogs
In order to run this
Have fun,
ms777
P.S. Thanks to Peter for his Toolbar routines http://www.oooforum.org/forum/viewtopic.phtml?t=50877
The main code:
The subroutines required:
this code shows two examples for custom designed toolbars. These are just very simple examples, the methods shown allow you to have complete control over your toolbar items and make them as fancy as you want. You only need to know OO Basic.
The first example generates a toolbar with a simple drop down box, very similar e.g. to the standard font selection drop down box. Whenever the user changes the selection, a listener is called (CBOX_itemStateChanged). In its current version, it only adds a line to the first sheet in the calc document. Overwrite this method to implement your own needs.
The second example uses the standard OO dialog capabilities to show a non modal dialog in the toolbar. I use it with a simple dialog created on the fly, but it should also work with dialogs defined by the OO Basic dialog editor capabilities. With this technique, you can transform all OO dialogs into non modal toolbar dialogs
In order to run this
- create a new calc document
- install the beanshell script listenercombiner.bsh from http://user.services.openoffice.org/en/ ... =21&t=4351 as outlined there.
- install the code in any module in the same document
- install the subroutines into any other module in the same document
- run the code
Have fun,
ms777
P.S. Thanks to Peter for his Toolbar routines http://www.oooforum.org/forum/viewtopic.phtml?t=50877
The main code:
Code: Select all
Global logRow
Global logSheet
Sub Main
'define the strings we need
toolbarResourceUrl = "private:resource/toolbar/custom_ms777"
toolbarUIName = "Combobox via interface combine"
itemLabel = "MyLabel"
itemCommandUrl = ".uno:ms777Combobox"
itemService = "ms777.ToolbarCombobox"
'for the logging ...
logRow = 0
logSheet = ThisComponent.sheets.getByIndex(0)
logSheet.getCellRangeByPosition(0,0,0,1000).clearContents(com.sun.star.sheet.CellFlags.STRING)
logMessage("Start")
'the to-be-combined interfaces XInitialization, XStatusListener, XUpdatable, XServiceInfo, XToolbarController
listXInitialization = createUnoListener("LGCB_","com.sun.star.lang.XInitialization")
listXUpdatable = createUnoListener("LGCB_","com.sun.star.util.XUpdatable")
listXToolbarController = createUnoListener("LGCB_","com.sun.star.frame.XToolbarController")
listXServiceInfo = createUnoListener("LGCB_","com.sun.star.lang.XServiceInfo")
listXStatusListener = createUnoListener("LGCB_","com.sun.star.frame.XStatusListener")
oScript = ThisComponent.getScriptProvider("").getScript("vnd.sun.star.script:listenercombiner.listenercombiner.bsh?language=BeanShell&location=document")
oScript.invoke(Array(itemService, listXInitialization, listXUpdatable, listXToolbarController, _
listXServiceInfo, listXStatusListener), Array(), Array())
call createToolbar(toolbarResourceUrl, toolbarUIName, itemLabel, itemCommandUrl, itemService)
logMessage("End")
End Sub
sub logMessage(sMessage as String)
logSheet.getCellByPosition(0,logRow).String = sMessage
logRow = logRow + 1
end sub
' here start the subs which are combined to form the toolbar window
'com.sun.star.lang.XInitialization
sub LGCB_initialize(args() as Any)
logMessage("initialize")
end sub
'com.sun.star.util.XUpdatable
sub LGCB_update()
logMessage("update")
end sub
'com.sun.star.lang.XServiceInfo
function LGCB_getImplementationName() as String
logMessage("getImplementationName")
LGCB_getImplementationName = "ms777.ToolbarCombobox"
end function
function LGCB_supportsService(s as String) as Boolean
logMessage("supportsService")
LGCB_supportsService = (s = "ms777.ToolbarCombobox")
end function
function LGCB_getSupportedServiceNames() as Any
logMessage("getSupportedServiceNames")
LGCB_getSupportedServiceNames = Array("ms777.ToolbarCombobox")
end function
'com.sun.star.frame.XStatusListener
sub LGCB_statusChanged(state as com.sun.star.frame.FeatureStateEvent)
logMessage("statusChanged")
end sub
sub LGCB_disposing(source as com.sun.star.lang.EventObject)
logMessage("disposing")
end sub
'com.sun.star.frame.XToolbarController
sub LGCB_execute(KeyModifier as integer)
logMessage("execute")
end sub
sub LGCB_click()
logMessage("click")
end sub
sub LGCB_doubleClick()
logMessage("doubleclick")
end sub
function LGCB_createPopupWindow() as com.sun.star.awt.XWindow
logMessage("createPopupWindow")
end function
function LGCB_createItemWindow(wParent as com.sun.star.awt.XWindow) as com.sun.star.awt.XWindow
logMessage("createItemWindow start")
LGCB_createItemWindow = generateCBOXWindow(wParent) 'for first example
'LGCB_createItemWindow = generateDialogWindow(wParent) 'for second example
logMessage("createItemWindow end")
end function
'-------------- first example: generate a combobox in the toolbar
' see my earlier post http://www.oooforum.org/forum/viewtopic.phtml?p=188664#188664
function generateCBOXWindow(wParent as com.sun.star.awt.XWindow) as com.sun.star.awt.XWindow
'the itemlistener, which is added to the toolbar combobox
listItemListener = createUnoListener("CBOX_", "com.sun.star.awt.XItemListener")
oWindow = makeAwtWindow(wParent, 0, 0, 230, 20, "combobox", com.sun.star.awt.WindowAttribute.SHOW or com.sun.star.awt.VclWindowPeerAttribute.DROPDOWN)
oWindow.addItemListener(listItemListener)
oWindow.setText("Enter Command Here")
oWindow.addItems(Array( "test", "foo", "bar", "test2", "foo2", "bar2" ), 0)
oWindow.setDropDownLineCount(6)
generateCBOXWindow = oWindow
end function
' the listener to get the combobox events back to OO Basic
sub CBOX_itemStateChanged(event as com.sun.star.awt.ItemEvent)
lSelected = event.selected
s = "selection change to item # " + lSelected
if lSelected >=0 then s = s & ": " & event.source.items(lSelected)
logMessage(s)
'xray event
end sub
'-------------- second example: hijack a normal OO Basic generated dialog
function generateDialogWindow(wParent as com.sun.star.awt.XWindow) as com.sun.star.awt.XWindow
oDialog = generateRadioButtonDialog(Array("first option", "longer option text", "even much more longer option text"))
wDialog = makeAwtWindow(wParent, 0, 0, oDialog.Size.width, oDialog.Size.height, "window", com.sun.star.awt.WindowAttribute.SHOW)
wDialog.Background = &HFF000000 'transparent
oControls = oDialog.Controls
for k=0 to UBound(oControls)
oControls(k).createPeer(wDialog.Toolkit, wDialog)
next k
generateDialogWindow = wDialog
end function
'generateRadioButtonDialog creates a dialog on the fly ...
'it expects an array of strings showing the options the user can select
'see http://www.oooforum.org/forum/viewtopic.phtml?p=205497#205497 for a standalone version
'and some (?) explanations
function generateRadioButtonDialog(astrOptions) as Any
Dim lTab as Long
const lDeltaFromEdge = 5 'controls spacing from the window edge and between controls
const lButtonWidth = 80
const lButtonHeight = 30
oActionListener = CreateUnoListener( "RBD_", "com.sun.star.awt.XActionListener" )
oDialogModel = createUnoService( "com.sun.star.awt.UnoControlDialogModel" )
oDialogControl = createUnoService( "com.sun.star.awt.UnoControlDialog" )
oDialogControl.setModel( oDialogModel )
lTab = 0
lRadioButtonMinHeight = -1
lRadioButtonMinWidth = -1
for k=0 to UBound(astrOptions) 'insert radio buttons and find out max height and width
oRadioButtonModel = oDialogModel.createInstance( "com.sun.star.awt.UnoControlRadioButtonModel" )
setNameTabLabel(oRadioButtonModel, "RB" & k, lTab, astrOptions(k))
oDialogModel.insertByName( oRadioButtonModel.Name, oRadioButtonModel )
PrefSize = oDialogControl.getControl( "RB" & k).PreferredSize
if PrefSize.Width > lRadioButtonMinWidth then lRadioButtonMinWidth = PrefSize.Width
if PrefSize.Height > lRadioButtonMinHeight then lRadioButtonMinHeight = PrefSize.Height
next k
for k=0 to UBound(astrOptions) 'set the size of the radiobutton controls, mark the first as set
oRadioButtonControl = oDialogControl.getControl( "RB" & k)
oRadioButtonControl.setPosSize(lDeltaFromEdge, lDeltaFromEdge*(k+1) + lRadioButtonMinHeight * k, lRadioButtonMinWidth, lRadioButtonMinHeight, com.sun.star.awt.PosSize.POSSIZE)
if (k=0) then oRadioButtonControl.State = True
next k
'insert the Accept Button
oButtonModel = oDialogModel.createInstance( "com.sun.star.awt.UnoControlButtonModel" )
setNameTabLabel(oButtonModel, "Accept", lTab, "Accept")
oDialogModel.insertByName( oButtonModel.Name, oButtonModel )
oButtonControl = oDialogControl.getControl( oButtonModel.Name )
oButtonControl.setPosSize(2*lDeltaFromEdge+lRadioButtonMinWidth, lDeltaFromEdge, lButtonWidth, lButtonHeight, com.sun.star.awt.PosSize.POSSIZE)
oButtonControl.addActionListener( oActionListener )
'now determine the size of the overall dialog
lDialogWidth = 3*lDeltaFromEdge + lRadioButtonMinWidth + lButtonWidth
lDialogHeight = (UBound(astrOptions)+1)*(lRadioButtonMinHeight+lDeltaFromEdge) + lDeltaFromEdge
oDialogControl.setPosSize( 0, 0, lDialogWidth, lDialogHeight, com.sun.star.awt.PosSize.POSSIZE)
generateRadioButtonDialog = oDialogControl
end function
sub setNameTabLabel(o, n as String, Tab as long, Label as String)
o.Name = n
o.TabIndex = Tab
o.Label = Label
Tab = Tab+1
end sub
Sub RBD_actionPerformed( oEvent As com.sun.star.awt.ActionEvent )
oDialogControl = oEvent.Source.Context
s = "Button " & oEvent.Source.Model.Name & " pressed"
oC = oDialogControl.Controls
for k=0 to UBound(oC)
if HasUnoInterfaces(oC(k), "com.sun.star.awt.XRadioButton") then
s = s & ", RadBut " & k & " state: " & oC(k).Model.State
endif
next k
logMessage(s)
end sub
The subroutines required:
Code: Select all
sub createToolbar(toolbarResourceUrl as String, toolbarUIName as String, itemLabel as String, _
itemCommandUrl as String, itemService as String)
'I heavily borrowed from Peter http://www.oooforum.org/forum/viewtopic.phtml?t=50877 when writing this
'register the itemService at the Toolbarfactory
oo = createUnoService("com.sun.star.frame.ToolbarControllerFactory")
if oo.hasController( itemCommandUrl, "") then oo.deregisterController( itemCommandUrl, "")
oo.registerController( itemCommandUrl, "", itemService)
'delete toolbar if existing
oLM = ThisComponent.CurrentController.Frame.Layoutmanager
if not IsNull(oLM.getElement(toolbarResourceUrl)) then oLM.destroyElement(toolbarResourceUrl)
'create toolbar
oLM.createElement(toolbarResourceUrl)
'insert one component into toolbar and set the UIName
oEL = oLM.getElement(toolbarResourceUrl)
oToolbarSettings = oEL.getSettings(true)
Dim aItem(1) as new com.sun.star.beans.PropertyValue
aItem(0).Name = "CommandURL"
aItem(0).Value = itemCommandUrl
aItem(1).Name = "Label"
aItem(1).Value = itemLabel
oToolbarSettings.insertByIndex( 0, aItem )
oToolbarSettings.UIName = toolbarUIName
oEL.setSettings(oToolbarSettings)
oEL.updateSettings
oLM.showElement(toolbarResourceUrl)
'make sure that the toolbar is docked in a separate new line in the docking area
cDockArea = com.sun.star.ui.DockingArea.DOCKINGAREA_TOP
Dim aPos as New com.sun.star.awt.Point
aPos.X = 0
aPos.Y = 0
oLM.dockWindow(toolbarResourceUrl,cDockArea,aPos)
end sub
function makeAwtWindow(wParent as com.sun.star.awt.XWindow, x as integer, y as integer, width as integer, height as integer, wServiceName as String, wAttribute as long) as com.sun.star.awt.XWindow
oToolkit = createUnoService("com.sun.star.awt.Toolkit")
' create WindowDescriptor
Dim rBounds as new com.sun.star.awt.Rectangle
rBounds.X = x
rBounds.Y = y
rBounds.width = width
rBounds.height = height
Dim wd as new com.sun.star.awt.WindowDescriptor
wd.Type = com.sun.star.awt.WindowClass.SIMPLE
'wd.Type = com.sun.star.awt.WindowClass.CONTAINER
wd.Parent = wParent
wd.Bounds = rBounds
wd.ParentIndex = -1
wd.WindowAttributes = wAttribute
wd.WindowServiceName = wServiceName
makeAwtWindow = oToolkit.createWindow(wd)
end function