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