xref: /aoo41x/main/sfx2/source/dialog/taskpane.cxx (revision cdf0e10c)
1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25  ************************************************************************/
26 
27 #include "precompiled_sfx2.hxx"
28 
29 #include "sfx2/taskpane.hxx"
30 #include "imagemgr.hxx"
31 #include "sfx2/sfxsids.hrc"
32 #include "sfx2/bindings.hxx"
33 #include "sfx2/dispatch.hxx"
34 #include "sfxresid.hxx"
35 #include "sfxlocal.hrc"
36 #include "helpid.hrc"
37 
38 /** === begin UNO includes === **/
39 #include <com/sun/star/frame/XModuleManager.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/ui/XToolPanel.hpp>
42 #include <com/sun/star/ui/XUIElementFactory.hpp>
43 #include <com/sun/star/awt/XWindowPeer.hpp>
44 #include <com/sun/star/awt/PosSize.hpp>
45 #include <com/sun/star/frame/XModuleManager.hpp>
46 #include <com/sun/star/graphic/XGraphicProvider.hpp>
47 #include <com/sun/star/accessibility/XAccessible.hpp>
48 #include <com/sun/star/awt/XControl.hpp>
49 /** === end UNO includes === **/
50 
51 #include <comphelper/componentcontext.hxx>
52 #include <comphelper/namedvaluecollection.hxx>
53 #include <comphelper/types.hxx>
54 #include <comphelper/processfactory.hxx>
55 #include <tools/diagnose_ex.h>
56 #include <svtools/toolpanel/toolpaneldeck.hxx>
57 #include <svtools/toolpanel/tablayouter.hxx>
58 #include <svtools/toolpanel/drawerlayouter.hxx>
59 #include <unotools/confignode.hxx>
60 #include <vcl/menu.hxx>
61 #include <vcl/svapp.hxx>
62 #include <toolkit/helper/vclunohelper.hxx>
63 #include <tools/urlobj.hxx>
64 #include <boost/noncopyable.hpp>
65 
66 //......................................................................................................................
67 namespace sfx2
68 {
69 //......................................................................................................................
70 
71     /** === begin UNO using === **/
72 	using ::com::sun::star::uno::Reference;
73 	using ::com::sun::star::uno::XInterface;
74 	using ::com::sun::star::uno::UNO_QUERY;
75 	using ::com::sun::star::uno::UNO_QUERY_THROW;
76 	using ::com::sun::star::uno::UNO_SET_THROW;
77 	using ::com::sun::star::uno::Exception;
78 	using ::com::sun::star::uno::RuntimeException;
79 	using ::com::sun::star::uno::Any;
80 	using ::com::sun::star::uno::makeAny;
81 	using ::com::sun::star::uno::Sequence;
82 	using ::com::sun::star::uno::Type;
83     using ::com::sun::star::frame::XModuleManager;
84     using ::com::sun::star::container::XNameAccess;
85     using ::com::sun::star::ui::XToolPanel;
86     using ::com::sun::star::ui::XUIElementFactory;
87     using ::com::sun::star::ui::XUIElement;
88     using ::com::sun::star::awt::XWindow;
89     using ::com::sun::star::frame::XModuleManager;
90     using ::com::sun::star::frame::XFrame;
91     using ::com::sun::star::lang::XComponent;
92     using ::com::sun::star::graphic::XGraphicProvider;
93     using ::com::sun::star::graphic::XGraphic;
94     using ::com::sun::star::accessibility::XAccessible;
95     using ::com::sun::star::awt::XControl;
96     /** === end UNO using === **/
97     namespace PosSize = ::com::sun::star::awt::PosSize;
98 
99 	//==================================================================================================================
100 	//= helpers
101 	//==================================================================================================================
102     namespace
103     {
104 	    //--------------------------------------------------------------------------------------------------------------
105         ::utl::OConfigurationTreeRoot lcl_getModuleUIElementStatesConfig( const ::rtl::OUString& i_rModuleIdentifier,
106             const ::rtl::OUString& i_rResourceURL = ::rtl::OUString() )
107         {
108             const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
109             ::rtl::OUStringBuffer aPathComposer;
110             try
111             {
112                 const Reference< XNameAccess > xModuleAccess( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW );
113                 const ::comphelper::NamedValueCollection aModuleProps( xModuleAccess->getByName( i_rModuleIdentifier ) );
114 
115                 const ::rtl::OUString sWindowStateRef( aModuleProps.getOrDefault( "ooSetupFactoryWindowStateConfigRef", ::rtl::OUString() ) );
116 
117                 aPathComposer.appendAscii( "org.openoffice.Office.UI." );
118                 aPathComposer.append( sWindowStateRef );
119                 aPathComposer.appendAscii( "/UIElements/States" );
120                 if ( i_rResourceURL.getLength() )
121                 {
122                     aPathComposer.appendAscii( "/" );
123                     aPathComposer.append( i_rResourceURL );
124                 }
125             }
126             catch( const Exception& )
127             {
128         	    DBG_UNHANDLED_EXCEPTION();
129             }
130             return ::utl::OConfigurationTreeRoot( aContext, aPathComposer.makeStringAndClear(), false );
131         }
132 
133 	    //--------------------------------------------------------------------------------------------------------------
134         ::rtl::OUString lcl_identifyModule( const Reference< XFrame >& i_rDocumentFrame )
135         {
136             ::rtl::OUString sModuleName;
137             try
138             {
139                 const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
140                 const Reference< XModuleManager > xModuleManager( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW );
141                 sModuleName = xModuleManager->identify( i_rDocumentFrame );
142             }
143             catch( const Exception& )
144             {
145             	DBG_UNHANDLED_EXCEPTION();
146             }
147             return sModuleName;
148         }
149 
150 	    //--------------------------------------------------------------------------------------------------------------
151         Reference< XFrame > lcl_getFrame( const SfxBindings* i_pBindings )
152         {
153             const SfxViewFrame* pViewFrame = i_pBindings->GetDispatcher()->GetFrame();
154             const SfxFrame& rFrame = pViewFrame->GetFrame();
155             const Reference< XFrame > xFrame( rFrame.GetFrameInterface() );
156             return xFrame;
157         }
158 
159 	    //--------------------------------------------------------------------------------------------------------------
160         ::rtl::OUString lcl_getPanelHelpURL( const ::utl::OConfigurationNode& i_rPanelConfigNode )
161         {
162             const ::rtl::OUString sHelpURL( ::comphelper::getString( i_rPanelConfigNode.getNodeValue( "HelpURL" ) ) );
163             return sHelpURL;
164         }
165 
166 	    //--------------------------------------------------------------------------------------------------------------
167         Image lcl_getPanelImage( const Reference< XFrame >& i_rDocFrame, const ::utl::OConfigurationNode& i_rPanelConfigNode )
168         {
169             const ::rtl::OUString sImageURL( ::comphelper::getString( i_rPanelConfigNode.getNodeValue( "ImageURL" ) ) );
170             if ( sImageURL.getLength() )
171             {
172                 try
173                 {
174                     ::comphelper::NamedValueCollection aMediaProperties;
175                     aMediaProperties.put( "URL", sImageURL );
176 
177                     // special handling: if the ImageURL denotes a CommandName, then retrieve the image for that command
178                     const sal_Char* pCommandImagePrefix = "private:commandimage/";
179                     const sal_Int32 nCommandImagePrefixLen = strlen( pCommandImagePrefix );
180                     if ( sImageURL.compareToAscii( pCommandImagePrefix, nCommandImagePrefixLen ) == 0 )
181                     {
182                         ::rtl::OUStringBuffer aCommandName;
183                         aCommandName.appendAscii( ".uno:" );
184                         aCommandName.append( sImageURL.copy( nCommandImagePrefixLen ) );
185                         const ::rtl::OUString sCommandName( aCommandName.makeStringAndClear() );
186 
187                         const sal_Bool bHiContrast( Application::GetSettings().GetStyleSettings().GetHighContrastMode() );
188                         const Image aPanelImage( GetImage( i_rDocFrame, sCommandName, sal_False, bHiContrast ) );
189                         return aPanelImage.GetXGraphic();
190                     }
191 
192                     // otherwise, delegate to the GraphicProvider
193                     const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
194                     const Reference< XGraphicProvider > xGraphicProvider( aContext.createComponent( "com.sun.star.graphic.GraphicProvider" ), UNO_QUERY_THROW );
195 
196                     const Reference< XGraphic > xGraphic( xGraphicProvider->queryGraphic( aMediaProperties.getPropertyValues() ), UNO_SET_THROW );
197                     return Image( xGraphic );
198                 }
199                 catch( const Exception& )
200                 {
201             	    DBG_UNHANDLED_EXCEPTION();
202                 }
203             }
204             return Image();
205         }
206     }
207 
208 	//==================================================================================================================
209 	//= TaskPaneDockingWindow
210 	//==================================================================================================================
211 	//------------------------------------------------------------------------------------------------------------------
212     TaskPaneDockingWindow::TaskPaneDockingWindow( SfxBindings* i_pBindings, TaskPaneWrapper& i_rWrapper, Window* i_pParent, WinBits i_nBits )
213         :TitledDockingWindow( i_pBindings, &i_rWrapper, i_pParent, i_nBits )
214         ,m_aTaskPane( GetContentWindow(), lcl_getFrame( i_pBindings ) )
215         ,m_aPaneController( m_aTaskPane, *this )
216     {
217         m_aTaskPane.Show();
218         SetText( String( SfxResId( SID_TASKPANE ) ) );
219     }
220 
221 	//------------------------------------------------------------------------------------------------------------------
222     void TaskPaneDockingWindow::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL )
223     {
224         m_aPaneController.ActivateToolPanel( i_rPanelURL );
225     }
226 
227 	//------------------------------------------------------------------------------------------------------------------
228     void TaskPaneDockingWindow::GetFocus()
229     {
230         TitledDockingWindow::GetFocus();
231         m_aTaskPane.GrabFocus();
232     }
233 
234 	//------------------------------------------------------------------------------------------------------------------
235     void TaskPaneDockingWindow::onLayoutDone()
236     {
237         m_aTaskPane.SetPosSizePixel( Point(), GetContentWindow().GetOutputSizePixel() );
238     }
239 
240 	//==================================================================================================================
241 	//= TaskPaneWrapper
242 	//==================================================================================================================
243 	//------------------------------------------------------------------------------------------------------------------
244     SFX_IMPL_DOCKINGWINDOW( TaskPaneWrapper, SID_TASKPANE );
245 
246 	//------------------------------------------------------------------------------------------------------------------
247     TaskPaneWrapper::TaskPaneWrapper( Window* i_pParent, sal_uInt16 i_nId, SfxBindings* i_pBindings, SfxChildWinInfo* i_pInfo )
248         :SfxChildWindow( i_pParent, i_nId )
249     {
250         pWindow = new TaskPaneDockingWindow( i_pBindings, *this, i_pParent,
251             WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE);
252 	    eChildAlignment = SFX_ALIGN_RIGHT;
253 
254 	    pWindow->SetHelpId( HID_TASKPANE_WINDOW );
255         pWindow->SetOutputSizePixel( Size( 300, 450 ) );
256 
257         dynamic_cast< SfxDockingWindow* >( pWindow )->Initialize( i_pInfo );
258 	    SetHideNotDelete( sal_True );
259 
260         pWindow->Show();
261     }
262 
263 	//------------------------------------------------------------------------------------------------------------------
264     void TaskPaneWrapper::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL )
265     {
266         TaskPaneDockingWindow* pDockingWindow = dynamic_cast< TaskPaneDockingWindow* >( GetWindow() );
267         ENSURE_OR_RETURN_VOID( pDockingWindow, "TaskPaneWrapper::ActivateToolPanel: invalid docking window implementation!" );
268         pDockingWindow->ActivateToolPanel( i_rPanelURL );
269     }
270 
271 	//==================================================================================================================
272 	//= CustomPanelUIElement
273 	//==================================================================================================================
274     class CustomPanelUIElement
275     {
276     public:
277         CustomPanelUIElement()
278             :m_xUIElement()
279             ,m_xToolPanel()
280             ,m_xPanelWindow()
281         {
282         }
283 
284         CustomPanelUIElement( const Reference< XUIElement >& i_rUIElement )
285             :m_xUIElement( i_rUIElement, UNO_SET_THROW )
286             ,m_xToolPanel( i_rUIElement->getRealInterface(), UNO_QUERY_THROW )
287             ,m_xPanelWindow( m_xToolPanel->getWindow(), UNO_SET_THROW )
288         {
289         }
290 
291         bool is() const { return m_xPanelWindow.is(); }
292 
293         const Reference< XUIElement >&  getUIElement() const { return m_xUIElement; }
294         const Reference< XToolPanel >&  getToolPanel() const { return m_xToolPanel; }
295         const Reference< XWindow >&     getPanelWindow() const { return m_xPanelWindow; }
296 
297     private:
298         Reference< XUIElement > m_xUIElement;
299         Reference< XToolPanel > m_xToolPanel;
300         Reference< XWindow >    m_xPanelWindow;
301     };
302 
303 	//==================================================================================================================
304 	//= CustomToolPanel
305 	//==================================================================================================================
306     class CustomToolPanel : public ::svt::ToolPanelBase
307     {
308     public:
309         CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState, const Reference< XFrame >& i_rFrame );
310 
311         virtual ::rtl::OUString GetDisplayName() const;
312         virtual Image GetImage() const;
313         virtual rtl::OString GetHelpID() const;
314         virtual void Activate( Window& i_rParentWindow );
315         virtual void Deactivate();
316         virtual void SetSizePixel( const Size& i_rPanelWindowSize );
317         virtual void GrabFocus();
318         virtual void Dispose();
319         virtual Reference< XAccessible >
320                     CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible );
321 
322         const ::rtl::OUString&
323                     GetResourceURL() const { return m_sResourceURL; }
324 
325     protected:
326         ~CustomToolPanel();
327 
328     private:
329         bool    impl_ensureToolPanelWindow( Window& i_rPanelParentWindow );
330         void    impl_updatePanelConfig( const bool i_bVisible ) const;
331 
332     private:
333         const ::rtl::OUString   m_sUIName;
334         const Image             m_aPanelImage;
335         const ::rtl::OUString   m_aPanelHelpURL;
336         const ::rtl::OUString   m_sResourceURL;
337         const ::rtl::OUString   m_sPanelConfigPath;
338         Reference< XFrame >     m_xFrame;
339         CustomPanelUIElement    m_aCustomPanel;
340         bool                    m_bAttemptedCreation;
341     };
342 
343     //------------------------------------------------------------------------------------------------------------------
344     CustomToolPanel::CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState, const Reference< XFrame >& i_rFrame )
345         :m_sUIName( ::comphelper::getString( i_rPanelWindowState.getNodeValue( "UIName" ) ) )
346         ,m_aPanelImage( lcl_getPanelImage( i_rFrame, i_rPanelWindowState ) )
347         ,m_aPanelHelpURL( lcl_getPanelHelpURL( i_rPanelWindowState ) )
348         ,m_sResourceURL( i_rPanelWindowState.getLocalName() )
349         ,m_sPanelConfigPath( i_rPanelWindowState.getNodePath() )
350         ,m_xFrame( i_rFrame )
351         ,m_aCustomPanel()
352         ,m_bAttemptedCreation( false )
353     {
354     }
355 
356     //------------------------------------------------------------------------------------------------------------------
357     CustomToolPanel::~CustomToolPanel()
358     {
359     }
360 
361     //------------------------------------------------------------------------------------------------------------------
362     bool CustomToolPanel::impl_ensureToolPanelWindow( Window& i_rPanelParentWindow )
363     {
364         if ( m_bAttemptedCreation )
365             return m_aCustomPanel.is();
366 
367         m_bAttemptedCreation = true;
368         try
369         {
370             const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
371             const Reference< XUIElementFactory > xFactory( aContext.createComponent( "com.sun.star.ui.UIElementFactoryManager" ), UNO_QUERY_THROW );
372 
373             ::comphelper::NamedValueCollection aCreationArgs;
374             aCreationArgs.put( "Frame", makeAny( m_xFrame ) );
375             aCreationArgs.put( "ParentWindow", makeAny( i_rPanelParentWindow.GetComponentInterface() ) );
376 
377             const Reference< XUIElement > xElement(
378                 xFactory->createUIElement( m_sResourceURL, aCreationArgs.getPropertyValues() ),
379                 UNO_SET_THROW );
380 
381             m_aCustomPanel = CustomPanelUIElement( xElement );
382         }
383         catch( const Exception& )
384         {
385         	DBG_UNHANDLED_EXCEPTION();
386         }
387         return m_aCustomPanel.is();
388     }
389 
390     //------------------------------------------------------------------------------------------------------------------
391     void CustomToolPanel::impl_updatePanelConfig( const bool i_bVisible ) const
392     {
393         ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
394         ::utl::OConfigurationTreeRoot aConfig( aContext, m_sPanelConfigPath, true );
395 
396         aConfig.setNodeValue( "Visible", makeAny( i_bVisible ) );
397         aConfig.commit();
398     }
399 
400     //------------------------------------------------------------------------------------------------------------------
401     ::rtl::OUString CustomToolPanel::GetDisplayName() const
402     {
403         return m_sUIName;
404     }
405 
406     //------------------------------------------------------------------------------------------------------------------
407     Image CustomToolPanel::GetImage() const
408     {
409         return m_aPanelImage;
410     }
411 
412 	static rtl::OString lcl_getHelpId( const ::rtl::OUString& _rHelpURL )
413     {
414         INetURLObject aHID( _rHelpURL );
415         if ( aHID.GetProtocol() == INET_PROT_HID )
416             return rtl::OUStringToOString( aHID.GetURLPath(), RTL_TEXTENCODING_UTF8 );
417         else
418             return rtl::OUStringToOString( _rHelpURL, RTL_TEXTENCODING_UTF8 );
419     }
420 
421     //------------------------------------------------------------------------------------------------------------------
422     rtl::OString CustomToolPanel::GetHelpID() const
423     {
424         return lcl_getHelpId( m_aPanelHelpURL );
425     }
426 
427     //------------------------------------------------------------------------------------------------------------------
428     void CustomToolPanel::Activate( Window& i_rParentWindow )
429     {
430         ENSURE_OR_RETURN_VOID( impl_ensureToolPanelWindow( i_rParentWindow ), "no panel to activate!" );
431 
432         // TODO: we might need a mechanism to decide whether the panel should be destroyed/re-created, or (as it is
433         // done now) hidden/shown
434         m_aCustomPanel.getPanelWindow()->setVisible( sal_True );
435 
436         // update the panel's configuration
437         impl_updatePanelConfig( true );
438     }
439 
440     //------------------------------------------------------------------------------------------------------------------
441     void CustomToolPanel::Deactivate()
442     {
443         ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to deactivate!" );
444 
445         m_aCustomPanel.getPanelWindow()->setVisible( sal_False );
446 
447         // update the panel's configuration
448         impl_updatePanelConfig( false );
449     }
450 
451     //------------------------------------------------------------------------------------------------------------------
452     void CustomToolPanel::SetSizePixel( const Size& i_rPanelWindowSize )
453     {
454         ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to position!" );
455 
456         try
457         {
458             m_aCustomPanel.getPanelWindow()->setPosSize( 0, 0, i_rPanelWindowSize.Width(), i_rPanelWindowSize.Height(),
459                 PosSize::POSSIZE );
460         }
461         catch( const Exception& )
462         {
463         	DBG_UNHANDLED_EXCEPTION();
464         }
465     }
466 
467     //------------------------------------------------------------------------------------------------------------------
468     void CustomToolPanel::GrabFocus()
469     {
470         ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to focus!" );
471 
472         m_aCustomPanel.getPanelWindow()->setFocus();
473     }
474 
475     //------------------------------------------------------------------------------------------------------------------
476     void CustomToolPanel::Dispose()
477     {
478         if ( !m_bAttemptedCreation )
479             // nothing to dispose
480             return;
481 
482         ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to destroy!" );
483         try
484         {
485             Reference< XComponent > xUIElementComponent( m_aCustomPanel.getUIElement(), UNO_QUERY_THROW );
486             xUIElementComponent->dispose();
487         }
488         catch( const Exception& )
489         {
490         	DBG_UNHANDLED_EXCEPTION();
491         }
492     }
493 
494     //------------------------------------------------------------------------------------------------------------------
495     Reference< XAccessible > CustomToolPanel::CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible )
496     {
497         ENSURE_OR_RETURN( m_aCustomPanel.is(), "no panel to ask!", NULL );
498 
499         Reference< XAccessible > xPanelAccessible;
500         try
501         {
502             xPanelAccessible.set( m_aCustomPanel.getToolPanel()->createAccessible( i_rParentAccessible ), UNO_SET_THROW );
503         }
504         catch( const Exception& )
505         {
506         	DBG_UNHANDLED_EXCEPTION();
507         }
508         return xPanelAccessible;
509     }
510 
511 	//==================================================================================================================
512 	//= ModuleTaskPane_Impl
513 	//==================================================================================================================
514     class ModuleTaskPane_Impl : public ::boost::noncopyable
515     {
516     public:
517         ModuleTaskPane_Impl( ModuleTaskPane& i_rAntiImpl, const Reference< XFrame >& i_rDocumentFrame,
518                 const IToolPanelCompare* i_pPanelCompare )
519             :m_rAntiImpl( i_rAntiImpl )
520             ,m_sModuleIdentifier( lcl_identifyModule( i_rDocumentFrame ) )
521             ,m_xFrame( i_rDocumentFrame )
522             ,m_aPanelDeck( i_rAntiImpl )
523         {
524             m_aPanelDeck.Show();
525             OnResize();
526             impl_initFromConfiguration( i_pPanelCompare );
527         }
528 
529         ~ModuleTaskPane_Impl()
530         {
531         }
532 
533         void    OnResize();
534         void    OnGetFocus();
535 
536         static bool ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier );
537 
538               ::svt::ToolPanelDeck& GetPanelDeck()          { return m_aPanelDeck; }
539         const ::svt::ToolPanelDeck& GetPanelDeck() const    { return m_aPanelDeck; }
540 
541         ::boost::optional< size_t >
542                     GetPanelPos( const ::rtl::OUString& i_rResourceURL );
543         ::rtl::OUString
544                     GetPanelResourceURL( const size_t i_nPanelPos ) const;
545 
546         void        SetDrawersLayout();
547         void        SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent );
548 
549     private:
550         void    impl_initFromConfiguration( const IToolPanelCompare* i_pPanelCompare );
551 
552         static bool
553                 impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL );
554 
555         DECL_LINK( OnActivatePanel, void* );
556 
557     private:
558         ModuleTaskPane&             m_rAntiImpl;
559         const ::rtl::OUString       m_sModuleIdentifier;
560         const Reference< XFrame >   m_xFrame;
561         ::svt::ToolPanelDeck        m_aPanelDeck;
562     };
563 
564 	//------------------------------------------------------------------------------------------------------------------
565     void ModuleTaskPane_Impl::OnResize()
566     {
567         m_aPanelDeck.SetPosSizePixel( Point(), m_rAntiImpl.GetOutputSizePixel() );
568     }
569 
570 	//------------------------------------------------------------------------------------------------------------------
571     void ModuleTaskPane_Impl::OnGetFocus()
572     {
573         m_aPanelDeck.GrabFocus();
574     }
575 
576 	//------------------------------------------------------------------------------------------------------------------
577     IMPL_LINK( ModuleTaskPane_Impl, OnActivatePanel, void*, i_pArg )
578     {
579         m_aPanelDeck.ActivatePanel( reinterpret_cast< size_t >( i_pArg ) );
580         return 1L;
581     }
582 
583 	//------------------------------------------------------------------------------------------------------------------
584     bool ModuleTaskPane_Impl::impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL )
585     {
586         return i_rResourceURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/" ) );
587     }
588 
589 	//------------------------------------------------------------------------------------------------------------------
590     void ModuleTaskPane_Impl::impl_initFromConfiguration( const IToolPanelCompare* i_pPanelCompare )
591     {
592         const ::utl::OConfigurationTreeRoot aWindowStateConfig( lcl_getModuleUIElementStatesConfig( m_sModuleIdentifier ) );
593         if ( !aWindowStateConfig.isValid() )
594             return;
595 
596         ::rtl::OUString sFirstVisiblePanelResource;
597         ::rtl::OUString sFirstPanelResource;
598 
599         const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() );
600         for (   const ::rtl::OUString* resource = aUIElements.getConstArray();
601                 resource != aUIElements.getConstArray() + aUIElements.getLength();
602                 ++resource
603             )
604         {
605             if ( !impl_isToolPanelResource( *resource ) )
606                 continue;
607 
608             sFirstPanelResource = *resource;
609 
610             ::utl::OConfigurationNode aResourceNode( aWindowStateConfig.openNode( *resource ) );
611             ::svt::PToolPanel pCustomPanel( new CustomToolPanel( aResourceNode, m_xFrame ) );
612 
613             size_t nPanelPos = m_aPanelDeck.GetPanelCount();
614             if ( i_pPanelCompare )
615             {
616                 // assuming that nobody will insert hundreths of panels, a simple O(n) search should suffice here ...
617                 while ( nPanelPos > 0 )
618                 {
619                     const short nCompare = i_pPanelCompare->compareToolPanelsURLs(
620                         *resource,
621                         GetPanelResourceURL( --nPanelPos )
622                     );
623                     if ( nCompare >= 0 )
624                     {
625                         ++nPanelPos;
626                         break;
627                     }
628                 }
629             }
630             nPanelPos = m_aPanelDeck.InsertPanel( pCustomPanel, nPanelPos );
631 
632             if ( ::comphelper::getBOOL( aResourceNode.getNodeValue( "Visible" ) ) )
633                 sFirstVisiblePanelResource = *resource;
634         }
635 
636         if ( sFirstVisiblePanelResource.getLength() == 0 )
637             sFirstVisiblePanelResource = sFirstPanelResource;
638 
639         if ( sFirstVisiblePanelResource.getLength() )
640         {
641             ::boost::optional< size_t > aPanelPos( GetPanelPos( sFirstVisiblePanelResource ) );
642             OSL_ENSURE( !!aPanelPos, "ModuleTaskPane_Impl::impl_isToolPanelResource: just inserted it, and it's not there?!" );
643             if ( !!aPanelPos )
644                 m_rAntiImpl.PostUserEvent( LINK( this, ModuleTaskPane_Impl, OnActivatePanel ), reinterpret_cast< void* >( *aPanelPos ) );
645         }
646     }
647 
648 	//------------------------------------------------------------------------------------------------------------------
649     bool ModuleTaskPane_Impl::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier )
650     {
651         const ::utl::OConfigurationTreeRoot aWindowStateConfig( lcl_getModuleUIElementStatesConfig( i_rModuleIdentifier ) );
652         if ( !aWindowStateConfig.isValid() )
653             return false;
654 
655         const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() );
656         for (   const ::rtl::OUString* resource = aUIElements.getConstArray();
657                 resource != aUIElements.getConstArray() + aUIElements.getLength();
658                 ++resource
659             )
660         {
661             if ( impl_isToolPanelResource( *resource ) )
662                 return true;
663         }
664         return false;
665     }
666 
667 	//------------------------------------------------------------------------------------------------------------------
668     ::boost::optional< size_t > ModuleTaskPane_Impl::GetPanelPos( const ::rtl::OUString& i_rResourceURL )
669     {
670         ::boost::optional< size_t > aPanelPos;
671         for ( size_t i = 0; i < m_aPanelDeck.GetPanelCount(); ++i )
672         {
673             const ::svt::PToolPanel pPanel( m_aPanelDeck.GetPanel( i ) );
674             const CustomToolPanel* pCustomPanel = dynamic_cast< const CustomToolPanel* >( pPanel.get() );
675             ENSURE_OR_CONTINUE( pCustomPanel != NULL, "ModuleTaskPane_Impl::GetPanelPos: illegal panel implementation!" );
676             if ( pCustomPanel->GetResourceURL() == i_rResourceURL )
677             {
678                 aPanelPos = i;
679                 break;
680             }
681         }
682         return aPanelPos;
683     }
684 
685 	//------------------------------------------------------------------------------------------------------------------
686     ::rtl::OUString ModuleTaskPane_Impl::GetPanelResourceURL( const size_t i_nPanelPos ) const
687     {
688         ENSURE_OR_RETURN( i_nPanelPos < m_aPanelDeck.GetPanelCount(), "ModuleTaskPane_Impl::GetPanelResourceURL: illegal panel position!", ::rtl::OUString() );
689         const ::svt::PToolPanel pPanel( m_aPanelDeck.GetPanel( i_nPanelPos ) );
690         const CustomToolPanel* pCustomPanel = dynamic_cast< const CustomToolPanel* >( pPanel.get() );
691         ENSURE_OR_RETURN( pCustomPanel != NULL, "ModuleTaskPane_Impl::GetPanelPos: illegal panel implementation!", ::rtl::OUString() );
692         return pCustomPanel->GetResourceURL();
693     }
694 
695 	//------------------------------------------------------------------------------------------------------------------
696     void ModuleTaskPane_Impl::SetDrawersLayout()
697     {
698         const ::svt::PDeckLayouter pLayouter( m_aPanelDeck.GetLayouter() );
699         const ::svt::DrawerDeckLayouter* pDrawerLayouter = dynamic_cast< const ::svt::DrawerDeckLayouter* >( pLayouter.get() );
700         if ( pDrawerLayouter != NULL )
701             // already have the proper layout
702             return;
703         m_aPanelDeck.SetLayouter( new ::svt::DrawerDeckLayouter( m_aPanelDeck, m_aPanelDeck ) );
704     }
705 
706 	//------------------------------------------------------------------------------------------------------------------
707     void ModuleTaskPane_Impl::SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent )
708     {
709         ::svt::PDeckLayouter pLayouter( m_aPanelDeck.GetLayouter() );
710         ::svt::TabDeckLayouter* pTabLayouter = dynamic_cast< ::svt::TabDeckLayouter* >( pLayouter.get() );
711         if  (   ( pTabLayouter != NULL )
712             &&  ( pTabLayouter->GetTabAlignment() == i_eTabAlignment )
713             &&  ( pTabLayouter->GetTabItemContent() == i_eTabContent )
714             )
715             // already have the requested layout
716             return;
717 
718         if ( pTabLayouter && ( pTabLayouter->GetTabAlignment() == i_eTabAlignment ) )
719         {
720             // changing only the item content does not require a new layouter instance
721             pTabLayouter->SetTabItemContent( i_eTabContent );
722             return;
723         }
724 
725         m_aPanelDeck.SetLayouter( new ::svt::TabDeckLayouter( m_aPanelDeck, m_aPanelDeck, i_eTabAlignment, i_eTabContent ) );
726     }
727 
728 	//==================================================================================================================
729 	//= ModuleTaskPane
730 	//==================================================================================================================
731 	//------------------------------------------------------------------------------------------------------------------
732     ModuleTaskPane::ModuleTaskPane( Window& i_rParentWindow, const Reference< XFrame >& i_rDocumentFrame )
733         :Window( &i_rParentWindow, WB_DIALOGCONTROL )
734         ,m_pImpl( new ModuleTaskPane_Impl( *this, i_rDocumentFrame, NULL ) )
735     {
736     }
737 
738 	//------------------------------------------------------------------------------------------------------------------
739     ModuleTaskPane::ModuleTaskPane( Window& i_rParentWindow, const Reference< XFrame >& i_rDocumentFrame,
740             const IToolPanelCompare& i_rCompare )
741         :Window( &i_rParentWindow, WB_DIALOGCONTROL )
742         ,m_pImpl( new ModuleTaskPane_Impl( *this, i_rDocumentFrame, &i_rCompare ) )
743     {
744     }
745 
746 	//------------------------------------------------------------------------------------------------------------------
747     ModuleTaskPane::~ModuleTaskPane()
748     {
749     }
750 
751 	//------------------------------------------------------------------------------------------------------------------
752     bool ModuleTaskPane::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier )
753     {
754         return ModuleTaskPane_Impl::ModuleHasToolPanels( i_rModuleIdentifier );
755     }
756 
757 	//------------------------------------------------------------------------------------------------------------------
758     bool ModuleTaskPane::ModuleHasToolPanels( const Reference< XFrame >& i_rDocumentFrame )
759     {
760         return ModuleTaskPane_Impl::ModuleHasToolPanels( lcl_identifyModule( i_rDocumentFrame ) );
761     }
762 
763 	//------------------------------------------------------------------------------------------------------------------
764     void ModuleTaskPane::Resize()
765     {
766         Window::Resize();
767         m_pImpl->OnResize();
768     }
769 
770 	//------------------------------------------------------------------------------------------------------------------
771     void ModuleTaskPane::GetFocus()
772     {
773         Window::GetFocus();
774         m_pImpl->OnGetFocus();
775     }
776 
777 	//------------------------------------------------------------------------------------------------------------------
778     ::svt::ToolPanelDeck& ModuleTaskPane::GetPanelDeck()
779     {
780         return m_pImpl->GetPanelDeck();
781     }
782 
783 	//------------------------------------------------------------------------------------------------------------------
784     const ::svt::ToolPanelDeck& ModuleTaskPane::GetPanelDeck() const
785     {
786         return m_pImpl->GetPanelDeck();
787     }
788 
789 	//------------------------------------------------------------------------------------------------------------------
790     ::boost::optional< size_t > ModuleTaskPane::GetPanelPos( const ::rtl::OUString& i_rResourceURL )
791     {
792         return m_pImpl->GetPanelPos( i_rResourceURL );
793     }
794 
795 	//------------------------------------------------------------------------------------------------------------------
796     ::rtl::OUString ModuleTaskPane::GetPanelResourceURL( const size_t i_nPanelPos ) const
797     {
798         return m_pImpl->GetPanelResourceURL( i_nPanelPos );
799     }
800 
801 	//------------------------------------------------------------------------------------------------------------------
802     void ModuleTaskPane::SetDrawersLayout()
803     {
804         m_pImpl->SetDrawersLayout();
805     }
806 
807 	//------------------------------------------------------------------------------------------------------------------
808     void ModuleTaskPane::SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent )
809     {
810         m_pImpl->SetTabsLayout( i_eTabAlignment, i_eTabContent );
811     }
812 
813     // =====================================================================================================================
814     // = PanelSelectorLayout
815     // =====================================================================================================================
816     enum PanelSelectorLayout
817     {
818         LAYOUT_DRAWERS,
819         LAYOUT_TABS_RIGHT,
820         LAYOUT_TABS_LEFT,
821         LAYOUT_TABS_TOP,
822         LAYOUT_TABS_BOTTOM
823     };
824 
825 	//==================================================================================================================
826 	//= helper
827 	//==================================================================================================================
828     namespace
829     {
830         PanelSelectorLayout lcl_getTabLayoutFromAlignment( const SfxChildAlignment i_eAlignment )
831         {
832             switch ( i_eAlignment )
833             {
834             case SFX_ALIGN_LEFT:
835                 return LAYOUT_TABS_LEFT;
836             case SFX_ALIGN_TOP:
837                 return LAYOUT_TABS_TOP;
838             case SFX_ALIGN_BOTTOM:
839                 return LAYOUT_TABS_BOTTOM;
840             default:
841                 return LAYOUT_TABS_RIGHT;
842             }
843         }
844     }
845 
846     // =====================================================================================================================
847     // = PanelDescriptor
848     // =====================================================================================================================
849     /** is a helper class for TaskPaneController_Impl, holding the details about a single panel which is not
850         contained in the IToolPanel implementation itself.
851     */
852     struct PanelDescriptor
853     {
854         ::svt::PToolPanel   pPanel;
855         bool                bHidden;
856 
857         PanelDescriptor()
858             :pPanel()
859             ,bHidden( false )
860         {
861         }
862 
863         PanelDescriptor( const ::svt::PToolPanel& i_rPanel )
864             :pPanel( i_rPanel )
865             ,bHidden( false )
866         {
867         }
868     };
869 
870 	//==================================================================================================================
871 	//= TaskPaneController_Impl
872 	//==================================================================================================================
873     class TaskPaneController_Impl   :public ::boost::noncopyable
874                                     ,public ::svt::IToolPanelDeckListener
875     {
876     public:
877         TaskPaneController_Impl(
878             ModuleTaskPane& i_rTaskPane,
879             TitledDockingWindow& i_rDockingWindow
880         );
881         ~TaskPaneController_Impl();
882 
883         void    SetDefaultTitle( const String& i_rTitle );
884         void    ActivateToolPanel( const ::rtl::OUString& i_rPanelURL );
885 
886     protected:
887         // IToolPanelDeckListener overridables
888         virtual void PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition );
889         virtual void PanelRemoved( const size_t i_nPosition );
890         virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
891         virtual void LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter );
892         virtual void Dying();
893 
894     private:
895         DECL_LINK( OnToolboxClicked, ToolBox* );
896         DECL_LINK( OnMenuItemSelected, Menu* );
897         DECL_LINK( DockingChanged, TitledDockingWindow* );
898         ::std::auto_ptr< PopupMenu > impl_createPopupMenu() const;
899 
900         /// sets the given layout for the panel selector
901         void    impl_setLayout( const PanelSelectorLayout i_eLayout, const bool i_bForce = false );
902 
903         /// returns the current layout of the panel selector
904         PanelSelectorLayout
905                 impl_getLayout() const { return m_eCurrentLayout; }
906 
907         void    impl_updateDockingWindowTitle();
908         void    impl_togglePanelVisibility( const size_t i_nLogicalPanelIndex );
909         size_t  impl_getLogicalPanelIndex( const size_t i_nVisibleIndex );
910 
911     private:
912         enum MenuId
913         {
914             MID_UNLOCK_TASK_PANEL = 1,
915             MID_LOCK_TASK_PANEL = 2,
916             MID_LAYOUT_TABS = 3,
917             MID_LAYOUT_DRAWERS = 4,
918             MID_FIRST_PANEL = 5
919         };
920 
921     private:
922         typedef ::std::vector< PanelDescriptor >    PanelDescriptors;
923 
924         ModuleTaskPane&         m_rTaskPane;
925         TitledDockingWindow&    m_rDockingWindow;
926         sal_uInt16                  m_nViewMenuID;
927         PanelSelectorLayout     m_eCurrentLayout;
928         PanelDescriptors        m_aPanelRepository;
929         bool                    m_bTogglingPanelVisibility;
930         ::rtl::OUString         m_sDefaultTitle;
931     };
932 
933 	//------------------------------------------------------------------------------------------------------------------
934     TaskPaneController_Impl::TaskPaneController_Impl( ModuleTaskPane& i_rTaskPane, TitledDockingWindow& i_rDockingWindow )
935         :m_rTaskPane( i_rTaskPane )
936         ,m_rDockingWindow( i_rDockingWindow )
937         ,m_nViewMenuID( 0 )
938         ,m_eCurrentLayout( LAYOUT_DRAWERS )
939         ,m_aPanelRepository()
940         ,m_bTogglingPanelVisibility( false )
941         ,m_sDefaultTitle()
942     {
943         m_rDockingWindow.ResetToolBox();
944         m_nViewMenuID = m_rDockingWindow.AddDropDownToolBoxItem(
945             String( SfxResId( STR_SFX_TASK_PANE_VIEW ) ),
946 			HID_TASKPANE_VIEW_MENU,
947             LINK( this, TaskPaneController_Impl, OnToolboxClicked )
948         );
949         m_rDockingWindow.SetEndDockingHdl( LINK( this, TaskPaneController_Impl, DockingChanged ) );
950         impl_setLayout( LAYOUT_DRAWERS, true );
951 
952         m_rTaskPane.GetPanelDeck().AddListener( *this );
953 
954         // initialize the panel repository
955         for ( size_t i = 0; i < m_rTaskPane.GetPanelDeck().GetPanelCount(); ++i )
956         {
957             ::svt::PToolPanel pPanel( m_rTaskPane.GetPanelDeck().GetPanel( i ) );
958             m_aPanelRepository.push_back( PanelDescriptor( pPanel ) );
959         }
960 
961         SetDefaultTitle( String( SfxResId( STR_SFX_TASKS ) ) );
962     }
963 
964 	//------------------------------------------------------------------------------------------------------------------
965     TaskPaneController_Impl::~TaskPaneController_Impl()
966     {
967         m_rTaskPane.GetPanelDeck().RemoveListener( *this );
968 
969         // remove the panels which are not under the control of the panel deck currently
970         for (   PanelDescriptors::iterator panelPos = m_aPanelRepository.begin();
971                 panelPos != m_aPanelRepository.end();
972                 ++panelPos
973             )
974         {
975             if ( panelPos->bHidden )
976                 panelPos->pPanel->Dispose();
977         }
978         m_aPanelRepository.clear();
979     }
980 
981     // -----------------------------------------------------------------------------------------------------------------
982     void TaskPaneController_Impl::SetDefaultTitle( const String& i_rTitle )
983     {
984         m_sDefaultTitle = i_rTitle;
985         impl_updateDockingWindowTitle();
986     }
987 
988 	//------------------------------------------------------------------------------------------------------------------
989     void TaskPaneController_Impl::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL )
990     {
991         ::boost::optional< size_t > aPanelPos( m_rTaskPane.GetPanelPos( i_rPanelURL ) );
992         ENSURE_OR_RETURN_VOID( !!aPanelPos, "TaskPaneController_Impl::ActivateToolPanel: no such panel!" );
993 
994         if ( aPanelPos == m_rTaskPane.GetPanelDeck().GetActivePanel() )
995         {
996             ::svt::PToolPanel pPanel( m_rTaskPane.GetPanelDeck().GetPanel( *aPanelPos ) );
997             pPanel->GrabFocus();
998         }
999         else
1000         {
1001             m_rTaskPane.GetPanelDeck().ActivatePanel( aPanelPos );
1002         }
1003     }
1004 
1005     // -----------------------------------------------------------------------------------------------------------------
1006     IMPL_LINK( TaskPaneController_Impl, DockingChanged, TitledDockingWindow*, i_pDockingWindow )
1007     {
1008         ENSURE_OR_RETURN( i_pDockingWindow && &m_rDockingWindow, "TaskPaneController_Impl::DockingChanged: where does this come from?", 0L );
1009 
1010         if ( impl_getLayout() == LAYOUT_DRAWERS )
1011             return 0L;
1012 
1013         impl_setLayout( lcl_getTabLayoutFromAlignment( i_pDockingWindow->GetAlignment() ) );
1014         return 1L;
1015     }
1016 
1017     // -----------------------------------------------------------------------------------------------------------------
1018     IMPL_LINK( TaskPaneController_Impl, OnToolboxClicked, ToolBox*, i_pToolBox )
1019     {
1020 	    if ( i_pToolBox->GetCurItemId() == m_nViewMenuID )
1021         {
1022             i_pToolBox->EndSelection();
1023 
1024             ::std::auto_ptr< PopupMenu > pMenu = impl_createPopupMenu();
1025             pMenu->SetSelectHdl( LINK( this, TaskPaneController_Impl, OnMenuItemSelected ) );
1026 
1027             // pass toolbox button rect so the menu can stay open on button up
1028             Rectangle aMenuRect( i_pToolBox->GetItemRect( m_nViewMenuID ) );
1029             aMenuRect.SetPos( i_pToolBox->GetPosPixel() );
1030             pMenu->Execute( &m_rDockingWindow, aMenuRect, POPUPMENU_EXECUTE_DOWN );
1031         }
1032 
1033 	    return 0;
1034     }
1035 
1036     // ---------------------------------------------------------------------------------------------------------------------
1037     IMPL_LINK( TaskPaneController_Impl, OnMenuItemSelected, Menu*, i_pMenu )
1038     {
1039         ENSURE_OR_RETURN( i_pMenu, "TaskPaneController_Impl::OnMenuItemSelected: illegal menu!", 0L );
1040 
1041         i_pMenu->Deactivate();
1042         switch ( i_pMenu->GetCurItemId() )
1043         {
1044             case MID_UNLOCK_TASK_PANEL:
1045                 m_rDockingWindow.SetFloatingMode( sal_True );
1046                 break;
1047 
1048             case MID_LOCK_TASK_PANEL:
1049                 m_rDockingWindow.SetFloatingMode( sal_False );
1050                 break;
1051 
1052             case MID_LAYOUT_DRAWERS:
1053                 impl_setLayout( LAYOUT_DRAWERS );
1054                 break;
1055 
1056             case MID_LAYOUT_TABS:
1057                 impl_setLayout( lcl_getTabLayoutFromAlignment( m_rDockingWindow.GetAlignment() ) );
1058                 break;
1059 
1060             default:
1061             {
1062                 size_t nPanelIndex = size_t( i_pMenu->GetCurItemId() - MID_FIRST_PANEL );
1063                 impl_togglePanelVisibility( nPanelIndex );
1064             }
1065             break;
1066         }
1067 
1068         return 1L;
1069     }
1070 
1071     // ---------------------------------------------------------------------------------------------------------------------
1072     size_t TaskPaneController_Impl::impl_getLogicalPanelIndex( const size_t i_nVisibleIndex )
1073     {
1074         size_t nLogicalIndex = 0;
1075         size_t nVisibleIndex( i_nVisibleIndex );
1076         for ( size_t i=0; i < m_aPanelRepository.size(); ++i )
1077         {
1078             if ( !m_aPanelRepository[i].bHidden )
1079             {
1080                 if ( !nVisibleIndex )
1081                     break;
1082                 --nVisibleIndex;
1083             }
1084             ++nLogicalIndex;
1085         }
1086         return nLogicalIndex;
1087     }
1088 
1089     // ---------------------------------------------------------------------------------------------------------------------
1090     void TaskPaneController_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition )
1091     {
1092         if ( m_bTogglingPanelVisibility )
1093             return;
1094 
1095         const size_t nLogicalIndex( impl_getLogicalPanelIndex( i_nPosition ) );
1096         m_aPanelRepository.insert( m_aPanelRepository.begin() + nLogicalIndex, PanelDescriptor( i_pPanel ) );
1097     }
1098 
1099     // ---------------------------------------------------------------------------------------------------------------------
1100     void TaskPaneController_Impl::PanelRemoved( const size_t i_nPosition )
1101     {
1102         if ( m_bTogglingPanelVisibility )
1103             return;
1104 
1105         const size_t nLogicalIndex( impl_getLogicalPanelIndex( i_nPosition ) );
1106         m_aPanelRepository.erase( m_aPanelRepository.begin() + nLogicalIndex );
1107     }
1108 
1109     // ---------------------------------------------------------------------------------------------------------------------
1110     void TaskPaneController_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
1111     {
1112         if ( impl_getLayout() == LAYOUT_DRAWERS )
1113             // no adjustment of the title when we use the classical "drawers" layout
1114             return;
1115 
1116         impl_updateDockingWindowTitle( );
1117         (void)i_rOldActive;
1118         (void)i_rNewActive;
1119     }
1120 
1121     // ---------------------------------------------------------------------------------------------------------------------
1122     void TaskPaneController_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter )
1123     {
1124         // not interested in
1125         (void)i_rNewLayouter;
1126     }
1127 
1128     // ---------------------------------------------------------------------------------------------------------------------
1129     void TaskPaneController_Impl::Dying()
1130     {
1131         OSL_ENSURE( false, "TaskPaneController_Impl::Dying: unexpected call!" );
1132         // We are expected to live longer than the ToolPanelDeck we work with. Since we remove ourself, in our dtor,
1133         // as listener from the panel deck, this method here should never be called.
1134     }
1135 
1136     // ---------------------------------------------------------------------------------------------------------------------
1137     void TaskPaneController_Impl::impl_togglePanelVisibility( const size_t i_nLogicalPanelIndex )
1138     {
1139         ENSURE_OR_RETURN_VOID( i_nLogicalPanelIndex < m_aPanelRepository.size(), "illegal index" );
1140 
1141         // get the actual panel index, within the deck
1142         size_t nActualPanelIndex(0);
1143         for ( size_t i=0; i < i_nLogicalPanelIndex; ++i )
1144         {
1145             if ( !m_aPanelRepository[i].bHidden )
1146                 ++nActualPanelIndex;
1147         }
1148 
1149         ::boost::optional< size_t > aActivatePanel;
1150 
1151         m_bTogglingPanelVisibility = true;
1152         if ( m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden )
1153         {
1154             OSL_VERIFY( m_rTaskPane.GetPanelDeck().InsertPanel( m_aPanelRepository[ i_nLogicalPanelIndex ].pPanel, nActualPanelIndex ) == nActualPanelIndex );
1155             // if there has not been an active panel before, activate the newly inserted one
1156             ::boost::optional< size_t > aActivePanel( m_rTaskPane.GetPanelDeck().GetActivePanel() );
1157             if ( !aActivePanel )
1158                 aActivatePanel = nActualPanelIndex;
1159         }
1160         else
1161         {
1162             OSL_VERIFY( m_rTaskPane.GetPanelDeck().RemovePanel( nActualPanelIndex ).get() == m_aPanelRepository[ i_nLogicalPanelIndex ].pPanel.get() );
1163         }
1164         m_bTogglingPanelVisibility = false;
1165         m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden = !m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden;
1166 
1167         if ( !!aActivatePanel )
1168             m_rTaskPane.GetPanelDeck().ActivatePanel( *aActivatePanel );
1169     }
1170 
1171     // ---------------------------------------------------------------------------------------------------------------------
1172     void TaskPaneController_Impl::impl_setLayout( const PanelSelectorLayout i_eLayout, const bool i_bForce )
1173     {
1174         if ( !i_bForce && ( m_eCurrentLayout == i_eLayout ) )
1175             return;
1176 
1177         switch ( i_eLayout )
1178         {
1179         case LAYOUT_DRAWERS:
1180             m_rTaskPane.SetDrawersLayout();
1181             break;
1182         case LAYOUT_TABS_TOP:
1183             m_rTaskPane.SetTabsLayout( ::svt::TABS_TOP, ::svt::TABITEM_IMAGE_ONLY );
1184             break;
1185         case LAYOUT_TABS_BOTTOM:
1186             m_rTaskPane.SetTabsLayout( ::svt::TABS_BOTTOM, ::svt::TABITEM_IMAGE_ONLY );
1187             break;
1188         case LAYOUT_TABS_LEFT:
1189             m_rTaskPane.SetTabsLayout( ::svt::TABS_LEFT, ::svt::TABITEM_IMAGE_ONLY );
1190             break;
1191         case LAYOUT_TABS_RIGHT:
1192             m_rTaskPane.SetTabsLayout( ::svt::TABS_RIGHT, ::svt::TABITEM_IMAGE_ONLY );
1193             break;
1194         }
1195         m_eCurrentLayout = i_eLayout;
1196 
1197         impl_updateDockingWindowTitle();
1198     }
1199 
1200     // ---------------------------------------------------------------------------------------------------------------------
1201     void TaskPaneController_Impl::impl_updateDockingWindowTitle()
1202     {
1203         ::boost::optional< size_t > aActivePanel( m_rTaskPane.GetPanelDeck().GetActivePanel() );
1204         if ( !aActivePanel || ( impl_getLayout() == LAYOUT_DRAWERS ) )
1205             m_rDockingWindow.SetTitle( m_sDefaultTitle );
1206         else
1207         {
1208             size_t nNewActive( *aActivePanel );
1209             for ( size_t i=0; i < m_aPanelRepository.size(); ++i )
1210             {
1211                 if ( m_aPanelRepository[i].bHidden )
1212                     continue;
1213 
1214                 if ( !nNewActive )
1215                 {
1216                     m_rDockingWindow.SetTitle( m_aPanelRepository[i].pPanel->GetDisplayName() );
1217                     break;
1218                 }
1219                 --nNewActive;
1220             }
1221         }
1222     }
1223 
1224     // ---------------------------------------------------------------------------------------------------------------------
1225     ::std::auto_ptr< PopupMenu > TaskPaneController_Impl::impl_createPopupMenu() const
1226     {
1227         ::std::auto_ptr<PopupMenu> pMenu( new PopupMenu );
1228         FloatingWindow* pMenuWindow = static_cast< FloatingWindow* >( pMenu->GetWindow() );
1229         if ( pMenuWindow != NULL )
1230         {
1231             pMenuWindow->SetPopupModeFlags ( pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE );
1232         }
1233 
1234         // Add one entry for every tool panel element to individually make
1235         // them visible or hide them.
1236         sal_uInt16 nIndex = MID_FIRST_PANEL;
1237         for ( size_t i=0; i<m_aPanelRepository.size(); ++i, ++nIndex )
1238         {
1239             const PanelDescriptor& rPanelDesc( m_aPanelRepository[i] );
1240             pMenu->InsertItem( nIndex, rPanelDesc.pPanel->GetDisplayName(), MIB_CHECKABLE );
1241             pMenu->CheckItem( nIndex, !rPanelDesc.bHidden );
1242         }
1243         pMenu->InsertSeparator();
1244 
1245     #if OSL_DEBUG_LEVEL > 0
1246         pMenu->InsertItem( MID_LAYOUT_TABS, String::CreateFromAscii( "Tab-Layout (exp.)" ), MIB_CHECKABLE );
1247         pMenu->CheckItem( MID_LAYOUT_TABS, impl_getLayout() != LAYOUT_DRAWERS );
1248         pMenu->InsertItem( MID_LAYOUT_DRAWERS, String::CreateFromAscii( "Drawer-Layout" ), MIB_CHECKABLE );
1249         pMenu->CheckItem( MID_LAYOUT_DRAWERS, impl_getLayout() == LAYOUT_DRAWERS );
1250 
1251         pMenu->InsertSeparator();
1252     #endif
1253 
1254         // Add entry for docking or un-docking the tool panel.
1255         if ( m_rDockingWindow.IsFloatingMode() )
1256             pMenu->InsertItem(
1257                 MID_LOCK_TASK_PANEL,
1258                 String( SfxResId( STR_SFX_DOCK ) )
1259             );
1260         else
1261             pMenu->InsertItem(
1262                 MID_UNLOCK_TASK_PANEL,
1263                 String( SfxResId( STR_SFX_UNDOCK ) )
1264             );
1265 
1266         pMenu->RemoveDisabledEntries( sal_False, sal_False );
1267 
1268         return pMenu;
1269     }
1270 
1271 	//==================================================================================================================
1272 	//= TaskPaneController
1273 	//==================================================================================================================
1274 	//------------------------------------------------------------------------------------------------------------------
1275     TaskPaneController::TaskPaneController( ModuleTaskPane& i_rTaskPane, TitledDockingWindow& i_rDockingWindow )
1276         :m_pImpl( new TaskPaneController_Impl( i_rTaskPane, i_rDockingWindow ) )
1277     {
1278     }
1279 
1280 	//------------------------------------------------------------------------------------------------------------------
1281     TaskPaneController::~TaskPaneController()
1282     {
1283     }
1284 
1285 	//------------------------------------------------------------------------------------------------------------------
1286     void TaskPaneController::SetDefaultTitle( const String& i_rTitle )
1287     {
1288         m_pImpl->SetDefaultTitle( i_rTitle );
1289     }
1290 
1291 	//------------------------------------------------------------------------------------------------------------------
1292     void TaskPaneController::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL )
1293     {
1294         m_pImpl->ActivateToolPanel( i_rPanelURL );
1295     }
1296 
1297 //......................................................................................................................
1298 } // namespace sfx2
1299 //......................................................................................................................
1300