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