Menu API Enhancement
The current Menu API lacks of several features, which are important from an extension developer's point of view. In the following we propose an attempt to enhance this API, by extending it with new interfaces providing the desired features.
You can get an idea of the current state of the Menu API by reading the relevant specification:
The following diagram (not really an UML one) pictures the current state of the Menu API:
With the red color, we picture the fact that
- com.sun.star.awt.XMenuExtended is not derived from com.sun.star.awt.XMenu, which is a none sense, since XMenuExtended is an extension of XMenu, and it is should be derived from XMenu; this has the drawback that if you have an XMenuExtended reference, and you want to use XMenu's methods, you need to query for this interface.
- com.sun.star.awt.XMenuExtended is not defined to be implemented by com.sun.star.awt.MenuBar and com.sun.star.awt.PopupMenu; this is a side effect of the rule that published services cannot implement unpublished interfaces.
- on one hand, this can be considered a documentation issue, as it has the (may be not very important) drawback that if you study the Menu API starting from the services you use to instantiate the objects, you may end up not realizing this XMenuExtended interface (this is a general problem with the API design, for example if you start from com.sun.star.ucb.SimpleFileAccess, you may never know that it implements the com.sun.star.ucb.XSimpleFileAccess3 ); also the other way around: if some day you face XMenuExtended, and select "use" on the top the interface reference page, you will find that there is (in theory) no use of it.
- on the other hand, this is also an usability issue (as we, API clients, are the API users): XMenuBar and XPopupMenu should have been derived from XMenuExtended (and this in turn from XMenu), as XMenuExtended describes extended features available both for MenuBar and PopupMenu. In the current state, if you have an XPopupMenu or an XMenuBar reference, and you want to use these extended menu functions, you have to query another reference to XMenuExtended, and so have to work with two different references of the same object.
Not visible from the specification, but as implementation issues, we can mention:
- com.sun.star.lang.XServiceInfo is not implemented in VCLXMenu (not so tragic...)
- in the way that com.sun.star.uno.XInterface and com.sun.star.lang.XTypeProvider are implemented in VCLXMenu, this has - for both a scripting language like OOo Basic and strong typed languages like Java/C++ - the drawback that a MenuBar object implements also all PopupMenu related methods, and vice versa [you can try this by instantiating these objects by they service name and querying their interfaces], what is obviously a nonsense (although internally the implementation cares for checking the type of object).
The enhanced Menu API should take care of this situation, providing not only an extended API, but an easy to use one (read: by querying the interface implemented by the PopupMenu, the API client should be able to invoke all the methods that are in fact available for this object, that is the specific and also the generic ones, available for both MenuBar and PopupMenu).
Extended Menu API
In our proposal, we try to achive this goal by introducing three new interfaces:
The idea is that if you need to use all the generic methods available for both PopupMenu and MenuBar, you only need an XMenuExtended2 reference; if you need to use all the methods available for a PopupMenu you query for XPopupMenuExtended; and in the case of a MenuBar, you query for XMenuBarExtended.
In a "perfect world", we shouldn't need to create new interfaces (like those awful XSomething1, XSomething2, ...) just to add methods that in a good design would belong to already existing interfaces: in such cases, one should be able to add a method just by specifying with the @since tag since when this method is available in this interface; but this is another problem, and should be discussed somewhere else.
Any way, in the current state of the API rules, we can get rid of all issues, as the extended API opens the new issue that XMenu::getPopupMenu() returns an XPopupMenu reference, that should be queried for its XPopupMenuExtended interface.
New features preview
Instead of describing the abstract specification, a visual preview will give a better idea of the extended Menu API features.
The following picture can be consider a typical "BEFORE and AFTER" as we see on commercials:
As seen in the picture above, the PopupMenu can now have a logo, that is drawn with a background gradient. Although this feature is not used in OOo (and extensions developers should try to follow OOo's look&feel in order to have a coherent user interface), the AWT API describes an abstract specification [if this is really true, or it just describes OOo implementation, is another topic], so the extended Menu API bring this feature leaving to the implementer (better said, client developer) the choice to follow OOo l&f.
A KeyEvent can be assigned to a PopupMenu item. This will only draw in the menu item, the localized text corresponding to it; as said in the spec., the KeyEvent is only used as a container to transport the shortcut information. The client code is responsible for listening to keyboard events (typicaly done via XUserInputInterception), and dispatch the respective command if desired.
Help text and tip
PopupMenu items can have now help tips and extended tips. This feature works just like the current OOo implementation, supporting also Extensible Help (custom help shipped with your extension may be displayed as extended tip if you assign to it a command, and then set this command at the menu item).
PopupMenu items can now have pictures.
Images can be rotated to a desired angle, and mirrored.
The developer has been given the freedom to choose whether to automatically scale his/her images to the standard size used by OOo (currently 16x16), or use images with custom size.
New Menu API (and its design problems)
The extended menu API adds the following types:
The following diagram (not really an UML one) pictures the proposed extended Menu API:
At first sight looks complicated (and indeed rather awful), but it tries to simplify the use of the Menu API by implementing multiple inheritance. The red arrows point the rule that publish API can not implement unpublished interfaces.
If the current API state could be changed, then the Menu API could be designed following an inheritance tree that respect the actual objects' design:
But in a "perfect" situation, we could only have three interfaces (XMenu describing state and behavior of both MenuBar and PopupMenu, XMenuBar only for MenuBar's, and XPopupMenu only for PopupMenu's; new methods could be added just by specifying since when they are available.
In the proposed specification, the com.sun.star.awt.XMenuBarExtended is only a way to ease the use of the MenuBar API thanks to multiple inheritance. But is that all there is to offer? Access and control over MenuBar elements is internally available (for example to the closer and custom buttons like the one used by the update feature); it has to be decided if these features will be provided also to API clients.
The following picture shows a preliminary implementation where a button can be added, and a listener registered to listen when it is de/highlighted and pressed. When the button is pressed, the extension takes a snapshot of the desktop (as it is implemented i Java, uses java.awt.Robot, but the UI showing the snapshot is UNO AWT).