How to insert tab pages to a dialog using Java?

Java, C++, C#, Delphi... - Using the UNO bridges
Post Reply
terabyte
Posts: 2
Joined: Fri Dec 26, 2014 10:08 am

How to insert tab pages to a dialog using Java?

Post by terabyte »

As a beginner I am using Java to create a UNO dialog with a number of tab pages. However, when I insert a UnoControlTabPageModel to its container, UnoControlTabPageContainerModel, I get a SIGSEV (see code and SIGSEV output below). I use Libreoffice + SDK 4.2.7 and a netbeans Apache Openoffice 4.0.6 plugin.

My question is: does anybody know how to successfully create a dialog with tab pages in Java? (Examples exist for Python and Basic (e.g., here), however, for this project I really need to use Java).

The SIGSEV occurs when I execute:

Code: Select all

xTabPageContainerModel.insertByIndex(0, oTabPageModel);
giving the following stacktrace (complete output attached):

Code: Select all

j  com.sun.star.bridges.jni_uno.JNI_proxy.dispatch_call(JLjava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;+0
j  com.sun.star.bridges.jni_uno.JNI_proxy.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+146
j  com.sun.proxy.$Proxy18.insertByIndex(ILjava/lang/Object;)V+23
j  com.kuijper.BTGUI.insertTabPage(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIS)Ljava/lang/Object;+176
j  com.kuijper.ConfigDialog.<init>(Lcom/sun/star/uno/XComponentContext;)V+49
j  com.kuijper.BibTexLib.dispatch(Lcom/sun/star/util/URL;[Lcom/sun/star/beans/PropertyValue;)V+40

a larger sample of the code is listed below (while the full file is on pastebin):

Code: Select all

// create a TabPage model using the dialog's
// MultiServiceFactory, which is contained in m_xMSFDialog
Object oTabPageModel = m_xMSFDialog.createInstance(
        "com.sun.star.awt.tab.UnoControlTabPageModel"
    );

// get the tab page model's interface, so that we can set certain
// properties to the TabPageModel
XTabPageModel xTabPageModel = (XTabPageModel)
        UnoRuntime.queryInterface(XTabPageModel.class,oTabPageModel);

// set properties of the tab page using XMultiPropertySet
XMultiPropertySet xTabPageMPSet = (XMultiPropertySet)
        UnoRuntime.queryInterface(
                XMultiPropertySet.class,
                xTabPageModel
        );

// set the actual properties
// strangely, setting properties such as ToolTip, while mentioned in the API docs
// results in an exception, so I am only setting the title property here
// http://www.openoffice.org/api/docs/common/ref/com/sun/star/awt/tab/XTabPageModel.html
xTabPageMPSet.setPropertyValues(
        new String[]{
            "Title"
        },
        new Object[]{
            new String("the title")
        });

// We also have to get the interface to the TabPageContainerModel
// as this contains the function InsertByIndex
XTabPageContainerModel xTabPageContainerModel = 
        (XTabPageContainerModel) UnoRuntime.queryInterface(
                XTabPageContainerModel.class, oTabPageContainerModel
        );

// add the model to the container
// Here, the SIGSEV occurs:
xTabPageContainerModel.insertByIndex(0, oTabPageModel);
Attachments
hs_err_pid8052.log
(121.59 KiB) Downloaded 278 times
LibreOffice 4.2.7.2 420m0(Build:2) on Ubuntu 14.04
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: How to insert tab pages to a dialog using Java?

Post by hanya »

Hi, welcom to this forum.

You have some troubles in createDialog method, but I can not tell what is wrong.
I can add the tab control on the dialog instantiated by css.awt.DialogProvider service even in Java. When I hack your code to use DialogProvider service to generate the dialog, the code worked well. I used the way to create dialog by instantiating css.awt.UnoControlDialogModel and UnoControlDialog services but I met some problems with that and I switched to use the DialogProvider. I have empty.xdl file that contains only dialog itself in some extension package and I use it as base dialog to construct something on it.

You are creating the page from the multiservice factory of the dialog model but use the following way to create new page:

Code: Select all

		XComponentContext xContext = xScriptContext.getComponentContext();
		XDialog xDialog = createDialog(xContext, "vnd.sun.star.script:Standard.Dialog1?location=application");
		if (xDialog == null) return;
		XControlModel xDialogModel = UnoRuntime.queryInterface(XControl.class, xDialog).getModel();
		XMultiServiceFactory xMsf = UnoRuntime.queryInterface(XMultiServiceFactory.class, xDialogModel);
		try {
			XNameContainer xNameContainer = UnoRuntime.queryInterface(XNameContainer.class, xDialogModel);
			
			Object tabPagesModel = xMsf.createInstance("com.sun.star.awt.tab.UnoControlTabPageContainerModel");
			xNameContainer.insertByName("tab", tabPagesModel);
			XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, tabPagesModel);
			xPropSet.setPropertyValue("Width", 100);
			xPropSet.setPropertyValue("Height", 100);
			
			XTabPageContainerModel xTabPagesModel = UnoRuntime.queryInterface(XTabPageContainerModel.class, tabPagesModel);
			
			XTabPageModel xTabPageModel1 = xTabPagesModel.createTabPage((short) 1);
			xTabPageModel1.setTitle("Page 1");
			xTabPagesModel.insertByIndex(0, xTabPageModel1);
			XTabPageModel xTabPageModel2 = xTabPagesModel.createTabPage((short) 2);
			xTabPageModel2.setTitle("Page 2");
			xTabPagesModel.insertByIndex(1, xTabPageModel2);
com.sun.star.awt.tab.XTabPageContainerModel interface provides createTabPage method to instantiate new page. This is the newer way than the way you are using.

Even you can make the tab control on the dialog, the tab page is not shown on LibreOffice 4.0 - 4.3 (I do not know about later version). It seems this is the bug but I have never seen the issue about it. It works well on Apache OpenOffice 3.4 -.

If you want to use tab control on LO, there is another implementation as com.sun.star.awt.UnoMultiPageModel service. I have used it on MRI extension.
I tried to write an example in Java but LO 4.3.4.1 failed to find Java macro on my environment to test myself. I wrote the following example in BeanShell, the code is not so different from the code written in Java.

Code: Select all

import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.beans.NamedValue;
import com.sun.star.awt.XControl;
import com.sun.star.awt.XControlModel;
import com.sun.star.awt.XControlContainer;
import com.sun.star.awt.XSimpleTabController;
import com.sun.star.awt.XDialog;
import com.sun.star.awt.XDialogProvider;
import com.sun.star.awt.tab.XTabPageContainerModel;
import com.sun.star.awt.tab.XTabPageModel;
import com.sun.star.beans.XPropertySet;
import com.sun.star.container.XNameContainer;
import com.sun.star.document.XDocumentInsertable;
import com.sun.star.frame.XController;
import com.sun.star.frame.XModel;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;

XComponentContext xContext = XSCRIPTCONTEXT.getComponentContext();
XMultiComponentFactory xMcf = xContext.getServiceManager();


Object oDialogProvider = xMcf.createInstanceWithContext("com.sun.star.awt.DialogProvider", xContext);
XDialogProvider xDialogProvider = UnoRuntime.queryInterface(XDialogProvider.class, oDialogProvider);
XDialog xDialog = xDialogProvider.createDialog("vnd.sun.star.script:Standard.Dialog1?location=application");

XControlModel xDialogModel = UnoRuntime.queryInterface(XControl.class, xDialog).getModel();
XMultiServiceFactory xMsf = UnoRuntime.queryInterface(XMultiServiceFactory.class, xDialogModel);
XNameContainer xNameContainer = UnoRuntime.queryInterface(XNameContainer.class, xDialogModel);

// On LibreOffice 4.0 - 4.3, css.awt.tab.UnoControlTabPageContainerModel service does not work well.
isAOO = true;
String tabServiceName = isAOO ? "com.sun.star.awt.tab.UnoControlTabPageContainerModel" : "com.sun.star.awt.UnoMultiPageModel";
String sTabControlName = "tab";
Object tabPagesModel = xMsf.createInstance(tabServiceName);
xNameContainer.insertByName(sTabControlName, tabPagesModel);
XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, tabPagesModel);
xPropSet.setPropertyValue("Width", 100);
xPropSet.setPropertyValue("Height", 100);

if (isAOO) {
    // AOO 3.4 -
    XTabPageContainerModel xTabPagesModel = UnoRuntime.queryInterface(XTabPageContainerModel.class, tabPagesModel);
    
    // Create new tab page through XTabPageContainerModel interface
    XTabPageModel xTabPageModel1 = xTabPagesModel.createTabPage((short) 1);
    xTabPageModel1.setTitle("Page 1");
    xTabPagesModel.insertByIndex(0, xTabPageModel1);
    XTabPageModel xTabPageModel2 = xTabPagesModel.createTabPage((short) 2);
    xTabPageModel2.setTitle("Page 2");
    xTabPagesModel.insertByIndex(1, xTabPageModel2);
} else {
    // LO 4 -
    XControlContainer xControlContaienr = UnoRuntime.queryInterface(XControlContainer.class, xDialog);
    XControl xTabPagesControl = xControlContaienr.getControl(sTabControlName);
    XSimpleTabController xTabController = UnoRuntime.queryInterface(XSimpleTabController.class, xTabPagesControl);
    XNameContainer xTabPageNameContainer = UnoRuntime.queryInterface(XNameContainer.class, tabPagesModel);
    
    // New page created through multi service factory of the dialog
    Object pageModel1 = xMsf.createInstance("com.sun.star.awt.UnoPageModel");
    xTabPageNameContainer.insertByName("page_1", pageModel1);
    NamedValue v = new NamedValue("Title", "Page 1");
    xTabController.setTabProps(1, new NamedValue[]{v});
    
    Object pageModel2 = xMsf.createInstance("com.sun.star.awt.UnoPageModel");
    xTabPageNameContainer.insertByName("page_2", pageModel2);
    NamedValue v = new NamedValue("Title", "Page 2");
    xTabController.setTabProps(2, new NamedValue[]{v});
}

xDialog.execute();

return 0;
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
terabyte
Posts: 2
Joined: Fri Dec 26, 2014 10:08 am

Re: How to insert tab pages to a dialog using Java?

Post by terabyte »

Hi Hanya,

many thanks for looking into this! I created an empty .xdl file by going to Tools > Macros > Organize Dialogs > Selecting Standard > New > setting name as 'Dialog1' > Save. After that, your second example worked like a charm in LibreOffice 4.2.7 as I got a working dialog with tab pages. Great!

Regarding the first piece of code, I filed a bug report as it is indeed not displaying any tabs in Libreoffice. See bug report https://bugs.freedesktop.org/show_bug.cgi?id=87884, in case you would like to comment on it.

Again, many thanks for your quick response!
LibreOffice 4.2.7.2 420m0(Build:2) on Ubuntu 14.04
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: How to insert tab pages to a dialog using Java?

Post by hanya »

I found the reason of the crash while inserting the new page by insertByIndex method. The reason is the peer of the dialog was not created before new page insertion. Create the peer of the dialog before adding new tab page into the tab pages container.
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
Post Reply