Creating Menus

From Apache OpenOffice Wiki
Jump to: navigation, search



If the developer wants to add menus to the Apache OpenOffice menu bar these should be added according the detailed description of the OpenOffice.org Wiki article Implementing an extended recent file popup menu controller.

Add-ons can use the menu bar integration of the add-on feature. More information can be found in Add-Ons.

Programmatic insertion of menus to a menu bar is possible for all windows that support the interface com.sun.star.awt.XTopWindow.

Unlike in Java, in Apache OpenOffice the term "PopupMenu" is used for all menus that can be either be used as location independent context menus or "ordinary" menus that are added to a menu bar.

The following example shows that:

  • Menus are created at the global service manager.
  • Following the definition of the constants group com.sun.star.awt.MenuItemStyle menu items may either work like radio buttons, check boxes or ordinary menu items. The constant AUTOCHECK changes the behavior of the menu in such a way that the menu item gets checked on its selection.
  • The first parameter nItemId of the method insertItem denotes an identifier of a menu item. This must be a unique identifier if you want to recognize a selected menu item unambiguously. The last parameter nPos denotes the position of the menu item in the menu. The unique identifier is ignored for non-selectable menu items. For all other menu items the identifier must always be unique.
  • "Radio-menuitems" are identified as a group by their positions within the menu, meaning that consecutive "radio - menuitems" automatically belong to the same radio button - group.
  • There is no Object representation for the menu items. After their creation, menu items are accessed by their ItemID within the menu.
  • To assign a shortcut key to a menu item, the tilde "~" prefixes the corresponding character of the menu text.
  public XPopupMenu getPopupMenu(){
  XPopupMenu xPopupMenu = null;
  try{
      // create a popup menu
      Object oPopupMenu = m_xMCF.createInstanceWithContext("stardiv.Toolkit.VCLXPopupMenu", m_xContext);
      xPopupMenu = (XPopupMenu) UnoRuntime.queryInterface(XPopupMenu.class, oPopupMenu);
      XMenuExtended xMenuExtended = (XMenuExtended) UnoRuntime.queryInterface(XMenuExtended.class, xPopupMenu);
 
      xPopupMenu.insertItem((short) 0, "~First Entry", MenuItemStyle.AUTOCHECK, (short) 0);
      xPopupMenu.insertItem((short) 1, "~First Radio Entry", (short) (MenuItemStyle.RADIOCHECK + MenuItemStyle.AUTOCHECK), (short) 1);
      xPopupMenu.insertItem((short) 2, "~Second Radio Entry", (short) (MenuItemStyle.RADIOCHECK + MenuItemStyle.AUTOCHECK), (short) 2);
      xPopupMenu.insertItem((short) 3, "~Third RadioEntry",(short) (MenuItemStyle.RADIOCHECK + MenuItemStyle.AUTOCHECK), (short) 3);
      xPopupMenu.insertSeparator((short)4);
      xPopupMenu.insertItem((short) 4, "F~ifth Entry", (short) (MenuItemStyle.CHECKABLE + MenuItemStyle.AUTOCHECK), (short) 5);
      xPopupMenu.insertItem((short) 5, "~Fourth Entry", (short) (MenuItemStyle.CHECKABLE + MenuItemStyle.AUTOCHECK), (short) 6);
      xPopupMenu.enableItem((short) 1, false);
      xPopupMenu.insertItem((short) 6, "~Sixth Entry", (short) 0, (short) 7);
      xPopupMenu.insertItem((short) 7, "~EightEntry", (short) (MenuItemStyle.RADIOCHECK + MenuItemStyle.AUTOCHECK), (short) 8);
      xPopupMenu.checkItem((short) 2, true);
      xPopupMenu.addMenuListener(this);
  }catch( Exception e ) {
      throw new java.lang.RuntimeException("cannot happen..."); 
  }
      return xPopupMenu;
  }

Issue https://qa.openoffice.org/issues/show_bug.cgi?id=76363 addressed the deprecated notation of the service "stardiv.Toolkit.VCLXPopupMenu"

The added XMenuListener of the menu has to implement several methods such as

  • select - invoked when the menu item is activated
  • highlight - invoked when the menu item is highlighted, for example when the mouse moves over it
  • activate/deactivate - depending on the context, menu items may be activated (enabled) or deactivated (disabled)

All these methods carry a com.sun.star.awt.MenuEvent parameter. The menu item at which the method has been triggered can be identified by the MenuId of this struct.

  public void select(MenuEvent menuEvent) {
      // find out which menu item has been triggered,
      // by getting the menu-id...
      switch (menuEvent.MenuId){
          case 0:
              // add your menu-item-specific code here:
              break;
          case 1:
              // add your menu-item-specific code here:
              break;
          default:
              //..
      }
  }
 
  public void highlight(MenuEvent menuEvent) {
  }
 
  public void deactivate(MenuEvent menuEvent) {
  }
 
  public void activate(MenuEvent menuEvent) {
  }

As we see, we encounter the Id again that helps us to identify the triggered menu item.

At last the create menu has to be added to a menu bar: As can be seen from the idl description of com.sun.star.awt.XMenuBar, it is a direct descendant of com.sun.star.awt.XMenu. The menus below the menu bar items are added by means of the method setPopupMenu.

  public void addMenuBar(XTopWindow _xTopWindow, XMenuListener _xMenuListener){
  try{
      // create a menubar at the global MultiComponentFactory...
      Object oMenuBar = m_xMCF.createInstanceWithContext("stardiv.Toolkit.VCLXMenuBar", m_xContext);
      // add the menu items...
      XMenuBar xMenuBar = (XMenuBar) UnoRuntime.queryInterface(XMenuBar.class, oMenuBar);
      xMenuBar.insertItem((short) 0, "~First MenuBar Item", com.sun.star.awt.MenuItemStyle.AUTOCHECK, (short) 0);
      xMenuBar.insertItem((short) 1, "~Second MenuBar Item", com.sun.star.awt.MenuItemStyle.AUTOCHECK, (short) 1);
      xMenuBar.setPopupMenu((short) 0, getPopupMenu());
      xMenuBar.addMenuListener(_xMenuListener);
      _xTopWindow.setMenuBar(xMenuBar);
  }catch( Exception e ) {
      throw new java.lang.RuntimeException("cannot happen..."); 
  }}

Accessibility

Certainly for many Apache OpenOffice extension developers, accessibility is an important issue. Luckily all UNO-AWT-elements automatically bring support for various accessibility aspects like keyboard navigation, scheming, assistive technology (AT), and much more, so that the developer does not even have to worry accessibility. A good introduction to this topic is the Wiki article at Accessibility. Some problems may arise and shall be dealt with in this chapter.

In the following scenario, a command button is inserted into a dialog. The label ">" of the button indicates that the activation of the button shifts some data from the left side to the right. As this label cannot be interpreted by the screenreader, an "AccessibleName" must be set at the control. Unfortunately this is not yet possible due to the issue https://www.openoffice.org/issues/show_bug.cgi?id=70296. At this stage, only a temporary solution can be offered that uses the deprecated interface com.sun.star.awt.XVclWindowPeer

  /** sets the AccessibilityName at a control
   * @param _xControl the control that the AccessibilityName is to be assigned to
   * @param _sAccessibilityName the AccessibilityName
   */
  public void setAccessibleName(XControl _xControl, String _sAccessibilityName){
       XVclWindowPeer xVclWindowPeer = (XVclWindowPeer) UnoRuntime.queryInterface(XVclWindowPeer.class, _xControl.getPeer());
       xVclWindowPeer.setProperty(""AccessibilityName"", "MyAccessibleName"); 
  }

Apache OpenOffice offers a high contrast mode, in which objects are displayed without fill colors or text colors. This mode will automatically be used when high contrast is chosen in the system settings. Extension developers with the demand to create accessible applications must consider this and provide High-Contrast images for their dialog controls. Also for this usecase, only a temporary solution based on the deprecated interface com.sun.star.awt.XVclWindowPeer can be offered:

  /** 
   * @param _xVclWindowPeer the windowpeer of a dialog control or the dialog itself
   * @return true if HighContrastMode is activated or false if HighContrastMode is deactivated
   */
      public boolean isHighContrastModeActivated(XVclWindowPeer _xVclWindowPeer){
      boolean bIsActivated = false;
      try {
          if (_xVclWindowPeer != null){
              int nUIColor = AnyConverter.toInt(_xVclWindowPeer.getProperty("DisplayBackgroundColor"));
              int nRed = getRedColorShare(nUIColor);
              int nGreen = getGreenColorShare(nUIColor);
              int nBlue = getBlueColorShare(nUIColor);
              int nLuminance = (( nBlue*28 + nGreen*151 + nRed*77 ) / 256 );
              boolean bisactivated = (nLuminance <= 25);
              return bisactivated;
          }
          else{
              return false;
          }
      } catch (IllegalArgumentException e) {
          e.printStackTrace(System.out);
      }
          return bIsActivated;
      }
 
      public static int getRedColorShare(int _nColor){
          int nRed = (int) _nColor/65536;
          int nRedModulo = _nColor % 65536;
          int nGreen = (int) (nRedModulo / 256);
          int nGreenModulo = (nRedModulo % 256);
          int nBlue = nGreenModulo;
          return nRed;
      }
 
      public static int getGreenColorShare(int _nColor){
          int nRed = (int) _nColor/65536;
          int nRedModulo = _nColor % 65536;
          int nGreen = (int) (nRedModulo / 256);
          return nGreen;
      }
 
      public static int getBlueColorShare(int _nColor){
          int nRed = (int) _nColor/65536;
          int nRedModulo = _nColor % 65536;
          int nGreen = (int) (nRedModulo / 256);
          int nGreenModulo = (nRedModulo % 256);
          int nBlue = nGreenModulo;
          return nBlue;
      }

The method isHighContrastModeActivated expects a com.sun.star.awt.XVclWindowPeer reference from any existing dialog control or of the dialog itself.

Issue https://www.openoffice.org/issues/show_bug.cgi?id=74568 addresses this problem and will certainly lead to a more elegant solution.

Rendering

The module com.sun.star.awt offers a set of interfaces to render graphics. These interfaces are not deprecated as they are used internally. Developers are advised not to use these interfaces because the future belongs to a new API called the SimpleCanvas API ( https://www.openoffice.org/gsl/canvas/api/rendering/XSimpleCanvas.html ). For this reason these interfaces shall only be briefly explained.

com.sun.star.awt.XDevice The pixel model is extremely device dependent because it is applicable to printers as well as to screens with all kind of resolutions. This interface provides information about a graphical output device. For example the method getFont() returns an object implementing com.sun.star.awt.XFont that describes a font on the respective device. The methods createBitmap() and createDisplayBitmap() create bitmap objects with the device depth (these objects are primarily used for internal use of graphic operations). The method createGraphics() returns an object providing a set of output operations by implementing the interface com.sun.star.awt.XGraphics. It offers methods to draw geometric figures like drawLine(), drawRect(), etc. and permits the assignment of clip regions that implement com.sun.star.awt.XRegion. By defining a clipping region the output is reduced to a certain area of a window in order to prevent other parts like the border or the menubar from being overdrawn by output operations. com.sun.star.awt.XRegion manages multiple rectangles which make up a region. Its main task is to perform adding, excluding, intersecting and moving operations on regions. A raster graphics image is defined by grid of pixels, that individually define a color. They are distinguished from vector graphics in that vector graphics represent an image through the use of geometric objects such as curves and polygons. The method setRasterOp() of com.sun.star.awt.XGraphics applies values specified in the enumeration com.sun.star.awt.RasterOperation on the pixels of a graphic.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages