Sat Jul 15 22:30:53 CEST 2006

OpenOffice.org menus and native menus

How menus work in practice in OpenOffice.org?

In this blog entry, I'll describe how native menus should work. For the description, I'll comment the source code of current aquavcl01 child workspace patched with my patch for menus. I do this because I need to clean up my notes and help also other people to understand what I have now and how to continue.

VCL is a deep magic :-) Too many classes, deep inheritance. I'll try to cast some light into our part and will describe the current status clearly (at least I hope so).

In the vcl's svdem (the file vcl/workben/svdem.cxx), we extend class WorkWindow (which itself extends SystemWindow which itself extends class Window ... OutputDevice ... Resource - now you know what I meant with "deep magic"):
class MyWin : public WorkWindow
{
public:
   MyWin( Window* pParent, WinBits nWinStyle );
   ...
   MenuBar   aMenuBar;
   PopupMenu aFileMenu;
   PopupMenu aEditMenu;
};
This means that our window will have one MenuBar (see declaration) and we will add two PopupMenus into it (see the declaration of PopupMenu).

menus File and Edit


In main, we instantiate the MyWin class in aMainWin window:
MyWin aMainWin( NULL, WB_APP | WB_STDWORK );
At this time, MenuBar and two PopupMenus are created. The method SalInstance::CreateMenu (AquaSalInstance::CreateMenu, see FIXME: link to ssa's document about native menus) is called with bMenuBar = TRUE for the MenuBar and twice with bMenuBar = FALSE for PopupMenus.

This means that both menu bar and top-level menus are SalMenu (in our case, AquaSalMenu) items and are created using the same method!

Now we have menu bar and two PopupMenu items created and can work with them.
aMainWin.aMenuBar.InsertItem( 1, XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
aMainWin.aMenuBar.InsertItem( 2, XubString( RTL_CONSTASCII_USTRINGPARAM( "Edit" ) ) );
We will insert two items into the menu bar aMenuBar - "File" (it will be item number 1) and "Edit" (item number 2). These are actually menu items - SalMenuItem (AquaSalMenuItems in our case; see the declaration of SalMenuItem). Notice, that "File" is not a menu, it is a menu item in the menu bar! This is important.
aMainWin.aMenuBar.SetPopupMenu( 1, &aMainWin.aFileMenu );
aMainWin.aMenuBar.SetPopupMenu( 2, &aMainWin.aEditMenu );
These two calls of SetPopupMenu method "connect" the menu items "File" and "Edit" of the menu bar with the actual sub-menus. Item number 1 in the menu bar aMenuBar is connected with the PopupMenu aFileMenu.

The first function call will call the method SetSubMenu with three arguments - the first one is the SalMenuItem representing "File", the second is the actual SalMenu which should be expanded when menu item "File" is clicked on. The third argument is the position in the native menu.

FIXME: I do not understand why we have to specify nPos here too, because the SalMenuItem already is inserted at some position in the menu bar. Isn't it thus redundant?
aMainWin.aFileMenu.InsertItem( 1, XubString( RTL_CONSTASCII_USTRINGPARAM( "Open" ) ));
aMainWin.aFileMenu.InsertItem( 2, XubString( RTL_CONSTASCII_USTRINGPARAM( "Close" ) ));
aMainWin.aFileMenu.InsertItem( 3, XubString( RTL_CONSTASCII_USTRINGPARAM( "Exit" ) ));
...
aMainWin.aEditMenu.InsertItem( 1, XubString( RTL_CONSTASCII_USTRINGPARAM( "Search" ) ));
aMainWin.aEditMenu.InsertItem( 2, XubString( RTL_CONSTASCII_USTRINGPARAM( "Replace" ) ));
We also have to fill actual sub-menus. Menu "File" will contain three entries "Open", "Close" and "Exit". Menu "Edit" will have two entries.

The method InsertItem is already described above. We will create three menu items - SalMenuItem (AquaSalMenuItems in our case) - and will insert them into the menu "File", and two into menu "Edit".
aMainWin.SetMenuBar( &aMainWin.aMenuBar );
At the end, we have to associate the menu bar with the window. This method will call SetMenu of the respective SalFrame object and do other stuff.

So this is the OpenOffice.org side of menus. I'll try to describe the Carbon side of the same soon so we see how to map it into the OpenOffice.org side :-)

Posted by Pavel | Permanent link | File under: OpenOffice.org