Write own Toolbars in Python
Posted: Sun Sep 04, 2022 11:10 am
Hi all,
the code below allows you do insert custom designed items into the toolbar. As an example, it inserts two selection boxes and one slider into the toolbar.
This is a rework of some beanshell / basic code in the old forum. If you are interested in the old code, KamiKanda attached it to a post on LO https://ask.libreoffice.org/t/toolbar-w ... -etc/70337. With Python, everything goes much easier
I run it in Visual Studio Code for fast design. The other method is to put it e.g. as toolbar.py into your user script folder (C:\Users\ms777\AppData\Roaming\OpenOffice\4\user\Scripts\python on my computer), and Execute Macro from a calc document, select the function doitAll. There is a wrapper around the main code, which detects if the code is called from VS Code or from a living calc document, and sets some globals accordingly.
Have fun,
ms777
AO 4.1.6 in Win10
the code below allows you do insert custom designed items into the toolbar. As an example, it inserts two selection boxes and one slider into the toolbar.
This is a rework of some beanshell / basic code in the old forum. If you are interested in the old code, KamiKanda attached it to a post on LO https://ask.libreoffice.org/t/toolbar-w ... -etc/70337. With Python, everything goes much easier
I run it in Visual Studio Code for fast design. The other method is to put it e.g. as toolbar.py into your user script folder (C:\Users\ms777\AppData\Roaming\OpenOffice\4\user\Scripts\python on my computer), and Execute Macro from a calc document, select the function doitAll. There is a wrapper around the main code, which detects if the code is called from VS Code or from a living calc document, and sets some globals accordingly.
Have fun,
ms777
AO 4.1.6 in Win10
Code: Select all
import uno
import unohelper
from subprocess import Popen
from com.sun.star.util import XUpdatable # type:ignore
from com.sun.star.frame import XToolbarController # type:ignore
from com.sun.star.frame import XStatusListener # type:ignore
from com.sun.star.lang import XInitialization # type:ignore
from com.sun.star.awt import Point # type:ignore
from com.sun.star.awt import XItemListener # type:ignore
from com.sun.star.awt import XAdjustmentListener # type:ignore
from com.sun.star.beans import PropertyValue # type:ignore
# define ctx, doc, smgr for (i) invocation from VS Code or (ii) invocation from OO execute macro
if __name__ == '__main__':
# invocation from VS Code
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
# start OO
lo_proc = Popen('"C:\Program Files (x86)\OpenOffice 4\program\soffice.exe" -accept=socket,host=localhost,port=2002;urp;', shell=True)
ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
doc = desktop.loadComponentFromURL('private:factory/scalc', '_default', 0, ())
elif __name__ == 'ooo_script_framework':
# invocation from OO execute macro
doc = XSCRIPTCONTEXT.getDocument() # type: ignore
ctx = XSCRIPTCONTEXT.getComponentContext() # type: ignore
smgr = ctx.ServiceManager
else:
raise Exception('__name__ is unknown: ' + __name__)
def xray(target):
global ctx
mspf = ctx.ServiceManager.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", ctx)
script_provider = mspf.createScriptProvider("")
script = script_provider.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application")
script.invoke((target,), (), ())
def logMessage(mes):
global logSheet
global logRow
logSheet.getCellByPosition(0,logRow).String = mes
logRow += 1
# wParent: uno.com.sun.star.awt.XWindow
# x, y, width, height: int
# wServiceName: str
# wAttribute: long
# returns -> uno.com.sun.star.awt..XWindow
def makeAwtWindow(wParent, x, y, width, height, wServiceName, wAttribute):
global smgr
global ctx
oToolkit = smgr.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
# create WindowDescriptor
wd = uno.createUnoStruct("com.sun.star.awt.WindowDescriptor")
wd.Type = uno.getConstantByName("com.sun.star.awt.WindowClass.SIMPLE")
wd.Parent = wParent
wd.Bounds = uno.createUnoStruct("com.sun.star.awt.Rectangle", x, y, width, height)
wd.ParentIndex = -1
wd.WindowAttributes = wAttribute
wd.WindowServiceName = wServiceName
return oToolkit.createWindow(wd)
def TestAwt():
global doc
parentWindow = doc.CurrentController.Frame.ContainerWindow
wAttribute = uno.getConstantByName("com.sun.star.awt.WindowAttribute.SHOW") | uno.getConstantByName("com.sun.star.awt.WindowClass.TOP")
oWindow = makeAwtWindow(parentWindow, 100, 100, 300, 200, "combobox", wAttribute)
oWindow.setBackground(0XFF00FF)
class ToolbarItem(unohelper.Base, XInitialization, XUpdatable, XToolbarController, XStatusListener):
def __init__( self, ctx, propModuleIdentifier, propFrame, propServiceManager, propParentWindow, propIdentifier, propCommandUrl ):
self.sCommandUrl = propCommandUrl.Value
print('in ToolbarItem constructor: ' + self.sCommandUrl)
return
# com.sun.star.lang.XInitialization
def initialize(self, args):
logMessage("initialize " + self.sCommandUrl)
# com.sun.star.util.XUpdatable
def update(self):
logMessage("update " + self.sCommandUrl)
# com.sun.star.frame.XStatusListener
def statusChanged(self, state):
logMessage("statusChanged " + self.sCommandUrl)
# com.sun.star.frame.XToolbarController
def execute(self, KeyModifier):
logMessage("execute " + self.sCommandUrl)
def click(self):
logMessage("click " + self.sCommandUrl)
def doubleClick(self):
logMessage("doubleclick " + self.sCommandUrl)
def createPopupWindow(self):
logMessage("createPopupWindow " + self.sCommandUrl)
return None
def createItemWindow(self, wParent):
pass
class ToolbarItemComboBox(ToolbarItem, XItemListener):
asOptions = ()
sText = ""
def createItemWindow(self, wParent):
logMessage("createItemWindow start " + self.sCommandUrl)
wAttribute = uno.getConstantByName("com.sun.star.awt.WindowAttribute.SHOW") | uno.getConstantByName("com.sun.star.awt.VclWindowPeerAttribute.DROPDOWN")
oWindow = makeAwtWindow(wParent, 0, 0, 230, 20, "combobox", wAttribute)
oWindow.addItemListener(self)
oWindow.setText(self.sText)
oWindow.addItems(self.asOptions, 0)
oWindow.setDropDownLineCount(6)
logMessage("createItemWindow end " + self.sCommandUrl)
return oWindow
def itemStateChanged(self, event):
self.lSelected = event.Selected
s = "selection change to item # " + str(self.lSelected)
if self.lSelected >= 0:
s = s + ": " + event.Source.getItem(self.lSelected)
s = s + ', ' + self.sCommandUrl
logMessage(s)
class ToolbarItemComboBox2(ToolbarItemComboBox):
pass
class ToolbarItemSchrollbar(ToolbarItem, XAdjustmentListener):
def createItemWindow(self, wParent):
logMessage("createItemWindow start " + self.sCommandUrl)
wAttribute = uno.getConstantByName("com.sun.star.awt.WindowAttribute.SHOW")
oWindow = makeAwtWindow(wParent, 0, 0, 230, 20, "scrollbar", wAttribute)
oWindow.addAdjustmentListener(self)
oWindow.setOrientation(uno.getConstantByName("com.sun.star.awt.ScrollBarOrientation.HORIZONTAL"))
oWindow.setValues(50, 10, 100)
logMessage("createItemWindow end " + self.sCommandUrl)
return oWindow
def adjustmentValueChanged(self, event):
s = "schrollbar changed to " + str(event.Value) + ', ' + self.sCommandUrl
logMessage(s)
def createToolbar(toolbarResourceUrl, toolbarUIName):
# delete toolbar if existing
oLM = doc.CurrentController.Frame.LayoutManager
if oLM.getElement(toolbarResourceUrl) is not None:
oLM.destroyElement(toolbarResourceUrl)
# create toolbar
oLM.createElement(toolbarResourceUrl)
oEL = oLM.getElement(toolbarResourceUrl)
oToolbarSettings = oEL.getSettings(True)
oToolbarSettings.UIName = toolbarUIName
oEL.setSettings(oToolbarSettings)
# dock the toolbar in the docking area. Not sure if necessary.
oLM.dockWindow(toolbarResourceUrl, uno.getConstantByName('com.sun.star.ui.DockingArea.DOCKINGAREA_TOP'), Point(0, 0))
def insertToolbarItems(toolbarResourceUrl, aItem):
# register the itemService at the Toolbarfactory
oo = smgr.createInstanceWithContext("com.sun.star.frame.ToolbarControllerFactory", ctx)
oLM = doc.CurrentController.Frame.LayoutManager
oEL = oLM.getElement(toolbarResourceUrl)
oToolbarSettings = oEL.getSettings(True)
for Item in aItem:
if oo.hasController( Item.itemCommandUrl, ""):
oo.deregisterController( Item.itemCommandUrl, "")
oo.registerController( Item.itemCommandUrl, "", Item.itemService)
prop1 = PropertyValue()
prop1.Name = "CommandURL"
prop1.Value = Item.itemCommandUrl
prop2 = PropertyValue()
prop2.Name = "Label"
prop2.Value = Item.itemLabel
uno.invoke( oToolbarSettings, "insertByIndex", (oToolbarSettings.Count, uno.Any("[]com.sun.star.beans.PropertyValue", (prop1, prop2))))
oEL.setSettings(oToolbarSettings)
def doItAll():
global logSheet
global logRow
print('Hallo')
#for the logging ...
logRow = 0
logSheet = doc.Sheets.getByIndex(0)
logSheet.getCellRangeByPosition(0,0,0,1000).clearContents(uno.getConstantByName('com.sun.star.sheet.CellFlags.STRING'))
#
logMessage('Hallo')
TestAwt()
xSM = ctx.getValueByName("/singletons/com.sun.star.lang.theServiceManager")
toolbarResourceUrl = "private:resource/toolbar/custom_ms777"
toolbarUIName = "toolbarUIName ms777"
ToolbarItemComboBox.asOptions = ( "test", "foo", "bar", "test2", "foo2", "bar2" )
ToolbarItemComboBox.sText = "Combo Box 1"
ToolbarItemComboBox.itemLabel = "LabelCombobox 1"
ToolbarItemComboBox.itemCommandUrl = ".uno:ms777Combobox"
ToolbarItemComboBox.itemService = "ms777.ToolbarCombobox"
ToolbarItemComboBox.itemServiceImpl = "ms777.impl.ToolbarCombobox"
ToolbarItemComboBox2.asOptions = ( "option A", "Karl Heinz")
ToolbarItemComboBox2.sText = "Combo Box 2"
ToolbarItemComboBox2.itemLabel = "LabelCombobox 2"
ToolbarItemComboBox2.itemCommandUrl = ".uno:ms777Combobox2"
ToolbarItemComboBox2.itemService = "ms777.ToolbarCombobox2"
ToolbarItemComboBox2.itemServiceImpl = "ms777.impl.ToolbarCombobox2"
ToolbarItemSchrollbar.itemLabel = "Label Scrollbar"
ToolbarItemSchrollbar.itemCommandUrl = ".uno:ms777Scrollbar"
ToolbarItemSchrollbar.itemService = "ms777.ToolbarScrollbar"
ToolbarItemSchrollbar.itemServiceImpl = "ms777.impl.ToolbarScrollbar"
# prop1 = PropertyValue()
# prop1.Name = "CommandURL"
# prop1.Value = itemComboBoxCommandUrl
# xt = ssf.createInstanceWithArgumentsAndContext((1, 2, 3, 4, 5, prop1), ctx)
# xray(xt)
# xray(xSM)
createToolbar(toolbarResourceUrl, toolbarUIName)
for Item in (ToolbarItemComboBox, ToolbarItemComboBox2, ToolbarItemSchrollbar):
ssf = unohelper.createSingleServiceFactory( Item, Item.itemServiceImpl, (Item.itemService,) )
xSM.insert(ssf)
insertToolbarItems(toolbarResourceUrl, (ToolbarItemComboBox, ToolbarItemComboBox2, ToolbarItemSchrollbar))
if __name__ == '__main__':
doItAll()
lo_proc.wait() # when run from VS code, better wait until AO is finished. Otherwise, some calls goto nowhere ...