[Libreoffice-commits] core.git: Branch 'feature/sidebar' - include/sfx2 officecfg/registry sfx2/source

Andre Fischer af at apache.org
Fri May 10 01:33:44 PDT 2013


 include/sfx2/sidebar/SidebarChildWindow.hxx                    |    2 
 include/sfx2/sidebar/Theme.hxx                                 |    1 
 officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu   |    9 
 officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs |    6 
 sfx2/source/sidebar/PanelDescriptor.hxx                        |    1 
 sfx2/source/sidebar/ResourceManager.cxx                        |  107 +-
 sfx2/source/sidebar/ResourceManager.hxx                        |   23 
 sfx2/source/sidebar/SidebarChildWindow.cxx                     |   23 
 sfx2/source/sidebar/SidebarController.cxx                      |  448 +++++++---
 sfx2/source/sidebar/SidebarController.hxx                      |   60 +
 sfx2/source/sidebar/SidebarDockingWindow.cxx                   |    6 
 sfx2/source/sidebar/TabBar.cxx                                 |   36 
 sfx2/source/sidebar/TabBar.hxx                                 |    3 
 sfx2/source/sidebar/TabItem.cxx                                |    5 
 sfx2/source/sidebar/Theme.cxx                                  |    8 
 15 files changed, 535 insertions(+), 203 deletions(-)

New commits:
commit f039e360fdad73305ba27a377613b7560b59195b
Author: Andre Fischer <af at apache.org>
Date:   Mon Apr 29 07:44:43 2013 +0000

    Resolves: #i122082# Hide sidebar panels for read only documents
    
    (cherry picked from commit aae247a34cd6f3bf421e57bbec08837d73ddf258)
    
    Conflicts:
    	sfx2/inc/sfx2/sidebar/SidebarChildWindow.hxx
    	sfx2/inc/sfx2/sidebar/Theme.hxx
    	sfx2/source/sidebar/SidebarChildWindow.cxx
    	sfx2/source/sidebar/SidebarController.cxx
    	sfx2/source/sidebar/SidebarDockingWindow.cxx
    
    Change-Id: Ib59132d6d5e177d5a02ee24973b0fb07114db60a

diff --git a/include/sfx2/sidebar/SidebarChildWindow.hxx b/include/sfx2/sidebar/SidebarChildWindow.hxx
index 23f9194..194f098 100644
--- a/include/sfx2/sidebar/SidebarChildWindow.hxx
+++ b/include/sfx2/sidebar/SidebarChildWindow.hxx
@@ -40,6 +40,8 @@ public:
         SfxChildWinInfo* pInfo);
 
     SFX_DECL_CHILDWINDOW_WITHID(SidebarChildWindow);
+
+    static sal_Int32 GetDefaultWidth (Window* pWindow);
 };
 
 
diff --git a/include/sfx2/sidebar/Theme.hxx b/include/sfx2/sidebar/Theme.hxx
index d34866b..0b75123 100644
--- a/include/sfx2/sidebar/Theme.hxx
+++ b/include/sfx2/sidebar/Theme.hxx
@@ -77,6 +77,7 @@ public:
         Image_PanelMenu,
         Image_ToolBoxItemSeparator,
         Image_Closer,
+        Image_CloseIndicator,
 
         __Image_Color,
 
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
index b435c9a..9c9ff63 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
@@ -831,6 +831,9 @@
         <prop oor:name="TitleBarIsOptional" oor:type="xs:boolean">
           <value>true</value>
         </prop>
+        <prop oor:name="ShowForReadOnlyDocument" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
         <prop oor:name="Id" oor:type="xs:string">
           <value>SwNavigatorPanel</value>
         </prop>
@@ -857,6 +860,9 @@
         <prop oor:name="TitleBarIsOptional" oor:type="xs:boolean">
           <value>true</value>
         </prop>
+        <prop oor:name="ShowForReadOnlyDocument" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
         <prop oor:name="Id" oor:type="xs:string">
           <value>ScNavigatorPanel</value>
         </prop>
@@ -883,6 +889,9 @@
         <prop oor:name="TitleBarIsOptional" oor:type="xs:boolean">
           <value>true</value>
         </prop>
+        <prop oor:name="ShowForReadOnlyDocument" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
         <prop oor:name="Id" oor:type="xs:string">
           <value>SdNavigatorPanel</value>
         </prop>
diff --git a/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs b/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
index f7a35a3..8d096b3 100644
--- a/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/UI/Sidebar.xcs
@@ -201,6 +201,12 @@
         </info>
         <value>10000</value>
       </prop>
+      <prop oor:name="ShowForReadOnlyDocument" oor:type="xs:boolean">
+        <info>
+          <desc>This flag controls whether the panel is shown when the document in the edit view is read only.</desc>
+        </info>
+        <value>false</value>
+      </prop>
       <prop oor:name="WantsCanvas" oor:type="xs:boolean">
         <info>
           <desc>Experimental: Set to true when panel wants to paint its content via a XCanvas.</desc>
diff --git a/sfx2/source/sidebar/PanelDescriptor.hxx b/sfx2/source/sidebar/PanelDescriptor.hxx
index cb39dbb..d06fb03 100644
--- a/sfx2/source/sidebar/PanelDescriptor.hxx
+++ b/sfx2/source/sidebar/PanelDescriptor.hxx
@@ -38,6 +38,7 @@ public:
     ContextList maContextList;
     ::rtl::OUString msImplementationURL;
     sal_Int32 mnOrderIndex;
+    bool mbShowForReadOnlyDocuments;
     bool mbWantsCanvas;
 
     PanelDescriptor (void);
diff --git a/sfx2/source/sidebar/ResourceManager.cxx b/sfx2/source/sidebar/ResourceManager.cxx
index 070bb1c..725471a 100644
--- a/sfx2/source/sidebar/ResourceManager.cxx
+++ b/sfx2/source/sidebar/ResourceManager.cxx
@@ -81,25 +81,6 @@ ResourceManager::~ResourceManager (void)
 
 
 
-const DeckDescriptor* ResourceManager::GetBestMatchingDeck (
-    const Context& rContext,
-    const Reference<frame::XFrame>& rxFrame)
-{
-    ReadLegacyAddons(rxFrame);
-
-    for (DeckContainer::const_iterator iDeck(maDecks.begin()), iEnd(maDecks.end());
-         iDeck!=iEnd;
-         ++iDeck)
-    {
-        if (iDeck->maContextList.GetMatch(rContext) != NULL)
-            return &*iDeck;
-    }
-    return NULL;
-}
-
-
-
-
 const DeckDescriptor* ResourceManager::GetDeckDescriptor (
     const ::rtl::OUString& rsDeckId) const
 {
@@ -157,14 +138,15 @@ void ResourceManager::SetIsDeckEnabled (
 
 
 
-const ResourceManager::IdContainer& ResourceManager::GetMatchingDecks (
-    IdContainer& rDeckIds,
+const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks (
+    DeckContextDescriptorContainer& rDecks,
     const Context& rContext,
+    const bool bIsDocumentReadOnly,
     const Reference<frame::XFrame>& rxFrame)
 {
     ReadLegacyAddons(rxFrame);
 
-    ::std::multimap<sal_Int32,OUString> aOrderedIds;
+    ::std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
     for (DeckContainer::const_iterator
              iDeck(maDecks.begin()),
              iEnd (maDecks.end());
@@ -172,22 +154,28 @@ const ResourceManager::IdContainer& ResourceManager::GetMatchingDecks (
          ++iDeck)
     {
         const DeckDescriptor& rDeckDescriptor (*iDeck);
-        if (rDeckDescriptor.maContextList.GetMatch(rContext) != NULL)
-            aOrderedIds.insert(::std::multimap<sal_Int32,OUString>::value_type(
-                    rDeckDescriptor.mnOrderIndex,
-                    rDeckDescriptor.msId));
+        if (rDeckDescriptor.maContextList.GetMatch(rContext) == NULL)
+            continue;
+        DeckContextDescriptor aDeckContextDescriptor;
+        aDeckContextDescriptor.msId = rDeckDescriptor.msId;
+        aDeckContextDescriptor.mbIsEnabled =
+            ! bIsDocumentReadOnly
+            || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxFrame);
+        aOrderedIds.insert(::std::multimap<sal_Int32,DeckContextDescriptor>::value_type(
+                rDeckDescriptor.mnOrderIndex,
+                aDeckContextDescriptor));
     }
 
-    for (::std::multimap<sal_Int32,OUString>::const_iterator
+    for (::std::multimap<sal_Int32,DeckContextDescriptor>::const_iterator
              iId(aOrderedIds.begin()),
              iEnd(aOrderedIds.end());
          iId!=iEnd;
          ++iId)
     {
-        rDeckIds.push_back(iId->second);
+        rDecks.push_back(iId->second);
     }
 
-    return rDeckIds;
+    return rDecks;
 }
 
 
@@ -209,20 +197,21 @@ const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatc
          ++iPanel)
     {
         const PanelDescriptor& rPanelDescriptor (*iPanel);
-        if (rPanelDescriptor.msDeckId.equals(rsDeckId))
-        {
-            const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
-            if (pEntry != NULL)
-            {
-                PanelContextDescriptor aPanelContextDescriptor;
-                aPanelContextDescriptor.msId = rPanelDescriptor.msId;
-                aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
-                aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
-                aOrderedIds.insert(::std::multimap<sal_Int32,PanelContextDescriptor>::value_type(
-                        rPanelDescriptor.mnOrderIndex,
-                        aPanelContextDescriptor));
-            }
-        }
+        if ( ! rPanelDescriptor.msDeckId.equals(rsDeckId))
+            continue;
+
+        const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
+        if (pEntry == NULL)
+            continue;
+
+        PanelContextDescriptor aPanelContextDescriptor;
+        aPanelContextDescriptor.msId = rPanelDescriptor.msId;
+        aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
+        aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
+        aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
+        aOrderedIds.insert(::std::multimap<sal_Int32,PanelContextDescriptor>::value_type(
+                rPanelDescriptor.mnOrderIndex,
+                aPanelContextDescriptor));
     }
 
     for (::std::multimap<sal_Int32,PanelContextDescriptor>::const_iterator
@@ -334,6 +323,8 @@ void ResourceManager::ReadPanelList (void)
             aPanelNode.getNodeValue("ImplementationURL"));
         rPanelDescriptor.mnOrderIndex = ::comphelper::getINT32(
             aPanelNode.getNodeValue("OrderIndex"));
+        rPanelDescriptor.mbShowForReadOnlyDocuments = ::comphelper::getBOOL(
+            aPanelNode.getNodeValue("ShowForReadOnlyDocument"));
         rPanelDescriptor.mbWantsCanvas = ::comphelper::getBOOL(
             aPanelNode.getNodeValue("WantsCanvas"));
         const OUString sDefaultMenuCommand (::comphelper::getString(
@@ -555,6 +546,7 @@ void ResourceManager::ReadLegacyAddons (const Reference<frame::XFrame>& rxFrame)
         rPanelDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL"));
         rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString());
         rPanelDescriptor.msImplementationURL = rsNodeName;
+        rPanelDescriptor.mbShowForReadOnlyDocuments = false;
     }
 
     // When there where invalid nodes then we have to adapt the size
@@ -641,4 +633,33 @@ void ResourceManager::GetToolPanelNodeNames (
 
 
 
+
+bool ResourceManager::IsDeckEnabled (
+    const OUString& rsDeckId,
+    const Context& rContext,
+    const Reference<frame::XFrame>& rxFrame) const
+{
+    // Check if any panel that matches the current context can be
+    // displayed.
+    ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
+    ResourceManager::Instance().GetMatchingPanels(
+        aPanelContextDescriptors,
+        rContext,
+        rsDeckId,
+        rxFrame);
+
+    for (ResourceManager::PanelContextDescriptorContainer::const_iterator
+             iPanel(aPanelContextDescriptors.begin()),
+             iEnd(aPanelContextDescriptors.end());
+         iPanel!=iEnd;
+         ++iPanel)
+    {
+        if (iPanel->mbShowForReadOnlyDocuments)
+            return true;
+    }
+
+    return false;
+}
+
+
 } } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ResourceManager.hxx b/sfx2/source/sidebar/ResourceManager.hxx
index cc9093c..80c0b0b 100644
--- a/sfx2/source/sidebar/ResourceManager.hxx
+++ b/sfx2/source/sidebar/ResourceManager.hxx
@@ -44,10 +44,6 @@ class ResourceManager
 public:
     static ResourceManager& Instance (void);
 
-    const DeckDescriptor* GetBestMatchingDeck (
-        const Context& rContext,
-        const cssu::Reference<css::frame::XFrame>& rxFrame);
-
     const DeckDescriptor* GetDeckDescriptor (
         const ::rtl::OUString& rsDeckId) const;
     const PanelDescriptor* GetPanelDescriptor (
@@ -64,19 +60,28 @@ public:
         const ::rtl::OUString& rsDeckId,
         const bool bIsEnabled);
 
-    typedef ::std::vector<rtl::OUString> IdContainer;
+    class DeckContextDescriptor
+    {
+    public:
+        ::rtl::OUString msId;
+        bool mbIsEnabled;
+    };
+    typedef ::std::vector<DeckContextDescriptor> DeckContextDescriptorContainer;
+
     class PanelContextDescriptor
     {
     public:
         ::rtl::OUString msId;
         ::rtl::OUString msMenuCommand;
         bool mbIsInitiallyVisible;
+        bool mbShowForReadOnlyDocuments;
     };
     typedef ::std::vector<PanelContextDescriptor> PanelContextDescriptorContainer;
 
-    const IdContainer& GetMatchingDecks (
-        IdContainer& rDeckDescriptors,
+    const DeckContextDescriptorContainer& GetMatchingDecks (
+        DeckContextDescriptorContainer& rDeckDescriptors,
         const Context& rContext,
+        const bool bIsDocumentReadOnly,
         const cssu::Reference<css::frame::XFrame>& rxFrame);
 
     const PanelContextDescriptorContainer& GetMatchingPanels (
@@ -113,6 +118,10 @@ private:
     void GetToolPanelNodeNames (
         ::std::vector<rtl::OUString>& rMatchingNames,
         const ::utl::OConfigurationTreeRoot aRoot) const;
+    bool IsDeckEnabled (
+        const ::rtl::OUString& rsDeckId,
+        const Context& rContext,
+        const cssu::Reference<css::frame::XFrame>& rxFrame) const;
 };
 
 
diff --git a/sfx2/source/sidebar/SidebarChildWindow.cxx b/sfx2/source/sidebar/SidebarChildWindow.cxx
index f02b37c..cb001ce 100644
--- a/sfx2/source/sidebar/SidebarChildWindow.cxx
+++ b/sfx2/source/sidebar/SidebarChildWindow.cxx
@@ -15,6 +15,8 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
+
+#include "TabBar.hxx"
 #include "sfx2/sidebar/SidebarChildWindow.hxx"
 #include "SidebarDockingWindow.hxx"
 #include "sfx2/sfxsids.hrc"
@@ -44,9 +46,9 @@ SidebarChildWindow::SidebarChildWindow (
     eChildAlignment = SFX_ALIGN_RIGHT;
 
     this->pWindow->SetHelpId(HID_SIDEBAR_WINDOW);
-    this->pWindow->SetOutputSizePixel(Size(300, 450));
+    this->pWindow->SetOutputSizePixel(Size(GetDefaultWidth(this->pWindow), 450));
 
-    SfxDockingWindow* pDockingParent = dynamic_cast<SfxDockingWindow*>(pParentWindow);
+    SfxDockingWindow* pDockingParent = dynamic_cast<SfxDockingWindow*>(this->pWindow);
     if (pDockingParent != NULL)
         pDockingParent->Initialize(pInfo);
     SetHideNotDelete(sal_True);
@@ -55,4 +57,21 @@ SidebarChildWindow::SidebarChildWindow (
 }
 
 
+
+
+sal_Int32 SidebarChildWindow::GetDefaultWidth (Window* pWindow)
+{
+    if (pWindow != NULL)
+    {
+        // Width of the paragraph panel.
+        const static sal_Int32 nMaxPropertyPageWidth (115);
+
+        return pWindow->LogicToPixel(Point(nMaxPropertyPageWidth,1), MAP_APPFONT).X()
+            + TabBar::GetDefaultWidth();
+    }
+    else
+        return 0;
+}
+
+
 } } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarController.cxx b/sfx2/source/sidebar/SidebarController.cxx
index c458442..7a6ef5e 100644
--- a/sfx2/source/sidebar/SidebarController.cxx
+++ b/sfx2/source/sidebar/SidebarController.cxx
@@ -23,6 +23,7 @@
 #include "SidebarResource.hxx"
 #include "TabBar.hxx"
 #include "sfx2/sidebar/Theme.hxx"
+#include "sfx2/sidebar/SidebarChildWindow.hxx"
 #include "SidebarDockingWindow.hxx"
 #include "Context.hxx"
 #include "Tools.hxx"
@@ -32,6 +33,7 @@
 #include "sfx2/titledockwin.hxx"
 #include "sfxlocal.hrc"
 #include <vcl/floatwin.hxx>
+#include <vcl/fixed.hxx>
 #include "splitwin.hxx"
 #include <svl/smplhint.hxx>
 #include <tools/link.hxx>
@@ -61,6 +63,15 @@ using ::rtl::OUString;
 
 #undef VERBOSE
 
+namespace
+{
+    const static OUString gsReadOnlyCommandName (A2S(".uno:EditDoc"));
+    const static sal_Int32 gnMaximumSidebarWidth (400);
+    const static sal_Int32 gnWidthCloseThreshold (70);
+    const static sal_Int32 gnWidthOpenThreshold (40);
+}
+
+
 namespace sfx2 { namespace sidebar {
 
 namespace {
@@ -85,15 +96,22 @@ SidebarController::SidebarController (
       mpTabBar(new TabBar(
               mpParentWindow,
               rxFrame,
-              ::boost::bind(&SidebarController::SwitchToDeck, this, _1),
+              ::boost::bind(&SidebarController::OpenThenSwitchToDeck, this, _1),
               ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2,_3))),
       mxFrame(rxFrame),
       maCurrentContext(OUString(), OUString()),
       msCurrentDeckId(A2S("PropertyDeck")),
       maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)),
       maContextChangeUpdate(::boost::bind(&SidebarController::UpdateConfigurations, this)),
-      mbIsDeckClosed(false),
-      mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width())
+      mbIsDeckRequestedOpen(),
+      mbIsDeckOpen(),
+      mbCanDeckBeOpened(true),
+      mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width()),
+      mxReadOnlyModeDispatch(),
+      mbIsDocumentReadOnly(false),
+      mpSplitWindow(NULL),
+      mnWidthOnSplitterButtonDown(0),
+      mpCloseIndicator()
 {
     if (pParentWindow == NULL)
     {
@@ -118,6 +136,13 @@ SidebarController::SidebarController (
         A2S(""),
         static_cast<css::beans::XPropertyChangeListener*>(this));
 
+    // Get the dispatch object as preparation to listen for changes of
+    // the read-only state.
+    const util::URL aURL (GetURL(gsReadOnlyCommandName));
+    mxReadOnlyModeDispatch = GetDispatch(aURL);
+    if (mxReadOnlyModeDispatch.is())
+        mxReadOnlyModeDispatch->addStatusListener(this, aURL);
+
     SwitchToDeck(A2S("default"));
 }
 
@@ -142,6 +167,14 @@ void SAL_CALL SidebarController::disposing (void)
         xMultiplexer->removeAllContextChangeEventListeners(
             static_cast<css::ui::XContextChangeEventListener*>(this));
 
+    if (mxReadOnlyModeDispatch.is())
+        mxReadOnlyModeDispatch->removeStatusListener(this, GetURL(gsReadOnlyCommandName));
+    if (mpSplitWindow != NULL)
+    {
+        mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
+        mpSplitWindow = NULL;
+    }
+
     if (mpParentWindow != NULL)
     {
         mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
@@ -203,6 +236,25 @@ void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChang
 
 
 
+void SAL_CALL SidebarController::statusChanged (const css::frame::FeatureStateEvent& rEvent)
+    throw(cssu::RuntimeException)
+{
+    bool bIsReadWrite (true);
+    if (rEvent.IsEnabled)
+        rEvent.State >>= bIsReadWrite;
+
+    if (mbIsDocumentReadOnly != !bIsReadWrite)
+    {
+        mbIsDocumentReadOnly = !bIsReadWrite;
+
+        // Force the current deck to update its panel list.
+        SwitchToDeck(msCurrentDeckId);
+    }
+}
+
+
+
+
 void SAL_CALL SidebarController::requestLayout (void)
     throw(cssu::RuntimeException)
 {
@@ -237,12 +289,36 @@ void SidebarController::NotifyResize (void)
     const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width());
     const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height());
 
+    mbIsDeckOpen = (nWidth > TabBar::GetDefaultWidth());
+
+    if (mnSavedSidebarWidth <= 0)
+        mnSavedSidebarWidth = nWidth;
+
+    bool bIsDeckVisible;
+    if (mbCanDeckBeOpened)
+    {
+        const bool bIsOpening (nWidth > mnWidthOnSplitterButtonDown);
+        if (bIsOpening)
+            bIsDeckVisible = nWidth >= TabBar::GetDefaultWidth() + gnWidthOpenThreshold;
+        else
+            bIsDeckVisible = nWidth >= TabBar::GetDefaultWidth() + gnWidthCloseThreshold;
+        mbIsDeckRequestedOpen = bIsDeckVisible;
+        UpdateCloseIndicator(!bIsDeckVisible);
+    }
+    else
+        bIsDeckVisible = false;
+
     // Place the deck.
     if (mpCurrentDeck)
     {
-        mpCurrentDeck->setPosSizePixel(0,0, nWidth-TabBar::GetDefaultWidth(), nHeight);
-        mpCurrentDeck->Show();
-        mpCurrentDeck->RequestLayout();
+        if (bIsDeckVisible)
+        {
+            mpCurrentDeck->setPosSizePixel(0,0, nWidth-TabBar::GetDefaultWidth(), nHeight);
+            mpCurrentDeck->Show();
+            mpCurrentDeck->RequestLayout();
+        }
+        else
+            mpCurrentDeck->Hide();
     }
 
     // Place the tab bar.
@@ -257,26 +333,34 @@ void SidebarController::NotifyResize (void)
             pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
     }
 
-    if (nWidth > TabBar::GetDefaultWidth())
-        mnSavedSidebarWidth = nWidth;
-
     RestrictWidth();
-#ifdef VERBOSE
-    if (mpCurrentDeck)
+}
+
+
+
+
+void SidebarController::ProcessNewWidth (const sal_Int32 nNewWidth)
+{
+    if ( ! mbIsDeckRequestedOpen)
+        return;
+
+    if (mbIsDeckRequestedOpen.get())
+     {
+        // Deck became large enough to be shown.  Show it.
+        mnSavedSidebarWidth = nNewWidth;
+        RequestOpenDeck();
+    }
+    else
     {
-        mpCurrentDeck->PrintWindowTree();
-        sal_Int32 nPanelIndex (0);
-        for (SharedPanelContainer::const_iterator
-                 iPanel(mpCurrentDeck->GetPanels().begin()),
-                 iEnd(mpCurrentDeck->GetPanels().end());
-             iPanel!=iEnd;
-             ++iPanel,++nPanelIndex)
-        {
-            OSL_TRACE("panel %d:", nPanelIndex);
-            (*iPanel)->PrintWindowTree();
-        }
+        // Deck became too small.  Close it completely.
+        // If window is wider than the tab bar then mark the deck as being visible, even when it its not.
+        // This is to trigger an adjustment of the width to the width of the tab bar.
+        mbIsDeckOpen = true;
+        RequestCloseDeck();
+
+        if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth())
+            mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
     }
-#endif
 }
 
 
@@ -288,44 +372,56 @@ void SidebarController::UpdateConfigurations (void)
     {
         maCurrentContext = maRequestedContext;
 
-        // Notify the tab bar about the updated set of decks.
-        ResourceManager::IdContainer aDeckIds;
+        // Find the set of decks that could be displayed for the new context.
+        ResourceManager::DeckContextDescriptorContainer aDecks;
         ResourceManager::Instance().GetMatchingDecks (
-            aDeckIds,
+            aDecks,
             maCurrentContext,
+            mbIsDocumentReadOnly,
             mxFrame);
-        mpTabBar->SetDecks(aDeckIds);
+        mpTabBar->SetDecks(aDecks);
 
-        // Check if the current deck is among the matching decks.
-        bool bCurrentDeckMatches (false);
-        for (ResourceManager::IdContainer::const_iterator
-                 iDeck(aDeckIds.begin()),
-                 iEnd(aDeckIds.end());
+        // Notify the tab bar about the updated set of decks.
+        mpTabBar->SetDecks(aDecks);
+
+        // Find the new deck.  By default that is the same as the old
+        // one.  If that is not set or not enabled, then choose the
+        // first enabled deck.
+        OUString sNewDeckId;
+        for (ResourceManager::DeckContextDescriptorContainer::const_iterator
+                 iDeck(aDecks.begin()),
+                 iEnd(aDecks.end());
              iDeck!=iEnd;
              ++iDeck)
         {
-            if (iDeck->equals(msCurrentDeckId))
+            if (iDeck->mbIsEnabled)
             {
-                bCurrentDeckMatches = true;
-                break;
+                if (iDeck->msId.equals(msCurrentDeckId))
+                {
+                    sNewDeckId = msCurrentDeckId;
+                    break;
+                }
+                else if (sNewDeckId.getLength() == 0)
+                    sNewDeckId = iDeck->msId;
             }
         }
 
-        DeckDescriptor const* pDeckDescriptor = NULL;
-        if ( ! bCurrentDeckMatches)
-            pDeckDescriptor = ResourceManager::Instance().GetBestMatchingDeck(maCurrentContext, mxFrame);
-        else
-            pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(msCurrentDeckId);
-        if (pDeckDescriptor != NULL)
+        if (sNewDeckId.getLength() == 0)
         {
-            msCurrentDeckId = pDeckDescriptor->msId;
-            SwitchToDeck(*pDeckDescriptor, maCurrentContext);
+            // We did not find a valid deck.
+            RequestCloseDeck();
+            return;
 
             // Tell the tab bar to highlight the button associated
             // with the deck.
-            mpTabBar->HighlightDeck(msCurrentDeckId);
+            mpTabBar->HighlightDeck(sNewDeckId);
         }
 
+        msCurrentDeckId = sNewDeckId;
+        SwitchToDeck(
+            *ResourceManager::Instance().GetDeckDescriptor(sNewDeckId),
+            maCurrentContext);
+
 #ifdef DEBUG
         // Show the context name in the deck title bar.
         if (mpCurrentDeck)
@@ -341,10 +437,20 @@ void SidebarController::UpdateConfigurations (void)
 
 
 
+void SidebarController::OpenThenSwitchToDeck (
+    const ::rtl::OUString& rsDeckId)
+{
+    RequestOpenDeck();
+    SwitchToDeck(rsDeckId);
+}
+
+
+
+
 void SidebarController::SwitchToDeck (
     const ::rtl::OUString& rsDeckId)
 {
-    if ( ! msCurrentDeckId.equals(rsDeckId) || mbIsDeckClosed)
+    if ( ! msCurrentDeckId.equals(rsDeckId) || ! mbIsDeckOpen)
     {
         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId);
         if (pDeckDescriptor != NULL)
@@ -374,9 +480,6 @@ void SidebarController::SwitchToDeck (
         msCurrentDeckId = rDeckDescriptor.msId;
     }
 
-    // Reopen the deck when necessary.
-    OpenDeck();
-
     // Determine the panels to display in the deck.
     ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
     ResourceManager::Instance().GetMatchingPanels(
@@ -413,6 +516,12 @@ void SidebarController::SwitchToDeck (
         return;
     }
 
+        // When the document is read-only, check if there are any panels that can still be displayed.
+    if (mbIsDocumentReadOnly)
+    {
+    }
+
+
     // Provide a configuration and Deck object.
     if ( ! mpCurrentDeck)
     {
@@ -420,7 +529,7 @@ void SidebarController::SwitchToDeck (
             new Deck(
                 rDeckDescriptor,
                 mpParentWindow,
-                ::boost::bind(&SidebarController::CloseDeck, this)));
+                ::boost::bind(&SidebarController::RequestCloseDeck, this)));
         msCurrentDeckTitle = rDeckDescriptor.msTitle;
     }
     if ( ! mpCurrentDeck)
@@ -438,6 +547,11 @@ void SidebarController::SwitchToDeck (
         const ResourceManager::PanelContextDescriptor& rPanelContexDescriptor (
             aPanelContextDescriptors[nReadIndex]);
 
+        // Determine if the panel can be displayed.
+        const bool bIsPanelVisible (!mbIsDocumentReadOnly || rPanelContexDescriptor.mbShowForReadOnlyDocuments);
+        if ( ! bIsPanelVisible)
+            continue;
+
         // Find the corresponding panel among the currently active
         // panels.
         SharedPanelContainer::const_iterator iPanel (::std::find_if(
@@ -501,28 +615,6 @@ bool SidebarController::ArePanelSetsEqual (
     const SharedPanelContainer& rCurrentPanels,
     const ResourceManager::PanelContextDescriptorContainer& rRequestedPanels)
 {
-#ifdef VERBOSE
-    OSL_TRACE("current panel list:");
-    for (SharedPanelContainer::const_iterator
-             iPanel(rCurrentPanels.begin()),
-             iEnd(rCurrentPanels.end());
-         iPanel!=iEnd;
-         ++iPanel)
-    {
-        OSL_TRACE("    panel %s", S2A((*iPanel)->GetId()));
-    }
-
-    OSL_TRACE("requested panels: ");
-    for (ResourceManager::PanelContextDescriptorContainer::const_iterator
-             iId(rRequestedPanels.begin()),
-             iEnd(rRequestedPanels.end());
-         iId!=iEnd;
-         ++iId)
-    {
-        OSL_TRACE("    panel %s", S2A(iId->msId));
-    }
-#endif
-
     if (rCurrentPanels.size() != rRequestedPanels.size())
         return false;
     for (sal_Int32 nIndex=0,nCount=rCurrentPanels.size(); nIndex<nCount; ++nIndex)
@@ -531,6 +623,11 @@ bool SidebarController::ArePanelSetsEqual (
             return false;
         if ( ! rCurrentPanels[nIndex]->GetId().equals(rRequestedPanels[nIndex].msId))
             return false;
+
+        // Check if the panels still can be displayed.  This may not be the case when
+        // the document just become rea-only.
+        if (mbIsDocumentReadOnly && ! rRequestedPanels[nIndex].mbShowForReadOnlyDocuments)
+            return false;
     }
     return true;
 }
@@ -626,14 +723,13 @@ Reference<ui::XUIElement> SidebarController::CreateUIElement (
 
 IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
 {
-    if (pEvent != NULL)
+    if (pEvent==NULL)
+        return sal_False;
+
+    if (pEvent->GetWindow() == mpParentWindow)
     {
         switch (pEvent->GetId())
         {
-            case VCLEVENT_WINDOW_GETFOCUS:
-            case VCLEVENT_WINDOW_LOSEFOCUS:
-                break;
-
             case VCLEVENT_WINDOW_SHOW:
             case VCLEVENT_WINDOW_RESIZE:
                 NotifyResize();
@@ -651,10 +747,34 @@ IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
                 dispose();
                 break;
 
+            case VCLEVENT_WINDOW_PAINT:
+                OSL_TRACE("Paint");
+                break;
+
             default:
                 break;
         }
     }
+    else if (pEvent->GetWindow()==mpSplitWindow && mpSplitWindow!=NULL)
+    {
+        switch (pEvent->GetId())
+        {
+            case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
+                mnWidthOnSplitterButtonDown = mpParentWindow->GetSizePixel().Width();
+                break;
+
+            case VCLEVENT_WINDOW_MOUSEBUTTONUP:
+            {
+                ProcessNewWidth(mpParentWindow->GetSizePixel().Width());
+                mnWidthOnSplitterButtonDown = 0;
+                break;
+            }
+
+            case SFX_HINT_DYING:
+                dispose();
+                break;
+         }
+    }
 
     return sal_True;
 }
@@ -683,16 +803,8 @@ void SidebarController::ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) co
 {
     try
     {
-        util::URL aURL;
-        aURL.Complete = rsMenuCommand;
-
-        const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory());
-        const Reference<util::XURLTransformer> xParser (
-            aComponentContext.createComponent("com.sun.star.util.URLTransformer"),
-            UNO_QUERY_THROW);
-        xParser->parseStrict(aURL);
-        Reference<frame::XDispatchProvider> xProvider (mxFrame, UNO_QUERY_THROW);
-        Reference<frame::XDispatch> xDispatch (xProvider->queryDispatch(aURL, OUString(), 0));
+        const util::URL aURL (GetURL(rsMenuCommand));
+        Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
         if (xDispatch.is())
             xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
     }
@@ -706,6 +818,33 @@ void SidebarController::ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) co
 
 
 
+util::URL SidebarController::GetURL (const ::rtl::OUString& rsCommand) const
+{
+    util::URL aURL;
+    aURL.Complete = rsCommand;
+
+    const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory());
+    const Reference<util::XURLTransformer> xParser (
+        aComponentContext.createComponent("com.sun.star.util.URLTransformer"),
+            UNO_QUERY_THROW);
+    xParser->parseStrict(aURL);
+
+    return aURL;
+}
+
+
+
+
+Reference<frame::XDispatch> SidebarController::GetDispatch (const util::URL& rURL) const
+{
+    Reference<frame::XDispatchProvider> xProvider (mxFrame, UNO_QUERY_THROW);
+    Reference<frame::XDispatch> xDispatch (xProvider->queryDispatch(rURL, OUString(), 0));
+    return xDispatch;
+}
+
+
+
+
 ::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu (
     const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
     const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const
@@ -819,35 +958,54 @@ IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu)
 
 
 
-void SidebarController::CloseDeck (void)
+void SidebarController::RequestCloseDeck (void)
 {
-    if ( ! mbIsDeckClosed)
-    {
-        mbIsDeckClosed = true;
-        if ( ! mpParentWindow->IsFloatingMode())
-            mnSavedSidebarWidth = SetChildWindowWidth(TabBar::GetDefaultWidth());
-        mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
+    mbIsDeckRequestedOpen = false;
+    UpdateDeckOpenState();
+}
 
-        if (mpCurrentDeck)
-            mpCurrentDeck->Hide();
 
-        NotifyResize();
-    }
+
+
+void SidebarController::RequestOpenDeck (void)
+{
+    mbIsDeckRequestedOpen = true;
+    UpdateDeckOpenState();
 }
 
 
 
 
-void SidebarController::OpenDeck (void)
+void SidebarController::UpdateDeckOpenState (void)
 {
-    if (mbIsDeckClosed)
-    {
-        mbIsDeckClosed = false;
-        SetChildWindowWidth(mnSavedSidebarWidth);
+    if ( ! mbIsDeckRequestedOpen)
+        // No state requested.
+        return;
 
-        if (mpCurrentDeck)
-            mpCurrentDeck->Show();
+    // Update (change) the open state when it either has not yet been initialized
+    // or when its value differs from the requested state.
+    if ( ! mbIsDeckOpen
+        || mbIsDeckOpen.get() != mbIsDeckRequestedOpen.get())
+    {
+        if (mbIsDeckRequestedOpen.get())
+        {
+            if (mnSavedSidebarWidth <= TabBar::GetDefaultWidth())
+                SetChildWindowWidth(SidebarChildWindow::GetDefaultWidth(mpParentWindow));
+            else
+                SetChildWindowWidth(mnSavedSidebarWidth);
+        }
+        else
+        {
+            if ( ! mpParentWindow->IsFloatingMode())
+                mnSavedSidebarWidth = SetChildWindowWidth(TabBar::GetDefaultWidth());
+            if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth())
+                mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
+            mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
+        }
 
+        mbIsDeckOpen = mbIsDeckRequestedOpen.get();
+        if (mbIsDeckOpen.get() && mpCurrentDeck)
+            mpCurrentDeck->Show(mbIsDeckOpen.get());
         NotifyResize();
     }
 }
@@ -863,13 +1021,11 @@ FocusManager& SidebarController::GetFocusManager (void)
 
 
 
-bool SidebarController::CanModifyChildWindowWidth (void) const
+bool SidebarController::CanModifyChildWindowWidth (void)
 {
-    SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+    SfxSplitWindow* pSplitWindow = GetSplitWindow();
     if (pSplitWindow == NULL)
-    {
-        return 0;
-    }
+        return false;
 
     sal_uInt16 nRow (0xffff);
     sal_uInt16 nColumn (0xffff);
@@ -877,7 +1033,7 @@ bool SidebarController::CanModifyChildWindowWidth (void) const
 
     sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn));
 
-    return nRowCount == 1;
+    return nRowCount==1;
 }
 
 
@@ -885,7 +1041,7 @@ bool SidebarController::CanModifyChildWindowWidth (void) const
 
 sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
 {
-    SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+    SfxSplitWindow* pSplitWindow = GetSplitWindow();
     if (pSplitWindow == NULL)
         return 0;
 
@@ -903,6 +1059,7 @@ sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
         Size(nNewWidth, aWindowSize.Height()),
         nColumn,
         nRow);
+    static_cast<SplitWindow*>(pSplitWindow)->Split();
 
     return static_cast<sal_Int32>(nColumnWidth);
 }
@@ -912,23 +1069,70 @@ sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
 
 void SidebarController::RestrictWidth (void)
 {
-    SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+    SfxSplitWindow* pSplitWindow = GetSplitWindow();
     if (pSplitWindow != NULL)
     {
         const sal_uInt16 nId (pSplitWindow->GetItemId(mpParentWindow));
         const sal_uInt16 nSetId (pSplitWindow->GetSet(nId));
-        // Minimum width is always that of the tabbar.
-        const sal_Int32 nMinimumWidth (TabBar::GetDefaultWidth());
-        // Maximum width depends on whether the deck is open or closed.
-        const sal_Int32 nMaximumWidth (
-            mbIsDeckClosed
-                ? TabBar::GetDefaultWidth()
-                : 400);
         pSplitWindow->SetItemSizeRange(
             nSetId,
-            Range(nMinimumWidth, nMaximumWidth));
-        if (nMinimumWidth == nMaximumWidth)
-            pSplitWindow->SetItemSize(nSetId, nMinimumWidth);
+            Range(TabBar::GetDefaultWidth(), gnMaximumSidebarWidth));
+    }
+}
+
+
+
+
+SfxSplitWindow* SidebarController::GetSplitWindow (void)
+{
+    if (mpSplitWindow == NULL)
+    {
+        if (mpParentWindow != NULL)
+        {
+            mpSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+            if (mpSplitWindow != NULL)
+                mpSplitWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
+        }
+    }
+
+    return mpSplitWindow;
+}
+
+
+
+
+void SidebarController::UpdateCloseIndicator (const bool bCloseAfterDrag)
+{
+    if (mpParentWindow == NULL)
+        return;
+
+    if (bCloseAfterDrag)
+    {
+        // Make sure that the indicator exists.
+        if ( ! mpCloseIndicator)
+        {
+            mpCloseIndicator.reset(new FixedImage(mpParentWindow));
+            FixedImage* pFixedImage = static_cast<FixedImage*>(mpCloseIndicator.get());
+            const Image aImage (Theme::GetImage(Theme::Image_CloseIndicator));
+            pFixedImage->SetImage(aImage);
+            pFixedImage->SetSizePixel(aImage.GetSizePixel());
+            pFixedImage->SetBackground(Theme::GetWallpaper(Theme::Paint_DeckBackground));
+        }
+
+        // Place and show the indicator.
+        const Size aWindowSize (mpParentWindow->GetSizePixel());
+        const Size aImageSize (mpCloseIndicator->GetSizePixel());
+        mpCloseIndicator->SetPosPixel(
+            Point(
+                aWindowSize.Width() - TabBar::GetDefaultWidth() - aImageSize.Width(),
+                (aWindowSize.Height() - aImageSize.Height())/2));
+        mpCloseIndicator->Show();
+    }
+    else
+    {
+        // Hide but don't delete the indicator.
+        if (mpCloseIndicator)
+            mpCloseIndicator->Hide();
     }
 }
 
diff --git a/sfx2/source/sidebar/SidebarController.hxx b/sfx2/source/sidebar/SidebarController.hxx
index 2d27736..0aa0883 100644
--- a/sfx2/source/sidebar/SidebarController.hxx
+++ b/sfx2/source/sidebar/SidebarController.hxx
@@ -29,12 +29,14 @@
 
 #include <com/sun/star/awt/XWindowPeer.hpp>
 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
 #include <com/sun/star/ui/XContextChangeEventListener.hpp>
 #include <com/sun/star/ui/XUIElement.hpp>
 #include <com/sun/star/ui/XSidebar.hpp>
 
 #include <boost/noncopyable.hpp>
-#include <cppuhelper/compbase3.hxx>
+#include <boost/optional.hpp>
+#include <cppuhelper/compbase4.hxx>
 #include <cppuhelper/basemutex.hxx>
 
 namespace css = ::com::sun::star;
@@ -43,13 +45,17 @@ namespace cssu = ::com::sun::star::uno;
 
 namespace
 {
-    typedef ::cppu::WeakComponentImplHelper3 <
+    typedef ::cppu::WeakComponentImplHelper4 <
         css::ui::XContextChangeEventListener,
         css::beans::XPropertyChangeListener,
-        css::ui::XSidebar
+        css::ui::XSidebar,
+        css::frame::XStatusListener
         > SidebarControllerInterfaceBase;
 }
 
+class SfxSplitWindow;
+class FixedBitmap;
+
 namespace sfx2 { namespace sidebar {
 
 class ContentPanelDescriptor;
@@ -82,6 +88,10 @@ public:
     virtual void SAL_CALL propertyChange (const css::beans::PropertyChangeEvent& rEvent)
         throw(cssu::RuntimeException);
 
+    // frame::XStatusListener
+    virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent)
+        throw(cssu::RuntimeException);
+
     // ui::XSidebar
     virtual void SAL_CALL requestLayout (void)
         throw(cssu::RuntimeException);
@@ -90,14 +100,16 @@ public:
 
     void SwitchToDeck (
         const ::rtl::OUString& rsDeckId);
+    void OpenThenSwitchToDeck (
+        const ::rtl::OUString& rsDeckId);
 
     /** Show only the tab bar, not the deck.
     */
-    void CloseDeck (void);
+    void RequestCloseDeck (void);
 
     /** Open the deck area and restore the parent window to its old width.
     */
-    void OpenDeck (void);
+    void RequestOpenDeck (void);
 
     FocusManager& GetFocusManager (void);
 
@@ -112,12 +124,36 @@ private:
     ::rtl::OUString msCurrentDeckTitle;
     AsynchronousCall maPropertyChangeForwarder;
     AsynchronousCall maContextChangeUpdate;
-    bool mbIsDeckClosed;
+
+    /** Two flags control whether the deck is displayed or if only the
+        tab bar remains visible.
+        The mbIsDeckOpen flag stores the current state while
+        mbIsDeckRequestedOpen stores how this state should be.  User
+        actions like clicking on the deck closer affect the
+        mbIsDeckRequestedOpen.  Normally both flags have the same
+        value.  A document being read-only can prevent the deck from opening.
+    */
+    ::boost::optional<bool> mbIsDeckRequestedOpen;
+    ::boost::optional<bool> mbIsDeckOpen;
+    bool mbCanDeckBeOpened;
+
     /** Before the deck is closed the sidebar width is saved into this variable,
         so that it can be restored when the deck is reopended.
     */
     sal_Int32 mnSavedSidebarWidth;
     FocusManager maFocusManager;
+    cssu::Reference<css::frame::XDispatch> mxReadOnlyModeDispatch;
+    bool mbIsDocumentReadOnly;
+    SfxSplitWindow* mpSplitWindow;
+    /** When the user moves the splitter then we remember the
+        width at that time.
+    */
+    sal_Int32 mnWidthOnSplitterButtonDown;
+    /** Control that is temporarily used as replacement for the deck
+        to indicate that when the current mouse drag operation ends, the
+        sidebar will only show the tab bar.
+    */
+    ::boost::scoped_ptr<Window> mpCloseIndicator;
 
     DECL_LINK(WindowEventHandler, VclWindowEvent*);
     /** Make maRequestedContext the current context.
@@ -141,6 +177,8 @@ private:
         const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
         const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const;
     void ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) const;
+    css::util::URL GetURL (const ::rtl::OUString& rsCommand) const;
+    cssu::Reference<css::frame::XDispatch> GetDispatch (const css::util::URL& rURL) const;
     ::boost::shared_ptr<PopupMenu> CreatePopupMenu (
         const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
         const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const;
@@ -151,21 +189,25 @@ private:
         That is only possible if there is no other docking window docked above or below the sidebar.
         Return whether the width of the child window can be modified.
     */
-    bool CanModifyChildWindowWidth (void) const;
+    bool CanModifyChildWindowWidth (void);
 
     /** Set the child window container to a new width.
         Return the old width.
     */
     sal_Int32 SetChildWindowWidth (const sal_Int32 nNewWidth);
 
-    void RestrictWidth (void);
-
     /** Update the icons displayed in the title bars of the deck and
         the panels.  This is called once when a deck is created and
         every time when a data change event is processed.
     */
     void UpdateTitleBarIcons (void);
 
+    void UpdateDeckOpenState (void);
+    void RestrictWidth (void);
+    SfxSplitWindow* GetSplitWindow (void);
+    void ProcessNewWidth (const sal_Int32 nNewWidth);
+    void UpdateCloseIndicator (const bool bIsIndicatorVisible);
+
     virtual void SAL_CALL disposing (void);
 };
 
diff --git a/sfx2/source/sidebar/SidebarDockingWindow.cxx b/sfx2/source/sidebar/SidebarDockingWindow.cxx
index ccfdbaa..1e01bb7 100644
--- a/sfx2/source/sidebar/SidebarDockingWindow.cxx
+++ b/sfx2/source/sidebar/SidebarDockingWindow.cxx
@@ -33,9 +33,9 @@ namespace sfx2 { namespace sidebar {
 SidebarDockingWindow::SidebarDockingWindow(
     SfxBindings* pSfxBindings,
     SidebarChildWindow& rChildWindow,
-    Window* pParent,
+    Window* pParentWindow,
     WinBits nBits)
-    : SfxDockingWindow(pSfxBindings, &rChildWindow, pParent, nBits),
+    : SfxDockingWindow(pSfxBindings, &rChildWindow, pParentWindow, nBits),
       mpSidebarController()
 {
     // Get the XFrame from the bindings.
@@ -117,7 +117,7 @@ sal_Bool SidebarDockingWindow::Close (void)
     {
         // Do not close the floating window.
         // Dock it and close just the deck instead.
-        mpSidebarController->CloseDeck();
+        mpSidebarController->RequestCloseDeck();
         SetFloatingMode(sal_False);
         mpSidebarController->NotifyResize();
         return sal_False;
diff --git a/sfx2/source/sidebar/TabBar.cxx b/sfx2/source/sidebar/TabBar.cxx
index c30953b..feebb14 100644
--- a/sfx2/source/sidebar/TabBar.cxx
+++ b/sfx2/source/sidebar/TabBar.cxx
@@ -101,7 +101,7 @@ sal_Int32 TabBar::GetDefaultWidth (void)
 
 
 void TabBar::SetDecks (
-    const ResourceManager::IdContainer& rDeckIds)
+    const ResourceManager::DeckContextDescriptorContainer& rDecks)
 {
     // Remove the current buttons.
     {
@@ -115,15 +115,15 @@ void TabBar::SetDecks (
         maItems.clear();
     }
 
-    maItems.resize(rDeckIds.size());
+    maItems.resize(rDecks.size());
     sal_Int32 nIndex (0);
-    for (ResourceManager::IdContainer::const_iterator
-             iDeckId(rDeckIds.begin()),
-             iEnd(rDeckIds.end());
-         iDeckId!=iEnd;
-         ++iDeckId)
+    for (ResourceManager::DeckContextDescriptorContainer::const_iterator
+             iDeck(rDecks.begin()),
+             iEnd(rDecks.end());
+         iDeck!=iEnd;
+         ++iDeck)
     {
-        const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(*iDeckId);
+        const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(iDeck->msId);
         if (pDescriptor == NULL)
         {
             OSL_ASSERT(pDescriptor!=NULL);
@@ -137,6 +137,8 @@ void TabBar::SetDecks (
         rItem.maDeckActivationFunctor = maDeckActivationFunctor;
         rItem.mbIsHiddenByDefault = false;
         rItem.mbIsHidden = ! pDescriptor->mbIsEnabled;
+
+        rItem.mpButton->Enable(iDeck->mbIsEnabled);
     }
 
     UpdateButtonIcons();
@@ -218,16 +220,24 @@ void TabBar::Layout (void)
 
 void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId)
 {
-    for (ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
+    Item* pItem = GetItemForId(rsDeckId);
+    if (pItem != NULL)
+        pItem->mpButton->Check();
+}
+
+
+
+
+TabBar::Item* TabBar::GetItemForId (const ::rtl::OUString& rsDeckId)
+{
+    for (ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
          iItem!=iEnd;
          ++iItem)
     {
         if (iItem->msDeckId.equals(rsDeckId))
-        {
-            iItem->mpButton->Check();
-            break;
-        }
+            return &*iItem;
     }
+    return NULL;
 }
 
 
diff --git a/sfx2/source/sidebar/TabBar.hxx b/sfx2/source/sidebar/TabBar.hxx
index 50ea6f3..2f158cb 100644
--- a/sfx2/source/sidebar/TabBar.hxx
+++ b/sfx2/source/sidebar/TabBar.hxx
@@ -70,7 +70,7 @@ public:
     static sal_Int32 GetDefaultWidth (void);
 
     void SetDecks (
-        const ResourceManager::IdContainer& rDeckIds);
+        const ResourceManager::DeckContextDescriptorContainer& rDecks);
     void HighlightDeck (const ::rtl::OUString& rsDeckId);
     void AddPopupMenuEntries (
         PopupMenu& rMenu,
@@ -104,6 +104,7 @@ private:
     PopupMenuProvider maPopupMenuProvider;
 
     RadioButton* CreateTabItem (const DeckDescriptor& rDeckDescriptor);
+    Item* GetItemForId (const ::rtl::OUString& rsId);
     Image GetItemImage (const DeckDescriptor& rDeskDescriptor) const;
     void Layout (void);
     void UpdateButtonIcons (void);
diff --git a/sfx2/source/sidebar/TabItem.cxx b/sfx2/source/sidebar/TabItem.cxx
index 059fabd..8bc0fd9 100644
--- a/sfx2/source/sidebar/TabItem.cxx
+++ b/sfx2/source/sidebar/TabItem.cxx
@@ -55,7 +55,6 @@ TabItem::~TabItem (void)
 
 void TabItem::Paint (const Rectangle& rUpdateArea)
 {
-    OSL_TRACE("TabItem::Paint");
     switch(mePaintType)
     {
         case PT_Theme:
@@ -81,12 +80,12 @@ void TabItem::Paint (const Rectangle& rUpdateArea)
                 (GetSizePixel().Height() - aIconSize.Height())/2);
             DrawImage(
                 aIconLocation,
-                aIcon);
+                aIcon,
+                IsEnabled() ? 0 : IMAGE_DRAW_DISABLE);
             break;
         }
         case PT_Native:
             Button::Paint(rUpdateArea);
-            //            DrawImage(maIconPosition, maIcon);
             break;
     }
 }
diff --git a/sfx2/source/sidebar/Theme.cxx b/sfx2/source/sidebar/Theme.cxx
index b7ef8b5..81d9517 100644
--- a/sfx2/source/sidebar/Theme.cxx
+++ b/sfx2/source/sidebar/Theme.cxx
@@ -362,6 +362,12 @@ void Theme::UpdateTheme (void)
             maPropertyIdToNameMap[Image_Closer],
             Any(A2S("private:graphicrepository/sfx2/res/closedoc.png")));
         setPropertyValue(
+            maPropertyIdToNameMap[Image_CloseIndicator],
+            Any(
+                mbIsHighContrastMode
+                    ? A2S("private:graphicrepository/res/commandimagelist/lch_decrementlevel.png")
+                    : A2S("private:graphicrepository/res/commandimagelist/lc_decrementlevel.png")));
+        setPropertyValue(
             maPropertyIdToNameMap[Image_ToolBoxItemSeparator],
             Any(
                 A2S("private:graphicrepository/sfx2/res/separator.png")));
@@ -778,6 +784,7 @@ void Theme::SetupPropertyMaps (void)
     AddEntry(Image_PanelMenu);
     AddEntry(Image_ToolBoxItemSeparator);
     AddEntry(Image_Closer);
+    AddEntry(Image_CloseIndicator);
 
     AddEntry(Color_DeckTitleFont);
     AddEntry(Color_PanelTitleFont);
@@ -847,6 +854,7 @@ Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem)
         case Image_PanelMenu:
         case Image_ToolBoxItemSeparator:
         case Image_Closer:
+        case Image_CloseIndicator:
             return PT_Image;
 
         case Color_DeckTitleFont:


More information about the Libreoffice-commits mailing list