LCOV - code coverage report
Current view: top level - sfx2/source/sidebar - SidebarController.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 327 503 65.0 %
Date: 2015-06-13 12:38:46 Functions: 23 38 60.5 %
Legend: Lines: hit not hit

          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             : #include "SidebarController.hxx"
      20             : #include "Deck.hxx"
      21             : #include "DeckTitleBar.hxx"
      22             : #include "Panel.hxx"
      23             : #include "PanelTitleBar.hxx"
      24             : #include "SidebarResource.hxx"
      25             : #include "TabBar.hxx"
      26             : #include <sfx2/sidebar/Theme.hxx>
      27             : #include <sfx2/sidebar/SidebarChildWindow.hxx>
      28             : #include <sfx2/sidebar/Tools.hxx>
      29             : #include "SidebarDockingWindow.hxx"
      30             : #include "Context.hxx"
      31             : 
      32             : #include <sfx2/sfxresid.hxx>
      33             : #include <sfx2/sfxsids.hrc>
      34             : #include <sfx2/titledockwin.hxx>
      35             : #include "sfxlocal.hrc"
      36             : #include <vcl/floatwin.hxx>
      37             : #include <vcl/fixed.hxx>
      38             : #include "splitwin.hxx"
      39             : #include <svl/smplhint.hxx>
      40             : #include <tools/link.hxx>
      41             : #include <toolkit/helper/vclunohelper.hxx>
      42             : #include <comphelper/processfactory.hxx>
      43             : #include <comphelper/namedvaluecollection.hxx>
      44             : 
      45             : #include <com/sun/star/frame/XDispatchProvider.hpp>
      46             : #include <com/sun/star/lang/XInitialization.hpp>
      47             : #include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
      48             : #include <com/sun/star/ui/ContextChangeEventObject.hpp>
      49             : #include <com/sun/star/ui/theUIElementFactoryManager.hpp>
      50             : #include <com/sun/star/util/XURLTransformer.hpp>
      51             : #include <com/sun/star/util/URL.hpp>
      52             : #include <com/sun/star/rendering/XSpriteCanvas.hpp>
      53             : 
      54             : #include <boost/bind.hpp>
      55             : #include <boost/function.hpp>
      56             : #include <boost/scoped_array.hpp>
      57             : 
      58             : using namespace css;
      59             : using namespace css::uno;
      60             : using ::rtl::OUString;
      61             : 
      62             : namespace
      63             : {
      64             :     const static char gsReadOnlyCommandName[] = ".uno:EditDoc";
      65             :     const static char gsHideSidebarCommandName[] = ".uno:Sidebar";
      66             :     const static sal_Int32 gnMaximumSidebarWidth (400);
      67             :     const static sal_Int32 gnWidthCloseThreshold (70);
      68             :     const static sal_Int32 gnWidthOpenThreshold (40);
      69             : }
      70             : 
      71             : namespace sfx2 { namespace sidebar {
      72             : 
      73         216 : SidebarController::SidebarControllerContainer SidebarController::maSidebarControllerContainer;
      74             : 
      75             : namespace {
      76             :     enum MenuId
      77             :     {
      78             :         MID_UNLOCK_TASK_PANEL = 1,
      79             :         MID_LOCK_TASK_PANEL,
      80             :         MID_HIDE_SIDEBAR,
      81             :         MID_CUSTOMIZATION,
      82             :         MID_RESTORE_DEFAULT,
      83             :         MID_FIRST_PANEL,
      84             :         MID_FIRST_HIDE = 1000
      85             :     };
      86             : 
      87             :     /** When in doubt, show this deck.
      88             :     */
      89             :     static const char gsDefaultDeckId[] = "PropertyDeck";
      90             : }
      91             : 
      92        3155 : SidebarController::SidebarController (
      93             :     SidebarDockingWindow* pParentWindow,
      94             :     const css::uno::Reference<css::frame::XFrame>& rxFrame)
      95             :     : SidebarControllerInterfaceBase(m_aMutex),
      96             :       mpCurrentDeck(),
      97             :       mpParentWindow(pParentWindow),
      98             :       mpTabBar(VclPtr<TabBar>::Create(
      99             :               mpParentWindow,
     100             :               rxFrame,
     101        3155 :               ::boost::bind(&SidebarController::OpenThenSwitchToDeck, this, _1),
     102        3155 :               ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2))),
     103             :       mxFrame(rxFrame),
     104             :       maCurrentContext(OUString(), OUString()),
     105             :       maRequestedContext(),
     106             :       mnRequestedForceFlags(SwitchFlag_NoForce),
     107             :       msCurrentDeckId(gsDefaultDeckId),
     108             :       msCurrentDeckTitle(),
     109             :       maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)),
     110             :       maContextChangeUpdate(::boost::bind(&SidebarController::UpdateConfigurations, this)),
     111             :       maAsynchronousDeckSwitch(),
     112             :       mbIsDeckRequestedOpen(),
     113             :       mbIsDeckOpen(),
     114             :       mbCanDeckBeOpened(true),
     115        6310 :       mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width()),
     116             :       maFocusManager(::boost::bind(&SidebarController::ShowPanel, this, _1)),
     117             :       mxReadOnlyModeDispatch(),
     118             :       mbIsDocumentReadOnly(false),
     119             :       mpSplitWindow(NULL),
     120       15775 :       mnWidthOnSplitterButtonDown(0)
     121             : {
     122             :     // Listen for context change events.
     123             :     css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
     124             :         css::ui::ContextChangeEventMultiplexer::get(
     125        3155 :             ::comphelper::getProcessComponentContext()));
     126        3155 :     if (xMultiplexer.is())
     127        3155 :         xMultiplexer->addContextChangeEventListener(
     128             :             static_cast<css::ui::XContextChangeEventListener*>(this),
     129        3155 :             mxFrame->getController());
     130             : 
     131             :     // Listen for window events.
     132        3155 :     mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
     133             : 
     134             :     // Listen for theme property changes.
     135        6310 :     Theme::GetPropertySet()->addPropertyChangeListener(
     136             :         OUString(""),
     137        3155 :         static_cast<css::beans::XPropertyChangeListener*>(this));
     138             : 
     139             :     // Get the dispatch object as preparation to listen for changes of
     140             :     // the read-only state.
     141        6310 :     const util::URL aURL (Tools::GetURL(gsReadOnlyCommandName));
     142        3155 :     mxReadOnlyModeDispatch = Tools::GetDispatch(mxFrame, aURL);
     143        3155 :     if (mxReadOnlyModeDispatch.is())
     144        3155 :         mxReadOnlyModeDispatch->addStatusListener(this, aURL);
     145             : 
     146        3155 :     SwitchToDeck(gsDefaultDeckId);
     147             : 
     148        6310 :     WeakReference<SidebarController> xWeakController (this);
     149             :     maSidebarControllerContainer.insert(
     150             :         SidebarControllerContainer::value_type(
     151             :             rxFrame,
     152        6310 :             xWeakController));
     153        3155 : }
     154             : 
     155        5626 : SidebarController::~SidebarController()
     156             : {
     157        5626 : }
     158             : 
     159           0 : SidebarController* SidebarController::GetSidebarControllerForFrame (
     160             :     const css::uno::Reference<css::frame::XFrame>& rxFrame)
     161             : {
     162           0 :     SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(rxFrame));
     163           0 :     if (iEntry == maSidebarControllerContainer.end())
     164           0 :         return NULL;
     165             : 
     166           0 :     css::uno::Reference<XInterface> xController (iEntry->second.get());
     167           0 :     if ( ! xController.is())
     168           0 :         return NULL;
     169             : 
     170           0 :     return dynamic_cast<SidebarController*>(xController.get());
     171             : }
     172             : 
     173        3155 : void SAL_CALL SidebarController::disposing()
     174             : {
     175        3155 :     mpCloseIndicator.disposeAndClear();
     176             : 
     177        3155 :     SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(mxFrame));
     178        3155 :     if (iEntry != maSidebarControllerContainer.end())
     179        3155 :         maSidebarControllerContainer.erase(iEntry);
     180             : 
     181        3155 :     maFocusManager.Clear();
     182             : 
     183             :     css::uno::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
     184             :         css::ui::ContextChangeEventMultiplexer::get(
     185        3155 :             ::comphelper::getProcessComponentContext()));
     186        3155 :     if (xMultiplexer.is())
     187        3155 :         xMultiplexer->removeAllContextChangeEventListeners(
     188        3155 :             static_cast<css::ui::XContextChangeEventListener*>(this));
     189             : 
     190        3155 :     if (mxReadOnlyModeDispatch.is())
     191        3155 :         mxReadOnlyModeDispatch->removeStatusListener(this, Tools::GetURL(gsReadOnlyCommandName));
     192        3155 :     if (mpSplitWindow != nullptr)
     193             :     {
     194        3147 :         mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
     195        3147 :         mpSplitWindow = NULL;
     196             :     }
     197             : 
     198        3155 :     if (mpParentWindow != nullptr)
     199             :     {
     200        3155 :         mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
     201        3155 :         mpParentWindow = NULL;
     202             :     }
     203             : 
     204        3155 :     if (mpCurrentDeck)
     205             :     {
     206        3155 :         mpCurrentDeck.disposeAndClear();
     207             :     }
     208             : 
     209        3155 :     mpTabBar.disposeAndClear();
     210             : 
     211        6310 :     Theme::GetPropertySet()->removePropertyChangeListener(
     212             :         OUString(""),
     213        3155 :         static_cast<css::beans::XPropertyChangeListener*>(this));
     214             : 
     215        3155 :     maContextChangeUpdate.CancelRequest();
     216        3155 :     maAsynchronousDeckSwitch.CancelRequest();
     217        3155 : }
     218             : 
     219        7261 : void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent)
     220             :     throw(css::uno::RuntimeException, std::exception)
     221             : {
     222             :     // Update to the requested new context asynchronously to avoid
     223             :     // subtle errors caused by SFX2 which in rare cases can not
     224             :     // properly handle a synchronous update.
     225       14522 :     maRequestedContext = Context(
     226             :         rEvent.ApplicationName,
     227        7261 :         rEvent.ContextName);
     228        7261 :     if (maRequestedContext != maCurrentContext)
     229             :     {
     230        4095 :         maAsynchronousDeckSwitch.CancelRequest();
     231        4095 :         maContextChangeUpdate.RequestCall();
     232             :     }
     233        7261 : }
     234             : 
     235           4 : void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject)
     236             :     throw(css::uno::RuntimeException, std::exception)
     237             : {
     238             :     (void)rEventObject;
     239             : 
     240           4 :     dispose();
     241           4 : }
     242             : 
     243           0 : void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChangeEvent& rEvent)
     244             :     throw(css::uno::RuntimeException, std::exception)
     245             : {
     246             :     (void)rEvent;
     247             : 
     248           0 :     maPropertyChangeForwarder.RequestCall();
     249           0 : }
     250             : 
     251        3601 : void SAL_CALL SidebarController::statusChanged (const css::frame::FeatureStateEvent& rEvent)
     252             :     throw(css::uno::RuntimeException, std::exception)
     253             : {
     254        3601 :     bool bIsReadWrite (true);
     255        3601 :     if (rEvent.IsEnabled)
     256        2466 :         rEvent.State >>= bIsReadWrite;
     257             : 
     258        3601 :     if (mbIsDocumentReadOnly != !bIsReadWrite)
     259             :     {
     260           1 :         mbIsDocumentReadOnly = !bIsReadWrite;
     261             : 
     262             :         // Force the current deck to update its panel list.
     263           1 :         if ( ! mbIsDocumentReadOnly)
     264           0 :             msCurrentDeckId = gsDefaultDeckId;
     265           1 :         mnRequestedForceFlags |= SwitchFlag_ForceSwitch;
     266           1 :         maAsynchronousDeckSwitch.CancelRequest();
     267           1 :         maContextChangeUpdate.RequestCall();
     268             :     }
     269        3601 : }
     270             : 
     271         370 : void SAL_CALL SidebarController::requestLayout()
     272             :     throw(css::uno::RuntimeException, std::exception)
     273             : {
     274         370 :     sal_Int32 nMinimalWidth = 0;
     275         370 :     if (mpCurrentDeck)
     276             :     {
     277         370 :         mpCurrentDeck->RequestLayout();
     278         370 :         nMinimalWidth = mpCurrentDeck->GetMinimalWidth();
     279             :     }
     280         370 :     RestrictWidth(nMinimalWidth);
     281         370 : }
     282             : 
     283           0 : void SidebarController::BroadcastPropertyChange()
     284             : {
     285           0 :     DataChangedEvent aEvent (DataChangedEventType::USER);
     286           0 :     mpParentWindow->NotifyAllChildren(aEvent);
     287           0 :     mpParentWindow->Invalidate(InvalidateFlags::Children);
     288           0 : }
     289             : 
     290       16012 : void SidebarController::NotifyResize()
     291             : {
     292       16012 :     if (!mpTabBar)
     293             :     {
     294             :         OSL_ASSERT(mpTabBar!=nullptr);
     295       16012 :         return;
     296             :     }
     297             : 
     298       16012 :     vcl::Window* pParentWindow = mpTabBar->GetParent();
     299       16012 :     sal_Int32 nTabBarDefaultWidth = TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor();
     300             : 
     301       16012 :     const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width());
     302       16012 :     const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height());
     303             : 
     304       16012 :     mbIsDeckOpen = (nWidth > nTabBarDefaultWidth);
     305             : 
     306       16012 :     if (mnSavedSidebarWidth <= 0)
     307        6309 :         mnSavedSidebarWidth = nWidth;
     308             : 
     309             :     bool bIsDeckVisible;
     310       16012 :     if (mbCanDeckBeOpened)
     311             :     {
     312       16012 :         const bool bIsOpening (nWidth > mnWidthOnSplitterButtonDown);
     313       16012 :         if (bIsOpening)
     314       12858 :             bIsDeckVisible = nWidth >= nTabBarDefaultWidth + gnWidthOpenThreshold;
     315             :         else
     316        3154 :             bIsDeckVisible = nWidth >= nTabBarDefaultWidth + gnWidthCloseThreshold;
     317       16012 :         mbIsDeckRequestedOpen = bIsDeckVisible;
     318       16012 :         UpdateCloseIndicator(!bIsDeckVisible);
     319             :     }
     320             :     else
     321           0 :         bIsDeckVisible = false;
     322             : 
     323       16012 :     if (mpCurrentDeck)
     324             :     {
     325       16012 :         SfxSplitWindow* pSplitWindow = GetSplitWindow();
     326       16012 :         WindowAlign eAlign = pSplitWindow ? pSplitWindow->GetAlign() : WINDOWALIGN_RIGHT;
     327             :         long nDeckX, nTabX;
     328       16012 :         if (eAlign == WINDOWALIGN_LEFT)     // attach the Sidebar towards the left-side of screen
     329             :         {
     330           0 :             nDeckX = nTabBarDefaultWidth;
     331           0 :             nTabX = 0;
     332             :         }
     333             :         else   // attach the Sidebar towards the right-side of screen
     334             :         {
     335       16012 :             nDeckX = 0;
     336       16012 :             nTabX = nWidth-nTabBarDefaultWidth;
     337             :         }
     338             : 
     339             :         // Place the deck first.
     340       16012 :         if (bIsDeckVisible)
     341             :         {
     342        2107 :             mpCurrentDeck->setPosSizePixel(nDeckX, 0, nWidth - nTabBarDefaultWidth, nHeight);
     343        2107 :             mpCurrentDeck->Show();
     344        2107 :             mpCurrentDeck->RequestLayout();
     345             :         }
     346             :         else
     347       13905 :             mpCurrentDeck->Hide();
     348             : 
     349             :         // Now place the tab bar.
     350       16012 :         mpTabBar->setPosSizePixel(nTabX, 0, nTabBarDefaultWidth, nHeight);
     351       16012 :         mpTabBar->Show();
     352             : 
     353             :     }
     354             : 
     355             :     // Determine if the closer of the deck can be shown.
     356       16012 :     sal_Int32 nMinimalWidth = 0;
     357       16012 :     if (mpCurrentDeck)
     358             :     {
     359       16012 :         DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
     360       16012 :         if (pTitleBar != NULL && pTitleBar->IsVisible())
     361        3609 :             pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
     362       16012 :         nMinimalWidth = mpCurrentDeck->GetMinimalWidth();
     363             :     }
     364             : 
     365       16012 :     RestrictWidth(nMinimalWidth);
     366             : }
     367             : 
     368           0 : void SidebarController::ProcessNewWidth (const sal_Int32 nNewWidth)
     369             : {
     370           0 :     if ( ! mbIsDeckRequestedOpen)
     371           0 :         return;
     372             : 
     373           0 :     if (mbIsDeckRequestedOpen.get())
     374             :      {
     375             :         // Deck became large enough to be shown.  Show it.
     376           0 :         mnSavedSidebarWidth = nNewWidth;
     377           0 :         RequestOpenDeck();
     378             :     }
     379             :     else
     380             :     {
     381             :         // Deck became too small.  Close it completely.
     382             :         // If window is wider than the tab bar then mark the deck as being visible, even when it its not.
     383             :         // This is to trigger an adjustment of the width to the width of the tab bar.
     384           0 :         mbIsDeckOpen = true;
     385           0 :         RequestCloseDeck();
     386             : 
     387           0 :         if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor())
     388           0 :             mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
     389             :     }
     390             : }
     391             : 
     392         612 : void SidebarController::UpdateConfigurations()
     393             : {
     394        1224 :     if (maCurrentContext != maRequestedContext
     395         612 :         || mnRequestedForceFlags!=SwitchFlag_NoForce)
     396             :     {
     397         610 :         maCurrentContext = maRequestedContext;
     398             : 
     399             :         // Find the set of decks that could be displayed for the new context.
     400         610 :         ResourceManager::DeckContextDescriptorContainer aDecks;
     401         610 :         ResourceManager::Instance().GetMatchingDecks (
     402             :             aDecks,
     403             :             maCurrentContext,
     404             :             mbIsDocumentReadOnly,
     405        1220 :             mxFrame);
     406             : 
     407             :         // Notify the tab bar about the updated set of decks.
     408         610 :         mpTabBar->SetDecks(aDecks);
     409             : 
     410             :         // Find the new deck.  By default that is the same as the old
     411             :         // one.  If that is not set or not enabled, then choose the
     412             :         // first enabled deck (which is PropertyDeck).
     413        1220 :         OUString sNewDeckId;
     414         621 :         for (ResourceManager::DeckContextDescriptorContainer::const_iterator
     415         610 :                  iDeck(aDecks.begin()),
     416         610 :                  iEnd(aDecks.end());
     417             :              iDeck!=iEnd;
     418             :              ++iDeck)
     419             :         {
     420         620 :             if (iDeck->mbIsEnabled)
     421             :             {
     422         610 :                 if (iDeck->msId.equals(msCurrentDeckId))
     423             :                 {
     424         609 :                     sNewDeckId = msCurrentDeckId;
     425         609 :                     break;
     426             :                 }
     427           1 :                 else if (sNewDeckId.getLength() == 0)
     428           1 :                     sNewDeckId = iDeck->msId;
     429             :             }
     430             :         }
     431             : 
     432         610 :         if (sNewDeckId.getLength() == 0)
     433             :         {
     434             :             // We did not find a valid deck.
     435           0 :             RequestCloseDeck();
     436         612 :             return;
     437             :         }
     438             : 
     439             :         // Tell the tab bar to highlight the button associated
     440             :         // with the deck.
     441         610 :         mpTabBar->HighlightDeck(sNewDeckId);
     442             : 
     443             :         const DeckDescriptor* pDescriptor =
     444         610 :             ResourceManager::Instance().GetDeckDescriptor(sNewDeckId);
     445             : 
     446         610 :         if (pDescriptor)
     447             :         {
     448             :             SwitchToDeck(
     449             :                 *pDescriptor,
     450         610 :                 maCurrentContext);
     451         610 :         }
     452             :     }
     453             : }
     454             : 
     455           0 : void SidebarController::OpenThenSwitchToDeck (
     456             :     const ::rtl::OUString& rsDeckId)
     457             : {
     458             :     // fdo#67627 Clicking a second time on a Deck icon will close the Deck
     459           0 :     if (IsDeckVisible(rsDeckId))
     460             :     {
     461             :         // fdo#88241 Summoning an undocked sidebar a second time should close sidebar
     462           0 :         if (!GetSplitWindow())
     463             :         {
     464           0 :             mpParentWindow->Close();
     465           0 :             return;
     466             :         }
     467             :         else
     468             :         {
     469           0 :             RequestCloseDeck();
     470           0 :             return;
     471             :         }
     472             :     }
     473           0 :     RequestOpenDeck();
     474           0 :     SwitchToDeck(rsDeckId);
     475           0 :     mpTabBar->Invalidate();
     476           0 :     mpTabBar->HighlightDeck(rsDeckId);
     477             : }
     478             : 
     479        3155 : void SidebarController::SwitchToDeck (
     480             :     const ::rtl::OUString& rsDeckId)
     481             : {
     482        6310 :     if ( ! msCurrentDeckId.equals(rsDeckId)
     483        3155 :         || ! mbIsDeckOpen
     484        3155 :         || mnRequestedForceFlags!=SwitchFlag_NoForce)
     485             :     {
     486        3155 :         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId);
     487        3155 :         if (pDeckDescriptor != NULL)
     488        3155 :             SwitchToDeck(*pDeckDescriptor, maCurrentContext);
     489             :     }
     490        3155 : }
     491             : 
     492        6969 : void SidebarController::SwitchToDeck (
     493             :     const DeckDescriptor& rDeckDescriptor,
     494             :     const Context& rContext)
     495             : {
     496        6969 :     maFocusManager.Clear();
     497             : 
     498        6969 :     const bool bForceNewDeck ((mnRequestedForceFlags&SwitchFlag_ForceNewDeck)!=0);
     499        6969 :     const bool bForceNewPanels ((mnRequestedForceFlags&SwitchFlag_ForceNewPanels)!=0);
     500             : 
     501       13938 :     if ( ! msCurrentDeckId.equals(rDeckDescriptor.msId)
     502        6969 :         || bForceNewDeck)
     503             :     {
     504             :         // When the deck changes then destroy the deck and all panels
     505             :         // and create everything new.
     506           1 :         mpCurrentDeck.disposeAndClear();
     507             : 
     508           1 :         msCurrentDeckId = rDeckDescriptor.msId;
     509             :     }
     510        6969 :     mpTabBar->HighlightDeck(msCurrentDeckId);
     511             : 
     512             :     // Determine the panels to display in the deck.
     513        6969 :     ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
     514        6969 :     ResourceManager::Instance().GetMatchingPanels(
     515             :         aPanelContextDescriptors,
     516             :         rContext,
     517             :         rDeckDescriptor.msId,
     518       13938 :         mxFrame);
     519             : 
     520        6969 :     if (aPanelContextDescriptors.empty())
     521             :     {
     522             :         // There are no panels to be displayed in the current context.
     523        3204 :         if (EnumContext::GetContextEnum(rContext.msContext) != EnumContext::Context_Empty)
     524             :         {
     525             :             // Switch to the "empty" context and try again.
     526             :             SwitchToDeck(
     527             :                 rDeckDescriptor,
     528             :                 Context(
     529             :                     rContext.msApplication,
     530        3204 :                     EnumContext::GetContextName(EnumContext::Context_Empty)));
     531        3204 :             return;
     532             :         }
     533             :         else
     534             :         {
     535             :             // This is already the "empty" context. Looks like we have
     536             :             // to live with an empty deck.
     537             :         }
     538             :     }
     539             : 
     540             :     // Provide a configuration and Deck object.
     541        3765 :     if ( ! mpCurrentDeck)
     542             :     {
     543             :         mpCurrentDeck.reset(
     544             :             VclPtr<Deck>::Create(
     545             :                 rDeckDescriptor,
     546             :                 mpParentWindow,
     547        3156 :                 ::boost::bind(&SidebarController::RequestCloseDeck, this)));
     548        3156 :         msCurrentDeckTitle = rDeckDescriptor.msTitle;
     549             : 
     550             :     }
     551        3765 :     if ( ! mpCurrentDeck)
     552           0 :         return;
     553             : 
     554             : #ifdef DEBUG
     555             :     // Show the context name in the deck title bar.
     556             :     DeckTitleBar* pDebugTitleBar = mpCurrentDeck->GetTitleBar();
     557             :     if (pDebugTitleBar != NULL)
     558             :         pDebugTitleBar->SetTitle(rDeckDescriptor.msTitle + " (" + maCurrentContext.msContext + ")");
     559             : #endif
     560             : 
     561             :     // Update the panel list.
     562        3765 :     const sal_Int32 nNewPanelCount (aPanelContextDescriptors.size());
     563        7530 :     SharedPanelContainer aNewPanels;
     564        3765 :     const SharedPanelContainer& rCurrentPanels (mpCurrentDeck->GetPanels());
     565             : 
     566        3765 :     aNewPanels.resize(nNewPanelCount);
     567        3765 :     sal_Int32 nWriteIndex (0);
     568        3765 :     bool bHasPanelSetChanged (false);
     569        8818 :     for (sal_Int32 nReadIndex=0; nReadIndex<nNewPanelCount; ++nReadIndex)
     570             :     {
     571             :         const ResourceManager::PanelContextDescriptor& rPanelContexDescriptor (
     572        5053 :             aPanelContextDescriptors[nReadIndex]);
     573             : 
     574             :         // Determine if the panel can be displayed.
     575        5053 :         const bool bIsPanelVisible (!mbIsDocumentReadOnly || rPanelContexDescriptor.mbShowForReadOnlyDocuments);
     576        5053 :         if ( ! bIsPanelVisible)
     577           1 :             continue;
     578             : 
     579             :         // Find the corresponding panel among the currently active
     580             :         // panels.
     581        5052 :         SharedPanelContainer::const_iterator iPanel = rCurrentPanels.end();
     582             : 
     583        5052 :         if (!bForceNewPanels)
     584             :         {
     585        5052 :             iPanel = rCurrentPanels.end();
     586        6885 :             for (auto a = rCurrentPanels.begin(); a != rCurrentPanels.end(); ++a)
     587             :             {
     588        1958 :                 if ((*a)->HasIdPredicate(rPanelContexDescriptor.msId))
     589             :                 {
     590         125 :                     iPanel = a;
     591         125 :                     break;
     592             :                 }
     593             :             }
     594             :         }
     595        5052 :         if (iPanel != rCurrentPanels.end())
     596             :         {
     597             :             // Panel already exists in current deck.  Reuse it.
     598         125 :             aNewPanels[nWriteIndex] = *iPanel;
     599         125 :             aNewPanels[nWriteIndex]->SetExpanded(rPanelContexDescriptor.mbIsInitiallyVisible);
     600             :         }
     601             :         else
     602             :         {
     603             :             // Panel does not yet exist or creation of new panels is forced.
     604             :             // Create it.
     605        9854 :             aNewPanels[nWriteIndex] = CreatePanel(
     606             :                 rPanelContexDescriptor.msId,
     607             :                 mpCurrentDeck->GetPanelParentWindow(),
     608             :                 rPanelContexDescriptor.mbIsInitiallyVisible,
     609        4927 :                 rContext);
     610        4927 :             bHasPanelSetChanged = true;
     611             :         }
     612        5052 :         if (aNewPanels[nWriteIndex] != nullptr)
     613             :         {
     614             :             // Depending on the context we have to change the command
     615             :             // for the "more options" dialog.
     616        4373 :             PanelTitleBar* pTitleBar = aNewPanels[nWriteIndex]->GetTitleBar();
     617        4373 :             if (pTitleBar != NULL)
     618             :             {
     619             :                 pTitleBar->SetMoreOptionsCommand(
     620             :                     rPanelContexDescriptor.msMenuCommand,
     621        4373 :                     mxFrame);
     622             :             }
     623             : 
     624        4373 :             ++nWriteIndex;
     625             :         }
     626             : 
     627             :     }
     628             :     // mpCurrentPanels - may miss stuff (?)
     629        3765 :     aNewPanels.resize(nWriteIndex);
     630             : 
     631        3765 :     SfxSplitWindow* pSplitWindow = GetSplitWindow();
     632        3765 :     sal_Int32 nTabBarDefaultWidth = TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor();
     633        3765 :     WindowAlign eAlign = pSplitWindow ? pSplitWindow->GetAlign() : WINDOWALIGN_RIGHT;
     634             :     long nDeckX;
     635        3765 :     if (eAlign == WINDOWALIGN_LEFT)     // attach the Sidebar towards the left-side of screen
     636             :     {
     637           0 :         nDeckX = nTabBarDefaultWidth;
     638             :     }
     639             :     else   // attach the Sidebar towards the right-side of screen
     640             :     {
     641        3765 :         nDeckX = 0;
     642             :     }
     643             : 
     644             :     // Activate the deck and the new set of panels.
     645        3765 :     mpCurrentDeck->setPosSizePixel(
     646             :         nDeckX,
     647             :         0,
     648        7530 :         mpParentWindow->GetSizePixel().Width() - nTabBarDefaultWidth,
     649       11295 :         mpParentWindow->GetSizePixel().Height());
     650             : 
     651        3765 :     mpCurrentDeck->ResetPanels(aNewPanels);
     652        3765 :     mpCurrentDeck->Show();
     653             : 
     654        3765 :     mpParentWindow->SetText(rDeckDescriptor.msTitle);
     655             : 
     656        3765 :     if (bHasPanelSetChanged)
     657        3693 :         NotifyResize();
     658             : 
     659             :     // Tell the focus manager about the new panels and tab bar
     660             :     // buttons.
     661        3765 :     maFocusManager.SetDeckTitle(mpCurrentDeck->GetTitleBar());
     662        3765 :     maFocusManager.SetPanels(aNewPanels);
     663        3765 :     mpTabBar->UpdateFocusManager(maFocusManager);
     664        7530 :     UpdateTitleBarIcons();
     665             : }
     666             : 
     667        4927 : VclPtr<Panel> SidebarController::CreatePanel (
     668             :     const OUString& rsPanelId,
     669             :     vcl::Window* pParentWindow,
     670             :     const bool bIsInitiallyExpanded,
     671             :     const Context& rContext)
     672             : {
     673        4927 :     const PanelDescriptor* pPanelDescriptor = ResourceManager::Instance().GetPanelDescriptor(rsPanelId);
     674        4927 :     if (pPanelDescriptor == NULL)
     675           0 :         return NULL;
     676             : 
     677             :     // Create the panel which is the parent window of the UIElement.
     678             :     VclPtr<Panel> pPanel = VclPtr<Panel>::Create(
     679             :         *pPanelDescriptor,
     680             :         pParentWindow,
     681             :         bIsInitiallyExpanded,
     682        4927 :         ::boost::bind(&Deck::RequestLayout, mpCurrentDeck.get()),
     683        9854 :         ::boost::bind(&SidebarController::GetCurrentContext, this));
     684             : 
     685             :     // Create the XUIElement.
     686             :     Reference<ui::XUIElement> xUIElement (CreateUIElement(
     687        9854 :             pPanel->GetComponentInterface(),
     688             :             pPanelDescriptor->msImplementationURL,
     689             :             pPanelDescriptor->mbWantsCanvas,
     690       19708 :             rContext));
     691        4927 :     if (xUIElement.is())
     692             :     {
     693             :         // Initialize the panel and add it to the active deck.
     694        4248 :         pPanel->SetUIElement(xUIElement);
     695             :     }
     696             :     else
     697             :     {
     698         679 :         pPanel.disposeAndClear();
     699             :     }
     700             : 
     701        9854 :     return pPanel;
     702             : }
     703             : 
     704        4927 : Reference<ui::XUIElement> SidebarController::CreateUIElement (
     705             :     const Reference<awt::XWindowPeer>& rxWindow,
     706             :     const ::rtl::OUString& rsImplementationURL,
     707             :     const bool bWantsCanvas,
     708             :     const Context& rContext)
     709             : {
     710             :     try
     711             :     {
     712        4927 :         const Reference<XComponentContext> xComponentContext (::comphelper::getProcessComponentContext() );
     713             :         const Reference<ui::XUIElementFactory> xUIElementFactory =
     714        9854 :                ui::theUIElementFactoryManager::get( xComponentContext );
     715             : 
     716             :        // Create the XUIElement.
     717        9854 :         ::comphelper::NamedValueCollection aCreationArguments;
     718        4927 :         aCreationArguments.put("Frame", makeAny(mxFrame));
     719        4927 :         aCreationArguments.put("ParentWindow", makeAny(rxWindow));
     720        4927 :         SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(mpParentWindow.get());
     721        4927 :         if (pSfxDockingWindow != NULL)
     722        4927 :             aCreationArguments.put("SfxBindings", makeAny(sal_uInt64(&pSfxDockingWindow->GetBindings())));
     723        4927 :         aCreationArguments.put("Theme", Theme::GetPropertySet());
     724        4927 :         aCreationArguments.put("Sidebar", makeAny(Reference<ui::XSidebar>(static_cast<ui::XSidebar*>(this))));
     725        4927 :         if (bWantsCanvas)
     726             :         {
     727           0 :             Reference<rendering::XSpriteCanvas> xCanvas (VCLUnoHelper::GetWindow(rxWindow)->GetSpriteCanvas());
     728           0 :             aCreationArguments.put("Canvas", makeAny(xCanvas));
     729             :         }
     730        4927 :         aCreationArguments.put("ApplicationName", makeAny(rContext.msApplication));
     731        4927 :         aCreationArguments.put("ContextName", makeAny(rContext.msContext));
     732             : 
     733             :         Reference<ui::XUIElement> xUIElement(
     734        4927 :             xUIElementFactory->createUIElement(
     735             :                 rsImplementationURL,
     736        4927 :                 Sequence<beans::PropertyValue>(aCreationArguments.getPropertyValues())),
     737        9175 :             UNO_QUERY_THROW);
     738             : 
     739        9175 :         return xUIElement;
     740             :     }
     741         679 :     catch(const Exception& rException)
     742             :     {
     743             :         SAL_WARN("sfx.sidebar", "Cannot create panel: " << rException.Message);
     744         679 :         return NULL;
     745             :     }
     746             : }
     747             : 
     748       91790 : IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
     749             : {
     750       45895 :     if (pEvent==NULL)
     751           0 :         return sal_IntPtr(false);
     752             : 
     753       45895 :     if (pEvent->GetWindow() == mpParentWindow)
     754             :     {
     755       32598 :         switch (pEvent->GetId())
     756             :         {
     757             :             case VCLEVENT_WINDOW_SHOW:
     758             :             case VCLEVENT_WINDOW_RESIZE:
     759       12319 :                 NotifyResize();
     760       12319 :                 break;
     761             : 
     762             :             case VCLEVENT_WINDOW_DATACHANGED:
     763             :                 // Force an update of deck and tab bar to reflect
     764             :                 // changes in theme (high contrast mode).
     765           3 :                 Theme::HandleDataChange();
     766           3 :                 UpdateTitleBarIcons();
     767           3 :                 mpParentWindow->Invalidate();
     768           3 :                 mnRequestedForceFlags |= SwitchFlag_ForceNewDeck | SwitchFlag_ForceNewPanels;
     769           3 :                 maAsynchronousDeckSwitch.CancelRequest();
     770           3 :                 maContextChangeUpdate.RequestCall();
     771           3 :                 break;
     772             : 
     773             :             case SFX_HINT_DYING:
     774           0 :                 dispose();
     775           0 :                 break;
     776             : 
     777             :             case VCLEVENT_WINDOW_PAINT:
     778             :                 OSL_TRACE("Paint");
     779           0 :                 break;
     780             : 
     781             :             default:
     782       20276 :                 break;
     783             :         }
     784             :     }
     785       13297 :     else if (pEvent->GetWindow()==mpSplitWindow && mpSplitWindow!=nullptr)
     786             :     {
     787       13297 :         switch (pEvent->GetId())
     788             :         {
     789             :             case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
     790           0 :                 mnWidthOnSplitterButtonDown = mpParentWindow->GetSizePixel().Width();
     791           0 :                 break;
     792             : 
     793             :             case VCLEVENT_WINDOW_MOUSEBUTTONUP:
     794             :             {
     795           0 :                 ProcessNewWidth(mpParentWindow->GetSizePixel().Width());
     796           0 :                 mnWidthOnSplitterButtonDown = 0;
     797           0 :                 break;
     798             :             }
     799             : 
     800             :             case SFX_HINT_DYING:
     801           0 :                 dispose();
     802           0 :                 break;
     803             :          }
     804             :     }
     805             : 
     806       45895 :     return sal_IntPtr(true);
     807             : }
     808             : 
     809           0 : void SidebarController::ShowPopupMenu (
     810             :     const Rectangle& rButtonBox,
     811             :     const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
     812             : {
     813           0 :     ::boost::shared_ptr<PopupMenu> pMenu = CreatePopupMenu(rMenuData);
     814           0 :     pMenu->SetSelectHdl(LINK(const_cast<SidebarController*>(this), SidebarController, OnMenuItemSelected));
     815             : 
     816             :     // pass toolbox button rect so the menu can stay open on button up
     817           0 :     Rectangle aBox (rButtonBox);
     818           0 :     aBox.Move(mpTabBar->GetPosPixel().X(), 0);
     819           0 :     pMenu->Execute(mpParentWindow, aBox, PopupMenuFlags::ExecuteDown);
     820           0 : }
     821             : 
     822           0 : ::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu (
     823             :     const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
     824             : {
     825             :     // Create the top level popup menu.
     826           0 :     ::boost::shared_ptr<PopupMenu> pMenu (new PopupMenu());
     827           0 :     FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
     828           0 :     if (pMenuWindow != NULL)
     829             :     {
     830           0 :         pMenuWindow->SetPopupModeFlags(pMenuWindow->GetPopupModeFlags() | FloatWinPopupFlags::NoMouseUpClose);
     831             :     }
     832             : 
     833             :     // Create sub menu for customization (hiding of deck tabs.)
     834           0 :     PopupMenu* pCustomizationMenu = new PopupMenu();
     835             : 
     836           0 :     SidebarResource aLocalResource;
     837             : 
     838             :     // Add one entry for every tool panel element to individually make
     839             :     // them visible or hide them.
     840           0 :     sal_Int32 nIndex (0);
     841           0 :     for(::std::vector<TabBar::DeckMenuData>::const_iterator
     842           0 :             iItem(rMenuData.begin()),
     843           0 :             iEnd(rMenuData.end());
     844             :         iItem!=iEnd;
     845             :         ++iItem,++nIndex)
     846             :     {
     847           0 :         const sal_Int32 nMenuIndex (nIndex+MID_FIRST_PANEL);
     848           0 :         pMenu->InsertItem(nMenuIndex, iItem->msDisplayName, MenuItemBits::RADIOCHECK);
     849           0 :         pMenu->CheckItem(nMenuIndex, iItem->mbIsCurrentDeck);
     850           0 :         pMenu->EnableItem(nMenuIndex, iItem->mbIsEnabled&&iItem->mbIsActive);
     851             : 
     852           0 :         const sal_Int32 nSubMenuIndex (nIndex+MID_FIRST_HIDE);
     853           0 :         if (iItem->mbIsCurrentDeck)
     854             :         {
     855             :             // Don't allow the currently visible deck to be disabled.
     856           0 :             pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MenuItemBits::RADIOCHECK);
     857           0 :             pCustomizationMenu->CheckItem(nSubMenuIndex, true);
     858             :         }
     859             :         else
     860             :         {
     861           0 :             pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MenuItemBits::CHECKABLE);
     862           0 :             pCustomizationMenu->CheckItem(nSubMenuIndex, iItem->mbIsActive);
     863             :         }
     864             :     }
     865             : 
     866           0 :     pMenu->InsertSeparator();
     867             : 
     868             :     // Add entry for docking or un-docking the tool panel.
     869           0 :     if (mpParentWindow->IsFloatingMode())
     870           0 :         pMenu->InsertItem(MID_LOCK_TASK_PANEL, SFX2_RESSTR(STR_SFX_DOCK));
     871             :     else
     872           0 :         pMenu->InsertItem(MID_UNLOCK_TASK_PANEL, SFX2_RESSTR(STR_SFX_UNDOCK));
     873             : 
     874           0 :     pMenu->InsertItem(MID_HIDE_SIDEBAR, SFX2_RESSTR(STRING_HIDE_SIDEBAR));
     875           0 :     pCustomizationMenu->InsertSeparator();
     876           0 :     pCustomizationMenu->InsertItem(MID_RESTORE_DEFAULT, SFX2_RESSTR(STRING_RESTORE));
     877             : 
     878           0 :     pMenu->InsertItem(MID_CUSTOMIZATION, SFX2_RESSTR(STRING_CUSTOMIZATION));
     879           0 :     pMenu->SetPopupMenu(MID_CUSTOMIZATION, pCustomizationMenu);
     880             : 
     881           0 :     pMenu->RemoveDisabledEntries(false, false);
     882             : 
     883           0 :     return pMenu;
     884             : }
     885             : 
     886           0 : IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu)
     887             : {
     888           0 :     if (pMenu == NULL)
     889             :     {
     890             :         OSL_ENSURE(pMenu!=NULL, "sfx2::sidebar::SidebarController::OnMenuItemSelected: illegal menu!");
     891           0 :         return 0;
     892             :     }
     893             : 
     894           0 :     pMenu->Deactivate();
     895           0 :     const sal_Int32 nIndex (pMenu->GetCurItemId());
     896           0 :     switch (nIndex)
     897             :     {
     898             :         case MID_UNLOCK_TASK_PANEL:
     899           0 :             mpParentWindow->SetFloatingMode(true);
     900           0 :             break;
     901             : 
     902             :         case MID_LOCK_TASK_PANEL:
     903           0 :             mpParentWindow->SetFloatingMode(false);
     904           0 :             break;
     905             : 
     906             :         case MID_RESTORE_DEFAULT:
     907           0 :             mpTabBar->RestoreHideFlags();
     908           0 :             break;
     909             : 
     910             :         case MID_HIDE_SIDEBAR:
     911             :         {
     912           0 :             const util::URL aURL (Tools::GetURL(gsHideSidebarCommandName));
     913           0 :             Reference<frame::XDispatch> mxDispatch (Tools::GetDispatch(mxFrame, aURL));
     914           0 :             if (mxDispatch.is())
     915           0 :                     mxDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
     916           0 :             break;
     917             :         }
     918             :         default:
     919             :         {
     920             :             try
     921             :             {
     922           0 :                 if (nIndex >= MID_FIRST_PANEL && nIndex<MID_FIRST_HIDE)
     923             :                 {
     924           0 :                     RequestOpenDeck();
     925           0 :                     SwitchToDeck(mpTabBar->GetDeckIdForIndex(nIndex - MID_FIRST_PANEL));
     926             :                 }
     927           0 :                 else if (nIndex >=MID_FIRST_HIDE)
     928           0 :                     if (pMenu->GetItemBits(nIndex) == MenuItemBits::CHECKABLE)
     929           0 :                         mpTabBar->ToggleHideFlag(nIndex-MID_FIRST_HIDE);
     930             :             }
     931           0 :             catch (RuntimeException&)
     932             :             {
     933             :             }
     934             :         }
     935           0 :         break;
     936             :     }
     937             : 
     938           0 :     return 1;
     939             : }
     940             : 
     941           0 : void SidebarController::RequestCloseDeck()
     942             : {
     943           0 :     mbIsDeckRequestedOpen = false;
     944           0 :     UpdateDeckOpenState();
     945             : 
     946             :     // remove highlight from TabBar, because Deck will be closed
     947           0 :     mpTabBar->RemoveDeckHighlight();
     948           0 : }
     949             : 
     950           0 : void SidebarController::RequestOpenDeck()
     951             : {
     952           0 :     mbIsDeckRequestedOpen = true;
     953           0 :     UpdateDeckOpenState();
     954           0 : }
     955             : 
     956           0 : bool SidebarController::IsDeckVisible(const OUString& rsDeckId)
     957             : {
     958           0 :     return mbIsDeckOpen && mbIsDeckOpen.get() && msCurrentDeckId == rsDeckId;
     959             : }
     960             : 
     961           0 : void SidebarController::UpdateDeckOpenState()
     962             : {
     963           0 :     if ( ! mbIsDeckRequestedOpen)
     964             :         // No state requested.
     965           0 :         return;
     966             : 
     967           0 :     sal_Int32 nTabBarDefaultWidth = TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor();
     968             : 
     969             :     // Update (change) the open state when it either has not yet been initialized
     970             :     // or when its value differs from the requested state.
     971           0 :     if ( ! mbIsDeckOpen
     972           0 :         || mbIsDeckOpen.get() != mbIsDeckRequestedOpen.get())
     973             :     {
     974           0 :         if (mbIsDeckRequestedOpen.get())
     975             :         {
     976           0 :             if (mnSavedSidebarWidth <= nTabBarDefaultWidth)
     977           0 :                 SetChildWindowWidth(SidebarChildWindow::GetDefaultWidth(mpParentWindow));
     978             :             else
     979           0 :                 SetChildWindowWidth(mnSavedSidebarWidth);
     980             :         }
     981             :         else
     982             :         {
     983           0 :             if ( ! mpParentWindow->IsFloatingMode())
     984           0 :                 mnSavedSidebarWidth = SetChildWindowWidth(nTabBarDefaultWidth);
     985           0 :             if (mnWidthOnSplitterButtonDown > nTabBarDefaultWidth)
     986           0 :                 mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
     987           0 :             mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
     988             :         }
     989             : 
     990           0 :         mbIsDeckOpen = mbIsDeckRequestedOpen.get();
     991           0 :         if (mbIsDeckOpen.get() && mpCurrentDeck)
     992           0 :             mpCurrentDeck->Show(mbIsDeckOpen.get());
     993           0 :         NotifyResize();
     994             :     }
     995             : }
     996             : 
     997        3609 : bool SidebarController::CanModifyChildWindowWidth()
     998             : {
     999        3609 :     SfxSplitWindow* pSplitWindow = GetSplitWindow();
    1000        3609 :     if (pSplitWindow == NULL)
    1001           0 :         return false;
    1002             : 
    1003        3609 :     sal_uInt16 nRow (0xffff);
    1004        3609 :     sal_uInt16 nColumn (0xffff);
    1005        3609 :     if (pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow))
    1006             :     {
    1007        3609 :         sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn));
    1008        3609 :         return nRowCount==1;
    1009             :     }
    1010             :     else
    1011           0 :         return false;
    1012             : }
    1013             : 
    1014           0 : sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
    1015             : {
    1016           0 :     SfxSplitWindow* pSplitWindow = GetSplitWindow();
    1017           0 :     if (pSplitWindow == NULL)
    1018           0 :         return 0;
    1019             : 
    1020           0 :     sal_uInt16 nRow (0xffff);
    1021           0 :     sal_uInt16 nColumn (0xffff);
    1022           0 :     pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow);
    1023           0 :     const long nColumnWidth (pSplitWindow->GetLineSize(nColumn));
    1024             : 
    1025           0 :     vcl::Window* pWindow = mpParentWindow;
    1026           0 :     const Size aWindowSize (pWindow->GetSizePixel());
    1027             : 
    1028             :     pSplitWindow->MoveWindow(
    1029             :         mpParentWindow,
    1030             :         Size(nNewWidth, aWindowSize.Height()),
    1031             :         nColumn,
    1032           0 :         nRow);
    1033           0 :     static_cast<SplitWindow*>(pSplitWindow)->Split();
    1034             : 
    1035           0 :     return static_cast<sal_Int32>(nColumnWidth);
    1036             : }
    1037             : 
    1038       16382 : void SidebarController::RestrictWidth (sal_Int32 nWidth)
    1039             : {
    1040       16382 :     SfxSplitWindow* pSplitWindow = GetSplitWindow();
    1041       16382 :     if (pSplitWindow != NULL)
    1042             :     {
    1043       13228 :         const sal_uInt16 nId (pSplitWindow->GetItemId(mpParentWindow.get()));
    1044       13228 :         const sal_uInt16 nSetId (pSplitWindow->GetSet(nId));
    1045             :         pSplitWindow->SetItemSizeRange(
    1046             :             nSetId,
    1047       13228 :             Range(TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor() + nWidth,
    1048       26456 :                   gnMaximumSidebarWidth * mpTabBar->GetDPIScaleFactor()));
    1049             :     }
    1050       16382 : }
    1051             : 
    1052       39768 : SfxSplitWindow* SidebarController::GetSplitWindow()
    1053             : {
    1054       39768 :     if (mpParentWindow != nullptr)
    1055             :     {
    1056       39768 :         SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
    1057       39768 :         if (pSplitWindow != mpSplitWindow)
    1058             :         {
    1059        3163 :             if (mpSplitWindow != nullptr)
    1060           8 :                 mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
    1061             : 
    1062        3163 :             mpSplitWindow = pSplitWindow;
    1063             : 
    1064        3163 :             if (mpSplitWindow != nullptr)
    1065        3155 :                 mpSplitWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
    1066             :         }
    1067       39768 :         return mpSplitWindow;
    1068             :     }
    1069             :     else
    1070           0 :         return NULL;
    1071             : }
    1072             : 
    1073       16012 : void SidebarController::UpdateCloseIndicator (const bool bCloseAfterDrag)
    1074             : {
    1075       16012 :     if (mpParentWindow == nullptr)
    1076       16012 :         return;
    1077             : 
    1078       16012 :     if (bCloseAfterDrag)
    1079             :     {
    1080             :         // Make sure that the indicator exists.
    1081       13905 :         if ( ! mpCloseIndicator)
    1082             :         {
    1083        3155 :             mpCloseIndicator.reset(VclPtr<FixedImage>::Create(mpParentWindow));
    1084        3155 :             FixedImage* pFixedImage = static_cast<FixedImage*>(mpCloseIndicator.get());
    1085        3155 :             const Image aImage (Theme::GetImage(Theme::Image_CloseIndicator));
    1086        3155 :             pFixedImage->SetImage(aImage);
    1087        3155 :             pFixedImage->SetSizePixel(aImage.GetSizePixel());
    1088        3155 :             pFixedImage->SetBackground(Theme::GetWallpaper(Theme::Paint_DeckBackground));
    1089             :         }
    1090             : 
    1091             :         // Place and show the indicator.
    1092       13905 :         const Size aWindowSize (mpParentWindow->GetSizePixel());
    1093       13905 :         const Size aImageSize (mpCloseIndicator->GetSizePixel());
    1094       13905 :         mpCloseIndicator->SetPosPixel(
    1095             :             Point(
    1096       13905 :                 aWindowSize.Width() - TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor() - aImageSize.Width(),
    1097       27810 :                 (aWindowSize.Height() - aImageSize.Height())/2));
    1098       13905 :         mpCloseIndicator->Show();
    1099             :     }
    1100             :     else
    1101             :     {
    1102             :         // Hide but don't delete the indicator.
    1103        2107 :         if (mpCloseIndicator)
    1104        2107 :             mpCloseIndicator->Hide();
    1105             :     }
    1106             : }
    1107             : 
    1108        3768 : void SidebarController::UpdateTitleBarIcons()
    1109             : {
    1110        3768 :     if ( ! mpCurrentDeck)
    1111        3768 :         return;
    1112             : 
    1113        3768 :     const bool bIsHighContrastModeActive (Theme::IsHighContrastMode());
    1114        3768 :     const ResourceManager& rResourceManager (ResourceManager::Instance());
    1115             : 
    1116             :     // Update the deck icon.
    1117        3768 :     const DeckDescriptor* pDeckDescriptor = rResourceManager.GetDeckDescriptor(mpCurrentDeck->GetId());
    1118        3768 :     if (pDeckDescriptor != NULL && mpCurrentDeck->GetTitleBar())
    1119             :     {
    1120             :         const OUString sIconURL(
    1121             :             bIsHighContrastModeActive
    1122             :                 ? pDeckDescriptor->msHighContrastTitleBarIconURL
    1123        3768 :                 : pDeckDescriptor->msTitleBarIconURL);
    1124        3768 :         mpCurrentDeck->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
    1125             :     }
    1126             : 
    1127             :     // Update the panel icons.
    1128        3768 :     const SharedPanelContainer& rPanels (mpCurrentDeck->GetPanels());
    1129        8141 :     for (SharedPanelContainer::const_iterator
    1130        3768 :              iPanel(rPanels.begin()), iEnd(rPanels.end());
    1131             :              iPanel!=iEnd;
    1132             :              ++iPanel)
    1133             :     {
    1134        4373 :         if ( ! *iPanel)
    1135           0 :             continue;
    1136        4373 :         if ((*iPanel)->GetTitleBar() == NULL)
    1137           0 :             continue;
    1138        4373 :         const PanelDescriptor* pPanelDescriptor = rResourceManager.GetPanelDescriptor((*iPanel)->GetId());
    1139        4373 :         if (pPanelDescriptor == NULL)
    1140           0 :             continue;
    1141             :         const OUString sIconURL (
    1142             :             bIsHighContrastModeActive
    1143             :                ? pPanelDescriptor->msHighContrastTitleBarIconURL
    1144        4373 :                : pPanelDescriptor->msTitleBarIconURL);
    1145        4373 :         (*iPanel)->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
    1146        4373 :     }
    1147             : }
    1148             : 
    1149           0 : void SidebarController::ShowPanel (const Panel& rPanel)
    1150             : {
    1151           0 :     if (mpCurrentDeck)
    1152           0 :         mpCurrentDeck->ShowPanel(rPanel);
    1153           0 : }
    1154             : 
    1155         648 : } } // end of namespace sfx2::sidebar
    1156             : 
    1157             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11