Framework/Tutorial/Context Menu Interception

From Apache OpenOffice Wiki
< Framework
Revision as of 12:46, 5 November 2008 by Cd (Talk | contribs)

Jump to: navigation, search

This tutorial will give you a detailed step-by-step insight into a very flexible way to add a context menu interceptor into OpenOffice.org 2.x/3.0. A Context menu interceptor must be implemented via UNO supporting the com.sun.star.ui.XContextMenuInterceptor interface. This tutorial will be split into small chapters which describe different aspects of context menu interception. Everybody is invited to participate. May be someone wants to translate the extension to a different language (e.g. Java or Python) or wants to have more information about a specific topic. You can set a link to this page, if you think that this page adds valuable information.

The reader of this tutorial should know the following

   * Programming with UNO
   * C++ knowledge (Using C++ with the SDK)
   * How to create an extension with the "OpenOffice.org SDK"

A context menu is displayed when an object is right clicked. Typically, a context menu has context dependent functions to manipulate the selected object, such as cut, copy and paste. Developers can intercept context menus before they are displayed to cancel the execution of a context menu, add, delete, or modify the menu by replacing context menu entries or complete sub menus. It is possible to provide new customized context menus.

General abstract of the context menu interception concept

Context menu interception architecture

Context Menu Interception Architecture.png

Context menu interception is implemented by the observer pattern. This pattern defines a one-to-many dependency between objects, so that when an object changes state, all its dependents are notified. The implementation supports more than one interceptor which are chained in a queue. The root access point for intercepting context menus is a com.sun.star.frame.Controller object. The controller implements the interface com.sun.star.ui.XContextMenuInterception to support context menu interception. A context menu interceptor must support the com.sun.star.ui.XContextMenuInterceptor interface. It's used by the interception implementation to notify an interceptor whenever a context menu is going to be shown.

UNO interfaces, services, structs and constants

com::sun::star::ui::XContextMenuInterceptor

module com { module sun { module star { module ui {
 
//============================================================================= 
 
/** This interface enables the object to be registered as an interceptor
    to change context menus or prevent them from being executed.
*/
 
published interface XContextMenuInterceptor : ::com::sun::star::uno::XInterface
{
    //-------------------------------------------------------------------------
    /** notifies the interceptor about the request to execute a context menu.
        The interceptor has to decide whether the menu should be executed with
        or without being modified or may ignore the call.
 
        @param aEvent
            provides information about the current context menu and other
            related data like mouse position, window and selection.
 
        @return 
            action which determines how the interception implementation should 
            proceed.
    */
    ContextMenuInterceptorAction notifyContextMenuExecute([in] ContextMenuExecuteEvent aEvent);
};
 
}; }; }; };

com::sun::star::ui::XContextMenuInterception

module com { module sun { module star { module ui {
 
//============================================================================= 
 
/** This interface enables the object to get interceptors registered that
    change context menu or prevent them from being executed.
*/
 
published interface XContextMenuInterception : ::com::sun::star::uno::XInterface
{
    //-------------------------------------------------------------------------
    /** registers am XContextMenuInterceptor, which will become the first
        interceptor in the chain of registered interceptors.
 
        @param Interceptor
            an interceptor which should be added at the start of the
            interceptor chain.
 
    */
    void registerContextMenuInterceptor([in] XContextMenuInterceptor Interceptor);
 
    //-------------------------------------------------------------------------
    /** removes an XContextMenuInterceptor which was previously registered
        using XContextMenuInterception::registerContextMenuInterceptor.
 
        The order of removals is arbitrary. It's not necessary to remove the
        last registered interceptor first.
 
        @param Interceptor
            an interceptor which should be removed from the interceptor
            chain.
 
    */
    void releaseContextMenuInterceptor([in] XContextMenuInterceptor Interceptor);
};
 
}; }; }; };

com::sun::star::ui::ContextMenuInterceptorAction

module com { module sun { module star { module ui {
 
//============================================================================= 
 
/** This interface enables the object to get interceptors registered that
    change context menu or prevent them from being executed.
*/
 
published enum ContextMenuInterceptorAction
{
    /** the XContextMenuInterceptor has ignored the call. The next registered
        interceptor should be notified.
    */
    IGNORED,
 
    /** the context menu must not be executed. The next registered interceptor
        should not be notified.
    */
    CANCELLED,
 
    /** the menu has been modified and should be executed without notifying the
        next registered interceptor.
    */
    EXECUTE_MODIFIED,
 
    /** the menu has been modified and the next registered interceptor should
        be notified.
    */
    CONTINUE_MODIFIED
};
 
}; }; }; };

com::sun::star::ui::ContextMenuExecuteEvent

module com { module sun { module star { module ui {
 
//============================================================================= 
 
/** This interface enables the object to get interceptors registered that
    change context menu or prevent them from being executed.
*/
 
published struct ContextMenuExecuteEvent
{
    /** contains the window where the context menu has been requested,
    */
    ::com::sun::star::awt::XWindow SourceWindow;
 
    /** contains the position where the context menu should be displayed.
    */
    ::com::sun::star::awt::Point ExecutePosition;
 
    /** enables access to the menu content. The implementing object
        has to support service com::sun::star::ui::ActionTriggerContainer
    */
    ::com::sun::star::container::XIndexContainer ActionTriggerContainer;
 
    /** provides the current selection inside the source window.
    */
    ::com::sun::star::view::XSelectionSupplier Selection;
};
 
}; }; }; };

How to implement a context menu interceptor

Register and Remove an Interceptor

The com.sun.star.ui.XContextMenuInterception interface enables the developer to register and remove an interceptor. When an interceptor is registered, it is notified whenever a context menu is about to be executed. Registering an interceptor adds it to the front of the interceptor chain, so that it is called first. The order of removals is arbitrary. It is not necessary to remove the interceptor that registered last.

Implementing the notification part

A context menu interceptor implements the com.sun.star.ui.XContextMenuInterceptor interface. This interface has one function that is called by the responsible controller whenever a context menu is about to be executed.

  ContextMenuInterceptorAction notifyContextMenuExecute ( [in] ContextMenuExecuteEvent aEvent)

The com.sun.star.ui.ContextMenuExecuteEvent is a struct that holds all the important information for an interceptor.

Members of com.sun.star.ui.ContextMenuExecuteEvent
ExecutePosition com.sun.star.awt.Point. Contains the position the context menu will be executed.
SourceWindow com.sun.star.awt.XWindow. Contains the window where the context menu has been requested.
ActionTriggerContainer com.sun.star.container.XIndexContainer. The structure of the intercepted context menu. The member implements the com.sun.star.ui.ActionTriggerContainer service.
Selection com.sun.star.view.XSelectionSupplier. Provides the current selection inside the source window.

Querying the menu structure

The ActionTriggerContainer member is an indexed container of context menu entries, where each menu entry is a property set. It implements the com.sun.star.ui.ActionTriggerContainer service. The interface com.sun.star.container.XIndexContainer directly accesses the intercepted context menu structure through methods to access, insert, remove and replace menu entries.

All elements inside an ActionTriggerContainer member support the com.sun.star.beans.XPropertySet interface to get and set property values. There are two different types of menu entries which support specific set of properties. The following table describe all properties, their type and purpose:

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