Ajout : Traduction de http://user.services.openoffice.org/en/ ... php?t=4352 :
Ceci est une traduction libre, elle se veut la plus précise et la plus claire possible mais n'est sans doute pas exempte de maladresses voire d'erreurs, vos corrections sont donc les bienvenues. Tout crédit revient à l'auteur original, ms777 du forum OpenOffice.org/en, merci à lui. (Remerciez le de ma part si vous avez un compte là bas !)
ms777 a écrit :Ce code montre 2 exemples de barre d'outils personnalisées. Ce sont des exemples simples, mais qui présentent des méthodes applicables pour rendre vos barres d'outils aussi complètes et sophistiquées que voulu.
Le premier exemple génère une barre d'outils contenant une simple Combobox. Lorsque l'utilisateur change la sélection, un listener est appelé (CBOX_itemStateChanged). La version actuelle ajoute juste une ligne sur la première feuille mais il suffit d'adapter cette partie du code pour arriver à vos fins.
Le second exemple montre qu'il est aussi possible d'utiliser dans une barre d'outils une boîte de dialogue (non modale ?) créée par macro ou via l'EDI.
Marche à suivre :
- Créer un nouveau document Calc
- Installer le script BeanShell "listenercombiner.bsh" : http://user.services.openoffice.org/en/ ... =21&t=4351
Outils > Macros > Gérer les macros > BeanShell...
Document actuel > Créer...
Nom de la nouvelle bibliothèque : "listenercombiner" > OK
listenercombiner > Créer...
Nom de la nouvelle macro : "listenercombiner" > OK
Coller le code ci-dessous à la place du contenu de la macro BeanShell dans la fenêtre qui s'ouvre (ctrl + A pour tout sélectionner) :
Code : Tout sélectionner package ms77705;
import com.sun.star.uno.Type;
import com.sun.star.uno.XInterface;
import com.sun.star.uno.XWeak;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.AnyConverter;
import com.sun.star.uno.Any;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uno.IQueryInterface;
import com.sun.star.lang.XTypeProvider;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lang.XSingleServiceFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XInitialization;
import com.sun.star.container.XSet;
import com.sun.star.container.XContentEnumerationAccess;
import com.sun.star.container.XEnumeration;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.lib.uno.helper.ComponentBase;
import java.util.Vector;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.SecurityException;
import java.lang.NoSuchMethodException;
// This prevents an error message when executing the script a second time
// The following two lines were working in OO 2.1
//xClassLoader = java.lang.ClassLoader.getSystemClassLoader();
//try { xClass = xClassLoader.loadClass("ms77731.ListenerFactory");}
// These two lines now work in OO 2.3 (?), OO 2.4
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
try { Class.forName("ms77705.ListenerFactory");}
catch (ClassNotFoundException e) {
System.out.println( "compiling ...");
public class ListenerFactory extends ComponentBase implements XServiceInfo, XSingleComponentFactory {
Object[] _args = {};
String sServiceName = "";
public ListenerFactory(Object[] args) {
System.out.println( "ms777Listener constr _args: "+_args);
System.out.println( "ms777Listener constr _args.len: "+_args.length);
sServiceName = AnyConverter.toString(args[0]);
_args = args;
for (i=0;i<_args.length;i++) { System.out.println( "ms777Listener constr _args: "+_args[i]); }
}
//XServiceInfo
public boolean supportsService( String sService ) { return ( sService.equals( sServiceName)); }
public String getImplementationName() { return sServiceName; }
public String[] getSupportedServiceNames() {
String[] retValue= new String[] {sServiceName};
return retValue;
}
//XSingleComponentFactory
public Object createInstanceWithContext(XComponentContext Context ) {
System.out.println( "ms777listener createInstanceWithContext");
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
ListenerCombination lc = new ListenerCombination(_args);
return lc.getProxy();
}
public Object createInstanceWithArgumentsAndContext(Object[] args, XComponentContext Context ) {
System.out.println( "ms777listener createInstanceWithContextAndArgs");
Object oProxy = createInstanceWithContext(Context);
XInitialization xi = UnoRuntime.queryInterface(XInitialization.class, oProxy);
if (!(xi==null)) xi.initialize(args);
return oProxy;
}
public class ListenerCombination extends ComponentBase {
Type[] _aType = {};
byte[] _implementationId = {};
Object[] _args = {};
Object oProxy = null;
ListenerCombination LF = null;
XInterface[] _argInterface = {};
InvocationHandler IH = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) {
System.out.println( "invoke start: method: " + method);
Class[] parameterTypes = method.getParameterTypes();
String name = method.getName();
Method m = null;
for (int iIF = -1; iIF < _argInterface.length; iIF++) {
Object OF = LF;
if (iIF>=0) OF = _argInterface[iIF];
try {
m = OF.getClass().getMethod(name, parameterTypes);
} catch (NoSuchMethodException nse) { }
catch (SecurityException se) { System.out.println("security exception");}
if (m!=null) {
Object oReturn = m.invoke(OF, args);
System.out.println( "invoke end success: OF: " + OF + ", returned: " + oReturn);
return oReturn;
}
}
System.out.println( "invoke end: returned null");
return null;
};
};
public ListenerCombination(Object[] args) {
super();
LF = this;
System.out.println( "in Constructor: superClass: " + getClass().getSuperclass());
_argInterface = new XInterface[args.length-1];
for (int k=1; k < args.length; k++) {
Type t = new Type(args[k].getType().getTypeName());
_argInterface[k-1] = UnoRuntime.queryInterface(t, args[k]);
System.out.println( "in Constructor: _argInterface: " + _argInterface[k-1]);
}
Class[] aInterfaces = new Class[_argInterface.length+3];
aInterfaces[0] = XComponent.class;
aInterfaces[1] = XWeak.class;
aInterfaces[2] = XTypeProvider.class;
for (k=0; k < _argInterface.length; k++) {
Class c = _argInterface[k].getClass().getInterfaces()[0];
System.out.println( "in Constructor: added Class: " + c );
aInterfaces[k+3] = c;
}
_aType = new Type[aInterfaces.length];
for (k=0; k < aInterfaces.length; k++) _aType[k] = new Type(aInterfaces[k]);
byte[] ab = super.getImplementationId();
_implementationId = new byte[ab.length+_argInterface.length];
for (int k=0; k < ab.length; k++) _implementationId[k] = ab[k];
for (int k=0; k < _argInterface.length; k++) _implementationId[k+ab.length] = (byte)(_argInterface.getClass().hashCode() & 0xff);
oProxy = Proxy.newProxyInstance(getClass().getClassLoader(), aInterfaces, IH);
}
public Object getProxy() { return oProxy; }
public Type[] getTypes() { return _aType; }
public byte[] getImplementationId() { return _implementationId; }
} // end of class ListenerCombination
}// end of class ListenerFactory
} // of try ClassNotFoundException
System.out.println( "after try ClassNotFoundException" );
Object TA = new ListenerFactory(ARGUMENTS);
//
//-------------------- create and register a factory for your class
//
System.out.println( "create and register factories start");
XComponentContext Context = XSCRIPTCONTEXT.getComponentContext();
xSM = Context.getValueByName("/singletons/com.sun.star.lang.theServiceManager");
xSMSet = UnoRuntime.queryInterface(XSet.class, xSM);
XContentEnumerationAccess xSMContEnum = UnoRuntime.queryInterface(XContentEnumerationAccess.class, xSM);
System.out.println( "create and register factories start 1, xSMContEnum: " + xSMContEnum);
String sService = AnyConverter.toString(ARGUMENTS[0]);
XEnumeration xEnum = (XEnumeration) xSMContEnum.createContentEnumeration(sService);
if (!(xEnum==null)) {
for( ; xEnum.hasMoreElements(); ) {
Object el = xEnum.nextElement();
xSMSet.remove(el);
System.out.println( "create and register factories: removed one service with name: " + sService);
}
}
xSMSet.insert(TA);
System.out.println( "create and register factories end");
return;
- Coller le code ci-dessous dans n'importe quel module Basic (Outils > Macros > Gérer les macros > OpenOffice.org Basic...) du document actuel :
Code : Tout sélectionner 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
Et enfin collez le code ci-dessous dans n'importe quel autre module Basic du document actuel :
Code : Tout sélectionner 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
Lancez la macro "Main" pour créer la barre d'outils, puis faites des tests !
Pour alterner entre les deux exemples, changer le contenu du sub LGCB_createItemWindow en suivant les instructions en commentaire.
Ces instructions produisent le fichier en pièce jointe.
Il m'a aussi été nécessaire de remplacer le fichier C:\Program Files\OpenOffice.org 3\Basis\program\classes\bsh.jar par le fichier original http://www.beanshell.org/bsh-2.0b4.jar pour éviter un message d'erreur récurrent, mais je crois bien que c'était suite à une fausse manipulation.
J'ai testé le premier exemple, ça marche bien. Même sans comprendre la majorité du code il est assez facile de l'adapter à ses besoins pour peu qu'on ait de bonnes notions de OOo Basic.
Bravo à spYre pour avoir découvert cette solution chez nos amis anglophones, et bon courage à Mobydick_62 pour la suite !
PS : je n'ai pas traduit le code et ne le ferais pas, mais je peux encore traduire les commentaires si le besoin s'en fait sentir.
PS2 : à l'origine je pensais qu'une solution existait via l'interface d'OpenOffice, je ne m'attendais pas à une solution mettant en oeuvre des macros ; il faudra probablement déplacer ce message vers une catégorie plus appropriée... |