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