just to start with the disclaimers:
- besides OO Basic, we need also a Beanshell Script
- it is limited to services implementing interfaces known to UNO
A complete explanation of the beanshell code (listenercombiner.bsh) would be too much. Good thing is: To use it, you do not have to understand it. listenercombiner expects one single parameter, which is an array. Its first element is a string with the service name, under which you want to register the created service. The following arguments are listeners generated by createUnoListener. The short OO Basic example uses only two very simple listeners, but you can expand to whatever number you want.
The generated UNO service then has all methods of the listener available as you can see by calling the methods or XRaying the object.
So what is this good for ? The reason I wrote this is that it allows you to gain complete design freedom over the custom toolbars using OO Basic only. In order to show self designed elements in the toolbar you have to implement an UNO service and register it with XUIControllerRegistration.registerController.
So stay tuned for some examples showing fancy toolbars ...
In order to run this
- for safety create a new calc document
- install listenercombiner.bsh into the documents beanshell code, using a library named also listenercombiner
- copy the basic code into some module in the same document.
Edit: Two examples are here: http://user.services.openoffice.org/en/ ... =21&t=4352
Edit May 26, 2008: I recently switched from OO 2.1 to OO 2.4 and found out that the beanshell code in this post does not work any longer. This is probably due to a change in the class loading happening in OO 2.3, which made the OO Beanshell incompatible with the 'normal' beanshell ( http://qa.openoffice.org/issues/show_bug.cgi?id=89978 ). In the next post, you find some code which works for OO2.3 (?) and certainly for OO 2.4.
The basic code:
Code: Select all
Sub Main
'the to-be-combined interfaces
listXNamed = createUnoListener("MS_", "com.sun.star.container.XNamed")
listXDialog = createUnoListener("MS_", "com.sun.star.awt.XDialog")
' run the beanshell script
oScript = ThisComponent.getScriptProvider("").getScript("vnd.sun.star.script:listenercombiner.listenercombiner.bsh?language=BeanShell&location=document")
oScript.invoke(Array("ms777.verysimpleservice", listXNamed, listXDialog), Array(), Array())
' create the service
oCombined = createUnoService("ms777.verysimpleservice")
' now play around...
xray oCombined
msgbox oCombined.getName()
oCombined.setName("New name")
oCombined.setTitle("new title")
msgbox oCombined.getTitle()
msgbox oCombined.execute()
oCombined.endExecute
end sub
'the interface com.sun.star.container.XNamed
function MS_getName() as String
msgbox "XNamed.getName called"
MS_getName = "Hi there ..."
end function
sub MS_setName(s as String)
msgbox "XNamed.setName called with " & s
end sub
'the interface com.sun.star.awt.XDialog
sub MS_setTitle(title as string)
msgbox "XDialog.setTitle called with " & title
end sub
function MS_getTitle() as string
msgbox "XDialog.getTitle called"
MS_getTitle = "some title here ..."
end function
function MS_execute() as integer
msgbox "XDialog.execute called"
MS_execute = 42
end function
sub MS_endExecute()
msgbox "XDialog.endExecute called"
end sub
Code: Select all
package ms77731;
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
xClassLoader = java.lang.ClassLoader.getSystemClassLoader();
try { xClass = xClassLoader.loadClass("ms77731.ListenerFactory");}
catch (ClassNotFoundException e) {
System.out.println( "compiling ...");
public class ListenerFactory extends ComponentBase implements XServiceInfo, XSingleComponentFactory {
Object[] _args = {};
String sServiceName = "";
public ListenerFactory(Object[] args) {
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 ) {
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;