截取上下文菜单

From Apache OpenOffice Wiki
Jump to: navigation, search


在对象上单击鼠标右键时,将显示上下文菜单。通常,上下文菜单提供了用于处理选定对象的上下文相关功能,例如剪切、复制和粘贴。开发者可以在上下文菜单显示之前将其截获,以取消上下文菜单的执行,也可以通过替换上下文菜单条目或整个子菜单来加入、删除以及更改菜单。可以提供新的自定义上下文菜单。


上下文菜单的截取由查看器模式实现。此模式定义了对象之间一对多的关系,这样,当一个对象更改状态时,将通知其所有相关的对象。此实现支持多个截取程序。用于截取上下文菜单的根访问点是一个 com.sun.star.frame.Controller 对象。控制器实现 com.sun.star.ui.XContextMenuInterception 接口以支持上下文菜单截取。


注册和删除截取程序

com.sun.star.ui.XContextMenuInterception 接口使开发者可以注册和删除截取程序代码。截取程序注册后,会在要执行上下文菜单时得到通知。注册截取程序可以将该程序添加到截取程序链的前面,因此它会最先被调用。删除顺序是随机的。不一定要先删除最后注册的截取程序。


编写截取程序

通知

上下文菜单截取程序可以实现 com.sun.star.ui.XContextMenuInterceptor 接口。此接口含有一个函数,要执行上下文菜单时,相应的控制器就会调用该函数。

  ContextMenuInterceptorAction notifyContextMenuExecute ( [in] ContextMenuExecuteEvent aEvent)

com.sun.star.ui.ContextMenuExecuteEvent 是一个保存截取程序所有重要信息的结构。

com.sun.star.ui.ContextMenuExecuteEvent 的成员
ExecutePosition com.sun.star.awt.Point。含有将要执行的上下文菜单的位置。
SourceWindow com.sun.star.awt.XWindow。含有请求上下文菜单时所在的窗口。
ActionTriggerContainer com.sun.star.container.XIndexContainer。被截取的上下文菜单的结

构。该成员可以实现 com.sun.star.ui.ActionTriggerContainer 服务。

Selection com.sun.star.view.XSelectionSupplier。提供源窗口中的当前选定内容。


查询菜单结构

ActionTriggerContainer 成员是上下文菜单条目的索引容器,其中的每个菜单条目均为一个属性集。它可以实现 com.sun.star.ui.ActionTriggerContainer 服务。com.sun.star.container.XIndexContainer 接口通过方法直接访问被截取的上下文菜单结构,以访问、插入、删除和替换菜单条目。


ActionTriggerContainer 成员中的所有元素均支持 com.sun.star.beans.XPropertySet 接口以获取和设定属性值。有两种不同类型的菜单条目含有各种属性集:

Type of Menu Entry Service Name
Menu entry "com.sun.star.ui.ActionTrigger"
Separator "com.sun.star.ui.ActionTriggerSeparator"


确定每个菜单条目的类型是非常必要的,因为这将有助于查询接口 com.sun.star.lang.XServiceInfo 的菜单项以及调用

  boolean supportsService ( [in] string ServiceName )


以下示例显示了一个用于确定正确菜单条目类型的小帮助程序类。

  // A helper class to determine the menu element type
  public class MenuElement
  {
      static public boolean IsMenuEntry( com.sun.star.beans.XPropertySet xMenuElement ) {
          com.sun.star.lang.XServiceInfo xServiceInfo =
              (com.sun.star.lang.XServiceInfo)UnoRuntime.queryInterface(
                  com.sun.star.lang.XServiceInfo.class, xMenuElement );
 
          return xServiceInfo.supportsService( "com.sun.star.ui.ActionTrigger" );
      }
 
      static public boolean IsMenuSeparator( com.sun.star.beans.XPropertySet xMenuElement ) { com.sun.star.lang.XServiceInfo xServiceInfo =
          (com.sun.star.lang.XServiceInfo)UnoRuntime.queryInterface(
              com.sun.star.lang.XServiceInfo.class, xMenuElement );
 
          return xServiceInfo.supportsService( "com.sun.star.ui.ActionTriggerSeparator" );
      }
  }

图 4.1:确定菜单元素类型 Figure 4.1: Determine the menu element type


可选菜单条目支持的 com.sun.star.ui.ActionTrigger 服务具有以下属性:

com.sun.star.ui.ActionTrigger 的属性
Text 字符串型。含有菜单条目标签的文字。
CommandURL 字符串型。含有命令 URL,命令 URL 用于定义用户选择某菜单条目时要执行的功能。
HelpURL 字符串型。此可选属性含有指向帮助文本的帮助 URL。
Image com.sun.star.awt.XBitmap。此属性含有显示在菜单标签左侧的图像。此属性可选,这样,如果该成员没有初始化,则不使用图像。
SubContainer com.sun.star.container.XIndexContainer。此属性含有一个可选的子菜单。


com.sun.star.ui.ActionTriggerSeparator 服务只定义了一个可选属性:

com.sun.star.ui.ActionTriggerSeparator 的属性
SeparatorType com.sun.star.ui.ActionTriggerSeparatorType。指定分隔符的具体类型。当前

可以使用以下类型:

  • const int LINE = 0
  • const int SPACE = 1
  • const int LINEBREAK = 2


更改菜单

不实现上下文菜单截取程序中的代码也可以完成某些任务,例如阻止激活上下文菜单。通常,更改上下文菜单是为了向用户提供其他功能。


如前面所述,上下文菜单结构通过 ActionTriggerContainer 成员进行查询,该成员是 com.sun.star.ui.ContextMenuExecuteEvent 结构的一部分。 com.sun.star.ui.ActionTriggerContainer 服务具有创建 com.sun.star.ui.ActionTriggerContainercom.sun.star.ui.ActionTriggerActionTriggerSeparator 对象的附加接口 com.sun.star.lang.XMultiServiceFactory。这些对象可用于扩展上下文菜单。


ActionTriggerContainer 实现的 com.sun.star.lang.XMultiServiceFactory 实现支持以下字符串: The com.sun.star.lang.XMultiServiceFactory implementation of the ActionTriggerContainer implementation supports the following strings:

字符串 对象
"com.sun.star.ui.ActionTrigger" 创建普通的菜单条目。
"com.sun.star.ui.ActionTriggerContainer" 创建空子菜单1
"com.sun.star.ui.ActionTriggerSeparator" 建立未指定的分隔符 2

1 子菜单无法单独存在。它必须插在 com.sun.star.ui.ActionTrigger 中!

2 分隔符没有特殊的类型。呈现未指定的分隔符是具体实现的任务。


完成截取

每个被调用的截取程序都会在调用返回后引导控制器继续操作。枚举 com.sun.star.ui.ContextMenuInterceptorAction 定义了可能的返回值。

com.sun.star.ui.ContextMenuInterceptorAction 的值
IGNORED 被调用的对象忽略了此调用。应该通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor
CANCELLED 不能执行上下文菜单。不会调用剩余的截取程序。
EXECUTE_MODIFIED 上下文菜单已更改并应执行,但不通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor
CONTINUE_MODIFIED 上下文菜单已被调用的对象更改。应该通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor


以下示例显示了一个上下文菜单截取程序,该程序将子菜单添加到在控制器(其中已注册了该 com.sun.star.ui.XContextMenuInterceptor)上截取的菜单中。该子菜单被插在上下文菜单的最顶端。它向用户提供了帮助功能,这些功能可以通过“帮助”菜单来访问。

import com.sun.star.ui.*;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.beans.XPropertySet;
import com.sun.star.container.XIndexContainer;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.Exception;
import com.sun.star.beans.UnknownPropertyException;
import com.sun.star.lang.IllegalArgumentException;
 
 
public class ContextMenuInterceptor implements XContextMenuInterceptor {
 
  public ContextMenuInterceptorAction notifyContextMenuExecute( 
  com.sun.star.ui.ContextMenuExecuteEvent aEvent ) throws RuntimeException {
 
    try {
      // Retrieve context menu container and query for service factory to
      // create sub menus, menu entries and separators
      com.sun.star.container.XIndexContainer xContextMenu = aEvent.ActionTriggerContainer;
      com.sun.star.lang.XMultiServiceFactory xMenuElementFactory = 
          (com.sun.star.lang.XMultiServiceFactory)UnoRuntime.queryInterface(
              com.sun.star.lang.XMultiServiceFactory.class, xContextMenu );
      if ( xMenuElementFactory != null ) {
          // create root menu entry for sub menu and sub menu
          com.sun.star.beans.XPropertySet xRootMenuEntry =
              (XPropertySet)UnoRuntime.queryInterface(
                  com.sun.star.beans.XPropertySet.class, 
                  xMenuElementFactory.createInstance ( "com.sun.star.ui.ActionTrigger" ));
 
              // create a line separator for our new help sub menu
              com.sun.star.beans.XPropertySet xSeparator = 
              (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( 
                  com.sun.star.beans.XPropertySet.class, 
                  xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTriggerSeparator" ) );
 
              Short aSeparatorType = new Short( ActionTriggerSeparatorType.LINE );
              xSeparator.setPropertyValue( "SeparatorType", (Object)aSeparatorType );
 
              // query sub menu for index container to get access
              com.sun.star.container.XIndexContainer xSubMenuContainer =
              (com.sun.star.container.XIndexContainer)UnoRuntime.queryInterface( 
                  com.sun.star.container.XIndexContainer.class,
                      xMenuElementFactory.createInstance( 
              "com.sun.star.ui.ActionTriggerContainer" ));
 
              // intialize root menu entry "Help"
              xRootMenuEntry.setPropertyValue( "Text", new String( "Help" ));
              xRootMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5410" ));
              xRootMenuEntry.setPropertyValue( "HelpURL", new String( "5410" ));
              xRootMenuEntry.setPropertyValue( "SubContainer", (Object)xSubMenuContainer );
 
              // create menu entries for the new sub menu
 
              // intialize help/content menu entry
              // entry "Content"
              XPropertySet xMenuEntry = (XPropertySet)UnoRuntime.queryInterface( 
                  XPropertySet.class, xMenuElementFactory.createInstance (
                      "com.sun.star.ui.ActionTrigger" ));
 
              xMenuEntry.setPropertyValue( "Text", new String( "Content" ));
              xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5401" ));
              xMenuEntry.setPropertyValue( "HelpURL", new String( "5401" ));
 
              // insert menu entry to sub menu
              xSubMenuContainer.insertByIndex ( 0, (Object)xMenuEntry );
 
              // intialize help/help agent
              // entry "Help Agent"
              xMenuEntry = (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( 
                  com.sun.star.beans.XPropertySet.class,
                      xMenuElementFactory.createInstance (
                          "com.sun.star.ui.ActionTrigger" ));
              xMenuEntry.setPropertyValue( "Text", new String( "Help Agent" ));
              xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5962" ));
              xMenuEntry.setPropertyValue( "HelpURL", new String( "5962" ));
 
              // insert menu entry to sub menu
              xSubMenuContainer.insertByIndex( 1, (Object)xMenuEntry );
 
              // intialize help/tips
              // entry "Tips"
              xMenuEntry = (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( 
                  com.sun.star.beans.XPropertySet.class,
                      xMenuElementFactory.createInstance( 
                          "com.sun.star.ui.ActionTrigger" ));
              xMenuEntry.setPropertyValue( "Text", new String( "Tips" ));
              xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5404" ));
              xMenuEntry.setPropertyValue( "HelpURL", new String( "5404" ));
 
              // insert menu entry to sub menu
              xSubMenuContainer.insertByIndex ( 2, (Object)xMenuEntry );
 
              // add separator into the given context menu
              xContextMenu.insertByIndex ( 0, (Object)xSeparator );
 
              // add new sub menu into the given context menu
              xContextMenu.insertByIndex ( 0, (Object)xRootMenuEntry );
 
              // The controller should execute the modified context menu and stop notifying other
              // interceptors.
              return com.sun.star.ui.ContextMenuInterceptorAction.EXECUTE_MODIFIED ;
          }
      }
      catch ( com.sun.star.beans.UnknownPropertyException ex ) {
          // do something useful
          // we used a unknown property 
      }
      catch ( com.sun.star.lang.IndexOutOfBoundsException ex ) {
          // do something useful
          // we used an invalid index for accessing a container
      }
      catch ( com.sun.star.uno.Exception ex ) {
          // something strange has happend!
      }
      catch ( java.lang.Throwable ex ) {
          // catch java exceptions - do something useful
      }
 
      return com.sun.star.ui.ContextMenuInterceptorAction.IGNORED;
  }
}
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages