截取上下文菜单
在对象上单击鼠标右键时,将显示上下文菜单。通常,上下文菜单提供了用于处理选定对象的上下文相关功能,例如剪切、复制和粘贴。开发者可以在上下文菜单显示之前将其截获,以取消上下文菜单的执行,也可以通过替换上下文菜单条目或整个子菜单来加入、删除以及更改菜单。可以提供新的自定义上下文菜单。
上下文菜单的截取由查看器模式实现。此模式定义了对象之间一对多的关系,这样,当一个对象更改状态时,将通知其所有相关的对象。此实现支持多个截取程序。用于截取上下文菜单的根访问点是一个 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。指定分隔符的具体类型。当前
可以使用以下类型:
|
更改菜单
不实现上下文菜单截取程序中的代码也可以完成某些任务,例如阻止激活上下文菜单。通常,更改上下文菜单是为了向用户提供其他功能。
如前面所述,上下文菜单结构通过 ActionTriggerContainer 成员进行查询,该成员是 com.sun.star.ui.ContextMenuExecuteEvent 结构的一部分。 com.sun.star.ui.ActionTriggerContainer 服务具有创建 com.sun.star.ui.ActionTriggerContainer、com.sun.star.ui.ActionTrigger 和 ActionTriggerSeparator 对象的附加接口 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). |