Difference between revisions of "Framework/Article/OpenOffice.org 2.0 User Interface Controller Internals"

From Apache OpenOffice Wiki
Jump to: navigation, search
(Replaced content with "= OpenOffice.org 2.0 User Interface Controller Internals = Category:Framework:Article")
Line 1: Line 1:
 
= OpenOffice.org 2.0 User Interface Controller Internals =
 
= OpenOffice.org 2.0 User Interface Controller Internals =
  
A typical OOo 2.0 document contains different user interface elements. They have to provide their functions to the user and display the current state of the document view.
 
 
If you want to know about the different controller type then you should read the controller tutorials available in the [[Framework#Articles_.26_Tutorials|articles&tutorials chapter]].
 
 
'''How and in which infrastructure do they work?'''
 
 
[[Image:OpenOffice2UserInterfaceElements.png]]
 
 
The user interface elements are using controllers for each of their elements to bind them to the dynamic state of the application module. It's the responsibility of every user interface controller to call and to display the current state of its bound function.
 
 
OOo 2.0 uses the following user interface controllers:
 
 
* Menubar
 
** Popup menu controller
 
** Generic menu item controller
 
** Internal menu controller
 
* Toolbar
 
** Generic toolbar item controller
 
** Specific toolbar item controller
 
* Statusbar
 
** Specific statusbar item controller
 
 
== Menubar ==
 
 
=== Generic menu item controller ===
 
 
A normal menu item is controlled by a generic menu item controller. A menu bar of an application module uses for about 90% of its menu items generic item controllers. For example the Edit - Undo, Redo and Edit - Cut, Copy and Paste menu items are implemented using generic menu item controllers.
 
 
A generic menu item controller supports the following interfaces:
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
published interface XStatusListener: com::sun::star::lang::XEventListener
 
{
 
  /** is called when the status of the feature changes.
 
    @param State
 
  provides information about changes of the requested feature */
 
[oneway] void statusChanged( [in] FeatureStateEvent State );
 
};
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
published struct FeatureStateEvent: com::sun::star::lang::EventObject
 
{
 
  //-------------------------------------------------------------------------
 
  /** contains the URL of the feature. */
 
  com::sun::star::util::URL FeatureURL;
 
 
  //-------------------------------------------------------------------------
 
  /** contains a descriptor of the feature for the user interface.*/
 
  string FeatureDescriptor;
 
 
  //-------------------------------------------------------------------------
 
  /** specifies whether the feature is currently enabled or disabled. */
 
  boolean IsEnabled;
 
 
  //-------------------------------------------------------------------------
 
  /** specifies whether the <type>XDispatch</type> has to be requeried. */
 
  boolean Requery;
 
 
  //-------------------------------------------------------------------------
 
  /** contains the state of the feature in this dispatch.*/
 
  any State;
 
};
 
}; }; }; };
 
</source>
 
 
It supports the following generic functions by listing to status updates provided by function statusChanged.<br/>
 
{| width="100%" border="1" cellpadding="4"
 
|- valign="TOP"
 
! width="15%" |
 
Variable
 
! width="42%" |
 
UNO Type/Poolitem
 
! width="43%" |
 
Action
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
String / SfxStringItem
 
| width="43%" |
 
Menu item changes its label to the content of the provided string.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
Boolean / SfxBoolItem
 
| width="43%" |
 
Menu item checks or unchecks its menu item, according to the boolean value.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
com.sun.star.frame.status.VisibilityItem / SfxVisibilityItem
 
| width="43%" |
 
Menu item will be made visible or invisible, according to the provided state.
 
|- valign="TOP"
 
| width="15%" |
 
IsEnabled
 
| width="42%" |
 
Boolean
 
| width="43%" |
 
Menu item is enabled or disabled according to the value of IsEnabled.
 
|}
 
<br/>
 
 
=== Internal menu controller ===
 
 
An Internal menu controllers is used for special menu items, like the window list (accessible via the Window popup menu). Internal menu controllers are completely responsible for their menu items. Currently there is no special menu controller which is implemented outside the framework library. There exists no UNO API to implement internal menu controllers.
 
 
=== Popup menu controller ===
 
 
A popup menu controller is a special menu controller which is responsible for a whole popup menu inside a menu bar. A popup menu controller must be a UNO service and registered in the configuration controller set, which can be found at org.openoffice.Office.UI.Controller/Registered/PopupMenu. The configuration set associates UNO service names implementing a popup menu controller with a command URL. The command URL is used by our XML based menu bar description. A popup menu controller is created by a popup menu controller factory which uses the configuration set to retrieve the correct service name and to initialize it.
 
<br/>
 
An abstract from the org.openoffice.Office.UI.Controller/Registered/PopupMenu:
 
 
<source lang="xml">
 
<!DOCTYPE oor:component-data SYSTEM "../../../../../component-update.dtd">
 
<oor:component-data oor:name="Controller" 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="Registered">
 
  <node oor:name="PopupMenu">
 
  <node oor:name="c1" oor:op="replace">
 
    <prop oor:name="Command">
 
    <value>.uno:CharFontName</value>
 
    </prop>
 
    <prop oor:name="Module">
 
    <value/>
 
    </prop>
 
    <prop oor:name="Controller">
 
    <value>com.sun.star.comp.framework.FontMenuController</value>
 
    </prop>
 
  </node>
 
  ...
 
</source>
 
A popup menu controller must support the following services / interfaces:<br />
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
service PopupMenuController
 
{
 
//-------------------------------------------------------------------------
 
/** supports functions to initialize and update a popup menu controller
 
    implementation.
 
 
    A popup menu controller implementation gets initialized with a
 
    com::sun::star::awt::XPopupMenu object. This assures
 
    that a popup menu controller can be implemented with any UNO based
 
    language.
 
*/
 
interface com::sun::star::frame::XPopupMenuController;
 
 
//-------------------------------------------------------------------------
 
/** provides functions to initialize a popup menu controller with
 
    specific data which are needed.
 
 
    This interface should not directly used. A factory service is responsible to
 
    initialize every controller correctly.
 
    popup menu controller needs at least two additional arguments
 
    provided as com::sun::star::beans::PropertyValue.
 
 
    Frame
 
    specifies the com::sun::star::frame::XFrame instance to which the
 
    popup menu controller belongs to.
 
 
    CommandURL
 
    specifies which popup menu controller should be created.
 
 
    @see PopupMenuControllerFactory
 
*/
 
interface com::sun::star::lang::XInitialization;
 
 
//-------------------------------------------------------------------------
 
/** used to brief the popup menu controller with new status information.
 
    A popup menu controller makes special functions available to users which
 
    normally depend on the state of other data. This interface is used to
 
    send this data to a controller implementation.
 
*/
 
interface com::sun::star::frame::XStatusListener;
 
};
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
interface XPopupMenuController : com::sun::star::uno::XInterface
 
{
 
    /** provides a com::sun::star::awt::XPopupMenu to a popup menu
 
        controller implementation. The controller must fill this popup
 
        menu with its functions.
 
 
        @param PopupMenu
 
        An empty popup menu that must be filled by the popup menu controller.
 
    */
 
    void setPopupMenu( [in] com::sun::star::awt::XPopupMenu PopupMenu );
 
 
    /** briefs the popup menu controller to update the contents of
 
        the provided popup menu to reflect the current state. A
 
        controller should never update the popup menu structure
 
        on its own to prevent performance problems. A better way
 
        would be that a controller registers itself as status listener
 
        for a command URL and immediately deregister after that.
 
        Therefore status updates will not be send regularly for a
 
        non visible popup menu.
 
    */
 
    void updatePopupMenu();
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module lang {
 
 
published interface XInitialization: com::sun::star::uno::XInterface
 
{
 
    // DocMerge from xml: method com::sun::star::lang::XInitialization::initialize
 
    /** initializes the object.
 
        It should be called directly after the object has been created.
 
    */
 
    void initialize( [in] sequence< any > aArguments ) raises( com::sun::star::uno::Exception );
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published interface XStatusListener: com::sun::star::lang::XEventListener
 
{
 
    /** is called when the status of the feature changes.
 
       
 
        @param State
 
        provides information about changes of the requested feature
 
    */
 
    [oneway] void statusChanged( [in] FeatureStateEvent State );
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published struct FeatureStateEvent: com::sun::star::lang::EventObject
 
{
 
    //-------------------------------------------------------------------------
 
    /** contains the URL of the feature.                                    */
 
    com::sun::star::util::URL FeatureURL;
 
 
    //-------------------------------------------------------------------------
 
    /** contains a descriptor of the feature for the user interface.        */
 
    string FeatureDescriptor;
 
 
    //-------------------------------------------------------------------------
 
    /** specifies whether the feature is currently enabled or disabled.      */
 
    boolean IsEnabled;
 
 
    //-------------------------------------------------------------------------
 
    /** specifies whether the XDispatch object has to be re-queried.        */
 
    boolean Requery;
 
 
    //-------------------------------------------------------------------------
 
    /** contains the state of the feature in this dispatch.                  */
 
    any State;
 
};
 
 
}; }; }; };
 
</source>
 
 
The framework project provides a base class to implement popup menu controller easier. It can be found in ''framework/inc/helper/popupmenucontrollerbase.hxx''. There are several implementations for popup menu controller in ''framework/source/uielement'' which uses the base class and can be used as templates.<br/>
 
<br/>
 
Currently OOo 2.0 provides the following popup menu controllers:
 
<br/>
 
 
{| width="100%" border="1" cellpadding="4"
 
|- valign="TOP"
 
! width="24%" |
 
Command
 
! width="12%" |
 
Modules
 
! width="31%" |
 
Service
 
! width="34%" |
 
Purpose
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:CharFontName</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.FontMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with all supported fonts.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:FontHeight</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.FontSizeMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with all supported font sizes.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:ObjectMenue</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.ObjectMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with all supported commands of an embedded object.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:InsertPageHeader</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.HeaderMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu to insert pages headers.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:InsertPageFooter</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.FooterMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu to insert page footers.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:ChangeControlType</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.ControlMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu to change the control type of a selected form control.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:AvailableToolbars</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.ToolBarsMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu to show/hide toolbars.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:ScriptOrganizer</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.MacrosMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with all available scripting languages.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:RecentFileList</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.RecentFilesMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with recently opened files.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:AddDirect</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.NewMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu to create document for all available application modules.</font>
 
|- valign="TOP"
 
| width="24%" |
 
<font size="2">.uno:AutoPilotMenu</font>
 
| width="12%" |
 
<font size="2">all</font>
 
| width="31%" |
 
<font size="2">com.sun.star.comp.framework.NewMenuController</font>
 
| width="34%" |
 
<font size="2">Provides a popup menu with all available wizards.</font>
 
|}
 
 
The menu bar is completely controlled by an UNO implementations and is not based on any old sfx2 code. Therefor old sfx2 based and new non-sfx2 application modules are equally supported.
 
 
== Toolbar ==
 
 
=== Toolbar item controller ===
 
 
Toolbar item controllers are responsible for a single toolbar button or toolbar item window (like a combobox, dropdown-box or an edit field). A toolbar item controller must support the following services and interfaces.
 
 
<br /><br />
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
service ToolbarController
 
{
 
    //-------------------------------------------------------------------------
 
    /** with this interface a component can receive events if a feature has
 
        changed.
 
       
 
        The toolbar controller implementation should register itself as a
 
        listener when its com::sun::star::util::XUpdatable interface has been called.
 
    */
 
    interface com::sun::star::frame::XStatusListener;
 
 
    //-------------------------------------------------------------------------
 
    /** used to initialize a component with required arguments.
 
       
 
        A toolbar controller needs at least three additional arguments provided as
 
        com::sun::star::beans::PropertyValue
 
 
        Frame
 
        a com::sun::star::frame::XFrame instance to which the toolbar controller belongs.
 
 
        CommandURL
 
        a string which specifies the command a toolbar controller is bound.
 
 
        ServiceManager
 
        a com::sun::star::lang::XMultiServiceFactory instance which can be used to
 
        create additional UNO services.
 
    */
 
    interface com::sun::star::lang::XInitialization;
 
 
    //-------------------------------------------------------------------------
 
    /** used to notify an implementation that it needs to add its listener or remove
 
        and add them again.
 
 
        A toolbar controller instance is ready for use after this call has been made
 
        the first time. The toolbar implementation guarantees that the controller's
 
        item window has been added to the toolbar and its reference is held by it.
 
    */
 
    interface com::sun::star::util::XUpdatable;
 
 
    //-------------------------------------------------------------------------
 
    /** used to notify changed features and requests for additional user interface
 
        items.
 
 
        Mostly used by a toolbar implementation to forward information to and request
 
        services from a toolbar controller component. This interface must be useable
 
        after com::sun::star::lang::XInitialitation::initialize has been called. The
 
        behavior of the interface is undefined if the controller component hasn't been
 
        initialized.
 
    */
 
    interface com::sun::star::frame::XToolbarController;
 
 
    //-------------------------------------------------------------------------
 
    /** used to notify and retrieve information that are specific for sub-toolbar
 
        controllers.
 
 
        Used by implementations that want to provide the toolbar button sub-toolbar
 
        function feature. A controller supporting this interface exchanges the
 
        function of its own toolbar button, that opened the sub-toolbar, with the
 
        one that has been selected on the sub-toolbar.
 
    */
 
    [optional] interface ::com::sun::star::frame::XSubToolbarController;
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published interface XStatusListener: com::sun::star::lang::XEventListener
 
{
 
/** is called when the status of the feature changes.
 
 
@param State
 
provides information about changes of the requested feature
 
*/
 
[oneway] void statusChanged( [in] FeatureStateEvent State );
 
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published struct FeatureStateEvent: com::sun::star::lang::EventObject
 
 
{
 
//-------------------------------------------------------------------------
 
 
/** contains the URL of the feature. */
 
com::sun::star::util::URL FeatureURL;
 
 
//-------------------------------------------------------------------------
 
 
/** contains a descriptor of the feature for the user interface.*/
 
string FeatureDescriptor;
 
 
//-------------------------------------------------------------------------
 
 
/** specifies whether the feature is currently enabled or disabled. */
 
boolean IsEnabled;
 
 
//-------------------------------------------------------------------------
 
 
/** specifies whether the <type>XDispatch</type> has to be requeried. */
 
boolean Requery;
 
 
//-------------------------------------------------------------------------
 
 
/** contains the state of the feature in this dispatch.*/
 
any State;
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module lang {
 
 
published interface XInitialization: com::sun::star::uno::XInterface
 
{
 
// DocMerge from xml: method com::sun::star::lang::XInitialization::initialize
 
/** initializes the object.
 
 
<p>It should be called directly after the object is created.
 
*/
 
void initialize( [in] sequence<any> aArguments )
 
raises( com::sun::star::uno::Exception );
 
};
 
 
//=============================================================================
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module util {
 
 
published interface XUpdatable: com::sun::star::uno::XInterface
 
{
 
//-------------------------------------------------------------------------
 
/** refreshes the data of the object from the connected data source. */
 
void update();
 
};
 
 
//=============================================================================
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
interface XToolbarController : com::sun::star::uno::XInterface
 
{
 
//=============================================================================
 
/** provides a function to execute the command which is bound to the toolbar controller.
 
 
@param
 
a combination of <type scope="com::sun::star::awt">KeyModifier</type> value that represent the current state of the modifier keys.
 
 
<p>
 
This function is usally called by a toolbar implementation when a user clicked on a toolbar button or pressed enter on the keyboard when the item has the input focus.
 
</p>
 
*/
 
void execute( [in] short KeyModifier );
 
 
//=============================================================================
 
/** notifies a component that a single click has been made on the toolbar item.
 
*/
 
void click();
 
 
//=============================================================================
 
/** notifies a component that a double click has been made on the toolbar item.
 
*/
 
void doubleClick();
 
 
//=============================================================================
 
/** requests to create a popup window for additional functions.
 
 
@return
 
a <type scope="com::sun::star::awt">XWindow</type> which provides additional functions to the user. The reference must be empty if component does not want to provide a separate window.
 
*/
 
com::sun::star::awt::XWindow createPopupWindow();
 
 
//=============================================================================
 
/** requests to create an item window which can be added to the toolbar.
 
 
@param Parent
 
a <type scope="com::sun::star::awt">XWindow</type> which must be used as a parent for the requested item window.
 
 
@return
 
a <type scope="com::sun::star::awt">XWindow</type> which can be added to a toolbar. The reference must be empty if a component does not want to provide an item window.
 
*/
 
com::sun::star::awt::XWindow createItemWindow( [in] com::sun::star::awt::XWindow Parent );
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
interface XSubToolbarController : com::sun::star::uno::XInterface
 
{
 
//=============================================================================
 
/** if the controller features a sub-toolbar.
 
 
@return
 
<TRUE/> if the controller offers a sub toolbar, otherwise <FALSE/>.
 
 
<p>
 
Enables implementations to dynamically decide to support sub-toolbars
 
or not.
 
</p>
 
*/
 
boolean opensSubToolbar();
 
 
//=============================================================================
 
/** provides the resource URL of the sub-toolbar this controller opens.
 
 
@return
 
name of the sub-toolbar this controller offers. A empty string
 
will be interpreted as if this controller offers no sub-toolbar.
 
*/
 
string getSubToolbarName();
 
 
//=============================================================================
 
/** gets called to notify a controller that a sub-toolbar function has been
 
selected.
 
 
@param aCommand
 
a string which identifies the function that has been selected by
 
a user.
 
*/
 
void functionSelected( [in] string aCommand );
 
 
//=============================================================================
 
/** gets called to notify a controller that it should set an image which
 
represents the current selected function.
 
 
<p>
 
Only the controller instance is able to set the correct image for the
 
current function. A toolbar implementation will ask sub-toolbar
 
controllers to update their image whenever it has to update the images
 
of all its buttons.
 
</p>
 
*/
 
void updateImage();
 
};
 
 
}; }; }; };
 
</source>
 
 
=== <font color="#000000"><font face="Albany, serif"><font size="5">Generic toolbar item controller</font></font></font> ===
 
 
A generic toolbar item controller is used by toolbar implementation for simple toolbar buttons. Normally most items of a toolbar consists of generic toolbar item controllers. They support the following generic functions by listening to status updates provided by the application module controller.
 
 
<br />
 
 
{| width="100%" border="1" cellpadding="4"
 
|- valign="TOP"
 
! width="15%" |
 
Variable
 
! width="42%" |
 
UNO Type/Poolitem
 
! width="43%" |
 
Action
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
String / SfxStringItem
 
| width="43%" |
 
Toolbar item changes its quick help and its label to the content of the provided string.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
Boolean / SfxBoolItem
 
| width="43%" |
 
Toolbar item checks or unchecks its item, according to the boolean value.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
com.sun.star.frame.status.VisibilityItem / SfxVisibilityItem
 
| width="43%" |
 
Toolbar item will be made visible or invisible according to the provided state.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
com.sun.star.frame.status.ItemStatus ( Will be directly retrieved with Dispatcher-&gt;QueryState(...) or transported by SfxItemState ).
 
| width="43%" |
 
Toolbar item is set to normal or tri-state according to the provided member ItemStatus.State (see <span style="font-weight: medium">''dont_care''</span> value in com.sun.star.frame.status.ItemState)
 
|- valign="TOP"
 
| width="15%" |
 
IsEnabled
 
| width="42%" |
 
Boolean
 
| width="43%" |
 
Toolbar item is enabled or disabled according to the value of IsEnabled.
 
|}
 
 
<br />
 
 
Generic toolbar item controllers are not able to support the creation of sub-toolbars or floating windows.
 
 
<br />
 
 
=== Specific toolbar item controllers ===
 
 
Specific toolbar item controllers are much more flexible and can support the creation of sub-toolbars or floating windows. As they are much more powerful they have sole responsibility to react correctly on status updates received by the application module controller.
 
 
{| width="100%" border="1" cellpadding="4"
 
|- valign="TOP"
 
! width="15%" |
 
Variable
 
! width="42%" |
 
UNO Type/Poolitem
 
! width="43%" |
 
Action required
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
Boolean / SfxBoolItem
 
| width="43%" |
 
Toolbar item checks or unchecks its item according to the boolean value, if this makes sense in the context.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
com.sun.star.frame.status.VisibilityItem / SfxVisibilityItem
 
| width="43%" |
 
Toolbar item should make itself visible or invisible according to the provided state.
 
|- valign="TOP"
 
| width="15%" |
 
State
 
| width="42%" |
 
com.sun.star.frame.status.ItemStatus ( Will be directly retrieved with Dispatcher-&gt;QueryState(...) or transported by SfxItemState ).
 
| width="43%" |
 
Toolbar item should set itself to normal or tri-state according to the provided member ItemStatus.State. It depends on the specific toolbar item if this makes sense.
 
|- valign="TOP"
 
| width="15%" |
 
IsEnabled
 
| width="42%" |
 
Boolean
 
| width="43%" |
 
Toolbar item must enabled or disabled itself according to the value of IsEnabled.
 
|}
 
 
<br /><br />
 
 
Specific toolbar item controllers must be registered in the configuration set org.openoffice.Office.UI.Controller/Registered/Toolbar when they are implemented via an UNO service.
 
 
An abstract from the Controller.xcu with registered specific toolbar item controllers:
 
 
<source lang="xml">
 
...
 
 
<node oor:name="ToolBar">
 
<node oor:name="c1" oor:op="replace">
 
  <prop oor:name="Command">
 
  <value>.uno:DBNewForm</value>
 
  </prop>
 
  <prop oor:name="Module">
 
  <value>com.sun.star.sdb.OfficeDatabaseDocument</value>
 
  </prop>
 
  <prop oor:name="Controller">
 
  <value>com.sun.star.sdb.ApplicationToolboxController</value>
 
  </prop>
 
</node>
 
<node oor:name="c2" oor:op="replace">
 
  <prop oor:name="Command">
 
  <value>.uno:Refresh</value>
 
  </prop>
 
  <prop oor:name="Module">
 
  <value>com.sun.star.sdb.OfficeDatabaseDocument</value>
 
  </prop>
 
  <prop oor:name="Controller">
 
  <value>com.sun.star.sdb.ApplicationToolboxController</value>
 
  </prop>
 
</node>
 
</node>
 
 
...
 
</source>
 
 
The framework provides a base class which makes it much easier to implement UNO based specific toolbar item controllers. It can be found in svtools/inc/toolboxcontroller.hxx.
 
 
The sfx2 based specific toolbar item controllers are registered by calling ''ToolbarControllerClass''<nowiki>::RegisterControl(SlotID, SfxModule* ). The framework implementation uses a special toolbar controller factory to create instances of sfx2 based specific toolbar item controllers. Sfx2 based specific toolbar controllers can use the known base class sfx2/inc/tbxctrl.hxx. It's a special wrapper which converts calls to the its UNO interfaces to the needs of sfx2 based toolbar controllers.</nowiki>
 
 
<source lang="cpp">
 
class SFX2_DLLPUBLIC SfxToolBoxControl:
 
    public ::com::sun::star::awt::XDockableWindowListener,
 
    public ::com::sun::star::frame::XSubToolbarController,
 
    public svt::ToolboxController
 
{
 
    friend class SfxToolbox;
 
    friend class SfxToolBox_Impl;
 
    friend class SfxToolboxCustomizer;
 
    friend class SfxPopupWindow;
 
    friend struct SfxTbxCtrlFactory;
 
 
    SfxToolBoxControl_Impl* pImpl;
 
 
protected:
 
    DECL_LINK( PopupModeEndHdl, void * );
 
    DECL_LINK( ClosePopupWindow, SfxPopupWindow * );
 
 
    // old SfxToolBoxControl methods
 
    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
 
    virtual void Select( BOOL bMod1 = FALSE );
 
    virtual void Select( USHORT nModifier );
 
 
    virtual void DoubleClick();
 
    virtual void Click();
 
    virtual SfxPopupWindowType GetPopupWindowType() const;
 
    virtual SfxPopupWindow* CreatePopupWindow();
 
    virtual SfxPopupWindow* CreatePopupWindowCascading();
 
    virtual Window* CreateItemWindow( Window *pParent );
 
 
    // Must be called by subclass to set a new popup window instance
 
    void SetPopupWindow( SfxPopupWindow* pWindow );
 
 
    // XInterface
 
    virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL acquire() throw();
 
    virtual void SAL_CALL release() throw();
 
 
    // XEventListener
 
    virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw( ::com::sun::star::uno::RuntimeException );
 
 
    // XComponent
 
    virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);
 
 
    // new controller API
 
    // XStatusListener
 
    virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );
 
 
    // XToolbarController
 
    virtual void SAL_CALL execute( sal_Int16 KeyModifier )
 
    throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL click()
 
    throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL doubleClick()
 
    throw (::com::sun::star::uno::RuntimeException);
 
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createPopupWindow()
 
    throw (::com::sun::star::uno::RuntimeException);
 
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& rParent )
 
    throw (::com::sun::star::uno::RuntimeException);
 
 
    // XSubToolbarController
 
    virtual ::sal_Bool SAL_CALL opensSubToolbar( ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual ::rtl::OUString SAL_CALL getSubToolbarName( ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL functionSelected( const ::rtl::OUString& aCommand ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL updateImage( ) throw (::com::sun::star::uno::RuntimeException);
 
 
    // XDockableWindowListener
 
    virtual void SAL_CALL startDocking( const ::com::sun::star::awt::DockingEvent& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual ::com::sun::star::awt::DockingData SAL_CALL docking( const ::com::sun::star::awt::DockingEvent& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL endDocking( const ::com::sun::star::awt::EndDockingEvent& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual sal_Bool SAL_CALL prepareToggleFloatingMode( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL toggleFloatingMode( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL closed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
 
    virtual void SAL_CALL endPopupMode( const ::com::sun::star::awt::EndPopupModeEvent& e ) throw (::com::sun::star::uno::RuntimeException);
 
 
    // helper methods
 
    void createAndPositionSubToolBar( const ::rtl::OUString& rSubToolBarResName );
 
    ::Size getPersistentFloatingSize( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, const ::rtl::OUString& rSubToolBarResName );
 
 
public:
 
    SFX_DECL_TOOLBOX_CONTROL();
 
 
    SfxToolBoxControl( USHORT nSlotID, USHORT nId, ToolBox& rBox, BOOL bShowStrings = FALSE );
 
    virtual ~SfxToolBoxControl();
 
 
    ToolBox& GetToolBox() const;
 
    unsigned short GetId() const;
 
    unsigned short GetSlotId() const;
 
 
    void Dispatch(
 
    const ::rtl::OUString& aCommand,
 
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs );
 
    static void Dispatch(
 
    const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider, const rtl::OUString& rCommand, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs );
 
 
    static SfxItemState GetItemState( const SfxPoolItem* pState );
 
    static SfxToolBoxControl* CreateControl( USHORT nSlotId, USHORT nTbxId, ToolBox *pBox, SfxModule *pMod );
 
};
 
</source>
 
 
== Statusbar ==
 
 
=== Specific statusbar item controller ===
 
 
The statusbar implementation only supports specific statusbar item controllers. There are no generic statusbar item controllers which could provide generic functions.
 
 
A statusbar item controller must support the following services and interfaces.
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
service StatusbarController
 
{
 
//-------------------------------------------------------------------------
 
/** with this interface a component can receive events if a feature has
 
changed.
 
 
<p>
 
The statusbar controller implementation should register itself as a
 
listener when its <member scope="com::sun::star::util">XUpdatable</member>
 
interface has been called.
 
</p>
 
*/
 
interface com::sun::star::frame::XStatusListener;
 
 
/** used to initialize a component with required arguments.
 
 
<b>A statusbar controller needs at least three additional arguments
 
provided as <type scope="com::sun::star::beans">PropertyValue</type>:
 
<ul>
 
<li><b>Frame</b><br>a
 
<type scope="com::sun::star::frame">XFrame</type> instance
 
to which the toolbar controller belongs.</li>
 
<li><b>CommandURL</b><br>a string which specifies the command a
 
statusbar controller is bound.</li>
 
<li><b>ServiceManager</b><br>a <type scope="com::sun::star::lang">
 
XMultiServiceFactory</type> instance which can be used to
 
create additional UNO services.</li>
 
</ul>
 
*/
 
interface com::sun::star::lang::XInitialization;
 
 
/** used to notify an implementation that it needs to add its listener or
 
remove and add them again.
 
 
<p>
 
A status bar controller instance is ready for use after this call has
 
been made the first time. The status bar implementation guarentees that
 
the controller's item window has been added to the status bar and its
 
reference is held by it.
 
</p>
 
*/
 
interface com::sun::star::util::XUpdatable;
 
 
//-------------------------------------------------------------------------
 
/** used to notify changed features and requests for additional user
 
interface items.
 
 
<p>
 
Mostly used by a status bar implementation to forward information to
 
and request services from a status bar controller component. This
 
interface must be useable after
 
<member scope="com::sun::star::lang">XInitialitation::initialize</member>
 
has been called. The behavior of the interface is undefined if the
 
controller component hasn't been initialized.
 
</p>
 
*/
 
interface com::sun::star::frame::XStatusbarController;
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published interface XStatusListener: com::sun::star::lang::XEventListener
 
{
 
    /** is called when the status of the feature changes.
 
       
 
        @param State
 
        provides information about changes of the requested feature
 
    */
 
    [oneway] void statusChanged( [in] FeatureStateEvent State );
 
 
};
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
published struct FeatureStateEvent: com::sun::star::lang::EventObject
 
{
 
    //-------------------------------------------------------------------------
 
    /** contains the URL of the feature.
 
    */
 
    com::sun::star::util::URL FeatureURL;
 
 
    //-------------------------------------------------------------------------
 
    /** contains a descriptor of the feature for the user interface.
 
    */
 
    string FeatureDescriptor;
 
 
    //-------------------------------------------------------------------------
 
    /** specifies whether the feature is currently enabled or disabled.
 
    */
 
    boolean IsEnabled;
 
 
    //-------------------------------------------------------------------------
 
    /** specifies whether the XDispatch object has to be requeried.
 
    */
 
    boolean Requery;
 
 
    //-------------------------------------------------------------------------
 
    /** contains the state of the feature in this dispatch.
 
    */
 
    any State;
 
 
};
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module lang {
 
 
published interface XInitialization: com::sun::star::uno::XInterface
 
{
 
// DocMerge from xml: method com::sun::star::lang::XInitialization::initialize
 
/** initializes the object.
 
 
<p>It should be called directly after the object is created.
 
*/
 
void initialize( [in] sequence<any> aArguments )
 
raises( com::sun::star::uno::Exception );
 
};
 
 
//=============================================================================
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module util {
 
 
published interface XUpdatable: com::sun::star::uno::XInterface
 
{
 
//-------------------------------------------------------------------------
 
/** refreshes the data of the object from the connected data source. */
 
void update();
 
};
 
 
//=============================================================================
 
 
}; }; }; };
 
</source>
 
 
<source lang="idl">
 
module com { module sun { module star { module frame {
 
 
interface XStatusbarController : ::com::sun::star::uno::XInterface
 
{
 
//=============================================================================
 
/** is called by a status bar if the mouse position is within the controller
 
and a mouse button has been pressed. If the controller has captured the
 
mouse input this function is also called when the mouse position is not
 
within the controller.
 
 
@param aMouseEvent
 
current information about the mouse pointer.
 
 
@return
 
return <TRUE/> if the event should not be processed and <FALSE/>
 
if the event should be processed by the status bar.
 
*/
 
boolean mouseButtonDown( [in] ::com::sun::star::awt::MouseEvent aMouseEvent );
 
 
//=============================================================================
 
/** is called by a status bar if the mouse position is within the controller
 
and a mouse has been moved. If the controller has captured the
 
mouse input this function is also called when the mouse position is not
 
within the controller.
 
 
@param aMouseEvent
 
current information about the mouse pointer.
 
 
@return
 
return <TRUE/> if the event should not be processed and <FALSE/>
 
if the event should be processed by the status bar.
 
*/
 
boolean mouseMove( [in] ::com::sun::star::awt::MouseEvent aMouseEvent );
 
 
//=============================================================================
 
/** is called by a status bar if the mouse position is within the controller
 
and a mouse button has been released. If the controller has captured the
 
mouse input this function is also called when the mouse position is not
 
within the controller.
 
 
@param aMouseEvent
 
current information about the mouse pointer.
 
 
@return
 
return <TRUE/> if the event should not be processed and <FALSE/>
 
if the event should be processed by the status bar.
 
*/
 
boolean mouseButtonUp( [in] ::com::sun::star::awt::MouseEvent aMouseEvent );
 
 
//=============================================================================
 
/** is called by a status bar if a command event is available for a controller.
 
 
@param aPos
 
the current mouse position in pixel.
 
 
@param nCommand
 
describes which command has been invoked.
 
 
@param bMouseEvent
 
<TRUE/> if the command is based on a mouse event, otherwise <FALSE/>.
 
 
@param aData
 
for future use only.
 
*/
 
void command( [in] ::com::sun::star::awt::Point aPos,
 
[in] long nCommand,
 
[in] boolean bMouseEvent,
 
[in] any aData );
 
 
//=============================================================================
 
/** is called by a status bar if a command event is available for a controller.
 
 
@param xGraphics
 
the current graphics which should be used for painting.
 
 
@param rOutputRectangle
 
the output rectangle for graphic operations.
 
 
@param nItemId
 
the item id of the controller.
 
 
@param nStyle
 
the style of the statusbar item. The controller should respect the provided
 
 
style when paints.
 
*/
 
void paint( [in] ::com::sun::star::awt::XGraphics xGraphics,
 
[in] ::com::sun::star::awt::Rectangle rOutputRectangle,
 
[in] long nItemId,
 
[in] long nStyle );
 
 
//=============================================================================
 
/** is called by a status bar if the user clicked with mouse into the
 
field of the corresponding control.
 
*/
 
void click();
 
 
//=============================================================================
 
/** is called by a status bar if the user double-clicked with mouse
 
into the field of the corresponding control.
 
*/
 
void doubleClick();
 
};
 
 
}; }; }; };
 
</source>
 
 
OOo 2.0 supports two kind of specific statusbar item controllers. UNO based specific statusbar item controllers must be registered in the configuration set org.openoffice.Office.UI.Controller/Registered/Statusbar.
 
 
An abstract from the Controller.xcu with registered specific statusbar item controllers:
 
 
<source lang="xml">
 
...
 
 
<node oor:name="StatusBar">
 
<node oor:name="c1" oor:op="replace">
 
  <prop oor:name="Command">
 
  <value>.uno:DBStatusType</value>
 
  </prop>
 
  <prop oor:name="Module">
 
  <value>com.sun.star.sdb.OfficeDatabaseDocument</value>
 
  </prop>
 
  <prop oor:name="Controller">
 
  <value>com.sun.star.sdb.ApplicationStatusbarController</value>
 
  </prop>
 
</node>
 
<node oor:name="c2" oor:op="replace">
 
  <prop oor:name="Command">
 
  <value>.uno:DBStatusDBName</value>
 
  </prop>
 
  <prop oor:name="Module">
 
  <value>com.sun.star.sdb.OfficeDatabaseDocument</value>
 
  </prop>
 
  <prop oor:name="Controller">
 
  <value>com.sun.star.sdb.ApplicationStatusbarController</value>
 
  </prop>
 
</node>
 
 
...
 
<node oor:name="c5" oor:op="replace">
 
  <prop oor:name="Command">
 
  <value>.uno:StatusbarLogo</value>
 
  </prop>
 
  <prop oor:name="Module">
 
  <value/>
 
  </prop>
 
  <prop oor:name="Controller">
 
  <value>com.sun.star.comp.framework.LogoImageStatusbarController</value>
 
  </prop>
 
</node>
 
 
...
 
</node>
 
</source>
 
 
The framework library provides a base class in svtools/inc/statusbarcontroller.hxx which makes it simpler to implement a UNO based specific status bar controller.
 
 
The sfx2 based specific statusbar item controllers are registered by calling ''StatusbarControllerClass''<nowiki>::RegisterControl(SlotID, SfxModule* ). The framework implementation uses a special statusbar controller factory to create instances of sfx2 based specific statusbar item controllers. Sfx2 based specific statusbar controllers can use the known base class sfx2/inc/stbitem.hxx. It's a special wrapper which converts calls to the its UNO interfaces to the needs of sfx2 based statusbar controllers.</nowiki>
 
 
<source lang="cpp">
 
class SFX2_DLLPUBLIC SfxStatusBarControl: public svt::StatusbarController
 
{
 
USHORT nSlotId;
 
USHORT nId;
 
StatusBar* pBar;
 
 
protected:
 
// new controller API
 
// XInterface
 
virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
 
virtual void SAL_CALL acquire() throw();
 
virtual void SAL_CALL release() throw();
 
 
// XEventListener
 
virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw( ::com::sun::star::uno::RuntimeException );
 
 
// XComponent
 
virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);
 
 
// XStatusListener
 
virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );
 
 
// XStatusbarController
 
virtual ::sal_Bool SAL_CALL mouseButtonDown( const ::com::sun::star::awt::MouseEvent& aMouseEvent ) throw (::com::sun::star::uno::RuntimeException);
 
virtual ::sal_Bool SAL_CALL mouseMove( const ::com::sun::star::awt::MouseEvent& aMouseEvent ) throw (::com::sun::star::uno::RuntimeException);
 
virtual ::sal_Bool SAL_CALL mouseButtonUp( const ::com::sun::star::awt::MouseEvent& aMouseEvent ) throw (::com::sun::star::uno::RuntimeException);
 
virtual void SAL_CALL command( const ::com::sun::star::awt::Point& aPos,
 
::sal_Int32 nCommand,
 
::sal_Bool bMouseEvent,
 
const ::com::sun::star::uno::Any& aData )
 
 
throw (::com::sun::star::uno::RuntimeException);
 
virtual void SAL_CALL paint( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XGraphics >& xGraphics,
 
const ::com::sun::star::awt::Rectangle& rOutputRectangle,
 
::sal_Int32 nItemId,
 
::sal_Int32 nStyle )
 
 
throw (::com::sun::star::uno::RuntimeException);
 
virtual void SAL_CALL click() throw (::com::sun::star::uno::RuntimeException);
 
virtual void SAL_CALL doubleClick() throw (::com::sun::star::uno::RuntimeException);
 
 
// Old sfx2 interface
 
virtual void StateChanged( USHORT nSID, SfxItemState eState,
 
const SfxPoolItem* pState );
 
virtual void Click();
 
virtual void DoubleClick();
 
virtual void Command( const CommandEvent& rCEvt );
 
virtual BOOL MouseButtonDown( const MouseEvent & );
 
virtual BOOL MouseMove( const MouseEvent & );
 
virtual BOOL MouseButtonUp( const MouseEvent & );
 
virtual void Paint( const UserDrawEvent &rUDEvt );
 
 
static USHORT convertAwtToVCLMouseButtons( sal_Int16 nAwtMouseButtons );
 
 
public:
 
SfxStatusBarControl( USHORT nSlotID, USHORT nId, StatusBar& rBar );
 
virtual ~SfxStatusBarControl();
 
 
USHORT GetSlotId() const { return nSlotId; }
 
USHORT GetId() const { return nId; }
 
StatusBar& GetStatusBar() const { return *pBar; }
 
void CaptureMouse();
 
void ReleaseMouse();
 
 
static SfxStatusBarControl* CreateControl( USHORT nSlotID, USHORT nId, StatusBar *pBar, SfxModule* );
 
};
 
</source>
 
 
=User interface controllers in the mixed sfx2/uno environment=
 
 
==How user interface controllers work in a pure UNO based environment?==
 
 
[[Image:EnvironmentPureUnoUserInterfaceController.png]]
 
 
==How user interface controllers work in our mixed sfx2/UNO based environment?==
 
 
[[Image:EnvironmentUserInterfaceController.png]]
 
 
 
Let's see what happens in more detail, especially when we switch from one layer to another one.
 
 
# A shell wants to invalidate a slot and calls SfxShell::Invalidate( SlotID ).
 
# The bindings updates the SfxStateCache for the provided slot ID normally through a update timer or directly.
 
# The SfxStateCache calls StateChanged with the new state on a SfxDispatchController_Impl object.
 
# The SfxDispatchController_Impl now maps the sfx2 state information based on SfxPoolItem to UNO information and sends them to UNO based toolbar controller.
 
 
<source lang="cpp">
 
...
 
 
::cppu::OInterfaceContainerHelper* pContnr = pDispatch->GetListeners().getContainer( aDispatchURL.Complete );
 
if ( bNotify && pContnr )
 
{
 
  ::com::sun::star::uno::Any aState;
 
  if ( ( eState >= SFX_ITEM_AVAILABLE ) && pState && !IsInvalidItem( pState ) && !pState->ISA(SfxVoidItem) )
 
  {
 
    // Retrieve metric from pool to have correct sub ID when calling QueryValue
 
    USHORT nSubId( 0 );
 
    SfxMapUnit eMapUnit( SFX_MAPUNIT_100TH_MM );
 
 
    // retrieve the core metric
 
    // it's enough to check the objectshell, the only shell that does not
 
    // use the pool of the document is SfxViewFrame, but it hasn't any metric parameters
 
    if ( pSlotServ && pDispatcher )
 
    {
 
      SfxShell* pShell = pDispatcher->GetShell( pSlotServ->GetShellLevel() );
 
      DBG_ASSERT( pShell, "Can't get core metric without shell!" );
 
      if ( pShell )
 
        eMapUnit = GetCoreMetric( pShell->GetPool(), nSID );
 
    }
 
 
    if ( eMapUnit == SFX_MAPUNIT_TWIP )
 
      nSubId |= CONVERT_TWIPS;
 
    pState->QueryValue( aState, (BYTE)nSubId );
 
  }
 
  else if ( eState == SFX_ITEM_DONTCARE )
 
  {
 
    // Use special uno struct to transport don't care state
 
    ::com::sun::star::frame::status::ItemStatus aItemStatus;
 
    aItemStatus.State = ::com::sun::star::frame::status::ItemState::dont_care;
 
    aState = makeAny( aItemStatus );
 
  }
 
 
  ::com::sun::star::frame::FeatureStateEvent aEvent;
 
  aEvent.FeatureURL = aDispatchURL;
 
  aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
 
  aEvent.IsEnabled = eState != SFX_ITEM_DISABLED;
 
  aEvent.Requery = sal_False;
 
  aEvent.State = aState;
 
 
  ::cppu::OInterfaceIteratorHelper aIt( *pContnr );
 
  while( aIt.hasMoreElements() )
 
  {
 
    try
 
    {
 
      ((::com::sun::star::frame::XStatusListener *)aIt.next())->statusChanged( aEvent );
 
    }
 
    catch( ::com::sun::star::uno::RuntimeException& )
 
    {
 
      aIt.remove();
 
    }
 
  }
 
}
 
 
...
 
</source>
 
 
How does QueryValue work and convert an item to UNO com::sun::star::uno::any?
 
 
<br />
 
 
You can find the base class of any pool item in ''svtools/inc/poolitem.hxx''
 
 
<source lang="cpp">
 
class SVL_DLLPUBLIC SfxPoolItem
 
{
 
friend class SfxItemPool;
 
friend class SfxItemDesruptor_Impl;
 
friend class SfxItemPoolCache;
 
friend class SfxItemSet;
 
friend class SfxVoidItem;
 
 
ULONG nRefCount; // Referenzzaehler
 
USHORT nWhich;
 
USHORT nKind;
 
 
private:
 
inline void SetRefCount( ULONG n );
 
inline void SetKind( USHORT n );
 
public:
 
inline ULONG AddRef( ULONG n = 1 ) const;
 
private:
 
inline ULONG ReleaseRef( ULONG n = 1 ) const;
 
SVL_DLLPRIVATE long Delete_Impl(void*);
 
 
protected:
 
SfxPoolItem( USHORT nWhich = 0 );
 
SfxPoolItem( const SfxPoolItem& );
 
 
public:
 
TYPEINFO();
 
 
virtual ~SfxPoolItem();
 
void SetWhich( USHORT nId )
 
{ DBG_CHKTHIS(SfxPoolItem, 0); nWhich = nId; }
 
USHORT Which() const { DBG_CHKTHIS(SfxPoolItem, 0); return nWhich; }
 
virtual int operator==( const SfxPoolItem& ) const = 0;
 
int operator!=( const SfxPoolItem& rItem ) const
 
{ return !(*this == rItem); }
 
virtual int Compare( const SfxPoolItem &rWith ) const;
 
virtual int Compare( const SfxPoolItem &rWith, const IntlWrapper& rIntlWrapper ) const;
 
 
virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePresentation,
 
SfxMapUnit eCoreMetric,
 
SfxMapUnit ePresentationMetric,
 
XubString &rText,
 
const IntlWrapper * pIntlWrapper = 0 ) const;
 
 
virtual USHORT GetVersion( USHORT nFileFormatVersion ) const;
 
virtual int ScaleMetrics( long lMult, long lDiv );
 
virtual int HasMetrics() const;
 
 
virtual BOOL QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
 
virtual BOOL PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );
 
 
virtual SfxPoolItem* Create( SvStream &, USHORT nItemVersion ) const;
 
virtual SvStream& Store( SvStream &, USHORT nItemVersion ) const;
 
virtual SfxPoolItem* Clone( SfxItemPool *pPool = 0 ) const = 0;
 
 
ULONG GetRefCount() const { return nRefCount; }
 
inline USHORT GetKind() const { return nKind; }
 
 
static bool readByteString(SvStream & rStream, UniString & rString);
 
static void writeByteString(SvStream & rStream,UniString const & rString);
 
static bool readUnicodeString(SvStream & rStream, UniString & rString, bool bUnicode);
 
static void writeUnicodeString(SvStream & rStream, UniString const & rString);
 
 
private:
 
SfxPoolItem& operator=( const SfxPoolItem& ); // n.i.!!
 
};
 
</source>
 
 
A example how to implement QueryValue can be found in the implementation of the SvxULSpaceItem (located in svx/source/items/frmitems.cxx).
 
 
<source lang="cpp">
 
sal_Bool SvxULSpaceItem::QueryValue( uno::Any& rVal, BYTE nMemberId ) const
 
{
 
  sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
 
  nMemberId &= ~CONVERT_TWIPS;
 
  switch( nMemberId )
 
  {
 
    // jetzt alles signed
 
    case 0:
 
    {
 
      ::com::sun::star::frame::status::UpperLowerMarginScale aUpperLowerMarginScale;
 
      aUpperLowerMarginScale.Upper = (sal_Int32)(bConvert ? TWIP_TO_MM100(nUpper) : nUpper);
 
      aUpperLowerMarginScale.Lower = (sal_Int32)(bConvert ? TWIP_TO_MM100(nLower) : nPropUpper);
 
      aUpperLowerMarginScale.ScaleUpper = (sal_Int16)nPropUpper;
 
      aUpperLowerMarginScale.ScaleLower = (sal_Int16)nPropLower;
 
      rVal <<= aUpperLowerMarginScale;
 
      break;
 
    }
 
    case MID_UP_MARGIN: rVal <<= (sal_Int32)(bConvert ? TWIP_TO_MM100(nUpper) : nUpper); break;
 
    case MID_LO_MARGIN: rVal <<= (sal_Int32)(bConvert ? TWIP_TO_MM100(nLower) : nLower); break;
 
    case MID_UP_REL_MARGIN: rVal <<= (sal_Int16) nPropUpper; break;
 
    case MID_LO_REL_MARGIN: rVal <<= (sal_Int16) nPropLower; break;
 
  }
 
  return sal_True;
 
}
 
</source>
 
 
# The UNO based toolbar controller now has to convert the state information (com::sun::star::uno::Any) again to provide it in a format that the sfx2 based toolbar controller implementation knows (SfxPoolItem).
 
 
<source lang="cpp">
 
// XStatusListener
 
 
void SAL_CALL SfxToolBoxControl::statusChanged( const FeatureStateEvent& rEvent )
 
throw ( ::com::sun::star::uno::RuntimeException )
 
{
 
    SfxViewFrame* pViewFrame = NULL;
 
    Reference < XController > xController;
 
 
    ::vos::OGuard aGuard( Application::GetSolarMutex() );
 
    if ( getFrameInterface().is() )
 
        xController = getFrameInterface()->getController();
 
 
    Reference < XDispatchProvider > xProvider( xController, UNO_QUERY );
 
    if ( xProvider.is() )
 
    {
 
        Reference < XDispatch > xDisp = xProvider->queryDispatch(
 
            rEvent.FeatureURL, ::rtl::OUString(), 0 );
 
        if ( xDisp.is() )
 
        {
 
            Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY );
 
            SfxOfficeDispatch* pDisp = NULL;
 
            if ( xTunnel.is() )
 
            {
 
                sal_Int64 nImplementation = xTunnel>getSomething
 
                SfxOfficeDispatch::impl_getStaticIdentifier() );
 
                pDisp = (SfxOfficeDispatch*)(nImplementation);
 
            }
 
 
            if ( pDisp )
 
                pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
 
        }
 
    }
 
 
    USHORT nSlotId = 0;
 
    SfxSlotPool& rPool = SFX_APP()->GetSlotPool( pViewFrame );
 
    const SfxSlot* pSlot = rPool.GetUnoSlot( rEvent.FeatureURL.Path );
 
    if ( pSlot )
 
        nSlotId = pSlot->GetSlotId();
 
 
    if ( nSlotId > 0 )
 
    {
 
        if ( rEvent.Requery )
 
            svt::ToolboxController::statusChanged( rEvent );
 
        else
 
        {
 
            SfxItemState eState = SFX_ITEM_DISABLED;
 
            SfxPoolItem* pItem = NULL;
 
           
 
            if ( rEvent.IsEnabled )
 
            {
 
                eState = SFX_ITEM_AVAILABLE;
 
                ::com::sun::star::uno::Type pType = rEvent.State.getValueType();
 
 
                if ( pType == ::getVoidCppuType() )
 
                {
 
                    pItem = new SfxVoidItem( nSlotId );
 
                    eState = SFX_ITEM_UNKNOWN;
 
                }
 
                else if ( pType == ::getBooleanCppuType() )
 
                {
 
                    sal_Bool bTemp ;
 
                    rEvent.State >>= bTemp ;
 
                    pItem = new SfxBoolItem( nSlotId, bTemp );
 
                }
 
                else if ( pType == ::getCppuType((const sal_uInt16*)0) )
 
                {
 
                    sal_uInt16 nTemp ;
 
                    rEvent.State >>= nTemp ;
 
                    pItem = new SfxUInt16Item( nSlotId, nTemp );
 
                }
 
                else if ( pType == ::getCppuType((const sal_uInt32*)0) )
 
                {
 
                    sal_uInt32 nTemp ;
 
                    rEvent.State >>= nTemp ;
 
                    pItem = new SfxUInt32Item( nSlotId, nTemp );
 
                }
 
                else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
 
                {
 
                    ::rtl::OUString sTemp ;
 
                    rEvent.State >>= sTemp ;
 
                    pItem = new SfxStringItem( nSlotId, sTemp );
 
                }
 
                else if ( pType == ::getCppuType(( const
 
                    ::com::sun::star::frame::status::ItemStatus* )0) )
 
                {
 
                    ItemStatus aItemStatus;
 
                    rEvent.State >>= aItemStatus;
 
                    eState = aItemStatus.State;
 
                    pItem = new SfxVoidItem( nSlotId );
 
                }
 
                else if ( pType == ::getCppuType(( const
 
                    ::com::sun::star::frame::status::Visibility*)0) )
 
                {
 
                    Visibility aVisibilityStatus;
 
                    rEvent.State >>= aVisibilityStatus;
 
                    pItem = new SfxVisibilityItem( nSlotId, aVisibilityStatus.bVisible );
 
                }
 
                else
 
                {
 
                    if ( pSlot )
 
                        pItem = pSlot->GetType()->CreateItem();
 
                    if ( pItem )
 
                    {
 
                        pItem->SetWhich( nSlotId );
 
                        pItem->PutValue( rEvent.State );
 
                    }
 
                    else
 
                        pItem = new SfxVoidItem( nSlotId );
 
                }
 
          }
 
 
          StateChanged( nSlotId, eState, pItem );
 
          delete pItem;
 
        }
 
    }
 
}
 
</source>
 
 
As you can see the implementation retrieves the type of the slot and creates an empty item of that type. Now it has to use PutValue to convert the UNO com::sun::star::uno::Any back to an item. Let's see how the SvxULSpaceItem implements PutValue:
 
 
<source lang="cpp">
 
sal_Bool SvxULSpaceItem::PutValue( const uno::Any& rVal, BYTE nMemberId )
 
{
 
    sal_Bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
 
    nMemberId &= ~CONVERT_TWIPS;
 
   
 
    sal_Int32 nVal;
 
    switch( nMemberId )
 
    {
 
        case 0:
 
        {
 
            ::com::sun::star::frame::status::UpperLowerMarginScale aUpperLowerMarginScale;
 
            if ( !(rVal >>= aUpperLowerMarginScale ))
 
                return sal_False;
 
            else
 
            {
 
                SetUpper((sal_uInt16)(bConvert ?
 
                    MM100_TO_TWIP( aUpperLowerMarginScale.Upper ) : aUpperLowerMarginScale.Upper));
 
                SetLower((sal_uInt16)(bConvert ?
 
                    MM100_TO_TWIP( aUpperLowerMarginScale.Lower ) : aUpperLowerMarginScale.Lower));
 
                if( aUpperLowerMarginScale.ScaleUpper > 1 )
 
                    nPropUpper = aUpperLowerMarginScale.ScaleUpper;
 
                if( aUpperLowerMarginScale.ScaleLower > 1 )
 
                    nPropUpper = aUpperLowerMarginScale.ScaleLower;
 
            }
 
        }
 
 
        case MID_UP_MARGIN :
 
            if(!(rVal >>= nVal) || nVal < 0)
 
                return sal_False;
 
            SetUpper((sal_uInt16)bConvert ? MM100_TO_TWIP(nVal) : nVal);
 
            break;
 
 
        case MID_LO_MARGIN :
 
            if(!(rVal >>= nVal) || nVal < 0)
 
                return sal_False;
 
            SetLower((sal_uInt16)bConvert ? MM100_TO_TWIP(nVal) : nVal);
 
            break;
 
 
        case MID_UP_REL_MARGIN:
 
        case MID_LO_REL_MARGIN:
 
        {
 
            sal_Int32 nRel;
 
            if((rVal >>= nRel) && nRel > 1 )
 
            {
 
                if(MID_UP_REL_MARGIN == nMemberId)
 
                    nPropUpper = nRel;
 
                else
 
                    nPropLower = nRel;
 
            }
 
            else
 
                return FALSE;
 
        }
 
        break;
 
 
        default:
 
            DBG_ERROR("unknown MemberId");
 
            return sal_False;
 
  }
 
 
 
  return sal_True;
 
}
 
</source>
 
 
'''''We should now see some very important rules that this conversion can work correctly.'''''
 
 
<br />
 
 
* Never use the value 0 of the nMemberID to convert the ''default part'' of an item. This will immediately break our user interface updates.
 
* If you want to add a new slot that can be used by the user interface, your MUST support Query- and PutValue. At least the default value 0 must be implemented.
 
* Never use other arguments to call a slot than the ones that are declared in your SDI file. The conversion methods in sfx2 use the type description of the slot to map UNO types to items and cannot do this for unknown arguments.
 
  
 
[[Category:Framework:Article]]
 
[[Category:Framework:Article]]

Revision as of 07:09, 2 May 2012

OpenOffice.org 2.0 User Interface Controller Internals

Personal tools