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).
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 :-)