Difference between revisions of "Sidebar"

From Apache OpenOffice Wiki
Jump to: navigation, search
(QA)
(QA)
Line 465: Line 465:
  
 
There are some simple documents for Writer, Calc and Impress then show you how switch to all the contexts and which panels should be visible then:
 
There are some simple documents for Writer, Calc and Impress then show you how switch to all the contexts and which panels should be visible then:
*Writer: [http://people.apache.org/~af/sidebar/qa/Contexts-Writer.odt Contexts-Writer.odt]
+
*Writer: [[File:Contexts-Writer.odt]]
*New Writer: [[File:Contexts-Writer.odt]]
+
 
*Calc: [http://people.apache.org/~af/sidebar/qa/Contexts-Calc.ods Contexts-Calc.ods]
 
*Calc: [http://people.apache.org/~af/sidebar/qa/Contexts-Calc.ods Contexts-Calc.ods]
 
*Impress: [http://people.apache.org/~af/sidebar/qa/Contexts-Impress.odp Contexts-Impress.odp]
 
*Impress: [http://people.apache.org/~af/sidebar/qa/Contexts-Impress.odp Contexts-Impress.odp]

Revision as of 13:37, 28 March 2013

The sidebar (working title) is a new feature likely to be in the 4.0 release. It combines ideas and code from both the Symphony sidebar and the OpenOffice Impress task pane.

The UX part of the work is described on another page. This page focuses on the API design and implementation.

Help in every form is welcome. After reading the general introductory stuff:


Status

  • New property panel "Page" is available.
  • Context switching is supported:
    • The set of panels in the property deck is updated accordingly
    • Panels update their controls according to the current context
  • Developer builds are available, see below

Screenshots:

27. Feb. 2013: Based sidebar colors on system colors provided by the SystemSettings class. The "Colors" panel (will not be in the release) shows all colors exported by SystemSettings. Screenshots are, from left to right, from Windows, Ubuntu and Mac. Sidebar-2013-02-27-windows.png, Sidebar-2013-02-27-linux.png, Sidebar-2013-02-27-mac.png.

Resources

Developer Builds

Current version is the first snapshot build from March, 20th, 2013 for

Changed since version 0.7:

  • New Page panel
  • Support of context switching
  • Missing panel types are represented by placeholders to give a better impression of the final feature.


Changed since version 0.6:

  • Closer of deck title bar closes the deck but leaves the tab bar visible.
  • The Impress panels are now available:
    • Layouts
    • Master pages (all, recent, used)
    • Custom animation
    • Slide transition
    • Table
  • A special activation of the sidebar is not necessary anymore. It works now out of the box.

Known Bugs and Enhancements

If you find any bugs in the sidebar or caused by the sidebar then please write a BugZilla issue for each and

  • Prefix the title with "sidebar:"
  • Mark them as blocker of issue 121420.
  • Assign it to me (awf dot aoo at googlemail dot com)

Known bugs are:

Requested improvements:

  • issue 121936 and issue 121937 request changes to the association of contexts and panels: show area and line panel for OLE objects, show the area panel for images.

SidebarWorkbench

There is a Java extension for development and debugging of the sidebar. It can be downloaded here. Note that it writes a log file to /tmp/sidebar.log. On Windows without cygwin this may not work. Do not use the developer builds for important documents: there may be dragons (aka severe bugs).

On Windows and Linux you can use it to

  1. add some dummy decks and panels to the sidebar.
  2. monitor the current context. It is displayed in a panel in the Properties deck.
  3. modify the look of the sidebar with an external Java dialog called "Theme Dialog".

The "Theme Dialog" has three sections:

Presets
Ten buttons let you choose between the nine themes proposed on this UX page. A tenth button activates a theme that is similar to the original Symphony sidebar.
Options
More fine grained options for changing the panel title bar background (normal, dark), the panel background (normal, white), use of Symphony icons, use of system colors (not yet fully implemented), use of the high contrast mode color scheme. The later does not activate the high contrast mode. It is just a quick way to activate the color scheme.
Properties
A list of all the properties in the sidebar theme XPropertySet that are evaluated for the look of the sidebar. Editing is not (yet) possible.

Glossary

Work in progress. Comments are welcome.

Schematic overview of sidebar components. Location of elements do not reflect UX design.
sidebar
Name of the feature and name of the control including all its components (icon bar, content panels).
Also known as task pane(l) or tool pane(l)
tab bar
Similar to a vertical tool bar. Clicking on buttons switches between sidebar decks.
deck
Contains one or more content panels. Only one deck is visible at any one time.
content panel
Displays information about the document and/or provides the means for document modification.
Each content panel focuses on one topic like font, table or shape properties.
There may be more than one content panel in a deck.
Examples are the task panels of the Impress task pane or the property views of the Symphony sidebar.
title bar
Displays the title for the current sidebar deck.
Can contain a closer button.
content panel title
Displays the title for one content panel. Optional when there is only one content panel.
configuration menu button
Opens a popup menu that allows switching between decks and also allows the activation and deactivation (tab is not shown) of decks.

Panels and Decks

At any one time there is one and only one deck visible. It contains one or more panels. There are rare occasions where there is no panel for a given context, but in this case a replacement panel is displayed with a message to the effect "intentionally left blank".

The set of decks available via the tab bar and panels inside a deck depend on the current context. Contexts are defined by different features or states. This can be the selection of shapes, text editing on/off, switching between views (in Impress).

Decks

Properties
This deck is visible by default. Context changes typically change the set of property panels inside this deck.
Master Pages
This Impress only deck contains three panels for the currently used, recently used and available master pages.
Custon Animation
Displayed only for Impress, this deck contains only one panel for displaying and modifying shape animations.
Slide Transition
Another Impress only deck. It contains one panel for slide transitions.

Panels

Text
Text properties.
Page
Page properties.
Area
Fill style properties for shapes.
Line
Border style properties for shapes
Position and Size
Position and size for shapes.
Graphic
Properties for images.
Layouts
Impress layouts.
Used in This Presentation
Master pages that are in use by the current Impress document.
Recently Used
Master pages that where recently used by the current Impress document.
Available for Use
All available master pages. Independent of the current Impress document.
Custom Animation
Shape animations.
Slide Transition
Slide transitions.
Table Design
Table properties for Impress documents.
Alignment
TBD.
Cell Appearance
TBD.
Number Format
TBD.
Paragraph
TBD.
Wrap
TBD.


Contexts

The following table shows the association between panels and dialogs for all supported contexts. It also lists whether panels are initially displayed expanded or collapsed and the uno command to use to open a more detailed dialog. Applications are abreviated:

  • SC - Calc
  • SD - Draw and Impress
  • SW - Writer
Panel Application Context Initially visible Detail dialog command
Alignment SC Auditing yes .uno:Hyphenate
Alignment SC Cell yes .uno:Hyphenate
Alignment SC EditCell yes .uno:Hyphenate
Alignment SC Pivot yes .uno:Hyphenate
Area SC Draw yes .uno:FormatArea
Area SD 3DObject yes .uno:FormatArea
Area SD Draw yes .uno:FormatArea
Area SD TextObject no .uno:FormatArea
Area SW Draw yes .uno:FormatArea
Cell Appearance SC Auditing yes .uno:FormatCellDialog
Cell Appearance SC Cell yes .uno:FormatCellDialog
Cell Appearance SC Pivot yes .uno:FormatCellDialog
Graphic SC Graphic yes -none-
Graphic SD Graphic yes -none-
Graphic SW Graphic yes -none-
Line SC Draw yes .uno:FormatLine
Line SC Graphic yes .uno:FormatLine
Line SD 3DObject yes .uno:FormatLine
Line SD Draw yes .uno:FormatLine
Line SD Graphic yes .uno:FormatLine
Line SD TextObject no .uno:FormatLine
Line SW Draw yes .uno:FormatLine
Number Format SC Auditing no .uno:FormatCellDialog
Number Format SC Cell no .uno:FormatCellDialog
Number Format SC Pivot no .uno:FormatCellDialog
Wrap SW Graphic yes .uno:ObjectWrapDialog
Wrap SW OLE yes .uno:ObjectWrapDialog
Wrap SW Frame yes .uno:ObjectWrapDialog
Layouts SD DrawPage yes -none-
Layouts SD HandoutPage yes -none-
Layouts SD NotesPage yes -none-
Layouts SD SlidesorterPage yes -none-
Page SW Table no .uno:PageDialog
Page SW Text no .uno:PageDialog
Paragraph SC DrawText yes .uno:ParagraphDialog
Paragraph SD 3DObject yes .uno:ParagraphDialog
Paragraph SD Draw no .uno:ParagraphDialog
Paragraph SD DrawText yes .uno:ParagraphDialog
Paragraph SD Graphic no .uno:ParagraphDialog
Paragraph SD Table yes .uno:ParagraphDialog
Paragraph SD TextObject yes .uno:ParagraphDialog
Paragraph SW Annotation yes .uno:ParagraphDialog
Paragraph SW DrawText yes .uno:ParagraphDialog
Paragraph SW Table yes .uno:ParagraphDialog
Paragraph SW Text yes .uno:ParagraphDialog
Position and Size SC Draw no .uno:TransformDialog
Position and Size SC Form yes .uno:TransformDialog
Position and Size SC Graphic no .uno:TransformDialog
Position and Size SC Media yes .uno:TransformDialog
Position and Size SC MultiObject yes .uno:TransformDialog
Position and Size SC OLE yes .uno:TransformDialog
Position and Size SD 3DObject yes .uno:TransformDialog
Position and Size SD Draw no .uno:TransformDialog
Position and Size SD Form yes .uno:TransformDialog
Position and Size SD Graphic no .uno:TransformDialog
Position and Size SD Media yes .uno:TransformDialog
Position and Size SD MultiObject yes .uno:TransformDialog
Position and Size SD OLE yes .uno:TransformDialog
Position and Size SD TextObject no .uno:TransformDialog
Position and Size SW Draw no .uno:TransformDialog
Position and Size SW Form yes .uno:TransformDialog
Position and Size SW Graphic yes .uno:GraphicDialog
Position and Size SW Media yes .uno:TransformDialog
Position and Size SW OLE yes .uno:FrameDialog
Table Design SD Table yes -none-
Text SC Auditing yes .uno:CellTextDlg
Text SC Cell yes .uno:CellTextDlg
Text SC DrawText yes .uno:FontDialog
Text SC EditCell yes .uno:FontDialog
Text SC Pivot yes .uno:CellTextDlg
Text SD 3DObject yes .uno:FontDialog
Text SD Draw no .uno:FontDialog
Text SD DrawText yes .uno:FontDialog
Text SD Graphic no .uno:FontDialog
Text SD OutlineTExt yes .uno:FontDialog
Text SD Table yes .uno:FontDialog
Text SD Textobj yes .uno:FontDialog
Text SW Annotation yes .uno:FontDialog
Text SW DrawText yes .uno:FontDialog
Text SW Table yes .uno:FontDialog
Text SW Text yes .uno:FontDialog

Implemenation design

The UI of the sidebar consists of two major components:

  • The buttons in the vertical tab bar on the right switch manually between sidebar decks.
  • The content area contains a two-tier hierarchy of deck and content panels. There is one deck visible at any one time. It contains one or more content panels. A content panel can be displayed expanded or collapsed.

The visible deck and content panels depend on the current context. Each context change may result in replacing one set of visible panels with another or changing the whole deck. A context consists of two strings:

  • The id of the current application (like com.sun.star.text.TextDocument for Writer).
  • The name of the actual context (like Text for text editing, Table for editing table content, or default for the default context)

Context

What makes up a context depends on the application. For example Text is the default context for Writer but in Impress you have to select a text object to enter that context.

Context change notification

Context changes are broadcast office wide via the com::sun::star::ui::ContextChangeEventMultiplexer singleton service and com::sun::star::ui::XContextChangeEventMultiplexer interface. In order to restrict the communication to one application window there exists the concept of the event focus. When you register as context change event listener or broadcast a change notification then you pass a event focus object. Only when listener and broadcaster use the same event focus object then the notification will pass from broadcaster to listener. Typically the event focus object is the controller of the application.

To make life easier for developers there exists the svx::sidebar::ContextChangeEventMultiplexer frontend that - figures out the application name and event focus from either a given frame::XController or SfxViewShell object. - accepts only enum values from sfx2::sidebar::EnumContext::Context to prevent typos in context names to not correctly deliver context change events.

On the receiving side of context change events there is the sfx2::sidebar::SidebarPanelBase base class for panel implementations. Let your panel implement the sfx2::sidebar::IContextChangeReceiver interface, use SidebarPanelBase (which probably needs a better name) as glue code between the sidebar framework and your panel and context change events will be delivered to you via the IContextChangeReceiver::HandleContextChange() method. Not all panels need to be informed about context changes. For many it is enough that they are activated for some contexts and deactivated for others.

Forced context changes

By default the property deck is displayed. The user can switch between decks by clicking on buttons in the tab bar. This will result in the forced notification of a context change.

Defining the set of decks and panels

Apart from the actual implementation the sidebar framework needs to know which decks and panels exists, which panels are to be displayed in each deck and for what configuration to display each deck and panel.

The configuration files Sidebar.xcs (schema) and Sidebar.xcu (data) can be found in the main/officecfg module. They describe a list of decks and a list of panels.

Decks

Each deck has

  • a unique id ("Id") which is referenced by panels that are to be displayed in the deck
  • a localized title ("Title") for display in the deck title bar
  • two URLs for the icon in the tab bar, one ("IconURL") is the default icon, the other ("HighContrastIconURL") is used when high contrast mode is active
  • an integer number ("OrderIndex") that describes the order in which deck icons are displayed in the tab bar; higher values result in locations farther down.
  • a string list of context descriptions ("ContextList") that specify for which contexts to display the deck; see more details about this in one of the next sections.

Panels

Each panel has

  • a unique id ("DeckId") which references a deck by its "Id" field; the panel will only be displayed in the referenced deck
  • a localized title ("Title") for display in the deck title bar
  • a flag ("TitleBarIsOptional") that indicates whether the title bar can be omitted when the panel is the only one in the deck
  • a command name ("DefaultMenuCommand") for opening a dialog with more detailed options (eg. ".uno:FormatArea"); when no command is given then no menu icon will be displayed in the panel title bar
  • an integer number ("OrderIndex") that describes the order in which panels are placed in their deck; higher values result in locations farther down.
  • a string list of context descriptions ("ContextList") that specify for which contexts to display the deck. See more details about this in the the next section.
  • a URL for specifying the implementation ("ImplementationURL") like private:resource/toolpanel/SvxPanelFactory/AreaPropertyPanel.

Context Specification

The "ContextList" properties of both decks and panels have basically a table form that is evaluated after each context change. If one of its rows matches the new context then deck or panel is displayed.

Rows are really separated by semicolons (or whatever you specify in the opening value tag). Formatting them into rows just makes reading their content easier. Each row contains three or four values which are separated by commas. Leading and trailing spaces are ignored.

Columns are:

Application name

This can be the full application name as returned by frame.ModuleManager but to increase readability shorter names can also be used. There is a special name, DrawImpress for the common case that decks and panels are handled exactly the same in Draw and Impress. Similarily WriterAndWeb covers the applications Writer and Writer/Web. Recognized values are:

com.sun.star.text.TextDocument
com.sun.star.text.WebDocument
com.sun.star.sheet.SpreadsheetDocument
com.sun.star.presentation.PresentationDocument
com.sun.star.drawing.DrawingDocument
            
Writer
WriterWeb
Calc
Impress
Draw
  
DrawImpress
WriterAndWeb
any
none

Most of these are self explanatory. DrawImpress and WriterAndWeb have been explained above. any matches any application while none matches no application. Use none to disable deck or panel temporarily during development.

Context name

Recognized values are 3DObject, Annotation, Auditing, Cell, Chart, Draw, DrawPage, DrawText, EditCell, Form, Frame, Graphic, HandoutPage, MasterPage, Media, Multiobj, OLE, OutlineText, Pivot, SlidesorterPage, Table, Text, TextObject. It is, however, possible to invent your own context names. The special value any matches any context name.

Initial state

Can be either visible or hidden. For decks this state decides whether the deck is initially enabled or disabled. You can change this state at runtime via the top button in the sidebar tab bar. For panels this state controls whether the panel is initially expanded or collapsed. Click on the panel title bar to toggle this state.

Menu command override

This optional value is only used for panels. It overrides the "DefaultMenuCommand" for the panel.

Here is an example for the "Area" property panel:

   <prop oor:name="ContextList">
       <value oor:separator=";">
           Calc,        Draw,       visible ;
           DrawImpress, 3DObject,   visible ;
           DrawImpress, Draw,       visible ;
           DrawImpress, TextObject, hidden  ;
           Writer,      Draw,       visible ;
       </value>
   </prop>

The panel will be displayed for the "Draw" context for all applications. For Draw and Impress it will also be shown for contexts "3DObject" and "TextObject". The panel will be initially expanded except for the "TextObject" context for Draw and Impress. For this context it will be initially collapsed.

Legacy addons

Legacy addons are find in the application specific WindowState configuration files and instaniated via the existing ui::UIElementFactoryManager infrastructure is used. 5.3 Sidebar

Implementation and Migration

Bugzilla issue 121420 is the toplevel issue for the implementation of the sidebar.

A large part of the implementation is already done:

  • Sidebar framework that provides decks, base classes for panels, the tab bar, etc.
  • Notification of context changes
  • API and configuration

But not all of the panels are implemented/migrated. The missing panels belong to two groups: panels that only exist in Symphony and controls that already exist in AOO as dialogs.

Migration of Symphony content panels

The list for content panels to migrate from Symphony for Writer(W), Calc(C), Impress(I) (see proposal) is:

sc/source/ui/propertypanel/alignmentpropertypage.cxx
sc/source/ui/propertypanel/appearpropertypage.cxx
sc/source/ui/propertypanel/numformatpropertypage.cxx
svx/source/propertypanel/paragraphpropertypage.cxx
  • text (W,I,C/cell selected,C/(text (editing cell text)) (started) 121798 (Already assigned to zhengfan)
svx/source/propertypanel/textpropertypage.cxx
  • wrap (W) 121799 (assigned to orw)
sw/source/ui/propertypanel/wrappropertypage.cxx

Migration/conversions of AOO dialogs

The list of controls that are content panels in Symphony and are dialogs in AOO (see proposal) is:

  • Style List
  • Clipart
  • Navigator
  • Functions
  • Data Pilot

How to help

The migration of the Symphony panels to OpenOffice is a lot of work. Here is how you can help.

QA

The implementation and migration of a feature of this size provides a lot of opportunities for introducing new bugs or break existing functionality. Please help us find them.

Snapshot builds are available for testing. Please see above for details.

There are some simple documents for Writer, Calc and Impress then show you how switch to all the contexts and which panels should be visible then:

These documents are not intended as test documents but as initial help for writing such documents.

Implementation/Migration

Introduction

The content in the sidebar is organized into decks, panels and tabs. There is always exactly one deck visible. It can contain one or more panels. Tabs are allow manual switching between decks. In general the current deck and its panels is defined by the current context. A context consists of an identifier for the application and one identifier for the actual context like text editing, cursor in table, image editing and so on.


Both UNO API and configuration represent a context with two strings:

UNO 
com/sun/star/ui/ContextChangeEventObject
registry 
org/openoffice/Office/UI/Sidebar.xcs / Context

For the C++ implementation there is a enum wrapper that allows switch() statements:

 sfx2/sidebar/EnumContext.hxx

like this

 void DoSomething (const EnumContext& rContext)
 { 
 switch (rContext.GetCombinedContext())
 {
 case CombinedEnumContext(Application_Calc, Context_Cell):
 ...

Notification of context changes

Notification of context changes is done via one single event multiplexer that is used by all documents and views:

service
com/sun/star/ui/ContextChangeEventMultiplexer.idl
interface
com/sun/star/ui/XContextChangeEventMultiplexer.idl

There is a C++ convenience wrapper in svx:

 svx/inc/sidebar/ContextChangeEventMultiplexer.hxx

that has a single static method:

 static void NotifyContextChange (
 const cssu::Reference<css::frame::XController>& rxController,
 const ::sfx2::sidebar::EnumContext::Context eContext);

It hides the messy instantiation of the UNO singleton and conversion of the parameters. The rxController is used for two things:

  1. Determine the application and fill in the right string/identifier in the resulting context change event.
  2. Allow listeners to be notified only for context changes of a single view

The eContext argument is defined in

 sfx2/sidebar/EnumContext.hxx
Task
  • Add calls to ContextChangeEventMultiplexer::NotifyContextChange() whenever a relevant context change occurs so that the sidebar can display the appropriate deck and panels.
  • Add missing contexts to EnumContext.hxx and Sidebar.xcs and provide a word or two of explanation.
Tips

Look for Update calls for SID_SVX_PROPERTY_CONTEXT

 in sfx2/source/control/dispatch.cxx, SfxDispatcher::Update_Impl()
 and sfx2/source/control/bindings.cxx, IMPL_LINK(SfxBindings, NextJob_Impl...)

and for calls to

 sfx2/source/view/viewfrm.cxx, SfxViewFrame::GetPropertyContextId()
Examples

Notification of start of text editing in Draw/Impress:

 sd/source/ui/func/futext.cxx, FuText::DoExecute()

Notification of Draw/Impress having been started:

 sd/source/ui/view/ViewShellBase.cxx, ViewShellBase::Activate()

Creation of a panel factory

Panels are created by factories via the ui::XUIElementFactory interface and its

 createUIElement(
 const ::rtl::OUString& rsResourceURL,
 const ::cssu::Sequence<css::beans::PropertyValue>& rArguments)

method.

Task

Implement the ui::XUIElementFactory interface.

The sidebar calles the createUIElement() method with the these arguments:

ParentWindow
a awt::XWindow object that is to be used as parent window for any new windows created by the panel. Both size and location of this parent window are modified by the panel layouter of the current deck. A panel that wants to layout its controls manually has to listen for size changes of the parent window.
Frame
the frame::XFrame object of the view for which the sidebar displays decks and panels.
SfxBindings
a pointer to an SfxBindings object (wrapped in a sal_uInt64) that can be used to create controls. This hack is intended as a temporary solution. It is desirable to replace it with a UNO based solution.

The panel factory is expected to create and return a ui::XUIElement object for a given URL. Create a new panel like this:

 if (sURL.equals("my/panel"))
 {
 Control* pPanelControl = new PanelControl(pParentWindow, xFrame, pBindings);
 return sfx2::sidebar::SidebarPanelBase::Create(
 rsResourceURL,
 xFrame,
 pPanel);
 }
Examples

See svx/source/sidebar/PanelFactory.cxx


Creation of a panel control

The content of a panel is typically painted by an instantiation of the vcl::Control class. The XUIElement interface gives access to the XWindow component of the control via the XUIElement::getWindow() method.

Task

Implement the XUIElement interface and add it to a panel factory.

Choose a panel factory in the module where the new panel class will be located. Add support for the panel class to the XUIElementFactory::createUIElement() method.

You can use the sfx2::sidebar::SidebarPanelBase class for taking care of the boiler plate code. Despite its name (which should be change) SidebarPanelBase is not a base class for the new panel class. Due to the design of the XUIElement interface (with its XUIElement::getRealInterface() and XUIElement::getWindow() methods) the XUIElement interface can be implemented independently from the actual panel control. SidebarPanelBase implements the XUIElement::getRealInterface() to return itself. It implements the XUIElement::getWindow() to return the awt::XWindow interface of the panel control. XUIElement::createAccessible() is not yet implemented. The SidebarPanelBase provides additional functionality:

  • Forwarding of context change events: It registers at the ContextChangeEventMultiplexer and forwards all relevant events to the panel control if it implements the ContextChangeReceiverInterface interface (which is a local class of SidebarPanelBase). It uses a

dynamic_cast<> to check if the interface is supported. If it is SidebarPanelBase converts the event data to an EnumContext object and calls ContextChangeReceiverInterface::HandleContextChange().

  • A simple implementation of the ui::XVerticalStackLayoutElement interface that returns the current height of the control (mpControl->GetSizePixel().Height()).

For the implementation or migration of the actual panel control see the following section.

Example

See svx/source/sidebar/PanelFactory.cxx for the use of the SidebarPanelBase class. See svx/source/sidebar/text/TextPropertyPanel.cxx for the implementation of the HandleContextChange method.

Migration of property pages

The Symphony property pages represent much functionality that in AOO can be found in toolbars. That may explain the extensive use of ToolBox controls in the panels.

Task
  • Migrate the panels listed in http://wiki.openoffice.org/wiki/AOO_Symphony_UX_Migration/Merge_Analysis_-_Task_Pane or come up with a better list.
  • Locate the panel implementation in the Symphony code branch. Typical places are:
    • svx/source/propertypanel/
    • sw/source/ui/propertypanel/
    • sc/source/ui/propertypanel/
    • sd/source/ui/propertypanel/
  • Use ::sfx2::sidebar::SidebarPanelBase and ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface

as base classes. These take care of registering at the ContextChangeEventMultiplexer and item controllers.

  • Replace member declarations of controls with scoped_ptrs, so that the controls can be created by a factory and can have a different, derived type:

Replace

 ToolBox maToolBoxIncDec;

with

 ::boost::scoped_ptr<Window> mpToolBoxIncDecBackground;
 ::boost::scoped_ptr<ToolBox> mpToolBoxIncDec;

The mpToolBoxIncDecBackground object is the background/border of the tool box control while mpToolBoxIncDec is the actual tool box object. Then, in the constructor replace

 maToolBoxIncDec (this, SVX_RES(TB_INCREASE_DECREASE)),

with

 mpToolBoxIncDecBackground(ControlFactory::CreateToolBoxBackground(this)),
 mpToolBoxIncDec(ControlFactory::CreateToolBox(
 mpToolBoxIncDecBackground.get(),
 SVX_RES(TB_INCREASE_DECREASE))),
  • Handle context changes:

Replace

 virtual void Init(PropertyContextType nContextId);

with

 virtual void HandleContextChange (
 const ::sfx2::sidebar::EnumContext aContext);

In the implementation replace

 void SvxTextPropertyPage::Init(PropertyContextType nContextId)
 {
 meContextType = nContextId;
 if( nContextId == PROPERTY_CONTEXT_SC_CELL || nContextId == PROPERTY_CONTEXT_SC_PIVOT ) //modified::add s

with

 void TextPropertyPanel::HandleContextChange (
 const ::sfx2::sidebar::EnumContext aContext)
 {
 if (maContext == aContext)
 {
 // Nothing to do.
 return;
 }
 maContext = aContext;
 switch (maContext.GetCombinedContext())
 {
 case CombinedEnumContext(Application_Calc, Context_Cell):
 case CombinedEnumContext(Application_Calc, Context_Pivot):

The first lines (above the switch() statement) could be moved into the base class.

  • Make a similar replacement wherever meContextType is used in if() statements.
  • Replace the use of SfxPropertyPageController with ::sfx2::sidebar::ControllerItem. Controller items connect items (basically the model of toolbar buttons) and state change listeners (the panel that you are migrating).

In the header replace

 SfxPropertyPageController maFontNameControl;

with

 ::sfx2::sidebar::ControllerItem maFontNameControl;

In the constructor replace

 maFontNameControl (SID_ATTR_CHAR_FONT, this, GetBindings())

with

 maFontNameControl (SID_ATTR_CHAR_FONT, *pBindings, *this)

Also transform

 void SvxTextPropertyPage::StateChangedImpl(USHORT nSID, SfxItemState eState, const SfxPoolItem* pState)

into

 virtual void NotifyItemUpdate(
 const sal_uInt16 nSId,
 const SfxItemState eState,
 const SfxPoolItem* pState);

to be informed of state changes.

  • Replace icons

Where possible we should use the standard AOO icons (although in same places we should thing about replacing the AOO icons with Symphony icons). Find the uno command name and do a replacement like:

 maToolBoxIncDec.SetItemImage(TBI_INCREASE, Application::GetSettings().GetStyleSettings().GetHighContrastMode()? maImgIncreaseHigh : maImgIncrease);
 maToolBoxIncDec.SetItemImage(TBI_DECREASE, Application::GetSettings().GetStyleSettings().GetHighContrastMode()? maImgDecreaseHigh : maImgDecrease);

with

 mpToolBoxIncDec->SetItemImage(TBI_INCREASE, GetIcon(A2S(".uno:Grow")));
 mpToolBoxIncDec->SetItemImage(TBI_DECREASE, GetIcon(A2S(".uno:Shrink")));

The GetIcon() method takes care (hopefully) of the high contrast mode.

  • One source file may contain more than one class definition. It is good practice to separate these into their own files. And it makes it easier for others to work on other panels in the same source file.
  • Use namespaces instead of the Svx class prefixes, ie use svx::sidebar namespace (or sw::sidebar, etc) and get rid of the Svx class prefixes.
Tips

Do the Draw/Impress panels last, these are more complicated than the others due to their use of an Impress specific framework.

Examples

See svx/source/sidebar/text/TextPropertyPanel.cxx in the sidebar branch for the first migrated panel.


Migration of popup controls

Some Symphony panels have non-trivial popup (or drop down) controls that contain more than a list of strings. These are often implemented via this pattern (taken from svx/source/propertypanel/areapropertypage.hxx). Variables:

   SfxPopupPanelWin* mpTrGrFloatWin;
   class SvxAreaTrGrPage;
   SvxAreaTrGrPage* mpTrGrPage; 

Functions:

   DECL_LINK( ClickTrGrHdl_Impl, ToolBox* );
   SvxAreaTrGrPage* GetTrGrPage();
   SfxPopupPanelWin* GetTrGrFloatWin();

The ClickTrGrHdl link is called when the popup is requested to be displayed. The GetTrGrPage() and GetTrGrFloatWin() functions contain identical code for constructing the popup windows and return either the inner or outer window. The code in all three methods is very similar for many different popups.

The new Popup class (header can be found in svx/inc/svx/sidebar) factors out the repeating code. It is a wrapper around the two classes PopupContainer and PopupControl. PopupContainer is the outer window that provides the actual drop-down functionality. Different popups use it as is. PopupControl is a base class for the inner windows that provide the actual popup content. Its parent is a PopupContainer object. For a new popup you have to derive from this class. It only provides painting the background and border.

The above variable and method declarations can be replaced by: Variables:

   AreaTransparencyGradientPopup maTrGrPopup;

Functions:

   DECL_LINK( ClickTrGrHdl_Impl, ToolBox* );
   PopupControl* CreateTransparencyGradientControl (PopupContainer* pParent);

One variable (maTrGrPopup, the Popup wrapper) instead of two. The ClickTrGrHdl is still there but its implementation is basically just a forward to maTrGrPopup.Show(). The new CreateTransparencyGradientControl() method is a factory method that returns a new instance of a class derived from PopupControl (in this example that class is AreaTransparencyGradientControl).

The maTrGrPopup member is initialized in the constructor of AreaPopupPanel like this:

   maTrGrPopup(this, ::boost::bind(&AreaPropertyPanel::CreateTransparencyGradientControl, this, _1)),

by which it is informed of how to create the inner PopupControl window.

For details please see the real life examples

   AreaPropertyPanel uses maTrGrPopup of type AreaTransparencyGradientPopup with control AreaTransparencyGradientControl
   AreaPropertyPanel uses maColorPopup of type ColorPopup with control ColorControl

Note that ColorPopup and Color Control can be found in svx/source/sidebar/tools because they are use by different panels.

   LinePropertyPanel uses maLineStylePopup of type LineStylePopup with control LineStyleControl
   LinePropertyPanel uses maLineWidthPopup of type LineWidthPopup with control LineWidthControl
   LinePropertyPanel uses maColorPopup of type ColorPopup with control ColorControl

Note that the factory methods CreateColorPopupControl() in AreaPropertyPanel and LinePropertyPanel differ slightly.

Existing implementation

Not all the API design and implementation work has to be started from scratch. There several parts that can be used/reused/adapted.

In main/sd/

The drawing framework is used for the Impress taskpane, all Impress views and the slide show. A tree of URLs (called a configuration) defines the different layers of containers (windows) and views (taskpane panels). SD views only modify a configuration, update and synchronization of the associated view shells is left to the ConfigurationController.

Contextual changes of tool bars are handled in SD in a single place by the ToolBarManager. It receives notifications about context changes by registering as listener at the EventMultiplexer.

Example: When an Impress shape enters text edit mode then sd::View sends an event to the EventMultiplexer. That forwards the event to the ToolBarManager. The ToolBarManager checks its set of rules, finds the one that activates the text edit tool bar and replaces the current context bar with the text edit bar.



Screenshots from the developer snapshots. In all three screenshots mouse is over the third button from the top in the sidebar, button above is selected. Click to enlarge.

Linux: screenshot-linux-sidebar-small.png Mac: screenshot-mac-sidebar-small.png Windows: screenshot-windows-sidebar-small.png

Detail views of regular toolbar buttons. Right "abc" button is selected, mouse is over left "abc" button.

Linux: screenshot-linux-toolbar.png Mac: screenshot-mac-toolbar.png Windows: screenshot-windows-toolbar-detail.png

Examples of toolbars in other applications:

Linux (file explorer): screenshot-linux-explorer-small.png Mac (Garageband): screenshot-mac-GarageBand-small.png Windows (File Explorer): screenshot-windows-Explorer-small.png


For comparison here is a screenshot from Symphony (on Windows):

screenshot-sidebar-symphony.png


In main/svtools/ and main/sfx2/

The unfinished implementation of an office wide toolpane with Symphony like functionality can be found in svtools/source/toolpanel/ and sfx2/source/dialog/taskpane/. See Framework/Article/Tool Panels Internals for details.

Existing API (main/offapi/)

XUIElement and XToolPanel from com::sun::star::ui provide an API abstraction of the toolpanel.

It is already possible to provide new tool panels from an extension.


In the symphony branch

The sidebar is implemented in sfx2/source/propertypanel. Base functionality for sidebar and content panes can be found in svx/source/propertypanel.

Find application specific content panels in sw/source/ui/propertypanel, sc/source/ui/propertypanel, sd/source/ui/propertypanel. In these directories the files propertydlg.cxx defines the set of panels that are to be displayed. These lists are hardcoded and can not be modified by extensions.

Painting of control backgrounds is also hardcoded. Look for instance at svx/source/propertypanel/paragraphpropertypage.cxx and search for calls to DrawGradient(). Colors for the background gradients are defined in every file that paints button backgrounds.

Personal tools