Framework/Article/General Architecture Of The Framework User Interface Implementation

From Apache OpenOffice Wiki
Jump to: navigation, search

This article describes the general architecture of the framework user interface implementation. The framework user interface implementation is responsible to provide application modules and users the following services:

  • Layout of the user interface elements
  • Creation, destruction and
  • Persistent and transient customization of the user interface elements


Overview

The following illustration shows the connections between the most important Framework objects. The blue objects are part of the Framework User Interface API implementation and gray objects are part of the general Framework API implementation.

Architecture.png

The Layout Manager

The layout manager is the central instance of a frame controlling the user interface. A layout manager controls the visibility, size and position of the user interface elements of OpenOffice.org. Every created frame has an associated layout manager that can be retrieved using the property LayoutManager. For OpenOffice.org 2.3 and earlier the layout manager is responsible for:

  • Menubar
  • Toolbars
  • Statusbar

Docking windows are controlled by a C++ implementation which is currently independent from the layout manager. It's planned to move the docking window implementation to the layout manager.

//============================================================================= 
 
 module com { module sun { module star { module frame {
 
//============================================================================= 
/** controls the layout of user interface elements which are part of a frame.
 
    Layout management is the process of determining the size and position of 
    user interface elements. By default, each Frame has a layout 
    manager -- it performs layout management for the user interface elements 
    within the frame. User interface elements can provide size and alignment 
    hints to layout managers, but layout managers have the final decision on 
    the size and position of those user interface elements. 
 
    @since OOo 2.0.0
*/
 
service LayoutManager
{
    /** central interface to query for, create, destroy and manipulate user 
        interface elements which are bound to a frame.
 
        @see ::com::sun::star::frame::XLayoutManager;
    */
    interface ::com::sun::star::frame::XLayoutManager;
 
    /** notification interface to receive status information about the state 
        of the connected frame.
 
        E.g., you can receive events of instantiation/destruction and
        activation/deactivation of a frame.
 
        @see XFrame::addFrameActionListener()
        @see XFrame::removeFrameActionListener()
    */
    interface ::com::sun::star::frame::XFrameActionListener;
 
    /** notification interface to receive change messages of user interface 
        elements which are part of the layout manager.
 
        E.g., you can receive events of insertion/replacing and
        removing of settings data of user interface elements.
 
        @see com::sun::star::ui::XUIConfiguration
    */
    interface ::com::sun::star::ui::XUIConfigurationListener;
 
    /** provides functions to merge menus for inplace editing of components
        inside OpenOffice.org.
    */
    interface ::com::sun::star::frame::XMenuBarMergingAcceptor;
 
    /** registers listeners that want to receive layout manager
        events.
    */
    [optional] interface ::com::sun::star::frame::XLayoutManagerEventBroadcaster;
 
    /** interface to support settings a menu bar for inplace editing of 
        components inside OpenOffice.org.
 
        @deprecated
    */    
    [optional] interface ::com::sun::star::frame::XInplaceLayout;
};
 
}; }; }; };

Example to retrieve the layout manager instance from a frame.

::com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropSet; 
 
xPropSet = ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >( xFrame, ::com::sun::star::uno::UNO_QUERY );
 
if ( xPropSet.is() )
{
    try
    {
        xLayoutManager.set( xPropSet->getPropertyValue( 
            ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))), 
            ::com::sun::star::uno::UNO_QUERY );
    }
    catch ( com::sun::star::beans::UnknownPropertyException& )
    {
    }
}

Address a single User Interface Element

The implementation uses a new URL schema to address any user interface element.

private:resource/<user interface element type>/<user interface element name>

  • User interface element types

Specifies to which type the request user interface element belongs to. The following user interface element types are defined: toolbar, menubar and statusbar

  • User interface element name

A user interface element name must specify unequivocally a single user interface element within the same type class of a module or document. The name is used to address the user interface definition file. For example, a user interface definition of a toolbar named “tablebar” should only exists once.

User-defined toolbars must start with “user_” following a unique name so they can be identified as user-defined. User-defined toolbars are not context sensitive an therefor are automatically created and shown by a layout manager instance. Add-on toolbars use the prefix "addon_" and are also controlled by the layout manager automatically.

The following example shows how to address a menu bar of an application module. private:resource/menubar/menubar

There is no need to specify the module for a user interface element as every frame which is bound to a document provides context information that is used to address the correct configuration data.

Toolbars

Modern GUI systems support toolbars which are rows, columns, or blocks of onscreen buttons or icons that, when clicked, activate certain functions of the program. Toolbars can be docked to the four sides of the main application window or float on the desktop. OpenOffice.org supports an unlimited number of toolbars.
Toolbars are addressed by the following generic schema:

private:resource/toolbar/<name of toolbar>

Custom toolbars which can be created by the user using "Tools - Customize - Toolbars" use the following schema:

private:resource/toolbar/custom_<name of custom toolbar>

Add-on toolbars which can be defined by extensions and use the following schema:

private:resource/toolbar/addon_<name of add-on toolbar>

The LayoutManager automatically determines the type of toolbar and according to the type controls the toolbars. Custom and add-on toolbars are never context dependent, while normal toolbars can be context or non-context sensitive.

Menubar

A menu bar is a region on GUI where application specific functions reside. Its purpose is to provide access to different application-specific menus, such as opening files, window manipulation or help.

The menu bar will be accessed by using the following schema:

private:resource/menubar/menubar

Statusbar

A status bar in GUI systems is a component (widget) that is often found at the bottom of windows. It's normally divided into sections, each of which shows different information. Its job is primarily to display information about the current state of its window.

A status bar is addressed by using the following schema:

private:resource/statusbar/statusbar

The User Interface Configuration API

Overview

OpenOffice.org support a user interface configuration API to adapt the user interface elements to the needs of users and developers. User interface configuration data can be global, module or document based. The global user interface configuration layer is only available for accelerators. The following user interface elements can be accessed via the user interface configuration API:

  • Tool bars
  • Menu bar
  • Status bar
  • Accelerators
  • Command images

The Module User Interface Configuration Manager

A module user interface configuration manager can be retrieved from the com::sun::star::ui::ModuleUIConfigurationManagerSupplier service which can be created with the OpenOffice.org service manager using its service specifier. One has to provide the module identifier retrieved from the com::sun::star::frame::ModuleManager service to specify which ModuleUIConfigurationManager should be accessed. The following code snippet shows how one can use the ModuleManager to identify the module bound to a frame. The module identifier can then be used to retrieve the ModuleUIConfigurationManager.

[cpp]

 ...
 
 try
 {
     ::rtl::OUString aModuleIdentifier;
     
     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager >( 
         xServiceManager->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
             "com.sun.star.frame.ModuleManager" ))), ::com::sun::star::uno::UNO_QUERY_THROW );
     
     aModuleIdentifier = xModuleManager->identify( 
         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( xFrame, ::com::sun::star::uno::UNO_QUERY ) );
     if ( aModuleIdentifier.getLength() )
     {
         ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier;
         xModuleCfgSupplier = Reference< XModuleUIConfigurationManagerSupplier >(
         xServiceManager->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 
             "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ))), ::com::sun::star::uno::UNO_QUERY_THROW );
         xModuleCfgMgr = ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfiguration >( 
             xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier ), ::com::sun::star::uno::UNO_QUERY );
     }
 }
 catch( ::com::sun::star::uno::Exception& )
 {
 }
 
 ...

The Document User Interface Configuration Manager

Persistence

User Interface Configuration Data Format

Maintenance of Menus, Toolbars and User Interface Commands

The resource file system which stored the user interface configuration data for older OpenOffice.org version is obsolete for most user interface elements of Openoffice.org 2.x (except context menus). As described in chapter 9 of the OpenOffice.org XML File Format documentation all user interface configuration data is stored in a XML based file, which has already been part of Openoffice.org 1.1. This chapter describes how to maintain the necessary files to add/replace and remove new menu items/toolbar items and user interface commands. Every OpenOffice.org module has a configuration file where all supported user interface commands are stored with their internationalized user interface command label. The label is used to set the correct text of a menu item. The implementation also creates a short command description from the label (without mnemonic and subsequent ...) which is used by toolbar items without an image and the short bubble help.

The configuration files for an installed OpenOffice.org are located at: <Office installation>/share/registry/org/openoffice/Office/UI. The schema definition of these configuration files can be found below:

[xml] <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE oor:component-schema SYSTEM "../../../../../component-schema.dtd"> <oor:component-schema xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oor:name="Commands" oor:package="org.openoffice.Office.UI" xml:lang="en-US">

 <info>
   <author>CD</author>
     <desc >Contains general information about ~ and rules, and about actions based on office commands.</desc>
 </info>
 <templates>
   <group oor:name="LabelType">
     <info>
       <desc>Provides a mapping between commands and their textual representation on the user interface.</desc>
     </info>
     <prop oor:name="Label" oor:type="xs:string" oor:localized="true">
       <info>
         <desc>A localized text that describes the command or identifier. Can be used as a label inside a menu or as short tool tip help.</desc>
       </info>
     </prop>
     <prop oor:name="ContextLabel" oor:type="xs:string" oor:localized="true">
       <info>
         <desc>A localized text that describes the identifier of a command in a structured menu.  </desc>
       </info>
     </prop>
     <prop oor:name="Properties" oor:type="xs:int">
       <info>
         <desc>
           Additional information about a single command.
           Bit 0 = Command has an image.
           Bit 1 = Image must be mirrored  (CTL/vertical text).
           Bit 2 = Image must be rotated (CTL/vertical text).
         </desc>
       </info>
       <value>0</value>
     </prop>
   </group>
 </templates>

<component/> </oor:component-schema>

A LabelType consists of three properties.

  • Label

A label contains the menu label text with an optional mnemonic (~) and possible “...” characters at the end to specify that a dialog will follow. The Office automatically creates a quick help text out of the label string, it removes the mnemonic and “...” characters at the end.

  • ContextLabel

This is a special label which is used for sub-menu entries located on level two or greater depth. There are some popup menus which have a label which describe an action, e.g. "Insert". All sub-menu entries of this popup menu should not contain "Insert" again (e.g. "Insert Picture").

  • Properties

A sal_Int32 type which specifies a bit field to store additional information about the command.

    • Bit 0 = The command has an associated image. The OpenOffice.org image manager tries to retrieve an image for this command.
    • Bit 1 = Image must be mirrored in CTL/vertical text contexts.
    • Bit 2 = Image must be rotated in CTL/vertical text contexts.

A command configuration file has two sets which store different information. Commands which can be executed must be added to the “Commands” set. To support the definition of popup menu labels and to have a unique identifier for every popup-menu there is a second set called “Popups”. Here only labels for popup-menus should be defined, no real command is allowed to be placed here! The following cutout shows the definition of the generic user interface command “.uno:TransformDialog”. [xml] <?xml version='1.0' encoding='UTF-8'?> <oor:component-data oor:name="GenericCommands" oor:package="org.openoffice.Office.UI" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <node oor:name="UserInterface">
   <node oor:name="Commands">
     <node oor:name=".uno:JustifyPara" oor:op="replace">
       <prop oor:name="Label" oor:type="xs:string">
         <value xml:lang="de">Blocksatz</value>
         <value xml:lang="en-US">Justified</value>
         ...
       </prop>
       <prop oor:name="Properties" oor:type="xs:int">
         <value>7</value>
       </prop>
     </node>
     ...
   </node>
   <node oor:name=”Popup”>
     ...
   </node>
 </node>

</oor:component-data>


The configuration files for all modules are maintained in the project officecfg within the folder officecfg/registry/data/org/openoffice/Office/UI.

Adding a new Toolbar

There are some additional steps necessary if you want to add a new toolbar to the Office. Two different situations are possible which must be handled:

Adding a shell based toolbar

A shell based toolbar will be opened/closed automatically by sfx2/framework code. Whenever the shell is pushed to the shell stack a open/close command is triggered at the framework based layout manager. As the sfx2 is the starting point for the open/close command the toolbar must be registered at the shell. You also need a unqiue identifier for your toolbar (in the past this was also the resource ID for the toolbar). The sfx has a mapping table which can be found in the file: sfx2/source/appl/workwin.cxx. It starts with the following lines:

[cpp] static const ResIdToResName pToolBarResToName[] = {

{ 558,      "fullscreenbar"        },
{ 560,      "standardbar",         },
{ 18003,    "formsnavigationbar"   },
...
{ 25000,    “newtoolbar”           }

};

You have to add a line which maps the unique identifier of your toolbar to the new internal toolbar name which also defines the xml filename which contains the structure data of the toolbar. You have to create the xml file and define the toolbar items within your toolbar. If your new shell is used by more than one application module you have to copy the xml file to the uiconfig folder of all dependent modules. The UI name for the toolbar must be specified within the window state configuration file of every module that uses the toolbar. The following example specifies the UI name for a new toolbar called “newtoolbar”:

[xml] <node oor:name="private:resource/toolbar/newtoolbar" oor:op="replace">

<prop oor:name="UIName" oor:type="xs:string">
<value xml:lang="en-US">My new toolbar</value>
<value xml:lang="de">Meine neue Toolbar</value>
</prop>

</node>

Adding a non-shell based toolbar

A non-shell based toolbar can be defined without adapting any sfx2/shell based code. You have to define a unique internal name for your toolbar, e.g newtoolbar. Create a xml file that specifies which commands are part of the toolbar. Copy the toolbar xml file to the application module projects that must have access to it (there exists a folder called “uiconfig” in every application project). The UI name for the toolbar must be specified within the window state configuration file of every module that uses the toolbar. The following example specifies the UI name for a new toolbar called “newtoolbar”: [xml] <node oor:name="private:resource/toolbar/newtoolbar" oor:op="replace">

<prop oor:name="UIName" oor:type="xs:string">
<value xml:lang="en-US">My new toolbar</value>
<value xml:lang="de">Meine neue Toolbar</value>
</prop>

</node>

How to add, replace or remove a User Interface Command

A sfx2 based Openoffice.org module should obtain a new slot ID and creates a SID_<COMMAND> definition for it (This is also true for non-sfx2 based modules which wants to create a new global command). It depends on the new command if it is part of the generic commands or only dependent on a single module. The slot must be defined within a SDI file of the chosen project. Generic commands can be part of the sfx2 or svx based SDI files. A module based command must be part of a respective module based SDI file. A already defined command definition can be used as a template, but must be carefully adapted. A very important step is to assign a new command name to the created user interface command. It must be at least unique within the generic and module based configuration file. Please keep in mind that command definitions are NOT case-sensitive and should be carefully chosen. The command cannot be changed after release as it is also part of the dispatch API. A user interface command must at least set one of the entries AccelConfig, MenuConfig, StatusBarConfig or ToolBoxConfig to true. Otherwise the command cannot be configured to a user interface element. The slot itself must be added to the correct shell. As the new command can also be part of the menu bar or a toolbar we have to add a new entry within the respective configuration file GenericCommands.xcu or the module dependent configuration file. This depends on the command itself. If the command should be part of the menu bar or a toolbar the command must be added to the XML based configuration file within the module's project.

Images

If the command has associated images you have to do the following additional steps:

Rename all your images to the following schema:

  • sc_<commandname> for small color images
  • lc_<commandname> for large color images
  • sch_<commandname> for small highcontrast images
  • lch_<commandname> for large highcontrast images

ATTENTION: The command name must be in a lower case ascii characters!

Copy the files to the following directories: res/commandimagelist, so_res/commandimagelist. If you work on a CWS you have to cwsadd these folders. Add a prop node called “Properties” to the command xcu file and set the integer value to the needed value. Please read the section before where this property node is explained. If you want to build your CWS you must also add the “framework” project to your CWS. You only need to do a dmake in the util folder to create a commandimagelist.ilst file. It contains the list of all image files within the commandimagelist folder of res and so_res.

Please don't use the old schema sc<number> as it is outdated and all images using this schema and are related to toolbars or menus will be removed. Their use is deprecated and only the above

Personal tools