Difference between revisions of "Framework/Tutorial/Accelerators"

From Apache OpenOffice Wiki
Jump to: navigation, search
(New page: This tutorial will give you a detailed step-by-step insight into accelerators in OpenOffice.org. Everybody is invited to participate. May be someone wants to translate the extension to a d...)
 
 
(17 intermediate revisions by one other user not shown)
Line 4: Line 4:
  
 
     * Programming with UNO
 
     * Programming with UNO
     * C++ knowledge (Using C++ with the SDK)
+
     * C++/Java knowledge (Using C++/Java with the SDK)
 
     * How to create an extension with the "OpenOffice.org SDK"
 
     * How to create an extension with the "OpenOffice.org SDK"
 +
 +
= General abstract of the OpenOffice.org accelerator concept =
 +
 +
== Accelerator architecture ==
 +
 +
[[image:Architecture_-_Accelerators.png]]
 +
 +
OpenOffice.org accelerators are available and stored on three different layers which have a pre-defined priority. The layers are:
 +
 +
{|border="1" cellpadding=4 style="border-collapse:collapse;"
 +
|-bgcolor=#EDEDED
 +
!colspan="2"|Priority of the different accelerator layers 
 +
|-
 +
|1. 
 +
|Document based accelerators
 +
|-
 +
|2.
 +
|Module based accelerators
 +
|-
 +
|3.
 +
|Global based accelerators
 +
|-
 +
|}
 +
 +
If a user presses a possible keyboard shorcut the framework implementation starts to check every layer (using the pre-defined order document, module, global) for a matching entry. If there is match the associated command URL is used to find a dispatch object where the command can be executed. If no matching entry has been found the current application module is asked to process the keyboard event.
 +
 +
== How to access the different accelerator layers ==
 +
 +
[[image:Access_to_Accelerator_Managers.png]]
 +
 +
=== Global Accelerator Manager ===
 +
 +
The global accelerator manager can be directly created by using the OpenOffice.org service manager. The service name of the global accelerator manager is called <idl>com.sun.star.ui.GlobalAcceleratorManager</idl>. This service provides just one interface where accelerators can be retrieved, changes and removed.
 +
 +
<source lang="idl">
 +
module com {  module sun {  module star {  module ui {
 +
 +
//-----------------------------------------------
 +
/** provides access to the global shortcut configuration set.
 +
 +
    <p> The GlobalAcceleratorConfiguration service can be created
 +
    by using an UNO service manager. It provides then access to
 +
    the global accelerator configuration.</p>
 +
   
 +
    @since OOo 2.0.0
 +
*/
 +
service GlobalAcceleratorConfiguration : XAcceleratorConfiguration
 +
{};
 +
 +
}; }; }; }; // com.sun.star
 +
 +
#endif
 +
</source>
 +
 +
=== Module Accelerator Manager ===
 +
 +
A module accelerator manager must be created via the one-instance service service <idl>com.sun.star.ui.ModuleUIConfigurationManagerSupplier</idl>.
 +
 +
<source lang="idl">
 +
module com { module sun { module star { module ui {
 +
 +
/** allows to retrieve user interface configuration managers related to
 +
    OpenOffice.org modules.
 +
 +
    @since OOo 2.0.0
 +
*/
 +
   
 +
interface XModuleUIConfigurationManagerSupplier : ::com::sun::star::uno::XInterface
 +
{
 +
    //----------------------------------------------------------------------
 +
    /** returns the requested module based user interface configuration manager.
 +
 +
        @param ModuleIdentifier
 +
            a module identifier which identifies an OpenOffice.org module. The
 +
            module identifier can be retrieved from the
 +
            <type scope=com::sun::star::frame>ModuleManager</type> service.
 +
 +
        @returns
 +
            an object implementing
 +
            <type scope="::com::sun::star::ui">ModuleUIConfigurationManager</type>
 +
            service. If the provided module identifier is unknown a
 +
            <type scope="com::sun::star::container">NoSuchElementException</type>
 +
            is thrown.
 +
    */
 +
    XUIConfigurationManager getUIConfigurationManager( [in] string ModuleIdentifier ) raises ( com::sun::star::container::NoSuchElementException );
 +
};
 +
 +
//=============================================================================
 +
 +
}; }; }; };
 +
 +
</source>
 +
This service provides access to the module specific ui configuration managers via the method <code>getUIConfigurationManager</code>. The module service name must be provided to access a certain module.
 +
 +
=== Document Accelerator Manager ===
 +
 +
<source lang="idl">
 +
module com { module sun { module star { module ui {
 +
 +
/** allows to retrieve the user interface configuration manager related to
 +
    an object.
 +
   
 +
    @since OOo 2.0.0
 +
*/
 +
   
 +
interface XUIConfigurationManagerSupplier : ::com::sun::star::uno::XInterface
 +
{
 +
    //----------------------------------------------------------------------
 +
    /** returns the user interface configuration manager related to the
 +
        object.
 +
 +
        @returns
 +
            an object implementing
 +
            <type scope="::com::sun::star::ui">UIConfigurationManager</type>
 +
            service.
 +
    */
 +
    XUIConfigurationManager getUIConfigurationManager();
 +
};
 +
 +
//=============================================================================
 +
 +
}; }; }; };
 +
</source>
 +
 +
<source lang="idl">
 +
module com { module sun { module star { module ui {
 +
 +
/** specifies a user interface configuration manager interface which
 +
    controls the structure of all customizable user interface
 +
    elements.
 +
   
 +
    @since OOo 2.0.0
 +
*/
 +
   
 +
interface XUIConfigurationManager : ::com::sun::star::uno::XInterface
 +
{
 +
    /** resets the configuration manager to the default user interface
 +
        configuration data.
 +
        <p>
 +
        This means that all user interface configuration data of the
 +
        instance will be removed. A module based user interface
 +
        configuration manager removes user defined elements, but set all
 +
        other elements back to default. It is not possible to remove
 +
        default elements from a module user interface configuration
 +
        manager.
 +
        </p>
 +
    */
 +
    void reset();
 +
 +
    /** retrieves information about all user interface elements within
 +
        the user interface configuration manager.
 +
 +
        @param ElementType
 +
            makes it possible to narrow the result set to only one type
 +
            of user interface elements. If all user interface element
 +
            types should be returned
 +
            <value scope=com::sun::star::ui>UIElementType::UNKNOWN</value>
 +
            must be provided.
 +
 +
        @return
 +
            returns all user interface elements within the user interface
 +
            configuration manager that meet the given ElementType
 +
            specification. <p>The following
 +
            <type scope="com::sun::star::beans">PropertyValue</type> entries
 +
            are defined inside the sequence for every user interface element.
 +
            <ul>
 +
                <li><b>ResourceURL<b/>specifies the unique resource URL for
 +
                the user interface element.</li>
 +
                <li><b>UIName<b/>specifies the user interface name for the
 +
                user interface element. Not all user interface elements have
 +
                set UIName. At least menubars do not.</li>
 +
            </ul>
 +
            <p>
 +
 +
        @see UIElementType
 +
    */
 +
    sequence< sequence< com::sun::star::beans::PropertyValue > > getUIElementsInfo( [in] short ElementType ) raises ( com::sun::star::lang::IllegalArgumentException );
 +
 +
    /** creates an empty settings data container.
 +
 +
        @return
 +
            an empty user interface element settings data container, which
 +
            implements <type>UIElementSettings</type>.
 +
    */
 +
    ::com::sun::star::container::XIndexContainer createSettings();
 +
 +
    /** determines if the settings of a user interface element is part the
 +
        user interface configuration manager.
 +
 +
        @param ResourceURL
 +
            a resource URL which identifies the user interface element. A
 +
            resourcce URL must meet the following syntax:
 +
            "private:resource/$type/$name. It is only allowed to use ascii
 +
            characters for type and name.
 +
 +
        @return
 +
            <TRUE/> if settings have been found, otherwise <FALSE/>.
 +
    */
 +
    boolean hasSettings( [in] string ResourceURL ) raises ( com::sun::star::lang::IllegalArgumentException );
 +
 +
    /** retrieves the settings of a user interface element.
 +
 +
        @param ResourceURL
 +
            a resource URL which identifies the user interface element. A
 +
            resourcce URL must meet the following syntax:
 +
            "private:resource/$type/$name. It is only allowed to use ascii
 +
            characters for type and name.
 +
 +
        @param bWriteable
 +
            must be <TRUE/> if the retrieved settings should be a writeable.
 +
            Otherwise <FALSE/> should be provided to get a shareable reference
 +
            to the settings data.
 +
 +
        @return
 +
            settings data of an existing user interface element, which
 +
            implements <type>UIElementSettings</type>. If the settings data
 +
            cannot be found a
 +
            <type scope="com::sun::star::container">NoSuchElementException</type>
 +
            is thrown.  If the <member>ResourceURL</member> is not valid or
 +
            describes an unknown type a
 +
            <type scope="com::sun::star::lang">IllegalArgumentException</type>
 +
            is thrown.
 +
    */
 +
    ::com::sun::star::container::XIndexAccess getSettings( [in] string ResourceURL, [in] boolean bWriteable ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException );
 +
 +
    /** replaces the settings of a user interface element with new settings.
 +
 +
        @param ResourceURL
 +
            a resource URL which identifies the user interface element to
 +
            be replaced. If no element with the given resource URL exists a
 +
            <type scope="com::sun::star::container">NoSuchElementException</type>
 +
            is thrown.
 +
 +
        @param aNewData
 +
            the new settings data of an existing user interface element, which
 +
            implements <type>UIElementSettings</type>.
 +
 +
        <p>
 +
        If the settings data cannot be found a
 +
        <type scope="com::sun::star::container">NoSuchElementException</type>
 +
        is thrown. If the <member>ResourceURL</member> is not valid or describes
 +
        an unknown type a
 +
        <type scope="com::sun::star::lang">IllegalArgumentException</type>
 +
        is thrown. If the configuration manager is read-only a
 +
        <type scope="com::sun::star::lang">IllegalAccessException</type> is
 +
        thrown.
 +
        </p>
 +
    */
 +
    void replaceSettings( [in] string ResourceURL, [in] ::com::sun::star::container::XIndexAccess aNewData ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 +
 +
    /** removes the settings of an existing user interface element.
 +
 +
        @param ResourceURL
 +
            a resource URL which identifies the user interface element settings
 +
            to be removed.
 +
           
 +
        <p>
 +
        If the settings data cannot be found a
 +
        <type scope="com::sun::star::container">NoSuchElementException</type> is
 +
        thrown. If the <member>ResourceURL</member> is not valid or describes an
 +
        unknown type a <type scope="com::sun::star::lang">IllegalArgumentException</type>
 +
        is thrown. If the configuration manager is read-only a
 +
        <type scope="com::sun::star::lang">IllegalAccessException</type> is thrown.
 +
        </p>
 +
    */
 +
    void removeSettings( [in] string ResourceURL ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 +
       
 +
    /** inserts the settings of a new user interface element.
 +
 +
        @param ResourceURL
 +
            a resource URL which identifies the new user interface element.
 +
 +
        @param aNewData
 +
            the settings data of the new user interface element, which implements
 +
            <type>UIElementSettings</type>.
 +
 +
        <p>
 +
        If the settings data is already present a
 +
        <type scope="com::sun::star::container">ElementExistException</type>
 +
        is thrown. If the <member>ResourceURL</member> is not valid or describes
 +
        an unknown type a <type scope="com::sun::star::lang">IllegalArgumentException</type>
 +
        is thrown. If the configuration manager is read-only a
 +
        <type scope="com::sun::star::lang">IllegalAccessException</type> is thrown.
 +
        </p>
 +
    */
 +
    void insertSettings( [in] string NewResourceURL, [in] ::com::sun::star::container::XIndexAccess aNewData ) raises ( com::sun::star::container::ElementExistException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 +
 +
    /** retrieves the image manager from the user interface configuration
 +
        manager.
 +
   
 +
        <p>
 +
        Every user interface configuration manager has one image manager
 +
        instance which controls all images of a module or document.
 +
        </p>
 +
 +
        @return
 +
            the image manager of the user interface configuration manager.
 +
    */
 +
    com::sun::star::uno::XInterface getImageManager();
 +
 +
    /** retrieves the keyboard short cut manager from the user interface
 +
        configuration manager.
 +
   
 +
        <p>
 +
        Every user interface configuration manager has one keyboard short cut
 +
        manager instance which controls all short cuts of a module or document.
 +
        </p>
 +
 +
        @return
 +
            the short cut manager of the user interface configuration manager.
 +
    */
 +
    com::sun::star::uno::XInterface getShortCutManager();
 +
 +
    /** retrieves the events manager from the user interface configuration manager.
 +
   
 +
        <p>
 +
        Every user interface configuration manager has one events manager
 +
        instance which controls the mapping of events to script URLs of a module
 +
        or document.
 +
        </p>
 +
 +
        @return
 +
            the events manager of the user interface configuration
 +
            manager, if one exists.
 +
    */
 +
    com::sun::star::uno::XInterface getEventsManager();
 +
};
 +
 +
//=============================================================================
 +
 +
}; }; }; };
 +
</source>
 +
 +
== Using an Accelerator Manager to retrieve or manipulate accelerators ==
 +
 +
The access to the accelerator manager is always done via the <idl>com.sun.star.ui.XAcceleratorConfiguration</idl> interface.
 +
 +
<source lang="idl">
 +
module com {  module sun {  module star {  module ui {
 +
 +
//-----------------------------------------------
 +
/** provides read/write access to an accelerator configuration set.
 +
 +
    <p>
 +
    Such configuration set base on:<br>
 +
    <ul>
 +
        <li>Key events structure</li>
 +
        <li>and Commands, which are represented as URLs; describing
 +
            a function, which and can be executed using the dispatch API.</li>
 +
    </ul>
 +
    </p>
 +
 +
<p>
 +
    Note further:<br>
 +
    All changes you made on this configration access modify the
 +
    the configuration set inside memory only. You have to use
 +
    the <type scope="com::sun::star::util">XFlushable</type> interface
 +
    (which must be available at the same implementation object too), to
 +
    make it persistent.
 +
    </p>
 +
   
 +
    @see    AcceleratorConfiguration
 +
    @see    <type scope="dom::sun::star::util">XFlushable</type>
 +
 +
    @since OOo 2.0.0
 +
*/
 +
interface XAcceleratorConfiguration
 +
{
 +
    //-------------------------------------------
 +
    /** return the list of all key events, which
 +
        are available at this configration set.
 +
       
 +
        <p>
 +
        The key events are the "primary keys" of this configuration sets.
 +
        Means: Commands are registerd for key events.
 +
        </p>
 +
       
 +
        <p>
 +
        Such key event can be mapped to its bound command,
 +
        using the method getCommandForKeyEvent().
 +
        </p>
 +
       
 +
        @see        getCommandForKeyEvent().
 +
       
 +
        @return    A list of key events.
 +
      */
 +
    sequence< com::sun::star::awt::KeyEvent > getAllKeyEvents();
 +
   
 +
    //-------------------------------------------
 +
    /** return the registered command for the specified key event.
 +
   
 +
        <p>
 +
        This function can be used to:<br>
 +
        <ul>
 +
            <li>by a generic service, which can execute commands if a
 +
                keyboard event occures.</li>
 +
            <li>or to iterate over the whole container and change some
 +
                accelerator bindings.</li>
 +
        </ul>
 +
        </p>
 +
       
 +
        @param  aKeyEvent
 +
                the key event, where the registered command is searched for.
 +
               
 +
        @return The registered command for the specified key event.
 +
               
 +
        @throws ::com::sun::star::container::NoSuchElementException
 +
                if the key event is an invalid one or does not exists
 +
                inside this configuration set.
 +
    */       
 +
    string getCommandByKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent )
 +
        raises(com::sun::star::container::NoSuchElementException);
 +
 +
    //-------------------------------------------
 +
    /** modify or create a key - command - binding.
 +
   
 +
        <p>
 +
        If the specified key event does not already exists inside this
 +
        configuration access, it will be created and the command will be
 +
        registered for it.
 +
        </p>
 +
       
 +
        <p>
 +
        If the specified key event already exists, its command will
 +
        be overwritten with the new command. There is no warning nor any error
 +
        about that! The outside code has to use the method getCommandForKeyEvent()
 +
        to check for possible collisions.
 +
        </p>
 +
       
 +
        <p>
 +
        Note: This method cant be used to remove entities from the configuration set.
 +
        Empty parameters will result into an exception!
 +
        Use the method removeKeyEvent() instead.
 +
        </p>
 +
       
 +
        @see    removeKeyEvent()
 +
       
 +
        @param  aKeyEvent
 +
                specify the key event, which must be updated or new created.
 +
               
 +
        @param  sCommand
 +
                the new command for the specified key event.
 +
 +
        @throws ::com::sun::star::lang::IllegalArgumentException
 +
                if the key event isnt a valid one. Commands can be
 +
                checked only, if they are empty. Because every URL schema can be used
 +
                by commands in general, so its not possible to validate it.               
 +
    */
 +
    void setKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent,
 +
                      [in] string                        sCommand )
 +
        raises(com::sun::star::lang::IllegalArgumentException);
 +
 +
    //-------------------------------------------
 +
    /** remove a key-command-binding from this configuration set.
 +
   
 +
        @param  aKeyEvent
 +
                the key event, which should be removed.
 +
               
 +
        @throws ::com::sun::star::container::NoSuchElementException
 +
                if the key event does not exists inside this configuration set.
 +
    */
 +
    void removeKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent )
 +
        raises(com::sun::star::container::NoSuchElementException);
 +
             
 +
    //-------------------------------------------
 +
    /** optimized access to the relation "command-key" instead
 +
        of "key-command" which is provided normaly by this interface.
 +
       
 +
        <p>
 +
        It can be used to implement collision handling, if more then one
 +
        key event match to the same command. The returned list contains all
 +
        possible key events - and the outside code can select an possible one.
 +
        Of course - mostly this list will contain only one key event ...
 +
        </p>
 +
       
 +
        @param  sCommand
 +
                the command, where key bindings are searched for.
 +
               
 +
        @return A list of <type scope="com::sun::star::awt">KeyEvent</type> structures,
 +
                where the pecified command is registered for.
 +
               
 +
        @throws ::com::sun::star::lang::IllegalArgumentException
 +
                if the specified command is empty. It cant be checked, if a command
 +
                is valid - because every URL schema can be used here.
 +
 +
        @throws ::com::sun::star::container::NoSuchElementException
 +
                if the specified command isnt empty but does not
 +
                occure inside this configuration set.
 +
    */
 +
    sequence< com::sun::star::awt::KeyEvent > getKeyEventsByCommand( [in] string sCommand )
 +
        raises(com::sun::star::lang::IllegalArgumentException  ,
 +
              com::sun::star::container::NoSuchElementException);
 +
             
 +
    //-------------------------------------------
 +
    /** optimized function to map a list of commands to a corresponding
 +
        list of key events.
 +
       
 +
        <p>
 +
        It provides a fast mapping, which is e.g. needed by a menu or toolbar implementation.
 +
        E.g. a sub menu is described by a list of commands - and the implementation of the menu
 +
        must show the corresponding shortcuts. Iteration over all items of this configuration
 +
        set can be very expensive.
 +
        </p>
 +
       
 +
        <p>
 +
        Instead to the method getKeyEventsForCommand() the returned list contains only
 +
        one(!) key event bound to one(!) requested command. If more then one key event
 +
        is bound to a command - a selection is done inside this method.
 +
        This internal selection cant be influenced from outside.
 +
        </p>
 +
       
 +
        @attention  Because its not defined, that any command (e.g. configured inside a menu)
 +
                    must have an accelerator - we cant reject the call if at least one command
 +
                    does not occure inside this configuration set ...
 +
                    We handle it more gracefully - and return an empty item instead of throwing
 +
                    and exception.
 +
       
 +
        @param  lCommandList
 +
                a list of commands
 +
               
 +
        @return A (non packed!) list of key events, where every item match by index
 +
                directly to a command of the specified <var>CommandList</var>.
 +
                If a command does not exists inside this configuration set, the
 +
                corresponding any value will be empty.
 +
 +
        @throws ::com::sun::star::lang::IllegalArgumentException
 +
                if at least one of the specified commands is empty.
 +
                It cant be checked, if a command is valid -
 +
                because every URL schema can be used here.
 +
    */
 +
    sequence< any > getPreferredKeyEventsForCommandList( [in] sequence< string > lCommandList )
 +
        raises(com::sun::star::lang::IllegalArgumentException);
 +
 +
    //-------------------------------------------
 +
    /** search for an key-command-binding inside this configuration set,
 +
        where the specified command is used.
 +
       
 +
        <p>
 +
        If such binding could be located, the command will be removed
 +
        from it. If as result of that the key binding will be empty,
 +
        if will be removed too.
 +
        </p>
 +
       
 +
        <p>
 +
        This is an optimized method, which can perform removing of commands
 +
        from this configuration set. Because normaly Commands are "foreign keys"
 +
        and key identifier the "primary keys" - it needs some work to remove
 +
        all commands outside this container ...
 +
        </p>
 +
       
 +
        @param  sCommand
 +
                the command, which should be removed from any key binding.
 +
               
 +
        @throws ::com::sun::star::lang::IllegalArgumentException
 +
                if the specified command is empty.
 +
               
 +
        @throws ::com::sun::star::container::NoSuchElementException
 +
                if the specified command isnt used inside this configuration set.
 +
    */
 +
    void removeCommandFromAllKeyEvents( [in] string sCommand )       
 +
        raises(com::sun::star::lang::IllegalArgumentException  ,
 +
              com::sun::star::container::NoSuchElementException);
 +
             
 +
    //-------------------------------------------
 +
    /** specifies a persistence interface which supports to
 +
        load/store accelerator configuration data to a storage
 +
        and to retrieve information about the current state.
 +
    */
 +
    interface com::sun::star::ui::XUIConfigurationPersistence;
 +
   
 +
    //-------------------------------------------
 +
    /** connects this configuration to a new storage
 +
        which must be used further on subsequent calls of
 +
        <type scope="com::sun::star::util::">XConfigurationPersistence.load()</type>
 +
        and <type scope="com::sun::star::util::">XConfigurationPersistence.store()</type>.
 +
    */
 +
    interface com::sun::star::ui::XUIConfigurationStorage;
 +
   
 +
    //-------------------------------------------
 +
    /** supports to notify other implementations about
 +
        changes of this accelerator configuration.
 +
    */
 +
    interface com::sun::star::ui::XUIConfiguration;
 +
   
 +
}; // interface XAcceleratorConfiguration
 +
 +
}; }; }; }; // com.sun.star
 +
 +
</source>
 +
 +
=== Sample Code ===
 +
 +
<source lang="cpp">
 +
// Create the global accelerator configuration service
 +
Reference< com::sun::star::ui::XacceleratorConfiguration > xGlobalAccelCfg(
 +
  m_xServiceManager->createInstance(
 +
    ::rtl::OUString("com.sun.star.ui.GlobalAcceleratorConfiguration")),
 +
  UNO_QUERY_THROW );
 +
 +
// set key event to define the accelerator
 +
com::sun:star::awt::KeyEvent aKeyEvent;
 +
aKeyEvent.KeyCode  = com::sun::star::awt::Key::S;
 +
aKeyEvent.Modifiers = com::sun::star::awt::KeyModifier::SHIFT|
 +
                      com::sun::star::awt::KeyModifier::MOD1;
 +
 +
// associate the accelerator with a command
 +
xGlobalAccelCfg->setKeyEvent(aKeyEvent, rtl::OUString::createFromAscii(“.uno:Open”));
 +
 +
// store the changes in the configuration
 +
xGlobalAccelCfg->store();
 +
</source>
 +
[[Category:Framework]]

Latest revision as of 09:33, 25 November 2009

This tutorial will give you a detailed step-by-step insight into accelerators in OpenOffice.org. 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++/Java knowledge (Using C++/Java with the SDK)
   * How to create an extension with the "OpenOffice.org SDK"

General abstract of the OpenOffice.org accelerator concept

Accelerator architecture

Architecture - Accelerators.png

OpenOffice.org accelerators are available and stored on three different layers which have a pre-defined priority. The layers are:

Priority of the different accelerator layers
1. Document based accelerators
2. Module based accelerators
3. Global based accelerators

If a user presses a possible keyboard shorcut the framework implementation starts to check every layer (using the pre-defined order document, module, global) for a matching entry. If there is match the associated command URL is used to find a dispatch object where the command can be executed. If no matching entry has been found the current application module is asked to process the keyboard event.

How to access the different accelerator layers

Access to Accelerator Managers.png

Global Accelerator Manager

The global accelerator manager can be directly created by using the OpenOffice.org service manager. The service name of the global accelerator manager is called com.sun.star.ui.GlobalAcceleratorManager. This service provides just one interface where accelerators can be retrieved, changes and removed.

module com {  module sun {  module star {  module ui {
 
//-----------------------------------------------
/** provides access to the global shortcut configuration set.
 
    <p> The GlobalAcceleratorConfiguration service can be created
    by using an UNO service manager. It provides then access to
    the global accelerator configuration.</p>
 
    @since OOo 2.0.0
*/
service GlobalAcceleratorConfiguration : XAcceleratorConfiguration 
{};
 
}; }; }; }; // com.sun.star
 
#endif

Module Accelerator Manager

A module accelerator manager must be created via the one-instance service service com.sun.star.ui.ModuleUIConfigurationManagerSupplier.

module com { module sun { module star { module ui { 
 
/** allows to retrieve user interface configuration managers related to
    OpenOffice.org modules.
 
    @since OOo 2.0.0
*/
 
interface XModuleUIConfigurationManagerSupplier : ::com::sun::star::uno::XInterface
{
    //----------------------------------------------------------------------
    /** returns the requested module based user interface configuration manager.
 
        @param ModuleIdentifier
            a module identifier which identifies an OpenOffice.org module. The 
            module identifier can be retrieved from the 
            <type scope=com::sun::star::frame>ModuleManager</type> service.
 
        @returns 
            an object implementing 
            <type scope="::com::sun::star::ui">ModuleUIConfigurationManager</type> 
            service. If the provided module identifier is unknown a 
            <type scope="com::sun::star::container">NoSuchElementException</type>
            is thrown.
    */
    XUIConfigurationManager getUIConfigurationManager( [in] string ModuleIdentifier ) raises ( com::sun::star::container::NoSuchElementException );
};
 
//=============================================================================
 
}; }; }; };

This service provides access to the module specific ui configuration managers via the method getUIConfigurationManager. The module service name must be provided to access a certain module.

Document Accelerator Manager

module com { module sun { module star { module ui { 
 
/** allows to retrieve the user interface configuration manager related to
    an object.
 
    @since OOo 2.0.0
*/
 
interface XUIConfigurationManagerSupplier : ::com::sun::star::uno::XInterface
{
    //----------------------------------------------------------------------
    /** returns the user interface configuration manager related to the 
        object.
 
        @returns 
            an object implementing 
            <type scope="::com::sun::star::ui">UIConfigurationManager</type> 
            service.
    */
    XUIConfigurationManager getUIConfigurationManager();
};
 
//=============================================================================
 
}; }; }; };
module com { module sun { module star { module ui { 
 
/** specifies a user interface configuration manager interface which 
    controls the structure of all customizable user interface 
    elements.
 
    @since OOo 2.0.0
*/
 
interface XUIConfigurationManager : ::com::sun::star::uno::XInterface
{
    /** resets the configuration manager to the default user interface 
        configuration data. 
        <p>
        This means that all user interface configuration data of the 
        instance will be removed. A module based user interface 
        configuration manager removes user defined elements, but set all
        other elements back to default. It is not possible to remove 
        default elements from a module user interface configuration 
        manager.
        </p>
    */
    void reset();
 
    /** retrieves information about all user interface elements within 
        the user interface configuration manager.
 
        @param ElementType
            makes it possible to narrow the result set to only one type 
            of user interface elements. If all user interface element 
            types should be returned 
            <value scope=com::sun::star::ui>UIElementType::UNKNOWN</value> 
            must be provided.
 
        @return
            returns all user interface elements within the user interface 
            configuration manager that meet the given ElementType 
            specification. <p>The following 
            <type scope="com::sun::star::beans">PropertyValue</type> entries 
            are defined inside the sequence for every user interface element.
            <ul>
                <li><b>ResourceURL<b/>specifies the unique resource URL for 
                the user interface element.</li>
                <li><b>UIName<b/>specifies the user interface name for the 
                user interface element. Not all user interface elements have 
                set UIName. At least menubars do not.</li>
            </ul>
            <p>
 
        @see UIElementType
    */
    sequence< sequence< com::sun::star::beans::PropertyValue > > getUIElementsInfo( [in] short ElementType ) raises ( com::sun::star::lang::IllegalArgumentException );
 
    /** creates an empty settings data container.
 
        @return
            an empty user interface element settings data container, which 
            implements <type>UIElementSettings</type>.
    */
    ::com::sun::star::container::XIndexContainer createSettings();
 
    /** determines if the settings of a user interface element is part the 
        user interface configuration manager.
 
        @param ResourceURL
            a resource URL which identifies the user interface element. A 
            resourcce URL must meet the following syntax: 
            "private:resource/$type/$name. It is only allowed to use ascii 
            characters for type and name. 
 
        @return
            <TRUE/> if settings have been found, otherwise <FALSE/>.
    */
    boolean hasSettings( [in] string ResourceURL ) raises ( com::sun::star::lang::IllegalArgumentException );
 
    /** retrieves the settings of a user interface element.
 
        @param ResourceURL
            a resource URL which identifies the user interface element. A 
            resourcce URL must meet the following syntax: 
            "private:resource/$type/$name. It is only allowed to use ascii 
            characters for type and name. 
 
        @param bWriteable
            must be <TRUE/> if the retrieved settings should be a writeable. 
            Otherwise <FALSE/> should be provided to get a shareable reference 
            to the settings data.
 
        @return
            settings data of an existing user interface element, which 
            implements <type>UIElementSettings</type>. If the settings data 
            cannot be found a 
            <type scope="com::sun::star::container">NoSuchElementException</type> 
            is thrown.  If the <member>ResourceURL</member> is not valid or 
            describes an unknown type a 
            <type scope="com::sun::star::lang">IllegalArgumentException</type>
            is thrown.
    */
    ::com::sun::star::container::XIndexAccess getSettings( [in] string ResourceURL, [in] boolean bWriteable ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException );
 
    /** replaces the settings of a user interface element with new settings.
 
        @param ResourceURL
            a resource URL which identifies the user interface element to 
            be replaced. If no element with the given resource URL exists a 
            <type scope="com::sun::star::container">NoSuchElementException</type> 
            is thrown.
 
        @param aNewData
            the new settings data of an existing user interface element, which 
            implements <type>UIElementSettings</type>.
 
        <p>
        If the settings data cannot be found a 
        <type scope="com::sun::star::container">NoSuchElementException</type> 
        is thrown. If the <member>ResourceURL</member> is not valid or describes 
        an unknown type a 
        <type scope="com::sun::star::lang">IllegalArgumentException</type>
        is thrown. If the configuration manager is read-only a 
        <type scope="com::sun::star::lang">IllegalAccessException</type> is 
        thrown.
        </p>
    */
    void replaceSettings( [in] string ResourceURL, [in] ::com::sun::star::container::XIndexAccess aNewData ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 
    /** removes the settings of an existing user interface element. 
 
        @param ResourceURL
            a resource URL which identifies the user interface element settings 
            to be removed. 
 
        <p>
        If the settings data cannot be found a 
        <type scope="com::sun::star::container">NoSuchElementException</type> is 
        thrown. If the <member>ResourceURL</member> is not valid or describes an 
        unknown type a <type scope="com::sun::star::lang">IllegalArgumentException</type> 
        is thrown. If the configuration manager is read-only a 
        <type scope="com::sun::star::lang">IllegalAccessException</type> is thrown.
        </p>
    */
    void removeSettings( [in] string ResourceURL ) raises ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 
    /** inserts the settings of a new user interface element.
 
        @param ResourceURL
            a resource URL which identifies the new user interface element.
 
        @param aNewData
            the settings data of the new user interface element, which implements 
            <type>UIElementSettings</type>.
 
        <p>
        If the settings data is already present a 
        <type scope="com::sun::star::container">ElementExistException</type> 
        is thrown. If the <member>ResourceURL</member> is not valid or describes 
        an unknown type a <type scope="com::sun::star::lang">IllegalArgumentException</type>
        is thrown. If the configuration manager is read-only a 
        <type scope="com::sun::star::lang">IllegalAccessException</type> is thrown.
        </p>
    */
    void insertSettings( [in] string NewResourceURL, [in] ::com::sun::star::container::XIndexAccess aNewData ) raises ( com::sun::star::container::ElementExistException, com::sun::star::lang::IllegalArgumentException, com::sun::star::lang::IllegalAccessException );
 
    /** retrieves the image manager from the user interface configuration 
        manager.
 
        <p>
        Every user interface configuration manager has one image manager 
        instance which controls all images of a module or document.
        </p>
 
        @return
            the image manager of the user interface configuration manager.
    */
    com::sun::star::uno::XInterface getImageManager();
 
    /** retrieves the keyboard short cut manager from the user interface 
        configuration manager. 
 
        <p>
        Every user interface configuration manager has one keyboard short cut 
        manager instance which controls all short cuts of a module or document.
        </p>
 
        @return
            the short cut manager of the user interface configuration manager.
    */
    com::sun::star::uno::XInterface getShortCutManager();
 
    /** retrieves the events manager from the user interface configuration manager. 
 
        <p>
        Every user interface configuration manager has one events manager 
        instance which controls the mapping of events to script URLs of a module 
        or document.
        </p>
 
        @return
            the events manager of the user interface configuration 
            manager, if one exists.
    */
    com::sun::star::uno::XInterface getEventsManager();
};
 
//=============================================================================
 
}; }; }; };

Using an Accelerator Manager to retrieve or manipulate accelerators

The access to the accelerator manager is always done via the com.sun.star.ui.XAcceleratorConfiguration interface.

module com {  module sun {  module star {  module ui {
 
//-----------------------------------------------
/** provides read/write access to an accelerator configuration set.
 
    <p>
    Such configuration set base on:<br>
    <ul>
        <li>Key events structure</li>
        <li>and Commands, which are represented as URLs; describing
            a function, which and can be executed using the dispatch API.</li>
    </ul>
    </p>
 
	<p>
    Note further:<br>
    All changes you made on this configration access modify the
    the configuration set inside memory only. You have to use
    the <type scope="com::sun::star::util">XFlushable</type> interface
    (which must be available at the same implementation object too), to
    make it persistent.
    </p>
 
    @see    AcceleratorConfiguration
    @see    <type scope="dom::sun::star::util">XFlushable</type>
 
    @since OOo 2.0.0
*/
interface XAcceleratorConfiguration
{
    //-------------------------------------------
    /** return the list of all key events, which
        are available at this configration set.
 
        <p>
        The key events are the "primary keys" of this configuration sets.
        Means: Commands are registerd for key events.
        </p>
 
        <p>
        Such key event can be mapped to its bound command,
        using the method getCommandForKeyEvent(). 
        </p>
 
        @see        getCommandForKeyEvent().
 
        @return     A list of key events.
      */
    sequence< com::sun::star::awt::KeyEvent > getAllKeyEvents();
 
    //-------------------------------------------
    /** return the registered command for the specified key event.
 
        <p>
        This function can be used to:<br>
        <ul>
            <li>by a generic service, which can execute commands if a
                keyboard event occures.</li>
            <li>or to iterate over the whole container and change some
                accelerator bindings.</li>
        </ul>
        </p>
 
        @param  aKeyEvent
                the key event, where the registered command is searched for.
 
        @return The registered command for the specified key event.
 
        @throws ::com::sun::star::container::NoSuchElementException
                if the key event is an invalid one or does not exists
                inside this configuration set.
     */        
    string getCommandByKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent )
        raises(com::sun::star::container::NoSuchElementException);
 
    //-------------------------------------------
    /** modify or create a key - command - binding.
 
        <p>
        If the specified key event does not already exists inside this
        configuration access, it will be created and the command will be
        registered for it.
        </p>
 
        <p>
        If the specified key event already exists, its command will
        be overwritten with the new command. There is no warning nor any error
        about that! The outside code has to use the method getCommandForKeyEvent()
        to check for possible collisions.
        </p>
 
        <p>
        Note: This method cant be used to remove entities from the configuration set.
        Empty parameters will result into an exception!
        Use the method removeKeyEvent() instead.
        </p>
 
        @see    removeKeyEvent()
 
        @param  aKeyEvent
                specify the key event, which must be updated or new created.
 
        @param  sCommand
                the new command for the specified key event.
 
        @throws ::com::sun::star::lang::IllegalArgumentException
                if the key event isnt a valid one. Commands can be
                checked only, if they are empty. Because every URL schema can be used
                by commands in general, so its not possible to validate it.                
     */
    void setKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent,
                      [in] string                        sCommand )
        raises(com::sun::star::lang::IllegalArgumentException);
 
    //-------------------------------------------
    /** remove a key-command-binding from this configuration set.
 
        @param  aKeyEvent
                the key event, which should be removed.
 
        @throws ::com::sun::star::container::NoSuchElementException
                if the key event does not exists inside this configuration set.
     */
    void removeKeyEvent( [in] com::sun::star::awt::KeyEvent aKeyEvent )
        raises(com::sun::star::container::NoSuchElementException);
 
    //-------------------------------------------
    /** optimized access to the relation "command-key" instead
        of "key-command" which is provided normaly by this interface.
 
        <p>
        It can be used to implement collision handling, if more then one
        key event match to the same command. The returned list contains all
        possible key events - and the outside code can select an possible one.
        Of course - mostly this list will contain only one key event ...
        </p>
 
        @param  sCommand
                the command, where key bindings are searched for.
 
        @return A list of <type scope="com::sun::star::awt">KeyEvent</type> structures,
                where the pecified command is registered for.
 
        @throws ::com::sun::star::lang::IllegalArgumentException
                if the specified command is empty. It cant be checked, if a command
                is valid - because every URL schema can be used here.
 
        @throws ::com::sun::star::container::NoSuchElementException
                if the specified command isnt empty but does not
                occure inside this configuration set.
     */
    sequence< com::sun::star::awt::KeyEvent > getKeyEventsByCommand( [in] string sCommand )
        raises(com::sun::star::lang::IllegalArgumentException   ,
               com::sun::star::container::NoSuchElementException);
 
    //-------------------------------------------
    /** optimized function to map a list of commands to a corresponding
        list of key events.
 
        <p>
        It provides a fast mapping, which is e.g. needed by a menu or toolbar implementation.
        E.g. a sub menu is described by a list of commands - and the implementation of the menu
        must show the corresponding shortcuts. Iteration over all items of this configuration
        set can be very expensive.
        </p>
 
        <p>
        Instead to the method getKeyEventsForCommand() the returned list contains only
        one(!) key event bound to one(!) requested command. If more then one key event
        is bound to a command - a selection is done inside this method.
        This internal selection cant be influenced from outside.
        </p>
 
        @attention  Because its not defined, that any command (e.g. configured inside a menu)
                    must have an accelerator - we cant reject the call if at least one command
                    does not occure inside this configuration set ...
                    We handle it more gracefully - and return an empty item instead of throwing
                    and exception.
 
        @param  lCommandList
                a list of commands
 
        @return A (non packed!) list of key events, where every item match by index
                directly to a command of the specified <var>CommandList</var>.
                If a command does not exists inside this configuration set, the
                corresponding any value will be empty.
 
        @throws ::com::sun::star::lang::IllegalArgumentException
                if at least one of the specified commands is empty.
                It cant be checked, if a command is valid -
                because every URL schema can be used here.
     */
    sequence< any > getPreferredKeyEventsForCommandList( [in] sequence< string > lCommandList )
        raises(com::sun::star::lang::IllegalArgumentException);
 
    //-------------------------------------------
    /** search for an key-command-binding inside this configuration set,
        where the specified command is used.
 
        <p>
        If such binding could be located, the command will be removed
        from it. If as result of that the key binding will be empty,
        if will be removed too.
        </p>
 
        <p>
        This is an optimized method, which can perform removing of commands
        from this configuration set. Because normaly Commands are "foreign keys"
        and key identifier the "primary keys" - it needs some work to remove
        all commands outside this container ...
        </p>
 
        @param  sCommand
                the command, which should be removed from any key binding.
 
        @throws ::com::sun::star::lang::IllegalArgumentException
                if the specified command is empty.
 
        @throws ::com::sun::star::container::NoSuchElementException
                if the specified command isnt used inside this configuration set.
     */
    void removeCommandFromAllKeyEvents( [in] string sCommand )        
        raises(com::sun::star::lang::IllegalArgumentException   ,
               com::sun::star::container::NoSuchElementException);
 
    //-------------------------------------------
    /** specifies a persistence interface which supports to
        load/store accelerator configuration data to a storage
        and to retrieve information about the current state.
     */
    interface com::sun::star::ui::XUIConfigurationPersistence;
 
    //-------------------------------------------
    /** connects this configuration to a new storage
        which must be used further on subsequent calls of
        <type scope="com::sun::star::util::">XConfigurationPersistence.load()</type>
        and <type scope="com::sun::star::util::">XConfigurationPersistence.store()</type>.
     */
    interface com::sun::star::ui::XUIConfigurationStorage;
 
    //-------------------------------------------
    /** supports to notify other implementations about
        changes of this accelerator configuration.
     */
    interface com::sun::star::ui::XUIConfiguration;
 
}; // interface XAcceleratorConfiguration
 
}; }; }; }; // com.sun.star

Sample Code

// Create the global accelerator configuration service
Reference< com::sun::star::ui::XacceleratorConfiguration > xGlobalAccelCfg( 
  m_xServiceManager->createInstance( 
    ::rtl::OUString("com.sun.star.ui.GlobalAcceleratorConfiguration")), 
  UNO_QUERY_THROW );
 
// set key event to define the accelerator
com::sun:star::awt::KeyEvent aKeyEvent;
aKeyEvent.KeyCode   = com::sun::star::awt::Key::S;
aKeyEvent.Modifiers = com::sun::star::awt::KeyModifier::SHIFT|
                      com::sun::star::awt::KeyModifier::MOD1;
 
// associate the accelerator with a command
xGlobalAccelCfg->setKeyEvent(aKeyEvent, rtl::OUString::createFromAscii(“.uno:Open”));
 
// store the changes in the configuration
xGlobalAccelCfg->store();
Personal tools