Re: Dynamic menus: with Java (Problem)

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic menus: with Java (Problem)

Carsten Driesner
Andrej Golovko wrote:

> Hi.
>
> I have a problem when trying to add custom menus to
> the OO 2.0 with Java.
>
> I've translated the Basic-based example from
> http://www.oooforum.org/forum/viewtopic.phtml?t=18491&highlight=
> into Java. It works only to some extent. The place
> with the problem is marked with the "PROBLEM" keyword
> in the code. Short: a custom submenu is not shown,
> something like the separator is shown insteed. The
> submenu is show under certain condition, this is
> mentioned in the code.

Hi Andrej,

I looked over your example and I am not sure what you want to do. Can
you please explain what do you want to achieve? Create a new top-level
menu or do you want to add a popup menu into an existing top-level menu,
like "File"?

One comment to your example. Please NEVER create a settings container
using a ui configuration manager and insert it into another container. A
container which is created by a ui configuration manager is always a
root container! Every container itself is a factory to create its own
sub containers. The referenced example in oooforum is wrong in that point!

Regards,
Carsten

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic menus: with Java (Problem)

Christoph Lutz
Hi Carsten,

thank you for answering the question of Andrej who is a colleague of
mine. I am continuing the work with Andrej's code.

> I looked over your example and I am not sure what you want to do. Can
> you please explain what do you want to achieve? Create a new top-level
> menu or do you want to add a popup menu into an existing top-level menu,
> like "File"?

For our own UNO-Component we would like to create a *new* top-level
menu that is able to contain either simple-Elements (Type.BUTTON) AND
nested Sub-Menus.

>
> One comment to your example. Please NEVER create a settings container
> using a ui configuration manager and insert it into another container. A
> container which is created by a ui configuration manager is always a
> root container! Every container itself is a factory to create its own
> sub containers. The referenced example in oooforum is wrong in that point!

I think this hint points us to the root of our problems, as we
currently always use the ModuleUIConfigurationManager to create new
settings-instances even for sub containers. I am trying to change
this, but I can't find the corresponding entry point. So which is the
access point for us to create new sub containers?

If my interpretation your statement above is correct, you say that
each settings-instance provides a corresponding factory for sub
containers. So I xray'ed an existing settings object, which I got
using the following basic-lines, but the object doesn't export an
Interface that seems to me the right one:

sMenuBar = "private:resource/menubar/menubar"
oModel = ThisComponent
oLayoutManager = oModel.getCurrentController().getFrame().LayoutManager()
oMenuBar = oLayoutManager.getElement( sMenuBar )
settings = oMenuBar.getSettings(true)

settings supports the following Interfaces:
com.sun.star.beans.XFastPropertySet
com.sun.star.beans.XMultiPropertySet
com.sun.star.beans.XPropertySet
com.sun.star.container.XElementAccess
com.sun.star.container.XIndexAccess
com.sun.star.container.XIndexContainer
com.sun.star.container.XIndexReplace
com.sun.star.lang.XSingleComponentFactory
com.sun.star.lang.XTypeProvider
com.sun.star.lang.XUnoTunnel
com.sun.star.uno.XInterface

Is it the XSingleComponentFactory I have to use to create the sub
containers? Just to write a quick test-example in basic: How can I
create a instance using basic? settings.createInstance() didn't work
and I don't know how to get the required XComponentContext in Basic to
call the settings.createInstanceWithContext()-Method.

best regards,
Christoph

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic menus: with Java (Problem)

Carsten Driesner
In reply to this post by Carsten Driesner
Christoph Lutz wrote:
> Hi Carsten,
>
> Is it the XSingleComponentFactory I have to use to create the sub
> containers? Just to write a quick test-example in basic: How can I
> create a instance using basic? settings.createInstance() didn't work
> and I don't know how to get the required XComponentContext in Basic to
> call the settings.createInstanceWithContext()-Method.
>
Hi Christoph,

Please look at the following example in Basic. It uses the function
CreatePopupMenu to create a new popup menu. The line of interest uses
the factory (the container) to create a sub container with
createInstanceWithContext().

Factory.createInstanceWithContext( GetDefaultContext() )

Example:
--------

Sub Main
        REM *** Creates a top-level popup menu on the Writer menu bar persistently.
        REM *** It checks if its popup menu has already been added to the menu bar
        REM *** and does nothing.
        REM *** The popup menu contains one menu item which call the Basic
macro test.

        REM *** Initialize strings
        sMenuBar = "private:resource/menubar/menubar"
        sMyPopupMenuCmdId = "vnd.openoffice.org:MyMenu"
       
        REM *** Retrieve the module configuration manager from central module
configuration manager supplier
        oModuleCfgMgrSupplier =
createUnoService("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")

        REM *** Retrieve the module configuration manager with module identifier
        REM *** See com.sun.star.frame.ModuleManager for more information
        oModuleCfgMgr = oModuleCfgMgrSupplier.getUIConfigurationManager(
"com.sun.star.text.TextDocument" )
        oMenuBarSettings = oModuleCfgMgr.getSettings( sMenuBar, true )
       
        REM *** Look for our top-level popup menu. Can be identified by the
CommandURL property.
        bHasAlreadyPopupMenu = false
        nCount = oMenuBarSettings.getCount()
        for i = 0 to nCount-1
                oPopupMenu() = oMenuBarSettings.getByIndex( i )
                nPopupMenuCount = ubound(oPopupMenu())
                for j = 0 to nPopupMenuCount
                        if oPopupMenu(j).Name = "CommandURL" then
                                if oPopupMenu(j).Value = sMyPopupMenuCmdId then
                                        bHasAlreadyPopupMenu = true
                                end if
                        endif
                next j
        next i
       
        MsgBox bHasAlreadyPopupMenu

        if not bHasAlreadyPopupMenu then
                sString = "My Macro's"
                oPopupMenu = CreatePopupMenu( sMyPopupMenuCmdId, sString,
oMenuBarSettings )
                oPopupMenuContainer = oPopupMenu(3).Value
                oMenuItem = CreateMenuItem( "macro:///Standard.Module1.Test()",
"Standard.Module1.Test" )
                oPopupMenuContainer.insertByIndex( 0, oMenuItem )
                oMenuBarSettings.insertByIndex( nCount, oPopupMenu )
                oModuleCfgMgr.replaceSettings( sMenuBar, oMenuBarSettings )
        end if
End Sub

Function CreatePopupMenu( CommandId, Label, Factory ) as Variant
        Dim aPopupMenu(3) as new com.sun.star.beans.PropertyValue

        aPopupMenu(0).Name = "CommandURL"
        aPopupMenu(0).Value = CommandId
        aPopupMenu(1).Name = "Label"
        aPopupMenu(1).Value = Label
        aPopupMenu(2).Name = "Type"
        aPopupMenu(2).Value = 0
        aPopupMenu(3).Name = "ItemDescriptorContainer"
        aPopupMenu(3).Value = Factory.createInstanceWithContext(
GetDefaultContext() )

        CreatePopupMenu = aPopupMenu()
End Function

Function CreateMenuItem( Command as String, Label as String ) as Variant
        Dim aMenuItem(2) as new com.sun.star.beans.PropertyValue

        aMenuItem(0).Name = "CommandURL"
        aMenuItem(0).Value = Command
        aMenuItem(1).Name = "Label"
        aMenuItem(1).Value = Label
        aMenuItem(2).Name = "Type"
        aMenuItem(2).Value = 0

    CreateMenuItem = aMenuItem()
End Function

Sub Test
   MsgBox( "Test" )
End Sub

Regards,
Carsten

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic menus: with Java (Problem)

Christoph Lutz
Hi Carsten,

sorry for the late answer, I was very busy during the last weeks...


2005/11/17, Carsten Driesner <[hidden email]>:
>
> Please look at the following example in Basic. It uses the function
> CreatePopupMenu to create a new popup menu. The line of interest uses
> the factory (the container) to create a sub container with
> createInstanceWithContext().


thank you for the example code. It works very well.

I would like to mention a behaviour I just noticed: the new created
popupmenu will not be restored after an restart of OOo, so there is no
persistence like described in your code comment... But I asume it was your
intention not to call the oModuleCfgMgr.store() method after the line "
oModuleCfgMgr.replaceSettings( sMenuBar, oMenuBarSettings )"? For my tests,
I added the respective line to your example-code.

But now to my question: I translated your example to java (I tried to do an
exaxt one-to-one-translation of your basic-example) and the java-code
bahaves slightly differt from the basic code: In basic, the popupmenu and
all elements are visible directly after calling the code. Using my
java-code, the popupmenu is created, but the element(s) in the popupmenu are
not visible. The strange thing is, that after the call of
oModuleCfgMgr.store() and a restart of OOo, the popupmenu and all its
previously unvisible item(s) get visible. Do you have got an idea, why the
items are not visible directly after creation, while the same code in basic
creates visible items? I think this might be a bug...

If you would like to follow, here's my translated java-code:

import com.sun.star.beans.PropertyValue;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.container.XIndexAccess;
import com.sun.star.container.XIndexContainer;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.ui.ItemType;
import com.sun.star.ui.XModuleUIConfigurationManagerSupplier;
import com.sun.star.ui.XUIConfigurationManager;
import com.sun.star.ui.XUIConfigurationPersistence;
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;

public class MenubarTest {

    public static void main(String[] args) throws java.lang.Exception {
        addItemToMenubar(Bootstrap.bootstrap());
        System.exit(0);
    }

    /**
     * Creates a top-level popup menu on the Writer menu bar persistently.
It
     * checks if its popup menu has already been added to the menu bar and
does
     * nothing. The popup menu contains one menu item which call the Basic
macro
     * test.
     *
     * @throws Exception
     */
    public static void addItemToMenubar(XComponentContext ctx)
            throws java.lang.Exception {

        // Initialize strings
        String sMenuBar = "private:resource/menubar/menubar";
        String sMyPopupMenuCmdId = "vnd.openoffice.org:MyMenu";

        // Retrieve the module configuration manager from central module
        // configuration manager supplier
        Object oModuleCfgMgrSupplier = ctx
            .getServiceManager().createInstanceWithContext(
                "com.sun.star.ui.ModuleUIConfigurationManagerSupplier",
ctx);
        XModuleUIConfigurationManagerSupplier xModuleUICfgMgrSupplier =
(XModuleUIConfigurationManagerSupplier) UnoRuntime
            .queryInterface(
                XModuleUIConfigurationManagerSupplier.class,
                oModuleCfgMgrSupplier);

        // Retrieve the module configuration manager with module
        // identifier
        // See com.sun.star.frame.ModuleManager for more information
        XUIConfigurationManager xModuleUICfgMgr = xModuleUICfgMgrSupplier
            .getUIConfigurationManager("com.sun.star.text.TextDocument");
        XIndexAccess oMenuBarSettings = xModuleUICfgMgr.getSettings(
            sMenuBar, true);
        XIndexContainer settingsContainer = (XIndexContainer) UnoRuntime
            .queryInterface(XIndexContainer.class, oMenuBarSettings);
        XSingleComponentFactory factory = (XSingleComponentFactory)
UnoRuntime
            .queryInterface(XSingleComponentFactory.class,
oMenuBarSettings);

        // Look for our top-level popup menu. Can be identified by the
        // CommandURL property.
        boolean bHasAlreadyPopupMenu = false;
        int nCount = oMenuBarSettings.getCount();
        for (int i = 0; i < nCount; ++i) {
            PropertyValue[] oPopupMenu = (PropertyValue[]) oMenuBarSettings
                .getByIndex(i);
            for (int j = 0; j < oPopupMenu.length; ++j) {
                if (oPopupMenu[j].Name.equals("CommandURL")) {
                    if (oPopupMenu[j].Value.equals(sMyPopupMenuCmdId)) {
                        bHasAlreadyPopupMenu = true;
                    }
                }
            }
        }

        System.out.println(bHasAlreadyPopupMenu);

        if (!bHasAlreadyPopupMenu) {
            String sString = "My Macro's";

            PropertyValue[] oPopupMenu = CreatePopupMenu(
                sMyPopupMenuCmdId, sString, factory, ctx);
            XIndexContainer oPopupMenuContainer = (XIndexContainer)
UnoRuntime
                .queryInterface(XIndexContainer.class, oPopupMenu[3].Value);

            PropertyValue[] oMenuItem = CreateMenuItem(
                "macro:///Standard.Module1.Test()", "Standard.Module1.Test
");
            oPopupMenuContainer.insertByIndex(0, oMenuItem);

            settingsContainer.insertByIndex(nCount, oPopupMenu);

            xModuleUICfgMgr.replaceSettings(sMenuBar, oMenuBarSettings);

            // make ist persistent (additional lines by clutz):
            XUIConfigurationPersistence xModuleUICfgMgrPers =
(XUIConfigurationPersistence) UnoRuntime
                .queryInterface(
                    XUIConfigurationPersistence.class, xModuleUICfgMgr);
            xModuleUICfgMgrPers.store();
        }

    }

    public static PropertyValue[] CreatePopupMenu(String commandID,
            String label, XSingleComponentFactory factory, XComponentContext
ctx)
            throws Exception {
        PropertyValue[] aPopupMenu = new PropertyValue[] { new
PropertyValue(),
                new PropertyValue(), new PropertyValue(), new
PropertyValue() };

        aPopupMenu[0].Name = "CommandURL";
        aPopupMenu[0].Value = commandID;
        aPopupMenu[1].Name = "Label";
        aPopupMenu[1].Value = label;
        aPopupMenu[2].Name = "Type";
        aPopupMenu[2].Value = new Integer(ItemType.DEFAULT);
        aPopupMenu[3].Name = "ItemDescriptorContainer";
        aPopupMenu[3].Value = factory.createInstanceWithContext(ctx);

        return aPopupMenu;
    }

    public static PropertyValue[] CreateMenuItem(String command, String
label) {
        PropertyValue[] aMenuItem = new PropertyValue[] { new
PropertyValue(),
                new PropertyValue(), new PropertyValue() };

        aMenuItem[0].Name = "CommandURL";
        aMenuItem[0].Value = command;
        aMenuItem[1].Name = "Label";
        aMenuItem[1].Value = label;
        aMenuItem[2].Name = "Type";
        aMenuItem[2].Value = new Integer(ItemType.DEFAULT);

        return aMenuItem;
    }
}


best regards,
Christoph
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic menus: with Java (Problem)

Carsten Driesner
In reply to this post by Carsten Driesner
Christoph Lutz wrote:

Hi Christoph,

> thank you for the example code. It works very well.
>
> I would like to mention a behaviour I just noticed: the new created
> popupmenu will not be restored after an restart of OOo, so there is no
> persistence like described in your code comment... But I asume it was your
> intention not to call the oModuleCfgMgr.store() method after the line "
> oModuleCfgMgr.replaceSettings( sMenuBar, oMenuBarSettings )"? For my tests,
> I added the respective line to your example-code.

Your are right I forgot to add the oModuleCfgMgr.store() call.

>
> But now to my question: I translated your example to java (I tried to do an
> exaxt one-to-one-translation of your basic-example) and the java-code
> bahaves slightly differt from the basic code: In basic, the popupmenu and
> all elements are visible directly after calling the code. Using my
> java-code, the popupmenu is created, but the element(s) in the popupmenu are
> not visible. The strange thing is, that after the call of
> oModuleCfgMgr.store() and a restart of OOo, the popupmenu and all its
> previously unvisible item(s) get visible. Do you have got an idea, why the
> items are not visible directly after creation, while the same code in basic
> creates visible items? I think this might be a bug...

I looked over your example and I cannot see an obviously problem. Please
give some days to check wants wrong here. I will let you know when I
have more information. It's possible that this might be a bug, although
OOo only uses this API internally for customization.

Regards,
Carsten

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]