From Apache OpenOffice Wiki
< API‎ | Samples‎ | Groovy
Jump to: navigation, search

About the Runtime Dialog Groovy Example

This is an example demonstrates creating a UNO Dialog and features use of XMultiPropertySet via a UNOCategory API helper. It based on the code in Documentation/DevGuide/Basic/Creating_Dialogs_at_Runtime.

The Code

import com.sun.star.awt.ActionEvent
import com.sun.star.awt.XButton
import com.sun.star.awt.XControl
import com.sun.star.awt.XControlContainer
import com.sun.star.awt.XControlModel
import com.sun.star.awt.XDialog
import com.sun.star.awt.XFixedText
import com.sun.star.awt.XToolkit
import com.sun.star.awt.XWindow
import com.sun.star.beans.XMultiPropertySet
import com.sun.star.beans.XPropertySet
import com.sun.star.container.XNameContainer
import com.sun.star.lang.EventObject
import com.sun.star.lang.XComponent
import com.sun.star.lang.XMultiComponentFactory
import com.sun.star.lang.XMultiServiceFactory
import com.sun.star.uno.UnoRuntime
import com.sun.star.uno.XComponentContext
import com.sun.star.awt.Rectangle
import com.sun.star.awt.WindowAttribute
import com.sun.star.awt.XThrobber
import com.sun.star.awt.XProgressBar
import com.sun.star.container.XIndexAccess
// Groovy script
/** method for creating a dialog at runtime */
class UnoCategory {
    public static Object uno(Object unoObj, Class clazz) { UnoRuntime.queryInterface(clazz, unoObj) }
    public static Object getAt(XPropertySet pset, String pname) { pset.getPropertyValue(pname) }
    public static void putAt(XPropertySet pset, String pname, Object newValue)
    { pset.setPropertyValue(pname, newValue) }
    public static Object getAt(XIndexAccess ndx, int x) { ndx.getByIndex(x) }
    public static void setMultiPropertySet(Object unoObj, Map properties)
        XMultiPropertySet pMSet = unoObj.uno(XMultiPropertySet)
        // Nasty hack to workaround problem when setting Height in the same setPropertyValues
        // call as other properties.
        // You also have to set Width after PositionX, fortunately the default for a map
        // literal in Groovy happens to be LinkedHashMap so the order of the keys is preserved.
        // If that weren't the case we'd have to deal with that here too.
        if ((properties.size() > 1) && properties.containsKey('Height')) {
            String[] propNames = ((properties.keySet() as List) - ['Height']) as String[]
            Object[] values = new Object[propNames.length]
            propNames.eachWithIndex { String n, int x -> values[x] = properties.get(n) }
            pMSet.setPropertyValues(propNames, values)
            // We use setProertyValues rather than setPropertyValue because it is probably
            // more performant than making the two UNO calls that would require.
            pMSet.setPropertyValues(['Height'] as String[], [properties.get('Height')] as Object[])
//            System.out.println("setMultiPropertySet-Height $propNames $values ${properties.get('Height')} ")
        } else {
            String[] propNames = properties.keySet() as String[]
            Object[] values = new Object[propNames.length]
            propNames.eachWithIndex { String n, int x -> values[x] = properties.get(n) }
            pMSet.setPropertyValues(propNames, values)
//            System.out.println("setMultiPropertySet $propNames $values ${pMSet instanceof XMultiPropertySet} ")
    public static XNameContainer leftShift(XNameContainer container, Map values)
//        System.out.println "leftShifting $values"
        values.each { name, value -> container.insertByName(name, value) }
        return container
/** action listener */
public class CountActionListenerImpl implements com.sun.star.awt.XActionListener
    XFixedText label
    String labelPrefix
    XProgressBar progressBar
    private int _nCounts = 0;
    // XEventListener
    public void disposing(EventObject eventObject)
//        System.out.println('CountActionListener disposing.')
        label = null
        progressBar = null
    // XActionListener
    public void actionPerformed(ActionEvent actionEvent)
        System.out.println('CountActionListener actionPerformed.')
        // increase click counter
        label.setText(labelPrefix + _nCounts);
        progressBar.value = (progressBar.value + 1) % 10
public class CancelActionListenerImpl implements com.sun.star.awt.XActionListener
    private XDialog dialog;
    // XEventListener
    public void disposing(EventObject eventObject)
//        System.out.println('CancelActionListener disposing.')
        dialog = null;
    // XActionListener
    public void actionPerformed(ActionEvent actionEvent)
        System.out.println('CancelActionListener ending execution.')
 This method creates a UNO modal dialog, fills it in, and return the object (com.sun.star.awt.UnoControlDialog).
 It must be called in the context of a use(UNOCategory).
Object createDialog(XComponentContext _xComponentContext) throws com.sun.star.uno.Exception
    final String _buttonName = 'Button1'
    final String _labelName = 'Label1'
    final String _labelPrefix = 'Counts : '
    final String _cancelButtonName = 'CancelButton1'
    final String _editName = 'Edit1'
    final String _throbberName = 'Throbber1'
    // get the service manager from the component context
    XMultiComponentFactory xMultiComponentFactory = _xComponentContext.getServiceManager();
    // create the dialog model and set the properties
    Object dialogModel = xMultiComponentFactory.createInstanceWithContext(
            "com.sun.star.awt.UnoControlDialogModel", _xComponentContext);
    // Can't set x/y and width/height at same time.
    // Just set width/height at let OOo pick the x/y.
    // This doesn't work to make dialog window resizable (it is moveable & closeable by default).
    dialogModel.multiPropertySet = [Width:150, Height:200, Title:'Runtime Dialog Demo'
        , Closeable: true, Moveable:true, Sizeable:true]
    // get the service manager from the dialog model
    XMultiServiceFactory xMultiServiceFactory = dialogModel.uno(XMultiServiceFactory)
    // create the button model and set the properties
    // This button gets the 0th TabIndex because it is the default button.
    // But just setting TabIndex doesn't seem to do the job for the default.
    // Apparently it is the first button added to the container.
    Object cancelButtonModel = xMultiServiceFactory.createInstance('com.sun.star.awt.UnoControlButtonModel')
    cancelButtonModel.multiPropertySet = [PositionX:90, PositionY:10, Width:50, Height:14
        , Name:_cancelButtonName, TabIndex:0, Label:"Cancel"]
    // create the button model and set the properties
    Object buttonModel = xMultiServiceFactory.createInstance('com.sun.star.awt.UnoControlButtonModel')
    buttonModel.multiPropertySet = [PositionX:10, PositionY:10, Width:50, Height:14
            , Name:_buttonName, TabIndex:1, Label:"Stop!"]
    // create the label model and set the properties
    Object labelModel = xMultiServiceFactory.createInstance('com.sun.star.awt.UnoControlFixedTextModel')
    labelModel.multiPropertySet = [PositionX:10, PositionY:30, Width:60, Height:14
        , Name:_labelName, TabIndex:3, Label:_labelPrefix]
    Object editModel = xMultiServiceFactory.createInstance('com.sun.star.awt.UnoControlEditModel')
    editModel.multiPropertySet = [PositionX:5, PositionY:45, Width:140, Height:150, Border:2 as Short /* Simple */
        , Name:_editName, TabIndex:2
        , HScroll:true, VScroll:true, MultiLine:true
        , LineEndFormat:2 as Short /* LINE_FEED */
        , Text:'This is some initial text.\nAnother line.\nFinis.']
    // create the label model and set the properties
    Object throbberModel = xMultiServiceFactory.createInstance('com.sun.star.awt.UnoControlProgressBarModel')
    throbberModel.multiPropertySet = [PositionX:80, PositionY:30, Width:60, Height:14
        , Name:_throbberName, TabIndex:4
        , ProgressValue:0, ProgressValueMin:0, ProgressValueMax:9]
    // insert the control models into the dialog model
    XNameContainer xNameCont = dialogModel.uno(XNameContainer)
    // Add the default button (Cancel) first.
    xNameCont.insertByName(_cancelButtonName, cancelButtonModel)
    xNameCont.insertByName(_buttonName, buttonModel)
    xNameCont.insertByName(_labelName, labelModel)
    xNameCont.insertByName(_editName, editModel)
    xNameCont.insertByName(_throbberName, throbberModel)
    // This is another way to use UnoCategory to do the above, but the syntax is a bit odd and adds some overhead.
//    dialogModel.uno(XNameContainer) <<
//        [(_buttonName):buttonModel, (_labelName):labelModel, (_cancelButtonName):cancelButtonModel]
    // create the dialog control and set the model
    Object dialog = xMultiComponentFactory.createInstanceWithContext(
            "com.sun.star.awt.UnoControlDialog", _xComponentContext);
    XControl xControl = dialog.uno(XControl)
    XDialog xDialog = dialog.uno(XDialog)
    // add an action listener to the button control
    XControlContainer xControlCont = dialog.uno(XControlContainer)
            new CountActionListenerImpl(label:xControlCont.getControl(_labelName).uno(XFixedText)
                    , labelPrefix:_labelPrefix
                    , progressBar:xControlCont.getControl(_throbberName).uno(XProgressBar)));
            new CancelActionListenerImpl(dialog:xDialog));
    // This doesn't seem to serve any purpose...
//    XWindow xWindow = xControl.uno(XWindow)
//    xWindow.setVisible(false);
//    This doesn't work to make dialog window resizable.
//    Short flags = (WindowAttribute.BORDER | WindowAttribute.MOVEABLE
//        | WindowAttribute.SIZEABLE | WindowAttribute.CLOSEABLE)
//    Rectangle posSize = xWindow.getPosSize()
//    xWindow.setPosSize(posSize.X, posSize.Y, posSize.Width, posSize.Height, flags)
    // create a peer
    Object toolkit = xMultiComponentFactory.createInstanceWithContext(
            "com.sun.star.awt.Toolkit", _xComponentContext);
    XToolkit xToolkit = toolkit.uno(XToolkit)
    xControl.createPeer(xToolkit, null);
    return dialog;
use (UnoCategory) {
    Object dialog = createDialog(XSCRIPTCONTEXT.componentContext)
    // execute the dialog, which won't return until it is closed.
    System.out.println('xDialog.execute has returned!')
    // we can put it up there again if we like.
    System.out.println('xDialog.execute has returned again!')
    // dispose the dialog
Personal tools