summaryrefslogtreecommitdiff
path: root/sfx2/source/sidebar
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/sidebar')
-rw-r--r--sfx2/source/sidebar/AsynchronousCall.cxx87
-rw-r--r--sfx2/source/sidebar/AsynchronousCall.hxx51
-rw-r--r--sfx2/source/sidebar/Context.cxx116
-rw-r--r--sfx2/source/sidebar/Context.hxx65
-rw-r--r--sfx2/source/sidebar/ContextChangeBroadcaster.cxx134
-rw-r--r--sfx2/source/sidebar/ContextList.cxx100
-rw-r--r--sfx2/source/sidebar/ContextList.hxx69
-rw-r--r--sfx2/source/sidebar/ContextMatcher.cxx136
-rw-r--r--sfx2/source/sidebar/ContextMatcher.hxx71
-rw-r--r--sfx2/source/sidebar/ControlFactory.cxx82
-rw-r--r--sfx2/source/sidebar/ControllerItem.cxx54
-rw-r--r--sfx2/source/sidebar/CustomImageRadioButton.cxx74
-rw-r--r--sfx2/source/sidebar/CustomImageRadioButton.hxx45
-rw-r--r--sfx2/source/sidebar/Deck.cxx384
-rw-r--r--sfx2/source/sidebar/Deck.hxx101
-rw-r--r--sfx2/source/sidebar/DeckConfiguration.cxx51
-rw-r--r--sfx2/source/sidebar/DeckConfiguration.hxx45
-rw-r--r--sfx2/source/sidebar/DeckDescriptor.cxx57
-rw-r--r--sfx2/source/sidebar/DeckDescriptor.hxx49
-rw-r--r--sfx2/source/sidebar/DeckLayouter.cxx511
-rw-r--r--sfx2/source/sidebar/DeckLayouter.hxx119
-rw-r--r--sfx2/source/sidebar/DeckTitleBar.cxx143
-rw-r--r--sfx2/source/sidebar/DeckTitleBar.hxx57
-rw-r--r--sfx2/source/sidebar/DrawHelper.cxx244
-rw-r--r--sfx2/source/sidebar/DrawHelper.hxx74
-rw-r--r--sfx2/source/sidebar/EnumContext.cxx326
-rw-r--r--sfx2/source/sidebar/FocusManager.cxx559
-rw-r--r--sfx2/source/sidebar/FocusManager.hxx108
-rw-r--r--sfx2/source/sidebar/MenuButton.cxx150
-rw-r--r--sfx2/source/sidebar/MenuButton.hxx52
-rw-r--r--sfx2/source/sidebar/Paint.cxx136
-rw-r--r--sfx2/source/sidebar/Paint.hxx80
-rw-r--r--sfx2/source/sidebar/Panel.cxx267
-rw-r--r--sfx2/source/sidebar/Panel.hxx86
-rw-r--r--sfx2/source/sidebar/PanelDescriptor.cxx60
-rw-r--r--sfx2/source/sidebar/PanelDescriptor.hxx49
-rw-r--r--sfx2/source/sidebar/PanelTitleBar.cxx185
-rw-r--r--sfx2/source/sidebar/PanelTitleBar.hxx62
-rw-r--r--sfx2/source/sidebar/PopupContainer.cxx50
-rw-r--r--sfx2/source/sidebar/ResourceManager.cxx621
-rw-r--r--sfx2/source/sidebar/ResourceManager.hxx121
-rw-r--r--sfx2/source/sidebar/Sidebar.cxx77
-rw-r--r--sfx2/source/sidebar/Sidebar.hrc53
-rw-r--r--sfx2/source/sidebar/Sidebar.hxx64
-rw-r--r--sfx2/source/sidebar/Sidebar.src158
-rw-r--r--sfx2/source/sidebar/SidebarChildWindow.cxx56
-rw-r--r--sfx2/source/sidebar/SidebarController.cxx927
-rw-r--r--sfx2/source/sidebar/SidebarController.hxx165
-rw-r--r--sfx2/source/sidebar/SidebarDockingWindow.cxx130
-rw-r--r--sfx2/source/sidebar/SidebarDockingWindow.hxx63
-rw-r--r--sfx2/source/sidebar/SidebarPanel.cxx171
-rw-r--r--sfx2/source/sidebar/SidebarPanel.hxx74
-rw-r--r--sfx2/source/sidebar/SidebarPanelBase.cxx251
-rw-r--r--sfx2/source/sidebar/SidebarResource.hxx35
-rw-r--r--sfx2/source/sidebar/SidebarToolBox.cxx153
-rw-r--r--sfx2/source/sidebar/SidebarToolBox.hxx52
-rw-r--r--sfx2/source/sidebar/TabBar.cxx385
-rw-r--r--sfx2/source/sidebar/TabBar.hxx120
-rw-r--r--sfx2/source/sidebar/TabItem.cxx143
-rw-r--r--sfx2/source/sidebar/TabItem.hxx54
-rw-r--r--sfx2/source/sidebar/Theme.cxx1148
-rw-r--r--sfx2/source/sidebar/TitleBar.cxx193
-rw-r--r--sfx2/source/sidebar/TitleBar.hxx72
-rw-r--r--sfx2/source/sidebar/ToolBox.hxx52
-rw-r--r--sfx2/source/sidebar/ToolBoxBackground.cxx148
-rw-r--r--sfx2/source/sidebar/ToolBoxBackground.hxx64
-rw-r--r--sfx2/source/sidebar/Tools.cxx150
-rw-r--r--sfx2/source/sidebar/Tools.hxx59
68 files changed, 10848 insertions, 0 deletions
diff --git a/sfx2/source/sidebar/AsynchronousCall.cxx b/sfx2/source/sidebar/AsynchronousCall.cxx
new file mode 100644
index 000000000000..54f5883622bd
--- /dev/null
+++ b/sfx2/source/sidebar/AsynchronousCall.cxx
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "AsynchronousCall.hxx"
+
+#include <vcl/svapp.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+AsynchronousCall::AsynchronousCall (const Action& rAction)
+ : maAction(rAction),
+ mnCallId(0)
+{
+}
+
+
+
+
+AsynchronousCall::~AsynchronousCall (void)
+{
+ CancelRequest();
+}
+
+
+
+
+void AsynchronousCall::RequestCall (const Action& rAction)
+{
+ CancelRequest();
+ maAction = rAction;
+ RequestCall();
+}
+
+
+
+
+void AsynchronousCall::RequestCall (void)
+{
+ if (mnCallId == 0)
+ {
+ Link aLink (LINK(this, AsynchronousCall, HandleUserCall));
+ mnCallId = Application::PostUserEvent(aLink);
+ }
+}
+
+
+
+
+void AsynchronousCall::CancelRequest (void)
+{
+ if (mnCallId != 0)
+ {
+ Application::RemoveUserEvent(mnCallId);
+ mnCallId = -1;
+ }
+}
+
+
+
+
+IMPL_LINK(AsynchronousCall, HandleUserCall, void*, EMPTYARG )
+{
+ mnCallId = 0;
+ if (maAction)
+ maAction();
+
+ return sal_True;
+}
+
+
+} } // end of namespace sfx2::sidebar
+
diff --git a/sfx2/source/sidebar/AsynchronousCall.hxx b/sfx2/source/sidebar/AsynchronousCall.hxx
new file mode 100644
index 000000000000..a1d0e2a883ef
--- /dev/null
+++ b/sfx2/source/sidebar/AsynchronousCall.hxx
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_ASYNCHRONOUS_CALL_HXX
+#define SFX_SIDEBAR_ASYNCHRONOUS_CALL_HXX
+
+#include <boost/function.hpp>
+#include <tools/solar.h>
+#include <tools/link.hxx>
+
+namespace sfx2 { namespace sidebar {
+
+/** A simple asynchronous call via Application::PostUserCall.
+*/
+class AsynchronousCall
+{
+public:
+ typedef ::boost::function<void(void)> Action;
+
+ AsynchronousCall (const Action& rAction);
+ ~AsynchronousCall (void);
+
+ void RequestCall (const Action& rAction);
+ void RequestCall (void);
+ void CancelRequest (void);
+
+private:
+ Action maAction;
+ sal_uLong mnCallId;
+
+ DECL_LINK(HandleUserCall, void*);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Context.cxx b/sfx2/source/sidebar/Context.cxx
new file mode 100644
index 000000000000..99edf6d82a14
--- /dev/null
+++ b/sfx2/source/sidebar/Context.cxx
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "Context.hxx"
+
+#define AnyApplicationName "any"
+#define AnyContextName "any"
+
+namespace sfx2 { namespace sidebar {
+
+const sal_Int32 Context::NoMatch = 4;
+const sal_Int32 Context::ApplicationWildcardMatch = 1;
+const sal_Int32 Context::ContextWildcardMatch = 2;
+const sal_Int32 Context::OptimalMatch = 0; // Neither application nor context name is "any".
+
+#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
+
+Context::Context (void)
+ : msApplication(A2S(AnyApplicationName)),
+ msContext(A2S(AnyContextName))
+{
+}
+
+
+
+
+Context::Context (
+ const ::rtl::OUString& rsApplication,
+ const ::rtl::OUString& rsContext)
+ : msApplication(rsApplication),
+ msContext(rsContext)
+{
+}
+
+
+
+
+sal_Int32 Context::EvaluateMatch (
+ const Context& rOther) const
+{
+ const bool bApplicationNameIsAny (rOther.msApplication.equalsAscii(AnyApplicationName));
+ if (rOther.msApplication.equals(msApplication) || bApplicationNameIsAny)
+ {
+ // Application name matches.
+ const bool bContextNameIsAny (rOther.msContext.equalsAscii(AnyContextName));
+ if (rOther.msContext.equals(msContext) || bContextNameIsAny)
+ {
+ // Context name matches.
+ return (bApplicationNameIsAny ? ApplicationWildcardMatch : 0)
+ + (bContextNameIsAny ? ContextWildcardMatch : 0);
+ }
+ }
+ return NoMatch;
+}
+
+
+
+
+sal_Int32 Context::EvaluateMatch (const ::std::vector<Context>& rOthers) const
+{
+ sal_Int32 nBestMatch (NoMatch);
+
+ for (::std::vector<Context>::const_iterator
+ iContext(rOthers.begin()),
+ iEnd(rOthers.end());
+ iContext!=iEnd;
+ ++iContext)
+ {
+ const sal_Int32 nMatch (EvaluateMatch(*iContext));
+ if (nMatch < nBestMatch)
+ {
+ if (nMatch == OptimalMatch)
+ {
+ // We will find no better match so stop searching.
+ return OptimalMatch;
+ }
+ nBestMatch = nMatch;
+ }
+ }
+ return nBestMatch;
+}
+
+
+
+
+bool Context::operator== (const Context& rOther) const
+{
+ return msApplication.equals(rOther.msApplication)
+ && msContext.equals(rOther.msContext);
+}
+
+
+
+
+bool Context::operator!= (const Context& rOther) const
+{
+ return ( ! msApplication.equals(rOther.msApplication))
+ || ( ! msContext.equals(rOther.msContext));
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Context.hxx b/sfx2/source/sidebar/Context.hxx
new file mode 100644
index 000000000000..df6fa631e64a
--- /dev/null
+++ b/sfx2/source/sidebar/Context.hxx
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_CONTEXT_HXX
+#define SFX_SIDEBAR_CONTEXT_HXX
+
+#include "rtl/ustring.hxx"
+
+#include <vector>
+
+namespace sfx2 { namespace sidebar {
+
+class Context
+{
+public:
+ ::rtl::OUString msApplication;
+ ::rtl::OUString msContext;
+
+ Context (void);
+ Context (
+ const ::rtl::OUString& rsApplication,
+ const ::rtl::OUString& rsContext);
+
+ /** When two contexts are matched against each other then
+ application or context name may have the wildcard value 'any'.
+ In order to prefer matches without wildcards over matches with
+ wildcards we introduce a integer evaluation for matches.
+ */
+ const static sal_Int32 NoMatch;
+ const static sal_Int32 OptimalMatch;
+ const static sal_Int32 ApplicationWildcardMatch;
+ const static sal_Int32 ContextWildcardMatch;
+
+ /** Return the numeric value that describes how good the match
+ between two contexts is.
+ Smaller values represent better matches.
+ */
+ sal_Int32 EvaluateMatch (const Context& rOther) const;
+
+ /** Return the best match against the given list of contexts.
+ */
+ sal_Int32 EvaluateMatch (const ::std::vector<Context>& rOthers) const;
+
+ bool operator== (const Context& rOther) const;
+ bool operator!= (const Context& rOther) const;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/ContextChangeBroadcaster.cxx b/sfx2/source/sidebar/ContextChangeBroadcaster.cxx
new file mode 100644
index 000000000000..463d1512df9a
--- /dev/null
+++ b/sfx2/source/sidebar/ContextChangeBroadcaster.cxx
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sfx2/sidebar/ContextChangeBroadcaster.hxx"
+#include "sfx2/sidebar/EnumContext.hxx"
+#include <com/sun/star/ui/ContextChangeEventObject.hpp>
+#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
+#include <com/sun/star/frame/XModuleManager.hpp>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
+
+
+using ::rtl::OUString;
+using namespace css;
+using namespace cssu;
+
+namespace sfx2 { namespace sidebar {
+
+
+ContextChangeBroadcaster::ContextChangeBroadcaster (void)
+ : msContextName(),
+ mbIsContextActive(false)
+{
+}
+
+
+
+ContextChangeBroadcaster::~ContextChangeBroadcaster (void)
+{
+}
+
+
+
+
+void ContextChangeBroadcaster::Initialize (const ::rtl::OUString& rsContextName)
+{
+ OSL_ASSERT( ! mbIsContextActive);
+
+ msContextName = rsContextName;
+}
+
+
+
+
+void ContextChangeBroadcaster::Activate (const cssu::Reference<css::frame::XFrame>& rxFrame)
+{
+ if (msContextName.getLength() > 0)
+ BroadcastContextChange(rxFrame, GetModuleName(rxFrame), msContextName);
+}
+
+
+
+
+void ContextChangeBroadcaster::Deactivate (const cssu::Reference<css::frame::XFrame>& rxFrame)
+{
+ if (msContextName.getLength() > 0)
+ {
+ BroadcastContextChange(
+ rxFrame,
+ GetModuleName(rxFrame),
+ EnumContext::GetContextName(EnumContext::Context_Default));
+ }
+}
+
+
+
+
+void ContextChangeBroadcaster::BroadcastContextChange (
+ const cssu::Reference<css::frame::XFrame>& rxFrame,
+ const ::rtl::OUString& rsModuleName,
+ const ::rtl::OUString& rsContextName)
+{
+ if (rsContextName.getLength() == 0)
+ return;
+
+ if ( ! rxFrame.is() || ! rxFrame->getController().is())
+ {
+ // Frame is (probably) being deleted. Broadcasting context
+ // changes is not necessary anymore.
+ return;
+ }
+
+ const css::ui::ContextChangeEventObject aEvent(
+ rxFrame->getController(),
+ rsModuleName,
+ rsContextName);
+
+ cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
+ css::ui::ContextChangeEventMultiplexer::get(
+ ::comphelper::getProcessComponentContext()));
+ if (xMultiplexer.is())
+ xMultiplexer->broadcastContextChangeEvent(aEvent, rxFrame->getController());
+}
+
+
+
+
+OUString ContextChangeBroadcaster::GetModuleName (const cssu::Reference<css::frame::XFrame>& rxFrame)
+{
+ if ( ! rxFrame.is() || ! rxFrame->getController().is())
+ return OUString();
+ OUString sModuleName;
+ try
+ {
+ const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory());
+ const Reference<frame::XModuleManager> xModuleManager (
+ aContext.createComponent("com.sun.star.frame.ModuleManager" ),
+ UNO_QUERY_THROW );
+ return xModuleManager->identify(rxFrame);
+ }
+ catch (const Exception&)
+ {
+ OSL_ENSURE(false, "can not determine module name");
+ }
+ return OUString();
+}
+
+
+
+} } // end of namespace ::sd::sidebar
diff --git a/sfx2/source/sidebar/ContextList.cxx b/sfx2/source/sidebar/ContextList.cxx
new file mode 100644
index 000000000000..aebfdbd1897d
--- /dev/null
+++ b/sfx2/source/sidebar/ContextList.cxx
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "ContextList.hxx"
+#include "Context.hxx"
+
+using ::rtl::OUString;
+
+namespace sfx2 { namespace sidebar {
+
+
+ContextList::ContextList (void)
+ : maEntries()
+{
+}
+
+
+
+
+ContextList::~ContextList (void)
+{
+}
+
+
+
+
+const ContextList::Entry* ContextList::GetMatch (const Context& rContext) const
+{
+ const ::std::vector<Entry>::const_iterator iEntry = FindBestMatch(rContext);
+ if (iEntry != maEntries.end())
+ return &*iEntry;
+ else
+ return NULL;
+}
+
+
+
+
+::std::vector<ContextList::Entry>::const_iterator ContextList::FindBestMatch (const Context& rContext) const
+{
+ sal_Int32 nBestMatch (Context::NoMatch);
+ ::std::vector<Entry>::const_iterator iBestMatch (maEntries.end());
+
+ for (::std::vector<Entry>::const_iterator
+ iEntry(maEntries.begin()),
+ iEnd(maEntries.end());
+ iEntry!=iEnd;
+ ++iEntry)
+ {
+ const sal_Int32 nMatch (rContext.EvaluateMatch(iEntry->maContext));
+ if (nMatch < nBestMatch)
+ {
+ nBestMatch = nMatch;
+ iBestMatch = iEntry;
+ }
+ if (nBestMatch == Context::OptimalMatch)
+ return iEntry;
+ }
+
+ return iBestMatch;
+}
+
+
+
+
+void ContextList::AddContextDescription (
+ const Context& rContext,
+ const bool bIsInitiallyVisible,
+ const OUString& rsMenuCommand)
+{
+ maEntries.push_back(Entry());
+ maEntries.back().maContext = rContext;
+ maEntries.back().mbIsInitiallyVisible = bIsInitiallyVisible;
+ maEntries.back().msMenuCommand = rsMenuCommand;
+}
+
+
+
+
+bool ContextList::IsEmpty (void)
+{
+ return maEntries.empty();
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ContextList.hxx b/sfx2/source/sidebar/ContextList.hxx
new file mode 100644
index 000000000000..f026ff9d3305
--- /dev/null
+++ b/sfx2/source/sidebar/ContextList.hxx
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_CONTEXT_LIST_HXX
+#define SFX_SIDEBAR_CONTEXT_LIST_HXX
+
+#include "Context.hxx"
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#include <vector>
+
+
+namespace sfx2 { namespace sidebar {
+
+
+class ContextList
+{
+public:
+ ContextList (void);
+ ~ContextList (void);
+
+ class Entry
+ {
+ public:
+ Context maContext;
+ bool mbIsInitiallyVisible;
+ ::rtl::OUString msMenuCommand;
+ };
+
+ /** Return <TRUE/> when the given context matches any of the stored contexts.
+ */
+ const Entry* GetMatch (
+ const Context& rContext) const;
+
+ void AddContextDescription (
+ const Context& rContext,
+ const bool bIsInitiallyVisible,
+ const ::rtl::OUString& rsMenuCommand);
+
+ /** Returns <TRUE/> when no call to AddContextDescription() was made before.
+ */
+ bool IsEmpty (void);
+
+
+private:
+ ::std::vector<Entry> maEntries;
+
+ ::std::vector<Entry>::const_iterator FindBestMatch (const Context& rContext) const;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/ContextMatcher.cxx b/sfx2/source/sidebar/ContextMatcher.cxx
new file mode 100644
index 000000000000..9de3567d8da1
--- /dev/null
+++ b/sfx2/source/sidebar/ContextMatcher.cxx
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "precompiled_sfx2.hxx"
+
+#include "ContextMatcher.hxx"
+#include "Context.hxx"
+
+using ::rtl::OUString;
+
+namespace sfx2 { namespace sidebar {
+
+namespace {
+ static const sal_Char* gsAny = "any";
+}
+
+
+
+ContextMatcher::ContextMatcher (void)
+ : maEntries()
+{
+}
+
+
+
+
+ContextMatcher::~ContextMatcher (void)
+{
+}
+
+
+
+
+sal_Int32 ContextMatcher::EvaluateMatch (
+ const Context& rContext) const
+{
+ sal_Int32 nBestMatch (Context::NoMatch);
+
+ for (::std::vector<Entry>::const_iterator
+ iEntry(maEntries.begin()),
+ iEnd(maEntries.end());
+ iEntry!=iEnd;
+ ++iEntry)
+ {
+ const sal_Int32 nMatch (EvaluateMatch(rContext, *iEntry));
+ if (nMatch < nBestMatch)
+ nBestMatch = nMatch;
+ if (nBestMatch == Context::OptimalMatch)
+ break;
+ }
+
+ return nBestMatch;
+}
+
+
+
+
+sal_Int32 ContextMatcher::EvaluateMatch (
+ const Context& rContext,
+ const Entry& rEntry) const
+{
+ sal_Int32 nApplicationMatch (Context::NoMatch);
+ if (rContext.msApplication.equals(rEntry.msApplicationName))
+ nApplicationMatch = 0;
+ else if (rEntry.msApplicationName.equalsAscii(gsAny))
+ nApplicationMatch = Context::ApplicationWildcardMatch;
+ else
+ return Context::NoMatch;
+
+ sal_Int32 nBestContextMatch (Context::NoMatch);
+ for (::std::vector<OUString>::const_iterator
+ iContext(rEntry.maContextNames.begin()),
+ iEnd(rEntry.maContextNames.end());
+ iContext!=iEnd;
+ ++iContext)
+ {
+ sal_Int32 nContextMatch (Context::NoMatch);
+ if (rContext.msContext.equals(*iContext))
+ nContextMatch = 0;
+ else if (iContext->equalsAscii(gsAny))
+ nContextMatch = Context::ContextWildcardMatch;
+ else
+ continue;
+ if (nContextMatch < nBestContextMatch)
+ nBestContextMatch = nContextMatch;
+ }
+
+ if (rEntry.mbIsContextListNegated)
+ nBestContextMatch = Context::NoMatch - nBestContextMatch;
+
+ return nApplicationMatch + nBestContextMatch;
+}
+
+
+
+
+void ContextMatcher::AddMatcher (
+ const ::rtl::OUString& rsApplicationName,
+ const ::std::vector<rtl::OUString>& rContextNames,
+ const bool bIsContextListNegated)
+{
+ maEntries.push_back(Entry());
+ maEntries.back().msApplicationName = rsApplicationName;
+ maEntries.back().maContextNames = rContextNames;
+ maEntries.back().mbIsContextListNegated = bIsContextListNegated;
+}
+
+
+
+
+void ContextMatcher::AddMatcher (
+ const ::rtl::OUString& rsApplicationName,
+ const ::rtl::OUString& rsContextName)
+{
+ maEntries.push_back(Entry());
+ maEntries.back().msApplicationName = rsApplicationName;
+ maEntries.back().maContextNames.push_back(rsContextName);
+ maEntries.back().mbIsContextListNegated = false;
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ContextMatcher.hxx b/sfx2/source/sidebar/ContextMatcher.hxx
new file mode 100644
index 000000000000..f34c078702bf
--- /dev/null
+++ b/sfx2/source/sidebar/ContextMatcher.hxx
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_CONTEXT_MATCHER_HXX
+#define SFX_SIDEBAR_CONTEXT_MATCHER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#include <vector>
+
+
+namespace sfx2 { namespace sidebar {
+
+class Context;
+
+
+/** Data read from the configuration for matching contexts.
+*/
+class ContextMatcher
+{
+public:
+ ContextMatcher (void);
+ ~ContextMatcher (void);
+
+ sal_Int32 EvaluateMatch (
+ const Context& rContext) const;
+
+ void AddMatcher (
+ const ::rtl::OUString& rsApplicationName,
+ const ::std::vector<rtl::OUString>& rContextNames,
+ const bool mbIsContextListNegated);
+ void AddMatcher (
+ const ::rtl::OUString& rsApplicationName,
+ const ::rtl::OUString& rsContextName);
+
+private:
+ class Entry
+ {
+ public:
+ ::rtl::OUString msApplicationName;
+ ::std::vector<rtl::OUString> maContextNames;
+ bool mbIsContextListNegated;
+ };
+ ::std::vector<Entry> maEntries;
+
+ sal_Int32 EvaluateMatch (
+ const Context& rContext,
+ const Entry& rEntry) const;
+
+};
+static bool IsMatchBetterThan (const sal_Int32 nMatchA, const sal_Int32 nMatchB);
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/ControlFactory.cxx b/sfx2/source/sidebar/ControlFactory.cxx
new file mode 100644
index 000000000000..43946e0cd061
--- /dev/null
+++ b/sfx2/source/sidebar/ControlFactory.cxx
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sidebar/ControlFactory.hxx"
+
+#include "MenuButton.hxx"
+#include "TabItem.hxx"
+#include "SidebarToolBox.hxx"
+#include "ToolBoxBackground.hxx"
+#include "CustomImageRadioButton.hxx"
+#include <vcl/toolbox.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+
+CheckBox* ControlFactory::CreateMenuButton (Window* pParentWindow)
+{
+ return new MenuButton(pParentWindow);
+}
+
+
+
+
+ImageRadioButton* ControlFactory::CreateTabItem (Window* pParentWindow)
+{
+ return new TabItem(pParentWindow);
+}
+
+
+
+
+ToolBox* ControlFactory::CreateToolBox (
+ Window* pParentWindow,
+ const ResId& rResId)
+{
+ SidebarToolBox* pToolBox = new SidebarToolBox(pParentWindow, rResId);
+ pToolBox->SetBorderWindow(pParentWindow);
+
+ pToolBox->Invalidate();
+
+ return pToolBox;
+}
+
+
+
+
+Window* ControlFactory::CreateToolBoxBackground (
+ Window* pParentWindow)
+{
+ ToolBoxBackground* pBorderWindow = new ToolBoxBackground(pParentWindow);
+ pBorderWindow->Show();
+ return pBorderWindow;
+}
+
+
+
+
+ImageRadioButton* ControlFactory::CreateCustomImageRadionButton(
+ Window* pParentWindow,
+ const ResId& rResId )
+{
+ return new CustomImageRadioButton(
+ pParentWindow,
+ rResId );
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ControllerItem.cxx b/sfx2/source/sidebar/ControllerItem.cxx
new file mode 100644
index 000000000000..e00241250227
--- /dev/null
+++ b/sfx2/source/sidebar/ControllerItem.cxx
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sidebar/ControllerItem.hxx"
+
+namespace sfx2 { namespace sidebar {
+
+ControllerItem::ControllerItem (
+ const sal_uInt16 nInId,
+ SfxBindings &rBindings,
+ ItemUpdateReceiverInterface& rItemUpdateReceiver)
+ : SfxControllerItem(nInId, rBindings),
+ mrItemUpdateReceiver(rItemUpdateReceiver)
+{
+}
+
+
+
+
+ControllerItem::~ControllerItem (void)
+{
+}
+
+
+
+
+void ControllerItem::StateChanged (
+ sal_uInt16 nSID,
+ SfxItemState eState,
+ const SfxPoolItem* pState)
+{
+ mrItemUpdateReceiver.NotifyItemUpdate(nSID, eState, pState);
+}
+
+ControllerItem::ItemUpdateReceiverInterface::~ItemUpdateReceiverInterface()
+{
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/CustomImageRadioButton.cxx b/sfx2/source/sidebar/CustomImageRadioButton.cxx
new file mode 100644
index 000000000000..adc0eed9cc97
--- /dev/null
+++ b/sfx2/source/sidebar/CustomImageRadioButton.cxx
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "CustomImageRadioButton.hxx"
+
+#include "DrawHelper.hxx"
+#include "Paint.hxx"
+#include "Tools.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+CustomImageRadioButton::CustomImageRadioButton (
+ Window* pParentWindow,
+ const ResId& rResId )
+ : ImageRadioButton( pParentWindow, rResId )
+{
+ SetStyle( GetStyle() | WB_NOPOINTERFOCUS );
+}
+
+
+CustomImageRadioButton::~CustomImageRadioButton (void)
+{
+}
+
+
+void CustomImageRadioButton::Paint (const Rectangle& /*rUpdateArea*/)
+{
+ Rectangle aPaintRect( Rectangle(Point(0,0), GetSizePixel() ) );
+ SetMouseRect( aPaintRect );
+ SetStateRect( aPaintRect );
+
+ const Theme::ThemeItem eBackground =
+ IsMouseOver()
+ ? Theme::Paint_TabItemBackgroundHighlight
+ : Theme::Paint_PanelBackground;
+ DrawHelper::DrawRoundedRectangle(
+ *this,
+ aPaintRect,
+ Theme::GetInteger(Theme::Int_ButtonCornerRadius),
+ IsChecked() || IsMouseOver() ? Theme::GetColor(Theme::Color_TabItemBorder) : Color(0xffffffff),
+ Theme::GetPaint( eBackground ) );
+
+ const Image& rIcon = GetModeRadioImage();
+ const Size aIconSize (rIcon.GetSizePixel());
+ const Point aIconLocation(
+ (GetSizePixel().Width() - aIconSize.Width())/2,
+ (GetSizePixel().Height() - aIconSize.Height())/2 );
+ DrawImage(
+ aIconLocation,
+ rIcon,
+ IsEnabled() ? 0 : IMAGE_DRAW_DISABLE );
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/CustomImageRadioButton.hxx b/sfx2/source/sidebar/CustomImageRadioButton.hxx
new file mode 100644
index 000000000000..a0e9614610f2
--- /dev/null
+++ b/sfx2/source/sidebar/CustomImageRadioButton.hxx
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_CUSTOM_IMAGE_RADIO_BUTTON_HXX
+#define SFX_SIDEBAR_CUSTOM_IMAGE_RADIO_BUTTON_HXX
+
+#include "vcl/button.hxx"
+
+#include "sfx2/sidebar/Theme.hxx"
+
+namespace sfx2 { namespace sidebar {
+
+/** A custom image radion button with more control over used colors for sidebar
+*/
+class CustomImageRadioButton
+ : public ImageRadioButton
+{
+public:
+ CustomImageRadioButton(
+ Window* pParentWindow,
+ const ResId& rResId );
+
+ virtual ~CustomImageRadioButton(void);
+
+ virtual void Paint( const Rectangle& rUpdateArea );
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Deck.cxx b/sfx2/source/sidebar/Deck.cxx
new file mode 100644
index 000000000000..a1f32ebed59b
--- /dev/null
+++ b/sfx2/source/sidebar/Deck.cxx
@@ -0,0 +1,384 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Deck.hxx"
+#include "DeckDescriptor.hxx"
+#include "DeckLayouter.hxx"
+#include "DrawHelper.hxx"
+#include "DeckTitleBar.hxx"
+#include "Paint.hxx"
+#include "Panel.hxx"
+#include "ToolBoxBackground.hxx"
+#include "Tools.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+#include <vcl/dockwin.hxx>
+#include <vcl/scrbar.hxx>
+#include <tools/svborder.hxx>
+
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+namespace {
+ static const sal_Int32 MinimalPanelHeight (25);
+}
+
+
+Deck::Deck (
+ const DeckDescriptor& rDeckDescriptor,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rCloserAction)
+ : Window(pParentWindow, 0),
+ msId(rDeckDescriptor.msId),
+ maIcon(),
+ msIconURL(rDeckDescriptor.msIconURL),
+ msHighContrastIconURL(rDeckDescriptor.msHighContrastIconURL),
+ maPanels(),
+ mpTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, this, rCloserAction)),
+ mpScrollClipWindow(new Window(this)),
+ mpScrollContainer(new ScrollContainerWindow(mpScrollClipWindow.get())),
+ mpFiller(new Window(this)),
+ mpVerticalScrollBar(new ScrollBar(this))
+{
+ SetBackground(Wallpaper());
+
+ mpScrollClipWindow->SetBackground(Wallpaper());
+ mpScrollClipWindow->Show();
+
+ mpScrollContainer->SetStyle(mpScrollContainer->GetStyle() | WB_DIALOGCONTROL);
+ mpScrollContainer->SetBackground(Wallpaper());
+ mpScrollContainer->Show();
+
+ mpVerticalScrollBar->SetScrollHdl(LINK(this, Deck, HandleVerticalScrollBarChange));
+
+#ifdef DEBUG
+ SetText(A2S("Deck"));
+ mpScrollClipWindow->SetText(A2S("ScrollClipWindow"));
+ mpFiller->SetText(A2S("Filler"));
+ mpVerticalScrollBar->SetText(A2S("VerticalScrollBar"));
+#endif
+}
+
+
+
+
+Deck::~Deck (void)
+{
+ Dispose();
+
+ // We have to explicitly trigger the destruction of panels.
+ // Otherwise that is done by one of our base class destructors
+ // without updating maPanels.
+ maPanels.clear();
+}
+
+
+
+
+void Deck::Dispose (void)
+{
+ SharedPanelContainer aPanels;
+ aPanels.swap(maPanels);
+ for (SharedPanelContainer::iterator
+ iPanel(aPanels.begin()),
+ iEnd(aPanels.end());
+ iPanel!=iEnd;
+ ++iPanel)
+ {
+ if (*iPanel)
+ {
+ (*iPanel)->Dispose();
+ OSL_ASSERT(iPanel->unique());
+ iPanel->reset();
+ }
+ }
+
+ mpTitleBar.reset();
+ mpFiller.reset();
+ mpVerticalScrollBar.reset();
+}
+
+
+
+
+const ::rtl::OUString& Deck::GetId (void) const
+{
+ return msId;
+}
+
+
+
+
+DeckTitleBar* Deck::GetTitleBar (void) const
+{
+ return mpTitleBar.get();
+}
+
+
+
+
+Rectangle Deck::GetContentArea (void) const
+{
+ const Size aWindowSize (GetSizePixel());
+ const int nBorderSize (Theme::GetInteger(Theme::Int_DeckBorderSize));
+
+ return Rectangle(
+ Theme::GetInteger(Theme::Int_DeckLeftPadding) + nBorderSize,
+ Theme::GetInteger(Theme::Int_DeckTopPadding) + nBorderSize,
+ aWindowSize.Width() - 1 - Theme::GetInteger(Theme::Int_DeckRightPadding) - nBorderSize,
+ aWindowSize.Height() - 1 - Theme::GetInteger(Theme::Int_DeckBottomPadding) - nBorderSize);
+}
+
+
+
+
+::rtl::OUString Deck::GetIconURL (const bool bIsHighContrastModeActive) const
+{
+ if (bIsHighContrastModeActive)
+ return msHighContrastIconURL;
+ else
+ return msIconURL;
+}
+
+
+
+
+void Deck::Paint (const Rectangle& rUpdateArea)
+{
+ (void) rUpdateArea;
+
+ const Size aWindowSize (GetSizePixel());
+ const SvBorder aPadding (
+ Theme::GetInteger(Theme::Int_DeckLeftPadding),
+ Theme::GetInteger(Theme::Int_DeckTopPadding),
+ Theme::GetInteger(Theme::Int_DeckRightPadding),
+ Theme::GetInteger(Theme::Int_DeckBottomPadding));
+
+ // Paint deck background outside the border.
+ Rectangle aBox(
+ 0,
+ 0,
+ aWindowSize.Width() - 1,
+ aWindowSize.Height() - 1);
+ DrawHelper::DrawBorder(
+ *this,
+ aBox,
+ aPadding,
+ Theme::GetPaint(Theme::Paint_DeckBackground),
+ Theme::GetPaint(Theme::Paint_DeckBackground));
+
+ // Paint the border.
+ const int nBorderSize (Theme::GetInteger(Theme::Int_DeckBorderSize));
+ aBox.Left() += aPadding.Left();
+ aBox.Top() += aPadding.Top();
+ aBox.Right() -= aPadding.Right();
+ aBox.Bottom() -= aPadding.Bottom();
+ const sfx2::sidebar::Paint& rHorizontalBorderPaint (Theme::GetPaint(Theme::Paint_HorizontalBorder));
+ DrawHelper::DrawBorder(
+ *this,
+ aBox,
+ SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize),
+ rHorizontalBorderPaint,
+ Theme::GetPaint(Theme::Paint_VerticalBorder));
+}
+
+
+
+
+void Deck::DataChanged (const DataChangedEvent& rEvent)
+{
+ (void)rEvent;
+ RequestLayout();
+}
+
+
+
+
+void Deck::SetPanels (const SharedPanelContainer& rPanels)
+{
+ maPanels = rPanels;
+
+ RequestLayout();
+}
+
+
+
+
+const SharedPanelContainer& Deck::GetPanels (void) const
+{
+ return maPanels;
+}
+
+
+
+
+void Deck::RequestLayout (void)
+{
+ // PrintWindowTree();
+
+ DeckLayouter::LayoutDeck(
+ GetContentArea(),
+ maPanels,
+ *GetTitleBar(),
+ *mpScrollClipWindow,
+ *mpScrollContainer,
+ *mpFiller,
+ *mpVerticalScrollBar);
+
+ Invalidate();
+}
+
+
+
+
+::Window* Deck::GetPanelParentWindow (void)
+{
+ return mpScrollContainer.get();
+}
+
+
+
+
+const char* GetWindowClassification (const Window* pWindow)
+{
+ const String& rsName (pWindow->GetText());
+ if (rsName.Len() > 0)
+ {
+ return ::rtl::OUStringToOString(rsName, RTL_TEXTENCODING_ASCII_US).getStr();
+ }
+ else
+ {
+ static char msWindow[] = "window";
+ return msWindow;
+ }
+}
+
+
+void Deck::PrintWindowSubTree (Window* pRoot, int nIndentation)
+{
+ static const char* sIndentation = " ";
+ const Point aLocation (pRoot->GetPosPixel());
+ const Size aSize (pRoot->GetSizePixel());
+ const char* sClassification = GetWindowClassification(pRoot);
+ const char* sVisible = pRoot->IsVisible() ? "visible" : "hidden";
+ OSL_TRACE("%s%x %s %s +%d+%d x%dx%d",
+ sIndentation+strlen(sIndentation)-nIndentation*4,
+ pRoot,
+ sClassification,
+ sVisible,
+ aLocation.X(),aLocation.Y(),
+ aSize.Width(),aSize.Height());
+
+ const sal_uInt16 nChildCount (pRoot->GetChildCount());
+ for (sal_uInt16 nIndex=0; nIndex<nChildCount; ++nIndex)
+ PrintWindowSubTree(pRoot->GetChild(nIndex), nIndentation+1);
+}
+
+
+
+
+void Deck::PrintWindowTree (void)
+{
+ PrintWindowSubTree(this, 0);
+}
+
+
+
+
+void Deck::PrintWindowTree (const ::std::vector<Panel*>& rPanels)
+{
+ (void)rPanels;
+
+ PrintWindowTree();
+}
+
+
+
+
+IMPL_LINK(Deck, HandleVerticalScrollBarChange,void*, EMPTYARG)
+{
+ const sal_Int32 nYOffset (-mpVerticalScrollBar->GetThumbPos());
+ mpScrollContainer->SetPosPixel(
+ Point(
+ mpScrollContainer->GetPosPixel().X(),
+ nYOffset));
+ return sal_True;
+}
+
+
+
+
+//----- Deck::ScrollContainerWindow -------------------------------------------
+
+Deck::ScrollContainerWindow::ScrollContainerWindow (Window* pParentWindow)
+ : Window(pParentWindow),
+ maSeparators()
+{
+#ifdef DEBUG
+ SetText(A2S("ScrollContainerWindow"));
+#endif
+}
+
+
+
+
+Deck::ScrollContainerWindow::~ScrollContainerWindow (void)
+{
+}
+
+
+
+
+void Deck::ScrollContainerWindow::Paint (const Rectangle& rUpdateArea)
+{
+ (void)rUpdateArea;
+
+ // Paint the separators.
+ const sal_Int32 nSeparatorHeight (Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
+ const sal_Int32 nLeft (0);
+ const sal_Int32 nRight (GetSizePixel().Width()-1);
+ const sfx2::sidebar::Paint& rHorizontalBorderPaint (Theme::GetPaint(Theme::Paint_HorizontalBorder));
+ for (::std::vector<sal_Int32>::const_iterator iY(maSeparators.begin()), iEnd(maSeparators.end());
+ iY!=iEnd;
+ ++iY)
+ {
+ DrawHelper::DrawHorizontalLine(
+ *this,
+ nLeft,
+ nRight,
+ *iY,
+ nSeparatorHeight,
+ rHorizontalBorderPaint);
+ }
+}
+
+
+
+
+void Deck::ScrollContainerWindow::SetSeparators (const ::std::vector<sal_Int32>& rSeparators)
+{
+ maSeparators = rSeparators;
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Deck.hxx b/sfx2/source/sidebar/Deck.hxx
new file mode 100644
index 000000000000..ae1cf196ad42
--- /dev/null
+++ b/sfx2/source/sidebar/Deck.hxx
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DECK_HXX
+#define SFX_SIDEBAR_DECK_HXX
+
+#include "Panel.hxx"
+
+#include <vcl/window.hxx>
+#include <vcl/image.hxx>
+#include <com/sun/star/ui/LayoutSize.hpp>
+
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+
+class ScrollBar;
+
+namespace css = ::com::sun::star;
+
+namespace sfx2 { namespace sidebar {
+
+class DeckDescriptor;
+class DeckTitleBar;
+
+
+/** This is the parent window of the panels.
+ It displays the deck title.
+*/
+class Deck
+ : public Window
+{
+public:
+ Deck (
+ const DeckDescriptor& rDeckDescriptor,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rCloserAction);
+ virtual ~Deck (void);
+
+ void Dispose (void);
+
+ const ::rtl::OUString& GetId (void) const;
+ DeckTitleBar* GetTitleBar (void) const;
+ Rectangle GetContentArea (void) const;
+ ::rtl::OUString GetIconURL (const bool bIsHighContrastModeActive) const;
+ void SetPanels (const SharedPanelContainer& rPanels);
+ const SharedPanelContainer& GetPanels (void) const;
+ void RequestLayout (void);
+ ::Window* GetPanelParentWindow (void);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+
+ void PrintWindowTree (void);
+ void PrintWindowTree (const ::std::vector<Panel*>& rPanels);
+ static void PrintWindowSubTree (Window* pRoot, int nIndentation);
+
+ class ScrollContainerWindow : public Window
+ {
+ public:
+ ScrollContainerWindow (Window* pParentWindow);
+ virtual ~ScrollContainerWindow (void);
+ virtual void Paint (const Rectangle& rUpdateArea);
+ void SetSeparators (const ::std::vector<sal_Int32>& rSeparators);
+ private:
+ ::std::vector<sal_Int32> maSeparators;
+ };
+
+private:
+ const ::rtl::OUString msTitle;
+ const ::rtl::OUString msId;
+ Image maIcon;
+ const ::rtl::OUString msIconURL;
+ const ::rtl::OUString msHighContrastIconURL;
+ SharedPanelContainer maPanels;
+ ::boost::scoped_ptr<DeckTitleBar> mpTitleBar;
+ ::boost::scoped_ptr<Window> mpScrollClipWindow;
+ ::boost::scoped_ptr<ScrollContainerWindow> mpScrollContainer;
+ ::boost::scoped_ptr<Window> mpFiller;
+ ::boost::scoped_ptr<ScrollBar> mpVerticalScrollBar;
+
+ DECL_LINK(HandleVerticalScrollBarChange,void*);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/DeckConfiguration.cxx b/sfx2/source/sidebar/DeckConfiguration.cxx
new file mode 100644
index 000000000000..7e87e04b0897
--- /dev/null
+++ b/sfx2/source/sidebar/DeckConfiguration.cxx
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "precompiled_sfx2.hxx"
+
+#include "DeckConfiguration.hxx"
+#include "Deck.hxx"
+
+
+namespace sfx2 { namespace sidebar {
+
+DeckConfiguration::DeckConfiguration (void)
+ : mpDeck(NULL),
+ maPanels()
+{
+}
+
+
+
+
+void DeckConfiguration::Dispose (void)
+{
+ if (mpDeck != NULL)
+ {
+ mpDeck->Dispose();
+
+ Deck* pDeck = mpDeck;
+ mpDeck = NULL;
+ OSL_TRACE("deleting deck window subtree");
+ pDeck->PrintWindowTree();
+ delete pDeck;
+ }
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DeckConfiguration.hxx b/sfx2/source/sidebar/DeckConfiguration.hxx
new file mode 100644
index 000000000000..8b118cbd6a37
--- /dev/null
+++ b/sfx2/source/sidebar/DeckConfiguration.hxx
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DECK_CONFIGURATION_HXX
+#define SFX_SIDEBAR_DECK_CONFIGURATION_HXX
+
+#include <vector>
+
+namespace sfx2 { namespace sidebar {
+
+class Deck;
+class Panel;
+
+
+class DeckConfiguration
+{
+public:
+ Deck* mpDeck;
+ ::std::vector<Panel*> maPanels;
+
+ DeckConfiguration (void);
+
+ void Dispose (void);
+};
+
+
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/DeckDescriptor.cxx b/sfx2/source/sidebar/DeckDescriptor.cxx
new file mode 100644
index 000000000000..be0c77d088a3
--- /dev/null
+++ b/sfx2/source/sidebar/DeckDescriptor.cxx
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DeckDescriptor.hxx"
+
+namespace sfx2 { namespace sidebar {
+
+DeckDescriptor::DeckDescriptor (void)
+ : msTitle(),
+ msId(),
+ msIconURL(),
+ msHighContrastIconURL(),
+ msHelpURL(),
+ msHelpText(),
+ maContextList(),
+ mnOrderIndex(10000) // Default value as defined in Sidebar.xcs
+{
+}
+
+
+
+
+DeckDescriptor::DeckDescriptor (const DeckDescriptor& rOther)
+ : msTitle(rOther.msTitle),
+ msId(rOther.msId),
+ msIconURL(rOther.msIconURL),
+ msHighContrastIconURL(rOther.msHighContrastIconURL),
+ msHelpURL(rOther.msHelpURL),
+ msHelpText(rOther.msHelpText),
+ maContextList(rOther.maContextList),
+ mnOrderIndex(rOther.mnOrderIndex)
+{
+}
+
+
+
+
+DeckDescriptor::~DeckDescriptor (void)
+{
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DeckDescriptor.hxx b/sfx2/source/sidebar/DeckDescriptor.hxx
new file mode 100644
index 000000000000..2c5a3d481f65
--- /dev/null
+++ b/sfx2/source/sidebar/DeckDescriptor.hxx
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DECK_DESCRIPTOR_HXX
+#define SFX_SIDEBAR_DECK_DESCRIPTOR_HXX
+
+#include "sfx2/sidebar/EnumContext.hxx"
+#include "ContextList.hxx"
+#include <boost/shared_ptr.hpp>
+
+
+namespace sfx2 { namespace sidebar {
+
+class DeckDescriptor
+{
+public:
+ ::rtl::OUString msTitle;
+ ::rtl::OUString msId;
+ ::rtl::OUString msIconURL;
+ ::rtl::OUString msHighContrastIconURL;
+ ::rtl::OUString msHelpURL;
+ ::rtl::OUString msHelpText;
+ ContextList maContextList;
+ bool mbIsEnabled;
+ sal_Int32 mnOrderIndex;
+
+ DeckDescriptor (void);
+ DeckDescriptor (const DeckDescriptor& rOther);
+ ~DeckDescriptor (void);
+};
+typedef ::boost::shared_ptr<DeckDescriptor> SharedDeckDescriptor;
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/DeckLayouter.cxx b/sfx2/source/sidebar/DeckLayouter.cxx
new file mode 100644
index 000000000000..b04f83b633d4
--- /dev/null
+++ b/sfx2/source/sidebar/DeckLayouter.cxx
@@ -0,0 +1,511 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DeckLayouter.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "Panel.hxx"
+#include "TitleBar.hxx"
+#include "Deck.hxx"
+
+#include <vcl/window.hxx>
+#include <vcl/scrbar.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+namespace {
+ static const sal_Int32 MinimalPanelHeight (25);
+}
+
+#define IterateLayoutItems(iterator_name,container) \
+ for(::std::vector<LayoutItem>::iterator \
+ iterator_name(container.begin()), \
+ iEnd(container.end()); \
+ iterator_name!=iEnd; \
+ ++iterator_name)
+
+
+
+void DeckLayouter::LayoutDeck (
+ const Rectangle aContentArea,
+ SharedPanelContainer& rPanels,
+ Window& rDeckTitleBar,
+ Window& rScrollClipWindow,
+ Window& rScrollContainer,
+ Window& rFiller,
+ ScrollBar& rVerticalScrollBar)
+{
+ if (aContentArea.GetWidth()<=0 || aContentArea.GetHeight()<=0)
+ return;
+ Rectangle aBox (PlaceDeckTitle(rDeckTitleBar, aContentArea));
+
+ if ( ! rPanels.empty())
+ {
+ // Prepare the layout item container.
+ ::std::vector<LayoutItem> aLayoutItems;
+ aLayoutItems.resize(rPanels.size());
+ for (sal_Int32 nIndex(0),nCount(rPanels.size()); nIndex<nCount; ++nIndex)
+ {
+ aLayoutItems[nIndex].mpPanel = rPanels[nIndex];
+ aLayoutItems[nIndex].mnPanelIndex = nIndex;
+ }
+ aBox = LayoutPanels(
+ aBox,
+ aLayoutItems,
+ rScrollClipWindow,
+ rScrollContainer,
+ rVerticalScrollBar,
+ false);
+ }
+ UpdateFiller(rFiller, aBox);
+}
+
+
+
+
+Rectangle DeckLayouter::LayoutPanels (
+ const Rectangle aContentArea,
+ ::std::vector<LayoutItem>& rLayoutItems,
+ Window& rScrollClipWindow,
+ Window& rScrollContainer,
+ ScrollBar& rVerticalScrollBar,
+ const bool bShowVerticalScrollBar)
+{
+ Rectangle aBox (PlaceVerticalScrollBar(rVerticalScrollBar, aContentArea, bShowVerticalScrollBar));
+
+ const sal_Int32 nWidth (aBox.GetWidth());
+
+ // Get the requested heights of the panels and the available
+ // height that is left when all panel titles and separators are
+ // taken into account.
+ sal_Int32 nAvailableHeight (aBox.GetHeight());
+ GetRequestedSizes(rLayoutItems, nAvailableHeight, aBox);
+ const sal_Int32 nTotalDecorationHeight (aBox.GetHeight() - nAvailableHeight);
+
+ // Analyze the requested heights.
+ // Determine the height that is available for panel content
+ // and count the different layouts.
+ sal_Int32 nTotalPreferredHeight (0);
+ sal_Int32 nTotalMinimumHeight (0);
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ nTotalMinimumHeight += iItem->maLayoutSize.Minimum;
+ nTotalPreferredHeight += iItem->maLayoutSize.Preferred;
+ }
+
+ if (nTotalMinimumHeight > nAvailableHeight
+ && ! bShowVerticalScrollBar)
+ {
+ // Not enough space, even when all panels are shrunk to their
+ // minimum height.
+ // Show a vertical scrollbar.
+ return LayoutPanels(
+ aContentArea,
+ rLayoutItems,
+ rScrollClipWindow,
+ rScrollContainer,
+ rVerticalScrollBar,
+ true);
+ }
+
+ // We are now in one of three modes.
+ // - The preferred height fits into the available size:
+ // Use the preferred size, distribute the remaining height bei
+ // enlarging panels.
+ // - The total minimum height fits into the available size:
+ // Use the minimum size, distribute the remaining height bei
+ // enlarging panels.
+ // - The total minimum height does not fit into the available
+ // size:
+ // Use the unmodified preferred height for all panels.
+
+ LayoutMode eMode (MinimumOrLarger);
+ if (bShowVerticalScrollBar)
+ eMode = Preferred;
+ else if (nTotalPreferredHeight <= nAvailableHeight)
+ eMode = PreferredOrLarger;
+ else
+ eMode = MinimumOrLarger;
+
+ if (eMode != Preferred)
+ {
+ const sal_Int32 nTotalHeight (eMode==MinimumOrLarger ? nTotalMinimumHeight : nTotalPreferredHeight);
+
+ DistributeHeights(
+ rLayoutItems,
+ nAvailableHeight-nTotalHeight,
+ aBox.GetHeight(),
+ eMode==MinimumOrLarger);
+ }
+
+ // Set position and size of the mpScrollClipWindow to the available
+ // size. Its child, the mpScrollContainer, may have a bigger
+ // height.
+ rScrollClipWindow.setPosSizePixel(aBox.Left(), aBox.Top(), aBox.GetWidth(), aBox.GetHeight());
+
+ const sal_Int32 nContentHeight (
+ eMode==Preferred
+ ? nTotalPreferredHeight + nTotalDecorationHeight
+ : aBox.GetHeight());
+ sal_Int32 nY = rVerticalScrollBar.GetThumbPos();
+ if (nContentHeight-nY < aBox.GetHeight())
+ nY = nContentHeight-aBox.GetHeight();
+ if (nY < 0)
+ nY = 0;
+ rScrollContainer.setPosSizePixel(
+ 0,
+ -nY,
+ nWidth,
+ nContentHeight);
+
+ if (bShowVerticalScrollBar)
+ SetupVerticalScrollBar(rVerticalScrollBar, nContentHeight, aBox.GetHeight());
+
+ const sal_Int32 nUsedHeight (PlacePanels(rLayoutItems, nWidth, eMode, rScrollContainer));
+ aBox.Top() += nUsedHeight;
+ return aBox;
+}
+
+
+
+
+sal_Int32 DeckLayouter::PlacePanels (
+ ::std::vector<LayoutItem>& rLayoutItems,
+ const sal_Int32 nWidth,
+ const LayoutMode eMode,
+ Window& rScrollContainer)
+{
+ ::std::vector<sal_Int32> aSeparators;
+ const sal_Int32 nDeckSeparatorHeight (Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
+ const sal_Int32 nPanelTitleBarHeight (Theme::GetInteger(Theme::Int_PanelTitleBarHeight));
+ sal_Int32 nY (0);
+
+ // Assign heights and places.
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ if (iItem->mpPanel == NULL)
+ continue;
+
+ Panel& rPanel (*iItem->mpPanel);
+
+ // Separator above the panel title bar.
+ aSeparators.push_back(nY);
+ nY += nDeckSeparatorHeight;
+
+ // Place the title bar.
+ TitleBar* pTitleBar = rPanel.GetTitleBar();
+ if (pTitleBar != NULL)
+ {
+ if (iItem->mbShowTitleBar)
+ {
+ pTitleBar->setPosSizePixel(0, nY, nWidth, nPanelTitleBarHeight);
+ pTitleBar->Show();
+ nY += nPanelTitleBarHeight;
+ }
+ else
+ {
+ pTitleBar->Hide();
+ }
+ }
+
+ if (rPanel.IsExpanded())
+ {
+ rPanel.Show();
+
+ // Determine the height of the panel depending on layout
+ // mode and distributed heights.
+ sal_Int32 nPanelHeight (0);
+ switch(eMode)
+ {
+ case MinimumOrLarger:
+ nPanelHeight = iItem->maLayoutSize.Minimum + iItem->mnDistributedHeight;
+ break;
+ case PreferredOrLarger:
+ nPanelHeight = iItem->maLayoutSize.Preferred + iItem->mnDistributedHeight;
+ break;
+ case Preferred:
+ nPanelHeight = iItem->maLayoutSize.Preferred;
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+
+ // Place the panel.
+ rPanel.setPosSizePixel(0, nY, nWidth, nPanelHeight);
+
+ nY += nPanelHeight;
+ }
+ else
+ {
+ rPanel.Hide();
+
+ // Add a separator below the collapsed panel, if it is the
+ // last panel in the deck.
+ if (iItem == rLayoutItems.end()-1)
+ {
+ // Separator below the panel title bar.
+ aSeparators.push_back(nY);
+ nY += nDeckSeparatorHeight;
+ }
+ }
+ }
+
+ Deck::ScrollContainerWindow* pScrollContainerWindow
+ = dynamic_cast<Deck::ScrollContainerWindow*>(&rScrollContainer);
+ if (pScrollContainerWindow != NULL)
+ pScrollContainerWindow->SetSeparators(aSeparators);
+
+ return nY;
+}
+
+
+
+
+void DeckLayouter::GetRequestedSizes (
+ ::std::vector<LayoutItem>& rLayoutItems,
+ sal_Int32& rAvailableHeight,
+ const Rectangle& rContentBox)
+{
+ rAvailableHeight = rContentBox.GetHeight();
+
+ const sal_Int32 nPanelTitleBarHeight (Theme::GetInteger(Theme::Int_PanelTitleBarHeight));
+ const sal_Int32 nDeckSeparatorHeight (Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
+
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ ui::LayoutSize aLayoutSize (ui::LayoutSize(0,0,0));
+ if (iItem->mpPanel != NULL)
+ {
+ if (rLayoutItems.size() == 1
+ && iItem->mpPanel->IsTitleBarOptional())
+ {
+ // There is only one panel and its title bar is
+ // optional => hide it.
+ rAvailableHeight -= nDeckSeparatorHeight;
+ iItem->mbShowTitleBar = false;
+ }
+ else
+ {
+ // Show the title bar and a separator above and below
+ // the title bar.
+ rAvailableHeight -= nPanelTitleBarHeight;
+ rAvailableHeight -= nDeckSeparatorHeight;
+ }
+
+ if (iItem->mpPanel->IsExpanded())
+ {
+ Reference<ui::XSidebarPanel> xPanel (iItem->mpPanel->GetPanelComponent());
+ if (xPanel.is())
+ aLayoutSize = xPanel->getHeightForWidth(rContentBox.GetWidth());
+ else
+ aLayoutSize = ui::LayoutSize(MinimalPanelHeight, 0, -1);
+ }
+ }
+ iItem->maLayoutSize = aLayoutSize;
+ }
+}
+
+
+
+
+void DeckLayouter::DistributeHeights (
+ ::std::vector<LayoutItem>& rLayoutItems,
+ const sal_Int32 nHeightToDistribute,
+ const sal_Int32 nContainerHeight,
+ const bool bMinimumHeightIsBase)
+{
+ if (nHeightToDistribute <= 0)
+ return;
+
+ sal_Int32 nRemainingHeightToDistribute (nHeightToDistribute);
+
+ // Compute the weights as difference between panel base height
+ // (either its minimum or preferred height) and the container height.
+ sal_Int32 nTotalWeight (0);
+ sal_Int32 nNoMaximumCount (0);
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ if (iItem->maLayoutSize.Maximum == 0)
+ continue;
+ if (iItem->maLayoutSize.Maximum < 0)
+ ++nNoMaximumCount;
+
+ const sal_Int32 nBaseHeight (
+ bMinimumHeightIsBase
+ ? iItem->maLayoutSize.Minimum
+ : iItem->maLayoutSize.Preferred);
+ if (nBaseHeight < nContainerHeight)
+ {
+ iItem->mnWeight = nContainerHeight - nBaseHeight;
+ nTotalWeight += iItem->mnWeight;
+ }
+ }
+
+ if (nTotalWeight == 0)
+ return;
+
+ // First pass of height distribution.
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ const sal_Int32 nBaseHeight (
+ bMinimumHeightIsBase
+ ? iItem->maLayoutSize.Minimum
+ : iItem->maLayoutSize.Preferred);
+ sal_Int32 nDistributedHeight (iItem->mnWeight * nHeightToDistribute / nTotalWeight);
+ if (nBaseHeight+nDistributedHeight > iItem->maLayoutSize.Maximum
+ && iItem->maLayoutSize.Maximum >= 0)
+ {
+ nDistributedHeight = ::std::max<sal_Int32>(0,iItem->maLayoutSize.Maximum - nBaseHeight);
+ }
+ iItem->mnDistributedHeight = nDistributedHeight;
+ nRemainingHeightToDistribute -= nDistributedHeight;
+ }
+
+ if (nRemainingHeightToDistribute == 0)
+ return;
+ OSL_ASSERT(nRemainingHeightToDistribute > 0);
+
+ // It is possible that not all of the height could be distributed
+ // because of Maximum heights being smaller than expected.
+ // Distribute the remaining height between the panels that have no
+ // Maximum (ie Maximum==-1).
+ if (nNoMaximumCount == 0)
+ {
+ // There are no panels with unrestricted height.
+ return;
+ }
+ const sal_Int32 nAdditionalHeightPerPanel (nRemainingHeightToDistribute / nNoMaximumCount);
+ // Handle rounding error.
+ sal_Int32 nAdditionalHeightForFirstPanel (nRemainingHeightToDistribute
+ - nNoMaximumCount*nAdditionalHeightPerPanel);
+ IterateLayoutItems(iItem,rLayoutItems)
+ {
+ if (iItem->maLayoutSize.Maximum < 0)
+ {
+ iItem->mnDistributedHeight += nAdditionalHeightPerPanel + nAdditionalHeightForFirstPanel;
+ nRemainingHeightToDistribute -= nAdditionalHeightPerPanel + nAdditionalHeightForFirstPanel;
+ }
+ }
+
+ OSL_ASSERT(nRemainingHeightToDistribute==0);
+}
+
+
+
+
+Rectangle DeckLayouter::PlaceDeckTitle (
+ Window& rDeckTitleBar,
+ const Rectangle& rAvailableSpace)
+{
+ if (static_cast<DockingWindow*>(rDeckTitleBar.GetParent()->GetParent())->IsFloatingMode())
+ {
+ // When the side bar is undocked then the outer system window displays the deck title.
+ rDeckTitleBar.Hide();
+ return rAvailableSpace;
+ }
+ else
+ {
+ const sal_Int32 nDeckTitleBarHeight (Theme::GetInteger(Theme::Int_DeckTitleBarHeight));
+ rDeckTitleBar.setPosSizePixel(
+ rAvailableSpace.Left(),
+ rAvailableSpace.Top(),
+ rAvailableSpace.GetWidth(),
+ nDeckTitleBarHeight);
+ rDeckTitleBar.Show();
+ return Rectangle(
+ rAvailableSpace.Left(),
+ rAvailableSpace.Top() + nDeckTitleBarHeight,
+ rAvailableSpace.Right(),
+ rAvailableSpace.Bottom());
+ }
+}
+
+
+
+
+Rectangle DeckLayouter::PlaceVerticalScrollBar (
+ ScrollBar& rVerticalScrollBar,
+ const Rectangle& rAvailableSpace,
+ const bool bShowVerticalScrollBar)
+{
+ if (bShowVerticalScrollBar)
+ {
+ const sal_Int32 nScrollBarWidth (rVerticalScrollBar.GetSizePixel().Width());
+ rVerticalScrollBar.setPosSizePixel(
+ rAvailableSpace.Right() - nScrollBarWidth + 1,
+ rAvailableSpace.Top(),
+ nScrollBarWidth,
+ rAvailableSpace.GetHeight());
+ rVerticalScrollBar.Show();
+ return Rectangle(
+ rAvailableSpace.Left(),
+ rAvailableSpace.Top(),
+ rAvailableSpace.Right() - nScrollBarWidth,
+ rAvailableSpace.Bottom());
+ }
+ else
+ {
+ rVerticalScrollBar.Hide();
+ return rAvailableSpace;
+ }
+}
+
+
+
+
+void DeckLayouter::SetupVerticalScrollBar(
+ ScrollBar& rVerticalScrollBar,
+ const sal_Int32 nContentHeight,
+ const sal_Int32 nVisibleHeight)
+{
+ OSL_ASSERT(nContentHeight > nVisibleHeight);
+
+ rVerticalScrollBar.SetRangeMin(0);
+ rVerticalScrollBar.SetRangeMax(nContentHeight-1);
+ rVerticalScrollBar.SetVisibleSize(nVisibleHeight);
+}
+
+
+
+
+void DeckLayouter::UpdateFiller (
+ Window& rFiller,
+ const Rectangle& rBox)
+{
+ if (rBox.GetHeight() > 0)
+ {
+ // Show the filler.
+ rFiller.SetBackground(Theme::GetPaint(Theme::Paint_PanelBackground).GetWallpaper());
+ rFiller.SetPosSizePixel(rBox.TopLeft(), rBox.GetSize());
+ rFiller.Show();
+ }
+ else
+ {
+ // Hide the filler.
+ rFiller.Hide();
+ }
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DeckLayouter.hxx b/sfx2/source/sidebar/DeckLayouter.hxx
new file mode 100644
index 000000000000..e1df7f277ec4
--- /dev/null
+++ b/sfx2/source/sidebar/DeckLayouter.hxx
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DECK_LAYOUTER_HXX
+#define SFX_SIDEBAR_DECK_LAYOUTER_HXX
+
+#include "Panel.hxx"
+
+#include <tools/gen.hxx>
+
+#include <com/sun/star/ui/LayoutSize.hpp>
+
+#include <vector>
+
+class ScrollBar;
+class Window;
+
+namespace css = ::com::sun::star;
+
+namespace sfx2 { namespace sidebar {
+
+class Panel;
+
+
+/** Helper class for layouting the direct and indirect children of a
+ deck like title bars, panels, and scroll bars.
+*/
+class DeckLayouter
+{
+public:
+ static void LayoutDeck (
+ const Rectangle aContentArea,
+ SharedPanelContainer& rPanels,
+ Window& pDeckTitleBar,
+ Window& pScrollClipWindow,
+ Window& pScrollContainer,
+ Window& pFiller,
+ ScrollBar& pVerticalScrollBar);
+
+private:
+ // Do not use constructor or destructor.
+ DeckLayouter (void);
+ ~DeckLayouter (void);
+
+ enum LayoutMode
+ {
+ MinimumOrLarger,
+ PreferredOrLarger,
+ Preferred
+ };
+ class LayoutItem
+ {
+ public:
+ SharedPanel mpPanel;
+ css::ui::LayoutSize maLayoutSize;
+ sal_Int32 mnDistributedHeight;
+ sal_Int32 mnWeight;
+ sal_Int32 mnPanelIndex;
+ bool mbShowTitleBar;
+
+ LayoutItem (void)
+ : mpPanel(),maLayoutSize(0,0,0),mnDistributedHeight(0),mnWeight(0),mnPanelIndex(0),mbShowTitleBar(true)
+ {}
+ };
+ static Rectangle LayoutPanels (
+ const Rectangle aContentArea,
+ ::std::vector<LayoutItem>& rLayoutItems,
+ Window& rScrollClipWindow,
+ Window& rScrollContainer,
+ ScrollBar& pVerticalScrollBar,
+ const bool bShowVerticalScrollBar);
+ static void GetRequestedSizes (
+ ::std::vector<LayoutItem>& rLayoutItem,
+ sal_Int32& rAvailableHeight,
+ const Rectangle& rContentBox);
+ static void DistributeHeights (
+ ::std::vector<LayoutItem>& rLayoutItems,
+ const sal_Int32 nHeightToDistribute,
+ const sal_Int32 nContainerHeight,
+ const bool bMinimumHeightIsBase);
+ static sal_Int32 PlacePanels (
+ ::std::vector<LayoutItem>& rLayoutItems,
+ const sal_Int32 nWidth,
+ const LayoutMode eMode,
+ Window& rScrollContainer);
+ static Rectangle PlaceDeckTitle (
+ Window& rTittleBar,
+ const Rectangle& rAvailableSpace);
+ static Rectangle PlaceVerticalScrollBar (
+ ScrollBar& rVerticalScrollBar,
+ const Rectangle& rAvailableSpace,
+ const bool bShowVerticalScrollBar);
+ static void SetupVerticalScrollBar(
+ ScrollBar& rVerticalScrollBar,
+ const sal_Int32 nContentHeight,
+ const sal_Int32 nVisibleHeight);
+ static void UpdateFiller (
+ Window& rFiller,
+ const Rectangle& rBox);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/DeckTitleBar.cxx b/sfx2/source/sidebar/DeckTitleBar.cxx
new file mode 100644
index 000000000000..008da73ba1ea
--- /dev/null
+++ b/sfx2/source/sidebar/DeckTitleBar.cxx
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DeckTitleBar.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+#include <vcl/image.hxx>
+
+#ifdef DEBUG
+#include "Tools.hxx"
+#endif
+
+
+namespace sfx2 { namespace sidebar {
+
+static const sal_Int32 gaLeftGripPadding (3);
+static const sal_Int32 gaRightGripPadding (3);
+
+
+DeckTitleBar::DeckTitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rCloserAction)
+ : TitleBar(rsTitle, pParentWindow, GetBackgroundPaint()),
+ mnCloserItemIndex(1),
+ maCloserAction(rCloserAction),
+ mbIsCloserVisible(rCloserAction)
+{
+ OSL_ASSERT(pParentWindow != NULL);
+
+ if (maCloserAction)
+ {
+ maToolBox.InsertItem(
+ mnCloserItemIndex,
+ Theme::GetImage(Theme::Image_Closer));
+ }
+
+#ifdef DEBUG
+ SetText(A2S("DeckTitleBar"));
+#endif
+}
+
+
+
+
+DeckTitleBar::~DeckTitleBar (void)
+{
+}
+
+
+
+
+void DeckTitleBar::SetCloserVisible (const bool bIsCloserVisible)
+{
+ if (mbIsCloserVisible != bIsCloserVisible)
+ {
+ mbIsCloserVisible = bIsCloserVisible;
+
+ if (mbIsCloserVisible)
+ maToolBox.InsertItem(
+ mnCloserItemIndex,
+ Theme::GetImage(Theme::Image_Closer));
+ else
+ maToolBox.RemoveItem(
+ maToolBox.GetItemPos(mnCloserItemIndex));
+ }
+}
+
+
+
+
+Rectangle DeckTitleBar::GetTitleArea (const Rectangle& rTitleBarBox)
+{
+ Image aGripImage (Theme::GetImage(Theme::Image_Grip));
+ return Rectangle(
+ aGripImage.GetSizePixel().Width() + gaLeftGripPadding + gaRightGripPadding,
+ rTitleBarBox.Top(),
+ rTitleBarBox.Right(),
+ rTitleBarBox.Bottom());
+}
+
+
+
+
+void DeckTitleBar::PaintDecoration (const Rectangle& rTitleBarBox)
+{
+ (void)rTitleBarBox;
+}
+
+
+
+
+sidebar::Paint DeckTitleBar::GetBackgroundPaint (void)
+{
+ return Theme::GetPaint(Theme::Paint_DeckTitleBarBackground);
+}
+
+
+
+
+Color DeckTitleBar::GetTextColor (void)
+{
+ return Theme::GetColor(Theme::Color_DeckTitleFont);
+}
+
+
+
+
+void DeckTitleBar::HandleToolBoxItemClick (const sal_uInt16 nItemIndex)
+{
+ if (nItemIndex == mnCloserItemIndex)
+ if (maCloserAction)
+ maCloserAction();
+}
+
+
+
+
+void DeckTitleBar::DataChanged (const DataChangedEvent& rEvent)
+{
+ maToolBox.SetItemImage(
+ mnCloserItemIndex,
+ Theme::GetImage(Theme::Image_Closer));
+ TitleBar::DataChanged(rEvent);
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DeckTitleBar.hxx b/sfx2/source/sidebar/DeckTitleBar.hxx
new file mode 100644
index 000000000000..aab05648fe93
--- /dev/null
+++ b/sfx2/source/sidebar/DeckTitleBar.hxx
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DECK_TITLE_BAR_HXX
+#define SFX_SIDEBAR_DECK_TITLE_BAR_HXX
+
+#include "TitleBar.hxx"
+
+#include <boost/function.hpp>
+
+
+namespace sfx2 { namespace sidebar {
+
+class DeckTitleBar
+ : public TitleBar
+{
+public:
+ DeckTitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rCloserAction);
+ virtual ~DeckTitleBar (void);
+
+ void SetCloserVisible (const bool bIsCloserVisible);
+
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+
+protected:
+ virtual Rectangle GetTitleArea (const Rectangle& rTitleBarBox);
+ virtual void PaintDecoration (const Rectangle& rTitleBarBox);
+ virtual sidebar::Paint GetBackgroundPaint (void);
+ virtual Color GetTextColor (void);
+ virtual void HandleToolBoxItemClick (const sal_uInt16 nItemIndex);
+
+private:
+ const sal_uInt16 mnCloserItemIndex;
+ const ::boost::function<void(void)> maCloserAction;
+ bool mbIsCloserVisible;
+};
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/DrawHelper.cxx b/sfx2/source/sidebar/DrawHelper.cxx
new file mode 100644
index 000000000000..f8172b2cf52c
--- /dev/null
+++ b/sfx2/source/sidebar/DrawHelper.cxx
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DrawHelper.hxx"
+#include "Paint.hxx"
+
+#include <vcl/lineinfo.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+void DrawHelper::DrawBorder (
+ OutputDevice& rDevice,
+ const Rectangle rBox,
+ const SvBorder aBorderSize,
+ const Paint& rHorizontalPaint,
+ const Paint& rVerticalPaint)
+{
+ // Draw top line.
+ DrawHorizontalLine(
+ rDevice,
+ rBox.Left(),
+ rBox.Right(),
+ rBox.Top(),
+ aBorderSize.Top(),
+ rHorizontalPaint);
+ // Draw bottom line.
+ DrawHorizontalLine(
+ rDevice,
+ rBox.Left()+aBorderSize.Left(),
+ rBox.Right(),
+ rBox.Bottom()-aBorderSize.Bottom()+1,
+ aBorderSize.Bottom(),
+ rHorizontalPaint);
+ // Draw left line.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Top()+aBorderSize.Top(),
+ rBox.Bottom(),
+ rBox.Left(),
+ aBorderSize.Left(),
+ rVerticalPaint);
+ // Draw right line.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Top()+aBorderSize.Top(),
+ rBox.Bottom()-aBorderSize.Bottom(),
+ rBox.Right()-aBorderSize.Right()+1,
+ aBorderSize.Right(),
+ rVerticalPaint);
+}
+
+
+
+
+void DrawHelper::DrawBevelBorder (
+ OutputDevice& rDevice,
+ const Rectangle rBox,
+ const SvBorder aBorderSize,
+ const Paint& rTopLeftPaint,
+ const Paint& rCenterPaint,
+ const Paint& rBottomRightPaint)
+{
+ // Draw top line.
+ DrawHorizontalLine(
+ rDevice,
+ rBox.Left(),
+ rBox.Right() - aBorderSize.Right(),
+ rBox.Top(),
+ aBorderSize.Top(),
+ rTopLeftPaint);
+ // Draw bottom line.
+ DrawHorizontalLine(
+ rDevice,
+ rBox.Left()+aBorderSize.Left(),
+ rBox.Right(),
+ rBox.Bottom()-aBorderSize.Bottom()+1,
+ aBorderSize.Bottom(),
+ rBottomRightPaint);
+ // Draw left line.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Top()+aBorderSize.Top(),
+ rBox.Bottom() - aBorderSize.Bottom(),
+ rBox.Left(),
+ aBorderSize.Left(),
+ rTopLeftPaint);
+ // Draw right line.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Top()+aBorderSize.Top(),
+ rBox.Bottom()-aBorderSize.Bottom(),
+ rBox.Right()-aBorderSize.Right()+1,
+ aBorderSize.Right(),
+ rBottomRightPaint);
+ // Draw top right corner.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Top(),
+ rBox.Top()+aBorderSize.Top()-1,
+ rBox.Right()-aBorderSize.Right()+1,
+ aBorderSize.Right(),
+ rCenterPaint);
+ // Draw bottom right corner.
+ DrawVerticalLine(
+ rDevice,
+ rBox.Bottom() - aBorderSize.Bottom()+1,
+ rBox.Bottom(),
+ rBox.Left(),
+ aBorderSize.Left(),
+ rCenterPaint);
+}
+
+
+
+
+void DrawHelper::DrawHorizontalLine(
+ OutputDevice& rDevice,
+ const sal_Int32 nLeft,
+ const sal_Int32 nRight,
+ const sal_Int32 nY,
+ const sal_Int32 nHeight,
+ const Paint& rPaint)
+{
+ switch (rPaint.GetType())
+ {
+ case Paint::NoPaint:
+ default:
+ break;
+
+ case Paint::ColorPaint:
+ {
+ const Color aColor (rPaint.GetColor());
+ rDevice.SetLineColor(aColor);
+ for (sal_Int32 nYOffset=0; nYOffset<nHeight; ++nYOffset)
+ rDevice.DrawLine(
+ Point(nLeft,nY+nYOffset),
+ Point(nRight,nY+nYOffset));
+ break;
+ }
+ case Paint::GradientPaint:
+ rDevice.DrawGradient(
+ Rectangle(
+ nLeft,
+ nY,
+ nRight,
+ nY+nHeight-1),
+ rPaint.GetGradient());
+ break;
+ }
+}
+
+
+
+
+void DrawHelper::DrawVerticalLine(
+ OutputDevice& rDevice,
+ const sal_Int32 nTop,
+ const sal_Int32 nBottom,
+ const sal_Int32 nX,
+ const sal_Int32 nWidth,
+ const Paint& rPaint)
+{
+ switch (rPaint.GetType())
+ {
+ case Paint::NoPaint:
+ default:
+ break;
+
+ case Paint::ColorPaint:
+ {
+ const Color aColor (rPaint.GetColor());
+ rDevice.SetLineColor(aColor);
+ for (sal_Int32 nXOffset=0; nXOffset<nWidth; ++nXOffset)
+ rDevice.DrawLine(
+ Point(nX+nXOffset, nTop),
+ Point(nX+nXOffset, nBottom));
+ break;
+ }
+ case Paint::GradientPaint:
+ rDevice.DrawGradient(
+ Rectangle(
+ nX,
+ nTop,
+ nX+nWidth-1,
+ nBottom),
+ rPaint.GetGradient());
+ break;
+ }
+}
+
+
+
+
+void DrawHelper::DrawRoundedRectangle (
+ OutputDevice& rDevice,
+ const Rectangle& rBox,
+ const sal_Int32 nCornerRadius,
+ const Color& rBorderColor,
+ const Paint& rFillPaint)
+{
+ rDevice.SetLineColor(rBorderColor);
+ switch(rFillPaint.GetType())
+ {
+ case Paint::NoPaint:
+ default:
+ rDevice.SetFillColor();
+ rDevice.DrawRect(rBox, nCornerRadius, nCornerRadius);
+ break;
+
+ case Paint::ColorPaint:
+ rDevice.SetFillColor(rFillPaint.GetColor());
+ rDevice.DrawRect(rBox, nCornerRadius, nCornerRadius);
+ break;
+
+ case Paint::GradientPaint:
+ rDevice.DrawGradient(
+ rBox,
+ rFillPaint.GetGradient());
+ rDevice.SetFillColor();
+ rDevice.DrawRect(rBox, nCornerRadius, nCornerRadius);
+ break;
+ }
+}
+
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DrawHelper.hxx b/sfx2/source/sidebar/DrawHelper.hxx
new file mode 100644
index 000000000000..45bf7ea9c25b
--- /dev/null
+++ b/sfx2/source/sidebar/DrawHelper.hxx
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DRAW_HELPER_HXX
+#define SFX_SIDEBAR_DRAW_HELPER_HXX
+
+#include "vcl/window.hxx"
+
+#include <tools/svborder.hxx>
+
+class Color;
+
+namespace sfx2 { namespace sidebar {
+
+class Paint;
+
+/** Some convenience functions for painting backgrounds and borders.
+*/
+class DrawHelper
+{
+public:
+ static void DrawBorder (
+ OutputDevice& rDevice,
+ const Rectangle rBox,
+ const SvBorder aBorderSize,
+ const Paint& rHorizontalPaint,
+ const Paint& rVerticalPaint);
+ static void DrawBevelBorder (
+ OutputDevice& rDevice,
+ const Rectangle rBox,
+ const SvBorder aBorderSize,
+ const Paint& rTopLeftPaint,
+ const Paint& rCenterPaint,
+ const Paint& rBottomRightPaint);
+ static void DrawHorizontalLine(
+ OutputDevice& rDevice,
+ const sal_Int32 nLeft,
+ const sal_Int32 nRight,
+ const sal_Int32 nY,
+ const sal_Int32 nHeight,
+ const Paint& rPaint);
+ static void DrawVerticalLine(
+ OutputDevice& rDevice,
+ const sal_Int32 nTop,
+ const sal_Int32 nBottom,
+ const sal_Int32 nX,
+ const sal_Int32 nWidth,
+ const Paint& rPaint);
+ static void DrawRoundedRectangle (
+ OutputDevice& rDevice,
+ const Rectangle& rBox,
+ const sal_Int32 nCornerRadius,
+ const Color& rBorderColor,
+ const Paint& rFillPaint);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/EnumContext.cxx b/sfx2/source/sidebar/EnumContext.cxx
new file mode 100644
index 000000000000..d8d39fb75aac
--- /dev/null
+++ b/sfx2/source/sidebar/EnumContext.cxx
@@ -0,0 +1,326 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sidebar/EnumContext.hxx"
+
+#include <map>
+
+namespace sfx2 { namespace sidebar {
+
+#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
+
+namespace {
+
+typedef ::std::map<rtl::OUString,EnumContext::Application> ApplicationMap;
+typedef ::std::vector<rtl::OUString> ApplicationVector;
+static ApplicationMap maApplicationMap;
+static ApplicationVector maApplicationVector;
+
+typedef ::std::map<rtl::OUString,EnumContext::Context> ContextMap;
+typedef ::std::vector<rtl::OUString> ContextVector;
+static ContextMap maContextMap;
+static ContextVector maContextVector;
+
+}
+
+const sal_Int32 EnumContext::NoMatch = 4;
+const sal_Int32 EnumContext::OptimalMatch = 0; // Neither application nor context name is "any".
+
+
+EnumContext::EnumContext (void)
+ : meApplication(Application_None),
+ meContext(Context_Unknown)
+{
+}
+
+
+
+
+EnumContext::EnumContext (
+ const Application eApplication,
+ const Context eContext)
+ : meApplication(eApplication),
+ meContext(eContext)
+{
+}
+
+
+
+
+EnumContext::EnumContext (
+ const ::rtl::OUString& rsApplicationName,
+ const ::rtl::OUString& rsContextName)
+ : meApplication(GetApplicationEnum(rsApplicationName)),
+ meContext(GetContextEnum(rsContextName))
+{
+}
+
+
+
+
+sal_Int32 EnumContext::GetCombinedContext (void) const
+{
+ return CombinedEnumContext(meApplication, meContext);
+}
+
+
+
+
+sal_Int32 EnumContext::GetCombinedContext_DI (void) const
+{
+ switch (meApplication)
+ {
+ case Application_Draw:
+ case Application_Impress:
+ return CombinedEnumContext(Application_DrawImpress, meContext);
+
+ case Application_Writer:
+ case Application_WriterWeb:
+ return CombinedEnumContext(Application_WriterAndWeb, meContext);
+
+ default:
+ return CombinedEnumContext(meApplication, meContext);
+ }
+}
+
+
+
+
+const ::rtl::OUString& EnumContext::GetApplicationName (void) const
+{
+ return EnumContext::GetApplicationName(meApplication);
+}
+
+
+
+
+const ::rtl::OUString& EnumContext::GetContextName (void) const
+{
+ return EnumContext::GetContextName(meContext);
+}
+
+
+
+
+bool EnumContext::operator== (const EnumContext aOther)
+{
+ return meApplication==aOther.meApplication
+ && meContext==aOther.meContext;
+}
+
+
+
+
+bool EnumContext::operator!= (const EnumContext aOther)
+{
+ return meApplication!=aOther.meApplication
+ || meContext!=aOther.meContext;
+}
+
+
+
+
+void EnumContext::AddEntry (const ::rtl::OUString& rsName, const Application eApplication)
+{
+ maApplicationMap[rsName] = eApplication;
+ OSL_ASSERT(eApplication<=__LastApplicationEnum);
+ if (maApplicationVector.size() <= size_t(eApplication))
+ maApplicationVector.resize(eApplication+1);
+ maApplicationVector[eApplication]=rsName;
+}
+
+
+
+
+void EnumContext::ProvideApplicationContainers (void)
+{
+ if (maApplicationMap.empty())
+ {
+ maApplicationVector.resize(static_cast<size_t>(EnumContext::__LastApplicationEnum)+1);
+ AddEntry(A2S("com.sun.star.text.TextDocument"), EnumContext::Application_Writer);
+ AddEntry(A2S("com.sun.star.text.WebDocument"), EnumContext::Application_WriterWeb);
+ AddEntry(A2S("com.sun.star.sheet.SpreadsheetDocument"), EnumContext::Application_Calc);
+ AddEntry(A2S("com.sun.star.drawing.DrawingDocument"), EnumContext::Application_Draw);
+ AddEntry(A2S("com.sun.star.presentation.PresentationDocument"), EnumContext::Application_Impress);
+
+ AddEntry(A2S("any"), EnumContext::Application_Any);
+ AddEntry(A2S("none"), EnumContext::Application_None);
+ }
+}
+
+
+
+
+EnumContext::Application EnumContext::GetApplicationEnum (const ::rtl::OUString& rsApplicationName)
+{
+ ProvideApplicationContainers();
+
+ ApplicationMap::const_iterator iApplication(
+ maApplicationMap.find(rsApplicationName));
+ if (iApplication != maApplicationMap.end())
+ return iApplication->second;
+ else
+ return EnumContext::Application_None;
+}
+
+
+
+
+const ::rtl::OUString& EnumContext::GetApplicationName (const Application eApplication)
+{
+ ProvideApplicationContainers();
+
+ const sal_Int32 nIndex (eApplication);
+ if (nIndex<0 || nIndex>= __LastApplicationEnum)
+ return maApplicationVector[Application_None];
+ else
+ return maApplicationVector[nIndex];
+}
+
+
+
+
+void EnumContext::AddEntry (const ::rtl::OUString& rsName, const Context eApplication)
+{
+ maContextMap[rsName] = eApplication;
+ OSL_ASSERT(eApplication<=__LastContextEnum);
+ if (maContextVector.size() <= size_t(eApplication))
+ maContextVector.resize(eApplication+1);
+ maContextVector[eApplication] = rsName;
+}
+
+
+
+
+void EnumContext::ProvideContextContainers (void)
+{
+ if (maContextMap.empty())
+ {
+ maContextVector.resize(static_cast<size_t>(__LastContextEnum)+1);
+ AddEntry(A2S("any"), Context_Any);
+ AddEntry(A2S("default"), Context_Default);
+ AddEntry(A2S("empty"), Context_Empty);
+#define AddContext(context) AddEntry(A2S(#context), Context_##context);
+ AddContext(3DObject);
+ AddContext(Annotation);
+ AddContext(Auditing);
+ AddContext(Cell);
+ AddContext(Chart);
+ AddContext(Chart);
+ AddContext(Draw);
+ AddContext(DrawPage);
+ AddContext(DrawText);
+ AddContext(EditCell);
+ AddContext(Form);
+ AddContext(Frame);
+ AddContext(Graphic);
+ AddContext(HandoutPage);
+ AddContext(MasterPage);
+ AddContext(Media);
+ AddContext(MultiObject);
+ AddContext(NotesPage);
+ AddContext(OLE);
+ AddContext(OutlineText);
+ AddContext(Pivot);
+ AddContext(SlidesorterPage);
+ AddContext(Table);
+ AddContext(Text);
+ AddContext(TextObject);
+#undef AddContext
+ }
+}
+
+
+
+
+EnumContext::Context EnumContext::GetContextEnum (const ::rtl::OUString& rsContextName)
+{
+ ProvideContextContainers();
+
+ ContextMap::const_iterator iContext(
+ maContextMap.find(rsContextName));
+ if (iContext != maContextMap.end())
+ return iContext->second;
+ else
+ return EnumContext::Context_Unknown;
+}
+
+
+
+
+const ::rtl::OUString& EnumContext::GetContextName (const Context eContext)
+{
+ ProvideContextContainers();
+
+ const sal_Int32 nIndex (eContext);
+ if (nIndex<0 || nIndex>= __LastContextEnum)
+ return maContextVector[Context_Unknown];
+ else
+ return maContextVector[nIndex];
+}
+
+
+
+
+sal_Int32 EnumContext::EvaluateMatch (
+ const EnumContext& rOther) const
+{
+ const bool bApplicationNameIsAny (rOther.meApplication == Application_Any);
+ if (rOther.meApplication==meApplication || bApplicationNameIsAny)
+ {
+ // Application name matches.
+ const bool bContextNameIsAny (rOther.meContext == Context_Any);
+ if (rOther.meContext==meContext || bContextNameIsAny)
+ {
+ // Context name matches.
+ return (bApplicationNameIsAny ? 1 : 0)
+ + (bContextNameIsAny ? 2 : 0);
+ }
+ }
+ return NoMatch;
+}
+
+
+
+
+sal_Int32 EnumContext::EvaluateMatch (const ::std::vector<EnumContext>& rOthers) const
+{
+ sal_Int32 nBestMatch (NoMatch);
+
+ for (::std::vector<EnumContext>::const_iterator
+ iContext(rOthers.begin()),
+ iEnd(rOthers.end());
+ iContext!=iEnd;
+ ++iContext)
+ {
+ const sal_Int32 nMatch (EvaluateMatch(*iContext));
+ if (nMatch < nBestMatch)
+ {
+ if (nMatch == OptimalMatch)
+ {
+ // We will find no better match so stop searching.
+ return OptimalMatch;
+ }
+ nBestMatch = nMatch;
+ }
+ }
+ return nBestMatch;
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/FocusManager.cxx b/sfx2/source/sidebar/FocusManager.cxx
new file mode 100644
index 000000000000..b5c2ec552333
--- /dev/null
+++ b/sfx2/source/sidebar/FocusManager.cxx
@@ -0,0 +1,559 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "FocusManager.hxx"
+#include "Panel.hxx"
+#include "Tools.hxx"
+#include "TitleBar.hxx"
+#include <vcl/button.hxx>
+#include <vcl/toolbox.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+namespace
+{
+ enum PanelComponent
+ {
+ PC_TitleBar,
+ PC_ToolBox,
+ PC_Content,
+ PC_None
+ };
+
+ PanelComponent GetFocusedComponent (const Panel& rPanel)
+ {
+ if (rPanel.HasFocus())
+ return PC_Content;
+ else if (rPanel.GetTitleBar() != NULL)
+ {
+ if (rPanel.GetTitleBar()->HasFocus())
+ return PC_TitleBar;
+ else if (rPanel.GetTitleBar()->GetToolBox().HasFocus())
+ return PC_ToolBox;
+ }
+ return PC_None;
+ }
+}
+
+
+FocusManager::FocusManager (void)
+ : maPanels(),
+ maButtons(),
+ mpTopLevelWindow(NULL)
+{
+}
+
+
+
+
+FocusManager::~FocusManager (void)
+{
+ Clear();
+}
+
+
+
+
+void FocusManager::GrabFocus (void)
+{
+ if ( ! maPanels.empty())
+ FocusPanel(0);
+}
+
+
+
+
+void FocusManager::Clear (void)
+{
+ ClearPanels();
+ ClearButtons();
+}
+
+
+
+void FocusManager::ClearPanels (void)
+{
+ SetTopLevelWindow(NULL);
+
+ ::std::vector<Panel*> aPanels;
+ aPanels.swap(maPanels);
+ for (::std::vector<Panel*>::iterator iPanel(aPanels.begin()),iEnd(aPanels.end());
+ iPanel!=iEnd;
+ ++iPanel)
+ {
+ UnregisterWindow(**iPanel);
+ if ((*iPanel)->GetTitleBar() != NULL)
+ {
+ UnregisterWindow(*(*iPanel)->GetTitleBar());
+ UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
+ }
+ }
+}
+
+
+
+
+void FocusManager::ClearButtons (void)
+{
+ ::std::vector<Window*> aButtons;
+ for (::std::vector<Window*>::iterator iButton(aButtons.begin()),iEnd(aButtons.end());
+ iButton!=iEnd;
+ ++iButton)
+ {
+ UnregisterWindow(**iButton);
+ }
+}
+
+
+
+
+void FocusManager::SetPanels (const SharedPanelContainer& rPanels)
+{
+ ClearPanels();
+ for(SharedPanelContainer::const_iterator iPanel(rPanels.begin()),iEnd(rPanels.end());
+ iPanel!=iEnd;
+ ++iPanel)
+ {
+ RegisterWindow(**iPanel);
+ if ((*iPanel)->GetTitleBar() != NULL)
+ {
+ RegisterWindow(*(*iPanel)->GetTitleBar());
+ RegisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
+ }
+ maPanels.push_back(iPanel->get());
+ }
+
+ RegisterTopLevelListener();
+}
+
+
+
+
+void FocusManager::SetButtons (const ::std::vector<Button*>& rButtons)
+{
+ ClearButtons();
+ for (::std::vector<Button*>::const_iterator iButton(rButtons.begin()),iEnd(rButtons.end());
+ iButton!=iEnd;
+ ++iButton)
+ {
+ RegisterWindow(**iButton);
+ maButtons.push_back(*iButton);
+ }
+}
+
+
+
+
+void FocusManager::RegisterWindow (Window& rWindow)
+{
+ rWindow.AddEventListener(LINK(this, FocusManager, WindowEventListener));
+}
+
+
+
+
+void FocusManager::UnregisterWindow (Window& rWindow)
+{
+ rWindow.RemoveEventListener(LINK(this, FocusManager, WindowEventListener));
+}
+
+
+
+
+void FocusManager::RegisterTopLevelListener (void)
+{
+ if (maPanels.empty())
+ return;
+ Window* pWindow = maPanels.front();
+ while (pWindow != NULL && pWindow->GetParent()!=NULL)
+ {
+ pWindow = pWindow->GetParent();
+ }
+ SetTopLevelWindow(pWindow);
+}
+
+
+
+
+void FocusManager::SetTopLevelWindow (Window* pWindow)
+{
+ if (mpTopLevelWindow != pWindow)
+ {
+ if (mpTopLevelWindow != NULL)
+ {
+ UnregisterWindow(*mpTopLevelWindow);
+ mpTopLevelWindow->RemoveChildEventListener(LINK(this, FocusManager, WindowEventListener));
+ }
+ mpTopLevelWindow = pWindow;
+ if (mpTopLevelWindow != NULL)
+ {
+ RegisterWindow(*mpTopLevelWindow);
+ mpTopLevelWindow->AddChildEventListener(LINK(this, FocusManager, WindowEventListener));
+ }
+ }
+}
+
+
+
+
+sal_Int32 FocusManager::GetPanelIndex (const Window& rWindow) const
+{
+ for (sal_Int32 nIndex=0,nCount(maPanels.size()); nIndex<nCount; ++nIndex)
+ {
+ if (maPanels[nIndex] == &rWindow)
+ return nIndex;
+ TitleBar* pTitleBar = maPanels[nIndex]->GetTitleBar();
+ if (pTitleBar == &rWindow)
+ return nIndex;
+ if (pTitleBar!=NULL && &pTitleBar->GetToolBox()==&rWindow)
+ return nIndex;
+ }
+ return -1;
+}
+
+
+
+
+sal_Int32 FocusManager::GetButtonIndex (const Window& rWindow) const
+{
+ for (sal_Int32 nIndex=0,nCount(maButtons.size()); nIndex<nCount; ++nIndex)
+ if (maButtons[nIndex] == &rWindow)
+ return nIndex;
+ return -1;
+}
+
+
+
+
+bool FocusManager::IsAnyPanelFocused (void) const
+{
+ for (::std::vector<Panel*>::const_iterator iPanel(maPanels.begin()),iEnd(maPanels.end());
+ iPanel!=iEnd;
+ ++iPanel)
+ {
+ if ((*iPanel)->HasFocus())
+ return true;
+ else if ((*iPanel)->HasChildPathFocus())
+ return true;
+ }
+ return false;
+}
+
+
+
+
+bool FocusManager::IsAnyButtonFocused (void) const
+{
+ for (::std::vector<Button*>::const_iterator iButton(maButtons.begin()),iEnd(maButtons.end());
+ iButton!=iEnd;
+ ++iButton)
+ {
+ if ((*iButton)->HasFocus())
+ return true;
+ }
+ return false;
+}
+
+
+
+
+void FocusManager::FocusPanel (const sal_Int32 nPanelIndex)
+{
+ Panel& rPanel (*maPanels[nPanelIndex]);
+ TitleBar* pTitleBar = rPanel.GetTitleBar();
+ if (pTitleBar!=NULL && pTitleBar->IsVisible())
+ {
+ rPanel.SetExpanded(true);
+ pTitleBar->GrabFocus();
+ }
+ else
+ FocusPanelContent(nPanelIndex);
+}
+
+
+
+
+void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex)
+{
+ Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow());
+ if (pWindow != NULL)
+ pWindow->GrabFocus();
+}
+
+
+
+
+void FocusManager::FocusButton (const sal_Int32 nButtonIndex)
+{
+ maButtons[nButtonIndex]->GrabFocus();
+ maButtons[nButtonIndex]->Invalidate();
+}
+
+
+
+
+void FocusManager::ClickButton (const sal_Int32 nButtonIndex)
+{
+ maButtons[nButtonIndex]->Click();
+ if (nButtonIndex > 0)
+ if ( ! maPanels.empty())
+ FocusPanel(0);
+ maButtons[nButtonIndex]->GetParent()->Invalidate();
+}
+
+
+
+
+void FocusManager::RemoveWindow (Window& rWindow)
+{
+ ::std::vector<Panel*>::iterator iPanel (::std::find(maPanels.begin(), maPanels.end(), &rWindow));
+ if (iPanel != maPanels.end())
+ {
+ UnregisterWindow(rWindow);
+ if ((*iPanel)->GetTitleBar() != NULL)
+ {
+ UnregisterWindow(*(*iPanel)->GetTitleBar());
+ UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
+ }
+ maPanels.erase(iPanel);
+ return;
+ }
+
+ ::std::vector<Button*>::iterator iButton (::std::find(maButtons.begin(), maButtons.end(), &rWindow));
+ if (iButton != maButtons.end())
+ {
+ UnregisterWindow(rWindow);
+ maButtons.erase(iButton);
+ return;
+ }
+}
+
+
+
+
+bool FocusManager::MoveFocusInsidePanel (
+ const sal_Int32 nPanelIndex,
+ const sal_Int32 nDirection)
+{
+ Panel& rPanel (*maPanels[nPanelIndex]);
+ switch (GetFocusedComponent(rPanel))
+ {
+ case PC_TitleBar:
+ if (nDirection > 0)
+ rPanel.GetTitleBar()->GetToolBox().GrabFocus();
+ else
+ FocusPanelContent(nPanelIndex);
+ return true;
+
+ case PC_ToolBox:
+ if (nDirection > 0)
+ FocusPanelContent(nPanelIndex);
+ else
+ rPanel.GetTitleBar()->GrabFocus();
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
+
+
+long FocusManager::NotifyDockingWindowEvent (const KeyEvent& rKeyEvent)
+{
+ switch(rKeyEvent.GetKeyCode().GetCode())
+ {
+ case KEY_F6:
+ if (rKeyEvent.GetKeyCode().IsShift())
+ {
+ if (IsAnyButtonFocused())
+ {
+ FocusPanel(0);
+ return 1;
+ }
+ }
+ else
+ {
+ if (IsAnyPanelFocused())
+ {
+ FocusButton(0);
+ return 1;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+
+
+
+void FocusManager::HandleKeyEvent (
+ const KeyCode& rKeyCode,
+ const Window& rWindow)
+{
+ if (rKeyCode.GetModifier() != 0)
+ return;
+
+ const sal_Int32 nPanelIndex (GetPanelIndex(rWindow));
+ sal_Int32 nButtonIndex (nPanelIndex==-1 ? GetButtonIndex(rWindow) : -1);
+
+ switch (rKeyCode.GetCode())
+ {
+ case KEY_F6:
+ if (nPanelIndex >= 0)
+ FocusButton(0);
+ else
+ return;
+ break;
+
+ case KEY_SPACE:
+ if (nPanelIndex >= 0)
+ {
+ if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar)
+ {
+ // Toggle the expansion state.
+ maPanels[nPanelIndex]->SetExpanded( ! maPanels[nPanelIndex]->IsExpanded());
+ }
+ }
+ else if (nButtonIndex >= 0)
+ {
+ // Activate the button.
+ ClickButton(nButtonIndex);
+ }
+ return;
+
+ case KEY_RETURN:
+ if (nPanelIndex >= 0)
+ {
+ if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar)
+ {
+ // Enter the panel.
+ FocusPanelContent(nPanelIndex);
+ }
+ }
+ else if (nButtonIndex >= 0)
+ {
+ // Activate the button.
+ ClickButton(nButtonIndex);
+ }
+ return;
+
+ case KEY_TAB:
+ if (nPanelIndex >= 0)
+ {
+ if (rKeyCode.IsShift())
+ MoveFocusInsidePanel(nPanelIndex, -1);
+ else
+ MoveFocusInsidePanel(nPanelIndex, +1);
+ }
+ break;
+
+ case KEY_LEFT:
+ case KEY_UP:
+ // Go to previous element in focus ring.
+ if (nPanelIndex >= 0)
+ {
+ FocusPanel((nPanelIndex + maPanels.size() - 1) % maPanels.size());
+ }
+ else if (nButtonIndex >= 0)
+ {
+ FocusButton((nButtonIndex + maButtons.size() - 1) % maButtons.size());
+ }
+ break;
+
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ // Go to next element in focus ring.
+ if (nPanelIndex >= 0)
+ {
+ FocusPanel((nPanelIndex + 1) % maPanels.size());
+ }
+ else if (nButtonIndex >= 0)
+ {
+ FocusButton((nButtonIndex + 1) % maButtons.size());
+ }
+ break;
+ }
+}
+
+
+
+
+void FocusManager::HandleTopLevelEvent (VclWindowEvent& rEvent)
+{
+ switch (rEvent.GetId())
+ {
+ case VCLEVENT_WINDOW_KEYINPUT:
+ {
+ KeyEvent* pKeyEvent = static_cast<KeyEvent*>(rEvent.GetData());
+ switch (pKeyEvent->GetKeyCode().GetCode())
+ {
+ case KEY_F6:
+ OSL_TRACE("");
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+IMPL_LINK(FocusManager, WindowEventListener, VclSimpleEvent*, pEvent)
+{
+ if (pEvent == NULL)
+ return 0;
+
+ if ( ! pEvent->ISA(VclWindowEvent))
+ return 0;
+
+ VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent);
+ Window* pSource = pWindowEvent->GetWindow();
+ if (pSource == NULL)
+ return 0;
+
+ if (pSource == mpTopLevelWindow)
+ HandleTopLevelEvent(*pWindowEvent);
+ else
+ switch (pWindowEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_KEYINPUT:
+ {
+ KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData());
+ HandleKeyEvent(pKeyEvent->GetKeyCode(), *pSource);
+ return 1;
+ }
+
+ case VCLEVENT_OBJECT_DYING:
+ RemoveWindow(*pSource);
+ return 1;
+
+ case VCLEVENT_WINDOW_GETFOCUS:
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ pSource->Invalidate();
+ }
+ return 0;
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/FocusManager.hxx b/sfx2/source/sidebar/FocusManager.hxx
new file mode 100644
index 000000000000..f811f5ef4ea4
--- /dev/null
+++ b/sfx2/source/sidebar/FocusManager.hxx
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_FOCUS_MANAGER_HXX
+#define SFX_SIDEBAR_FOCUS_MANAGER_HXX
+
+#include "Panel.hxx"
+#include <tools/link.hxx>
+
+class Button;
+class KeyCode;
+class VclSimpleEvent;
+
+namespace sfx2 { namespace sidebar {
+
+/** Concentrate all focus handling in this class.
+ There are two rings of windows that accept the input focus: panels
+ and tab bar buttons.
+ Arrow keys move the focus between them. Tab moves focus between rings.
+*/
+class FocusManager
+{
+public:
+ FocusManager (void);
+ ~FocusManager (void);
+
+ /** Forget all panels and buttons. Remove all window listeners.
+ */
+ void Clear (void);
+
+ /** Transfer the focus into the sidebar tree of windows. This is
+ typically called from the SidebarChildWindow as result of
+ pressing the F6 key.
+ */
+ void GrabFocus (void);
+
+ /** Handle the key event that was sent to the docking window.
+ */
+ long NotifyDockingWindowEvent (const KeyEvent& rKeyEvent);
+
+ void SetPanels (const SharedPanelContainer& rPanels);
+
+ void SetButtons (const ::std::vector<Button*>& rButtons);
+
+private:
+ ::std::vector<Panel*> maPanels;
+ ::std::vector<Button*> maButtons;
+ Window* mpTopLevelWindow;
+
+ /** Listen for key events for panels and buttons.
+ */
+ DECL_LINK(WindowEventListener, VclSimpleEvent*);
+
+ void ClearPanels (void);
+ void ClearButtons (void);
+
+ /** Let the focus manager listen for window events for the given
+ window.
+ */
+ void RegisterWindow (Window& rWindow);
+ void UnregisterWindow (Window& rWindow);
+ void RegisterTopLevelListener (void);
+
+ /** Remove the window from the panel or the button container.
+ */
+ void RemoveWindow (Window& rWindow);
+
+ sal_Int32 GetPanelIndex (const Window& rWindow) const;
+ sal_Int32 GetButtonIndex (const Window& rWindow) const;
+ bool IsAnyPanelFocused (void) const;
+ bool IsAnyButtonFocused (void) const;
+
+ /** Set the focus to the title bar of the panel or, if the the
+ title bar is not visible, directly to the panel.
+ */
+ void FocusPanel (const sal_Int32 nPanelIndex);
+ void FocusPanelContent (const sal_Int32 nPanelIndex);
+ void FocusButton (const sal_Int32 nButtonIndex);
+ void ClickButton (const sal_Int32 nButtonIndex);
+ bool MoveFocusInsidePanel (
+ const sal_Int32 nPanelIndex,
+ const sal_Int32 nDirection);
+
+ void HandleKeyEvent (
+ const KeyCode& rKeyCode,
+ const Window& rWindow);
+
+ void SetTopLevelWindow (Window* pWindow);
+ void HandleTopLevelEvent (VclWindowEvent& rEvent);
+};
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/MenuButton.cxx b/sfx2/source/sidebar/MenuButton.cxx
new file mode 100644
index 000000000000..5b28220b8637
--- /dev/null
+++ b/sfx2/source/sidebar/MenuButton.cxx
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "MenuButton.hxx"
+
+#include "DrawHelper.hxx"
+#include "Paint.hxx"
+#include "Tools.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+MenuButton::MenuButton (Window* pParentWindow)
+ : CheckBox(pParentWindow),
+ mbIsLeftButtonDown(false),
+ mePaintType(PT_Theme)
+{
+#ifdef DEBUG
+ SetText(A2S("MenuButton"));
+#endif
+}
+
+
+
+
+MenuButton::~MenuButton (void)
+{
+}
+
+
+
+
+void MenuButton::Paint (const Rectangle& rUpdateArea)
+{
+ switch(mePaintType)
+ {
+ case PT_Theme:
+ default:
+ {
+ const bool bIsSelected (IsChecked());
+ const bool bIsHighlighted (IsMouseOver() || HasFocus());
+ DrawHelper::DrawRoundedRectangle(
+ *this,
+ Rectangle(Point(0,0), GetSizePixel()),
+ 3,
+ bIsHighlighted||bIsSelected
+ ? Theme::GetColor(Theme::Color_TabItemBorder)
+ : Color(0xffffffff),
+ bIsHighlighted
+ ? Theme::GetPaint(Theme::Paint_TabItemBackgroundHighlight)
+ : Theme::GetPaint(Theme::Paint_TabItemBackgroundNormal));
+
+ const Image aIcon(Button::GetModeImage());
+ const Size aIconSize (aIcon.GetSizePixel());
+ const Point aIconLocation(
+ (GetSizePixel().Width() - aIconSize.Width())/2,
+ (GetSizePixel().Height() - aIconSize.Height())/2);
+ DrawImage(
+ aIconLocation,
+ aIcon);
+ break;
+ }
+ case PT_Native:
+ Button::Paint(rUpdateArea);
+ // DrawImage(maIconPosition, maIcon);
+ break;
+ }
+}
+
+
+
+
+void MenuButton::MouseMove (const MouseEvent& rEvent)
+{
+ if (rEvent.IsEnterWindow() || rEvent.IsLeaveWindow())
+ Invalidate();
+ CheckBox::MouseMove(rEvent);
+}
+
+
+
+
+void MenuButton::MouseButtonDown (const MouseEvent& rMouseEvent)
+{
+#if 0
+ Hide();
+ CheckBox::MouseButtonDown(rMouseEvent);
+ Show();
+#else
+ if (rMouseEvent.IsLeft())
+ {
+ mbIsLeftButtonDown = true;
+ CaptureMouse();
+ Invalidate();
+ }
+#endif
+}
+
+
+
+
+void MenuButton::MouseButtonUp (const MouseEvent& rMouseEvent)
+{
+#if 0
+ Hide();
+ CheckBox::MouseButtonUp(rMouseEvent);
+ Show();
+#else
+ if (IsMouseCaptured())
+ ReleaseMouse();
+
+ if (rMouseEvent.IsLeft())
+ {
+ if (mbIsLeftButtonDown)
+ {
+ Check();
+ Click();
+ GetParent()->Invalidate();
+ }
+ }
+ if (mbIsLeftButtonDown)
+ {
+ mbIsLeftButtonDown = false;
+ Invalidate();
+ }
+#endif
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/MenuButton.hxx b/sfx2/source/sidebar/MenuButton.hxx
new file mode 100644
index 000000000000..13587dd312ce
--- /dev/null
+++ b/sfx2/source/sidebar/MenuButton.hxx
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_MENU_BUTTON_HXX
+#define SFX_SIDEBAR_MENU_BUTTON_HXX
+
+#include "vcl/button.hxx"
+
+
+namespace sfx2 { namespace sidebar {
+
+class MenuButton
+ : public CheckBox
+{
+public:
+ MenuButton (Window* pParentWindow);
+ virtual ~MenuButton (void);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void MouseMove (const MouseEvent& rEvent);
+ virtual void MouseButtonDown (const MouseEvent& rMouseEvent);
+ virtual void MouseButtonUp (const MouseEvent& rMouseEvent);
+
+protected:
+ using CheckBox::FillLayoutData;
+
+private:
+ bool mbIsLeftButtonDown;
+ enum PaintType {
+ PT_Native,
+ PT_Theme
+ } mePaintType;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Paint.cxx b/sfx2/source/sidebar/Paint.cxx
new file mode 100644
index 000000000000..20f9bb938113
--- /dev/null
+++ b/sfx2/source/sidebar/Paint.cxx
@@ -0,0 +1,136 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "Paint.hxx"
+#include "Tools.hxx"
+#include <com/sun/star/awt/Gradient.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace sfx2 { namespace sidebar {
+
+Paint::Paint (void)
+ : meType(NoPaint)
+{
+}
+
+
+
+
+Paint::Paint (const Color& rColor)
+ : meType(ColorPaint),
+ maValue(rColor)
+{
+}
+
+
+
+
+Paint::Paint (const Gradient& rGradient)
+ : meType(GradientPaint),
+ maValue(rGradient)
+{
+}
+
+
+
+
+Paint Paint::Create (const cssu::Any& rValue)
+{
+ ColorData aColor (0);
+ if (rValue >>= aColor)
+ return Paint(Color(aColor));
+
+ awt::Gradient aAwtGradient;
+ if (rValue >>= aAwtGradient)
+ return Paint(Tools::AwtToVclGradient(aAwtGradient));
+
+ return Paint();
+}
+
+
+
+
+void Paint::Set (const Paint& rOther)
+{
+ meType = rOther.meType;
+ maValue = rOther.maValue;
+}
+
+
+
+
+Paint::Type Paint::GetType (void) const
+{
+ return meType;
+}
+
+
+
+
+const Color& Paint::GetColor (void) const
+{
+ if (meType != ColorPaint)
+ {
+ assert(meType==ColorPaint);
+ static Color aErrorColor;
+ return aErrorColor;
+ }
+ else
+ return ::boost::get<Color>(maValue);
+}
+
+
+
+
+const Gradient& Paint::GetGradient (void) const
+{
+ if (meType != GradientPaint)
+ {
+ assert(meType==GradientPaint);
+ static Gradient aErrorGradient;
+ return aErrorGradient;
+ }
+ else
+ return ::boost::get<Gradient>(maValue);
+}
+
+
+
+
+Wallpaper Paint::GetWallpaper (void) const
+{
+ switch (meType)
+ {
+ case Paint::NoPaint:
+ default:
+ return Wallpaper();
+ break;
+
+ case Paint::ColorPaint:
+ return Wallpaper(GetColor());
+ break;
+
+ case Paint::GradientPaint:
+ return Wallpaper(GetGradient());
+ break;
+ }
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Paint.hxx b/sfx2/source/sidebar/Paint.hxx
new file mode 100644
index 000000000000..e6840a9533e5
--- /dev/null
+++ b/sfx2/source/sidebar/Paint.hxx
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_PAINT_HXX
+#define SFX_SIDEBAR_PAINT_HXX
+
+#include <tools/color.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/wall.hxx>
+#include <com/sun/star/awt/Gradient.hpp>
+
+#include <boost/variant.hpp>
+
+namespace cssu = ::com::sun::star::uno;
+
+namespace sfx2 { namespace sidebar {
+
+/** Abstraction of different ways to fill outlines.
+ Can be
+ - none (empty: outline is not filled)
+ - singular color
+ - gradient
+*/
+class Paint
+{
+public:
+ enum Type
+ {
+ NoPaint,
+ ColorPaint,
+ GradientPaint
+ };
+
+ // Create a Paint object for an Any that may contain a color, a
+ // awt::Gradient, or nothing.
+ static Paint Create (const cssu::Any& rValue);
+
+ // Create paint with type NoPaint.
+ explicit Paint (void);
+
+ // Create a Paint object for the given color.
+ explicit Paint (const Color& rColor);
+
+ // Create a Paint object for the given gradient.
+ explicit Paint (const Gradient& rGradient);
+
+ void Set (const ::sfx2::sidebar::Paint& rOther);
+
+ Type GetType (void) const;
+ const Color& GetColor (void) const;
+ const Gradient& GetGradient (void) const;
+
+ Wallpaper GetWallpaper (void) const;
+
+private:
+ Type meType;
+ ::boost::variant<
+ Color,
+ Gradient
+ > maValue;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Panel.cxx b/sfx2/source/sidebar/Panel.cxx
new file mode 100644
index 000000000000..5389b4ff444b
--- /dev/null
+++ b/sfx2/source/sidebar/Panel.cxx
@@ -0,0 +1,267 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Panel.hxx"
+#include "PanelTitleBar.hxx"
+#include "PanelDescriptor.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "Paint.hxx"
+
+#ifdef DEBUG
+#include "Tools.hxx"
+#include "Deck.hxx"
+#endif
+
+#include <tools/svborder.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/ui/XToolPanel.hpp>
+
+#include <boost/bind.hpp>
+
+
+using namespace css;
+using namespace cssu;
+
+
+
+namespace sfx2 { namespace sidebar {
+
+Panel::Panel (
+ const PanelDescriptor& rPanelDescriptor,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rDeckLayoutTrigger,
+ const ::boost::function<void(void)>& rShowMenuFunctor)
+ : Window(pParentWindow),
+ msPanelId(rPanelDescriptor.msId),
+ mpTitleBar(new PanelTitleBar(
+ rPanelDescriptor.msTitle,
+ pParentWindow,
+ this,
+ rShowMenuFunctor)),
+ mbIsTitleBarOptional(rPanelDescriptor.mbIsTitleBarOptional),
+ mxElement(),
+ mxPanelComponent(),
+ mbIsExpanded(true),
+ maDeckLayoutTrigger(rDeckLayoutTrigger)
+{
+ SetBackground(Theme::GetPaint(Theme::Paint_PanelBackground).GetWallpaper());
+
+#ifdef DEBUG
+ OSL_TRACE("creating Panel at %x", this);
+ SetText(A2S("Panel"));
+#endif
+}
+
+
+
+
+Panel::~Panel (void)
+{
+ OSL_TRACE("destroying Panel at %x", this);
+ Dispose();
+}
+
+
+
+
+void Panel::Dispose (void)
+{
+ mxPanelComponent = NULL;
+
+ if (mxElement.is())
+ {
+ Reference<lang::XComponent> xComponent (mxElement->getRealInterface(), UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+
+ {
+ Reference<lang::XComponent> xComponent (mxElement, UNO_QUERY);
+ mxElement = NULL;
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+
+ {
+ Reference<lang::XComponent> xComponent (GetElementWindow(), UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+
+ mpTitleBar.reset();
+}
+
+
+
+
+TitleBar* Panel::GetTitleBar (void) const
+{
+ return mpTitleBar.get();
+}
+
+
+
+
+bool Panel::IsTitleBarOptional (void) const
+{
+ return mbIsTitleBarOptional;
+}
+
+
+
+
+void Panel::SetUIElement (const Reference<ui::XUIElement>& rxElement)
+{
+ mxElement = rxElement;
+ if (mxElement.is())
+ {
+ mxPanelComponent.set(mxElement->getRealInterface(), UNO_QUERY);
+ }
+}
+
+
+
+
+void Panel::SetExpanded (const bool bIsExpanded)
+{
+ if (mbIsExpanded != bIsExpanded)
+ {
+ mbIsExpanded = bIsExpanded;
+ maDeckLayoutTrigger();
+ }
+}
+
+
+
+
+bool Panel::IsExpanded (void) const
+{
+ return mbIsExpanded;
+}
+
+
+
+
+bool Panel::HasIdPredicate (const ::rtl::OUString& rsId) const
+{
+ if (this == NULL)
+ return false;
+ else
+ return msPanelId.equals(rsId);
+}
+
+
+
+
+const ::rtl::OUString& Panel::GetId (void) const
+{
+ return msPanelId;
+}
+
+
+
+
+void Panel::Paint (const Rectangle& rUpdateArea)
+{
+ Window::Paint(rUpdateArea);
+}
+
+
+
+
+void Panel::Resize (void)
+{
+ Window::Resize();
+
+ // Forward new size to window of XUIElement.
+ Reference<awt::XWindow> xElementWindow (GetElementWindow());
+ if (xElementWindow.is())
+ {
+ const Size aSize (GetSizePixel());
+ xElementWindow->setPosSize(
+ 0,
+ 0,
+ aSize.Width(),
+ aSize.Height(),
+ awt::PosSize::POSSIZE);
+ }
+}
+
+
+
+
+void Panel::Activate (void)
+{
+ Window::Activate();
+}
+
+
+
+
+
+void Panel::DataChanged (const DataChangedEvent& rEvent)
+{
+ (void)rEvent;
+ SetBackground(Theme::GetPaint(Theme::Paint_PanelBackground).GetWallpaper());
+}
+
+
+
+
+Reference<ui::XSidebarPanel> Panel::GetPanelComponent (void) const
+{
+ return mxPanelComponent;
+}
+
+
+
+
+void Panel::PrintWindowTree (void)
+{
+#ifdef DEBUG
+ Window* pElementWindow = VCLUnoHelper::GetWindow(GetElementWindow());
+ if (pElementWindow != NULL)
+ {
+ OSL_TRACE("panel parent is %x", pElementWindow->GetParent());
+ Deck::PrintWindowSubTree(pElementWindow, 2);
+ }
+ else
+ OSL_TRACE(" panel is empty");
+#endif
+}
+
+
+
+
+Reference<awt::XWindow> Panel::GetElementWindow (void)
+{
+ if (mxElement.is())
+ {
+ Reference<ui::XToolPanel> xToolPanel(mxElement->getRealInterface(), UNO_QUERY);
+ if (xToolPanel.is())
+ return xToolPanel->getWindow();
+ }
+
+ return NULL;
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Panel.hxx b/sfx2/source/sidebar/Panel.hxx
new file mode 100644
index 000000000000..ce6cb3c12eb6
--- /dev/null
+++ b/sfx2/source/sidebar/Panel.hxx
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_PANEL_HXX
+#define SFX_SIDEBAR_PANEL_HXX
+
+#include <vcl/window.hxx>
+
+#include <com/sun/star/ui/XUIElement.hpp>
+#include <com/sun/star/ui/XSidebarPanel.hpp>
+
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+namespace sfx2 { namespace sidebar {
+
+class PanelDescriptor;
+class TitleBar;
+
+
+class Panel
+ : public Window
+{
+public:
+ Panel (
+ const PanelDescriptor& rPanelDescriptor,
+ Window* pParentWindow,
+ const ::boost::function<void(void)>& rDeckLayoutTrigger,
+ const ::boost::function<void(void)>& rShowMenuFunctor);
+ virtual ~Panel (void);
+
+ void Dispose (void);
+
+ TitleBar* GetTitleBar (void) const;
+ bool IsTitleBarOptional (void) const;
+ void SetUIElement (const cssu::Reference<css::ui::XUIElement>& rxElement);
+ cssu::Reference<css::ui::XSidebarPanel> GetPanelComponent (void) const;
+ cssu::Reference<css::awt::XWindow> GetElementWindow (void);
+ void SetExpanded (const bool bIsExpanded);
+ bool IsExpanded (void) const;
+ bool HasIdPredicate (const ::rtl::OUString& rsId) const;
+ const ::rtl::OUString& GetId (void) const;
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void Resize (void);
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+ virtual void Activate (void);
+
+ void PrintWindowTree (void);
+
+private:
+ const ::rtl::OUString msPanelId;
+ ::boost::scoped_ptr<TitleBar> mpTitleBar;
+ const bool mbIsTitleBarOptional;
+ cssu::Reference<css::ui::XUIElement> mxElement;
+ cssu::Reference<css::ui::XSidebarPanel> mxPanelComponent;
+ bool mbIsExpanded;
+ const ::boost::function<void(void)> maDeckLayoutTrigger;
+ Rectangle maBoundingBox;
+};
+typedef ::boost::shared_ptr<Panel> SharedPanel;
+typedef ::std::vector<SharedPanel> SharedPanelContainer;
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/PanelDescriptor.cxx b/sfx2/source/sidebar/PanelDescriptor.cxx
new file mode 100644
index 000000000000..31e3b9e3c139
--- /dev/null
+++ b/sfx2/source/sidebar/PanelDescriptor.cxx
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PanelDescriptor.hxx"
+
+
+namespace sfx2 { namespace sidebar {
+
+PanelDescriptor::PanelDescriptor (void)
+ : msTitle(),
+ mbIsTitleBarOptional(false),
+ msId(),
+ msDeckId(),
+ msHelpURL(),
+ maContextList(),
+ msImplementationURL(),
+ mnOrderIndex(10000), // Default value as defined in Sidebar.xcs
+ mbWantsCanvas(false)
+{
+}
+
+
+
+
+PanelDescriptor::PanelDescriptor (const PanelDescriptor& rOther)
+ : msTitle(rOther.msTitle),
+ mbIsTitleBarOptional(rOther.mbIsTitleBarOptional),
+ msId(rOther.msId),
+ msDeckId(rOther.msDeckId),
+ msHelpURL(rOther.msHelpURL),
+ maContextList(rOther.maContextList),
+ msImplementationURL(rOther.msImplementationURL),
+ mnOrderIndex(rOther.mnOrderIndex),
+ mbWantsCanvas(rOther.mbWantsCanvas)
+{
+}
+
+
+
+PanelDescriptor::~PanelDescriptor (void)
+{
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/PanelDescriptor.hxx b/sfx2/source/sidebar/PanelDescriptor.hxx
new file mode 100644
index 000000000000..a9b34456d762
--- /dev/null
+++ b/sfx2/source/sidebar/PanelDescriptor.hxx
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_PANEL_DESCRIPTOR_HXX
+#define SFX_SIDEBAR_PANEL_DESCRIPTOR_HXX
+
+#include "sfx2/sidebar/EnumContext.hxx"
+#include "ContextList.hxx"
+#include <boost/shared_ptr.hpp>
+
+
+namespace sfx2 { namespace sidebar {
+
+class PanelDescriptor
+{
+public:
+ ::rtl::OUString msTitle;
+ sal_Bool mbIsTitleBarOptional;
+ ::rtl::OUString msId;
+ ::rtl::OUString msDeckId;
+ ::rtl::OUString msHelpURL;
+ ContextList maContextList;
+ ::rtl::OUString msImplementationURL;
+ sal_Int32 mnOrderIndex;
+ bool mbWantsCanvas;
+
+ PanelDescriptor (void);
+ PanelDescriptor (const PanelDescriptor& rPanelDescriptor);
+ ~PanelDescriptor (void);
+};
+typedef ::boost::shared_ptr<PanelDescriptor> SharedPanelDescriptor;
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/PanelTitleBar.cxx b/sfx2/source/sidebar/PanelTitleBar.cxx
new file mode 100644
index 000000000000..ded65fb8a458
--- /dev/null
+++ b/sfx2/source/sidebar/PanelTitleBar.cxx
@@ -0,0 +1,185 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PanelTitleBar.hxx"
+
+#include "Paint.hxx"
+#include "Panel.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+#include <tools/svborder.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/image.hxx>
+
+#ifdef DEBUG
+#include "Tools.hxx"
+#endif
+
+
+namespace sfx2 { namespace sidebar {
+
+
+static const sal_Int32 gaLeftIconPadding (5);
+static const sal_Int32 gaRightIconPadding (5);
+
+
+PanelTitleBar::PanelTitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ Panel* pPanel,
+ const ::boost::function<void(void)>& rMenuAction)
+ : TitleBar(rsTitle, pParentWindow, GetBackgroundPaint()),
+ mbIsLeftButtonDown(false),
+ mpPanel(pPanel),
+ mnMenuItemIndex(1),
+ maMenuAction(rMenuAction)
+{
+ OSL_ASSERT(mpPanel != NULL);
+
+ if (maMenuAction)
+ {
+ maToolBox.InsertItem(
+ mnMenuItemIndex,
+ Theme::GetImage(Theme::Image_PanelMenu));
+ maToolBox.SetOutStyle(TOOLBOX_STYLE_FLAT);
+ }
+
+#ifdef DEBUG
+ SetText(A2S("PanelTitleBar"));
+#endif
+}
+
+
+
+
+PanelTitleBar::~PanelTitleBar (void)
+{
+}
+
+
+
+
+Rectangle PanelTitleBar::GetTitleArea (const Rectangle& rTitleBarBox)
+{
+ if (mpPanel != NULL)
+ {
+ Image aImage (mpPanel->IsExpanded()
+ ? Theme::GetImage(Theme::Image_Expand)
+ : Theme::GetImage(Theme::Image_Collapse));
+ return Rectangle(
+ aImage.GetSizePixel().Width() + gaLeftIconPadding + gaRightIconPadding,
+ rTitleBarBox.Top(),
+ rTitleBarBox.Right(),
+ rTitleBarBox.Bottom());
+ }
+ else
+ return rTitleBarBox;
+}
+
+
+
+
+void PanelTitleBar::PaintDecoration (const Rectangle& rTitleBarBox)
+{
+ (void)rTitleBarBox;
+
+ if (mpPanel != NULL)
+ {
+ Image aImage (mpPanel->IsExpanded()
+ ? Theme::GetImage(Theme::Image_Collapse)
+ : Theme::GetImage(Theme::Image_Expand));
+ const Point aTopLeft (
+ gaLeftIconPadding,
+ (GetSizePixel().Height()-aImage.GetSizePixel().Height())/2);
+ DrawImage(aTopLeft, aImage);
+ }
+}
+
+
+
+
+Paint PanelTitleBar::GetBackgroundPaint (void)
+{
+ return Theme::GetPaint(Theme::Paint_PanelTitleBarBackground);
+}
+
+
+
+
+Color PanelTitleBar::GetTextColor (void)
+{
+ return Theme::GetColor(Theme::Color_PanelTitleFont);
+}
+
+
+
+
+void PanelTitleBar::HandleToolBoxItemClick (const sal_uInt16 nItemIndex)
+{
+ if (nItemIndex == mnMenuItemIndex)
+ if (maMenuAction)
+ maMenuAction();
+}
+
+
+
+
+void PanelTitleBar::MouseButtonDown (const MouseEvent& rMouseEvent)
+{
+ if (rMouseEvent.IsLeft())
+ {
+ mbIsLeftButtonDown = true;
+ CaptureMouse();
+ }
+}
+
+
+
+
+void PanelTitleBar::MouseButtonUp (const MouseEvent& rMouseEvent)
+{
+ if (IsMouseCaptured())
+ ReleaseMouse();
+
+ if (rMouseEvent.IsLeft())
+ {
+ if (mbIsLeftButtonDown)
+ {
+ if (mpPanel != NULL)
+ {
+ mpPanel->SetExpanded( ! mpPanel->IsExpanded());
+ Invalidate();
+ }
+ }
+ }
+ if (mbIsLeftButtonDown)
+ mbIsLeftButtonDown = false;
+}
+
+
+
+
+void PanelTitleBar::DataChanged (const DataChangedEvent& rEvent)
+{
+ maToolBox.SetItemImage(
+ mnMenuItemIndex,
+ Theme::GetImage(Theme::Image_PanelMenu));
+ TitleBar::DataChanged(rEvent);
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/PanelTitleBar.hxx b/sfx2/source/sidebar/PanelTitleBar.hxx
new file mode 100644
index 000000000000..f76edcb4eaad
--- /dev/null
+++ b/sfx2/source/sidebar/PanelTitleBar.hxx
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_PANEL_TITLE_BAR_HXX
+#define SFX_SIDEBAR_PANEL_TITLE_BAR_HXX
+
+#include "TitleBar.hxx"
+
+#include <boost/function.hpp>
+
+
+namespace sfx2 { namespace sidebar {
+
+class Panel;
+
+class PanelTitleBar
+ : public TitleBar
+{
+public:
+ PanelTitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ Panel* pPanel,
+ const ::boost::function<void(void)>& rMenuAction);
+ virtual ~PanelTitleBar (void);
+
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+ virtual void MouseButtonDown (const MouseEvent& rMouseEvent);
+ virtual void MouseButtonUp (const MouseEvent& rMouseEvent);
+
+protected:
+ virtual Rectangle GetTitleArea (const Rectangle& rTitleBarBox);
+ virtual void PaintDecoration (const Rectangle& rTitleBarBox);
+ virtual sidebar::Paint GetBackgroundPaint (void);
+ virtual Color GetTextColor (void);
+ virtual void HandleToolBoxItemClick (const sal_uInt16 nItemIndex);
+
+private:
+ bool mbIsLeftButtonDown;
+ Panel* mpPanel;
+ const sal_uInt16 mnMenuItemIndex;
+ const ::boost::function<void(void)> maMenuAction;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/PopupContainer.cxx b/sfx2/source/sidebar/PopupContainer.cxx
new file mode 100644
index 000000000000..adf55a1b2a9c
--- /dev/null
+++ b/sfx2/source/sidebar/PopupContainer.cxx
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "precompiled_sfx2.hxx"
+
+#include "sfx2/sidebar/PopupContainer.hxx"
+
+namespace sfx2 { namespace sidebar {
+
+PopupContainer::PopupContainer (Window* pParent)
+ : FloatingWindow(pParent, WB_SYSTEMWINDOW | WB_3DLOOK)
+{
+}
+
+
+
+
+PopupContainer::~PopupContainer (void)
+{
+}
+
+
+
+
+long PopupContainer::Notify (NotifyEvent& rEvent)
+{
+ if (rEvent.GetType() == EVENT_LOSEFOCUS)
+ {
+ if( ! HasChildPathFocus(sal_True))
+ EndPopupMode();
+ }
+ return FloatingWindow::Notify(rEvent);
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ResourceManager.cxx b/sfx2/source/sidebar/ResourceManager.cxx
new file mode 100644
index 000000000000..efb1fa134820
--- /dev/null
+++ b/sfx2/source/sidebar/ResourceManager.cxx
@@ -0,0 +1,621 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ResourceManager.hxx"
+#include "Tools.hxx"
+
+#include <unotools/confignode.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/stlunosequence.hxx>
+
+#include <rtl/ustrbuf.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/frame/XModuleManager.hpp>
+
+#include <map>
+
+
+
+using ::rtl::OUString;
+using namespace css;
+using namespace cssu;
+
+namespace sfx2 { namespace sidebar {
+
+class ResourceManager::Deleter
+{
+public:
+ void operator() (ResourceManager* pObject)
+ {
+ delete pObject;
+ }
+};
+
+
+ResourceManager& ResourceManager::Instance (void)
+{
+ static ResourceManager maInstance;
+ return maInstance;
+}
+
+
+
+
+ResourceManager::ResourceManager (void)
+ : maDecks(),
+ maPanels(),
+ maProcessedApplications()
+{
+ ReadDeckList();
+ ReadPanelList();
+}
+
+
+
+
+ResourceManager::~ResourceManager (void)
+{
+ maPanels.clear();
+ maDecks.clear();
+}
+
+
+
+
+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
+{
+ for (DeckContainer::const_iterator
+ iDeck(maDecks.begin()),
+ iEnd(maDecks.end());
+ iDeck!=iEnd;
+ ++iDeck)
+ {
+ if (iDeck->msId.equals(rsDeckId))
+ return &*iDeck;
+ }
+ return NULL;
+}
+
+
+
+
+const PanelDescriptor* ResourceManager::GetPanelDescriptor (
+ const ::rtl::OUString& rsPanelId) const
+{
+ for (PanelContainer::const_iterator
+ iPanel(maPanels.begin()),
+ iEnd(maPanels.end());
+ iPanel!=iEnd;
+ ++iPanel)
+ {
+ if (iPanel->msId.equals(rsPanelId))
+ return &*iPanel;
+ }
+ return NULL;
+}
+
+
+
+
+void ResourceManager::SetIsDeckEnabled (
+ const ::rtl::OUString& rsDeckId,
+ const bool bIsEnabled)
+{
+ for (DeckContainer::iterator
+ iDeck(maDecks.begin()),
+ iEnd(maDecks.end());
+ iDeck!=iEnd;
+ ++iDeck)
+ {
+ if (iDeck->msId.equals(rsDeckId))
+ {
+ iDeck->mbIsEnabled = bIsEnabled;
+ return;
+ }
+ }
+}
+
+
+
+
+const ResourceManager::IdContainer& ResourceManager::GetMatchingDecks (
+ IdContainer& rDeckIds,
+ const Context& rContext,
+ const Reference<frame::XFrame>& rxFrame)
+{
+ ReadLegacyAddons(rxFrame);
+
+ ::std::multimap<sal_Int32,OUString> aOrderedIds;
+ for (DeckContainer::const_iterator
+ iDeck(maDecks.begin()),
+ iEnd (maDecks.end());
+ iDeck!=iEnd;
+ ++iDeck)
+ {
+ const DeckDescriptor& rDeckDescriptor (*iDeck);
+ if (rDeckDescriptor.maContextList.GetMatch(rContext) != NULL)
+ aOrderedIds.insert(::std::multimap<sal_Int32,OUString>::value_type(
+ rDeckDescriptor.mnOrderIndex,
+ rDeckDescriptor.msId));
+ }
+
+ for (::std::multimap<sal_Int32,OUString>::const_iterator
+ iId(aOrderedIds.begin()),
+ iEnd(aOrderedIds.end());
+ iId!=iEnd;
+ ++iId)
+ {
+ rDeckIds.push_back(iId->second);
+ }
+
+ return rDeckIds;
+}
+
+
+
+
+const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels (
+ PanelContextDescriptorContainer& rPanelIds,
+ const Context& rContext,
+ const ::rtl::OUString& rsDeckId,
+ const Reference<frame::XFrame>& rxFrame)
+{
+ ReadLegacyAddons(rxFrame);
+
+ ::std::multimap<sal_Int32,PanelContextDescriptor> aOrderedIds;
+ for (PanelContainer::const_iterator
+ iPanel(maPanels.begin()),
+ iEnd(maPanels.end());
+ iPanel!=iEnd;
+ ++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));
+ }
+ }
+ }
+
+ for (::std::multimap<sal_Int32,PanelContextDescriptor>::const_iterator
+ iId(aOrderedIds.begin()),
+ iEnd(aOrderedIds.end());
+ iId!=iEnd;
+ ++iId)
+ {
+ rPanelIds.push_back(iId->second);
+ }
+
+ return rPanelIds;
+}
+
+
+
+
+void ResourceManager::ReadDeckList (void)
+{
+ const ::utl::OConfigurationTreeRoot aDeckRootNode (
+ ::comphelper::getProcessComponentContext(),
+ A2S("org.openoffice.Office.UI.Sidebar/Content/DeckList"),
+ false);
+ if ( ! aDeckRootNode.isValid() )
+ return;
+
+ const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
+ const sal_Int32 nCount (aDeckNodeNames.getLength());
+ maDecks.resize(nCount);
+ sal_Int32 nWriteIndex(0);
+ for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
+ {
+ const ::utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(aDeckNodeNames[nReadIndex]));
+ if ( ! aDeckNode.isValid())
+ continue;
+
+ DeckDescriptor& rDeckDescriptor (maDecks[nWriteIndex++]);
+
+ rDeckDescriptor.msTitle = ::comphelper::getString(
+ aDeckNode.getNodeValue("Title"));
+ rDeckDescriptor.msId = ::comphelper::getString(
+ aDeckNode.getNodeValue("Id"));
+ rDeckDescriptor.msIconURL = ::comphelper::getString(
+ aDeckNode.getNodeValue("IconURL"));
+ rDeckDescriptor.msHighContrastIconURL = ::comphelper::getString(
+ aDeckNode.getNodeValue("HighContrastIconURL"));
+ rDeckDescriptor.msHelpURL = ::comphelper::getString(
+ aDeckNode.getNodeValue("HelpURL"));
+ rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
+ rDeckDescriptor.mbIsEnabled = true;
+ rDeckDescriptor.mnOrderIndex = ::comphelper::getINT32(
+ aDeckNode.getNodeValue("OrderIndex"));
+
+ ReadContextList(
+ aDeckNode,
+ rDeckDescriptor.maContextList,
+ OUString());
+ }
+
+ // When there where invalid nodes then we have to adapt the size
+ // of the deck vector.
+ if (nWriteIndex<nCount)
+ maDecks.resize(nWriteIndex);
+}
+
+
+
+
+void ResourceManager::ReadPanelList (void)
+{
+ const ::utl::OConfigurationTreeRoot aPanelRootNode (
+ ::comphelper::getProcessComponentContext(),
+ A2S("org.openoffice.Office.UI.Sidebar/Content/PanelList"),
+ false);
+ if ( ! aPanelRootNode.isValid() )
+ return;
+
+ const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
+ const sal_Int32 nCount (aPanelNodeNames.getLength());
+ maPanels.resize(nCount);
+ sal_Int32 nWriteIndex (0);
+ for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
+ {
+ const ::utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(aPanelNodeNames[nReadIndex]));
+ if ( ! aPanelNode.isValid())
+ continue;
+
+ PanelDescriptor& rPanelDescriptor (maPanels[nWriteIndex++]);
+
+ rPanelDescriptor.msTitle = ::comphelper::getString(
+ aPanelNode.getNodeValue("Title"));
+ rPanelDescriptor.mbIsTitleBarOptional = ::comphelper::getBOOL(
+ aPanelNode.getNodeValue("TitleBarIsOptional"));
+ rPanelDescriptor.msId = ::comphelper::getString(
+ aPanelNode.getNodeValue("Id"));
+ rPanelDescriptor.msDeckId = ::comphelper::getString(
+ aPanelNode.getNodeValue("DeckId"));
+ rPanelDescriptor.msHelpURL = ::comphelper::getString(
+ aPanelNode.getNodeValue("HelpURL"));
+ rPanelDescriptor.msImplementationURL = ::comphelper::getString(
+ aPanelNode.getNodeValue("ImplementationURL"));
+ rPanelDescriptor.mnOrderIndex = ::comphelper::getINT32(
+ aPanelNode.getNodeValue("OrderIndex"));
+ rPanelDescriptor.mbWantsCanvas = ::comphelper::getBOOL(
+ aPanelNode.getNodeValue("WantsCanvas"));
+ const OUString sDefaultMenuCommand (::comphelper::getString(
+ aPanelNode.getNodeValue("DefaultMenuCommand")));
+
+ ReadContextList(
+ aPanelNode,
+ rPanelDescriptor.maContextList,
+ sDefaultMenuCommand);
+ }
+
+ // When there where invalid nodes then we have to adapt the size
+ // of the deck vector.
+ if (nWriteIndex<nCount)
+ maPanels.resize(nWriteIndex);
+}
+
+
+
+
+void ResourceManager::ReadContextList (
+ const ::utl::OConfigurationNode& rParentNode,
+ ContextList& rContextList,
+ const OUString& rsDefaultMenuCommand) const
+{
+ const Any aValue = rParentNode.getNodeValue("ContextList");
+ Sequence<OUString> aValues;
+ sal_Int32 nCount;
+ if (aValue >>= aValues)
+ nCount = aValues.getLength();
+ else
+ nCount = 0;
+
+ for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
+ {
+ const OUString sValue (aValues[nIndex]);
+ sal_Int32 nCharacterIndex (0);
+ const OUString sApplicationName (sValue.getToken(0, ',', nCharacterIndex).trim());
+ if (nCharacterIndex < 0)
+ {
+ if (sApplicationName.getLength() == 0)
+ {
+ // This is a valid case: in the XML file the separator
+ // was used as terminator. Using it in the last line
+ // creates an additional but empty entry.
+ break;
+ }
+ else
+ {
+ OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma");
+ continue;
+ }
+ }
+
+ const OUString sContextName (sValue.getToken(0, ',', nCharacterIndex).trim());
+ if (nCharacterIndex < 0)
+ {
+ OSL_ASSERT("expecting three or four values per ContextList entry, separated by comma");
+ continue;
+ }
+
+ const OUString sInitialState (sValue.getToken(0, ',', nCharacterIndex).trim());
+
+ // The fourth argument is optional.
+ const OUString sMenuCommandOverride (
+ nCharacterIndex<0
+ ? OUString()
+ : sValue.getToken(0, ',', nCharacterIndex).trim());
+ const OUString sMenuCommand (
+ sMenuCommandOverride.getLength()>0
+ ? (sMenuCommandOverride.equalsAscii("none")
+ ? OUString()
+ : sMenuCommandOverride)
+ : rsDefaultMenuCommand);
+
+ EnumContext::Application eApplication (EnumContext::GetApplicationEnum(sApplicationName));
+ EnumContext::Application eApplication2 (EnumContext::Application_None);
+ if (eApplication == EnumContext::Application_None
+ && !sApplicationName.equals(EnumContext::GetApplicationName(EnumContext::Application_None)))
+ {
+ // Handle some special names: abbreviations that make
+ // context descriptions more readable.
+ if (sApplicationName.equalsAscii("Writer"))
+ eApplication = EnumContext::Application_Writer;
+ else if (sApplicationName.equalsAscii("Calc"))
+ eApplication = EnumContext::Application_Calc;
+ else if (sApplicationName.equalsAscii("Draw"))
+ eApplication = EnumContext::Application_Draw;
+ else if (sApplicationName.equalsAscii("Impress"))
+ eApplication = EnumContext::Application_Impress;
+ else if (sApplicationName.equalsAscii("DrawImpress"))
+ {
+ // A special case among the special names: it is
+ // common to use the same context descriptions for
+ // both Draw and Impress. This special case helps to
+ // avoid duplication in the .xcu file.
+ eApplication = EnumContext::Application_Draw;
+ eApplication2 = EnumContext::Application_Impress;
+ }
+ else if (sApplicationName.equalsAscii("WriterAndWeb"))
+ {
+ // Another special case for Writer and WriterWeb.
+ eApplication = EnumContext::Application_Writer;
+ eApplication2 = EnumContext::Application_WriterWeb;
+ }
+ else
+ {
+ OSL_ASSERT("application name not recognized");
+ continue;
+ }
+ }
+
+ const EnumContext::Context eContext (EnumContext::GetContextEnum(sContextName));
+ if (eContext == EnumContext::Context_Unknown)
+ {
+ OSL_ASSERT("context name not recognized");
+ continue;
+ }
+
+ bool bIsInitiallyVisible;
+ if (sInitialState.equalsAscii("visible"))
+ bIsInitiallyVisible = true;
+ else if (sInitialState.equalsAscii("hidden"))
+ bIsInitiallyVisible = false;
+ else
+ {
+ OSL_ASSERT("unrecognized state");
+ continue;
+ }
+
+ if (eApplication != EnumContext::Application_None)
+ rContextList.AddContextDescription(
+ Context(
+ EnumContext::GetApplicationName(eApplication),
+ EnumContext::GetContextName(eContext)),
+ bIsInitiallyVisible,
+ sMenuCommand);
+ if (eApplication2 != EnumContext::Application_None)
+ rContextList.AddContextDescription(
+ Context(
+ EnumContext::GetApplicationName(eApplication2),
+ EnumContext::GetContextName(eContext)),
+ bIsInitiallyVisible,
+ sMenuCommand);
+ }
+}
+
+
+
+
+void ResourceManager::ReadLegacyAddons (const Reference<frame::XFrame>& rxFrame)
+{
+ // Get module name for given frame.
+ ::rtl::OUString sModuleName (GetModuleName(rxFrame));
+ if (sModuleName.getLength() == 0)
+ return;
+ if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end())
+ {
+ // Addons for this application have already been read.
+ // There is nothing more to do.
+ return;
+ }
+
+ // Mark module as processed. Even when there is an error that
+ // prevents the configuration data from being read, this error
+ // will not be triggered a second time.
+ maProcessedApplications.insert(sModuleName);
+
+ // Get access to the configuration root node for the application.
+ ::utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
+ if ( ! aLegacyRootNode.isValid())
+ return;
+
+ // Process child nodes.
+ ::std::vector<OUString> aMatchingNodeNames;
+ GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode);
+ const sal_Int32 nCount (aMatchingNodeNames.size());
+ size_t nDeckWriteIndex (maDecks.size());
+ size_t nPanelWriteIndex (maPanels.size());
+ maDecks.resize(maDecks.size() + nCount);
+ maPanels.resize(maPanels.size() + nCount);
+ for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
+ {
+ const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
+ const ::utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
+ if ( ! aChildNode.isValid())
+ continue;
+
+ DeckDescriptor& rDeckDescriptor (maDecks[nDeckWriteIndex++]);
+ rDeckDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName"));
+ rDeckDescriptor.msId = rsNodeName;
+ rDeckDescriptor.msIconURL = ::comphelper::getString(aChildNode.getNodeValue("ImageURL"));
+ rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL;
+ rDeckDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL"));
+ rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
+ rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString());
+ rDeckDescriptor.mbIsEnabled = true;
+
+ PanelDescriptor& rPanelDescriptor (maPanels[nPanelWriteIndex++]);
+ rPanelDescriptor.msTitle = ::comphelper::getString(aChildNode.getNodeValue("UIName"));
+ rPanelDescriptor.mbIsTitleBarOptional = true;
+ rPanelDescriptor.msId = rsNodeName;
+ rPanelDescriptor.msDeckId = rsNodeName;
+ rPanelDescriptor.msHelpURL = ::comphelper::getString(aChildNode.getNodeValue("HelpURL"));
+ rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, A2S("any")), true, OUString());
+ rPanelDescriptor.msImplementationURL = rsNodeName;
+ }
+
+ // When there where invalid nodes then we have to adapt the size
+ // of the deck and panel vectors.
+ if (nDeckWriteIndex < maDecks.size())
+ maDecks.resize(nDeckWriteIndex);
+ if (nPanelWriteIndex < maPanels.size())
+ maPanels.resize(nPanelWriteIndex);
+}
+
+
+
+
+::rtl::OUString ResourceManager::GetModuleName (
+ const cssu::Reference<css::frame::XFrame>& rxFrame)
+{
+ if ( ! rxFrame.is() || ! rxFrame->getController().is())
+ return OUString();
+
+ try
+ {
+ const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory());
+ const Reference<frame::XModuleManager> xModuleManager (
+ aContext.createComponent("com.sun.star.frame.ModuleManager"),
+ UNO_QUERY_THROW);
+ return xModuleManager->identify(rxFrame);
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return OUString();
+}
+
+
+
+
+::utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (
+ const ::rtl::OUString& rsModuleName) const
+{
+ try
+ {
+ const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory());
+ const Reference<container::XNameAccess> xModuleAccess (
+ aContext.createComponent("com.sun.star.frame.ModuleManager"),
+ UNO_QUERY_THROW);
+ const ::comphelper::NamedValueCollection aModuleProperties (xModuleAccess->getByName(rsModuleName));
+ const ::rtl::OUString sWindowStateRef (aModuleProperties.getOrDefault(
+ "ooSetupFactoryWindowStateConfigRef",
+ ::rtl::OUString()));
+
+ ::rtl::OUStringBuffer aPathComposer;
+ aPathComposer.appendAscii("org.openoffice.Office.UI.");
+ aPathComposer.append(sWindowStateRef);
+ aPathComposer.appendAscii("/UIElements/States");
+
+ return ::utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(),
+ aPathComposer.makeStringAndClear(), false);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return ::utl::OConfigurationTreeRoot();
+}
+
+
+
+
+void ResourceManager::GetToolPanelNodeNames (
+ ::std::vector<OUString>& rMatchingNames,
+ const ::utl::OConfigurationTreeRoot aRoot) const
+{
+ Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
+ const sal_Int32 nCount (aChildNodeNames.getLength());
+ for (sal_Int32 nIndex(0); nIndex<nCount; ++nIndex)
+ {
+ if (aChildNodeNames[nIndex].matchAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/")))
+ rMatchingNames.push_back(aChildNodeNames[nIndex]);
+ }
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ResourceManager.hxx b/sfx2/source/sidebar/ResourceManager.hxx
new file mode 100644
index 000000000000..cc9093c34b92
--- /dev/null
+++ b/sfx2/source/sidebar/ResourceManager.hxx
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_RESOURCE_MANAGER_HXX
+#define SFX_SIDEBAR_RESOURCE_MANAGER_HXX
+
+#include "DeckDescriptor.hxx"
+#include "PanelDescriptor.hxx"
+#include "Context.hxx"
+#include <unotools/confignode.hxx>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <set>
+#include <boost/shared_ptr.hpp>
+
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+namespace sfx2 { namespace sidebar {
+
+class Context;
+class ContextList;
+
+/** Read the content of the Sidebar.xcu file and provide access
+ methods so that the sidebar can easily decide which content panels
+ to display for a certain context.
+*/
+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 (
+ const ::rtl::OUString& rsPanelId) const;
+
+ /** Excluded or include a deck from being displayed in the tab
+ bar.
+ Note that this value is not persistent.
+ The flag can not be set directly at a DeckDescriptor object
+ because the ResourceManager gives access to to them only
+ read-only.
+ */
+ void SetIsDeckEnabled (
+ const ::rtl::OUString& rsDeckId,
+ const bool bIsEnabled);
+
+ typedef ::std::vector<rtl::OUString> IdContainer;
+ class PanelContextDescriptor
+ {
+ public:
+ ::rtl::OUString msId;
+ ::rtl::OUString msMenuCommand;
+ bool mbIsInitiallyVisible;
+ };
+ typedef ::std::vector<PanelContextDescriptor> PanelContextDescriptorContainer;
+
+ const IdContainer& GetMatchingDecks (
+ IdContainer& rDeckDescriptors,
+ const Context& rContext,
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+
+ const PanelContextDescriptorContainer& GetMatchingPanels (
+ PanelContextDescriptorContainer& rPanelDescriptors,
+ const Context& rContext,
+ const ::rtl::OUString& rsDeckId,
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+
+ static ::rtl::OUString GetModuleName (
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+
+private:
+ ResourceManager (void);
+ ~ResourceManager (void);
+ class Deleter;
+ friend class Deleter;
+
+ typedef ::std::vector<DeckDescriptor> DeckContainer;
+ DeckContainer maDecks;
+ typedef ::std::vector<PanelDescriptor> PanelContainer;
+ PanelContainer maPanels;
+ mutable ::std::set<rtl::OUString> maProcessedApplications;
+
+ void ReadDeckList (void);
+ void ReadPanelList (void);
+ void ReadContextList (
+ const ::utl::OConfigurationNode& rNode,
+ ContextList& rContextList,
+ const ::rtl::OUString& rsDefaultMenuCommand) const;
+ void ReadLegacyAddons (
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+ ::utl::OConfigurationTreeRoot GetLegacyAddonRootNode (
+ const ::rtl::OUString& rsModuleName) const;
+ void GetToolPanelNodeNames (
+ ::std::vector<rtl::OUString>& rMatchingNames,
+ const ::utl::OConfigurationTreeRoot aRoot) const;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Sidebar.cxx b/sfx2/source/sidebar/Sidebar.cxx
new file mode 100644
index 000000000000..af3797a2b49a
--- /dev/null
+++ b/sfx2/source/sidebar/Sidebar.cxx
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "precompiled_sfx2.hxx"
+
+#include "Sidebar.hxx"
+#include "ResourceManager.hxx"
+
+using namespace css;
+using namespace cssu;
+
+namespace sfx2 { namespace sidebar {
+
+Sidebar::Sidebar(
+ Window& rParentWindow,
+ const Reference<frame::XFrame>& rxDocumentFrame)
+ : Window(&rParentWindow, WB_DIALOGCONTROL)
+{
+ ContentPanelManager::Instance();
+}
+
+
+
+
+Sidebar::~Sidebar (void)
+{
+}
+
+
+
+
+void Sidebar::Resize (void)
+{
+ Window::Resize();
+ // m_pImpl->OnResize();
+}
+
+
+
+
+void Sidebar::GetFocus (void)
+{
+ Window::GetFocus();
+ // m_pImpl->OnGetFocus();
+}
+
+
+
+
+void Sidebar::DataChanged (const DataChangedEvent& rDataChangedEvent)
+{
+ if (rDataChangedEvent.GetType() == DATACHANGED_SETTINGS
+ && (rDataChangedEvent.GetFlags() & SETTINGS_STYLE)!= 0)
+ {
+ Invalidate();
+ }
+ else
+ Window::DataChanged(rDataChangedEvent);
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Sidebar.hrc b/sfx2/source/sidebar/Sidebar.hrc
new file mode 100644
index 000000000000..852648c6a929
--- /dev/null
+++ b/sfx2/source/sidebar/Sidebar.hrc
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <sfx2/sfx.hrc>
+
+#define RID_SIDEBAR_RESOURCE (RID_SFX_SIDEBAR_START + 0)
+
+#define IMAGE_SIDEBAR_PLUS 1
+#define IMAGE_SIDEBAR_MINUS 3
+#define IMAGE_SIDEBAR_GRIP 5
+#define IMAGE_SIDEBAR_MENU 7
+#define IMAGE_SIDEBAR_DETAIL_DIALOG 9
+#define IMAGE_SIDEBAR_TOOLBOX_SEPARATOR 11
+#define IMAGE_SIDEBAR_DECK_3D_LARGE 20
+#define IMAGE_SIDEBAR_DECK_3D_SMALL 22
+#define IMAGE_SIDEBAR_DECK_ANIMATION_LARGE 30
+#define IMAGE_SIDEBAR_DECK_ANIMATION_SMALL 32
+#define IMAGE_SIDEBAR_DECK_COLORS_LARGE 40
+#define IMAGE_SIDEBAR_DECK_COLORS_SMALL 42
+#define IMAGE_SIDEBAR_DECK_EYEDROPPER_LARGE 50
+#define IMAGE_SIDEBAR_DECK_EYEDROPPER_SMALL 52
+#define IMAGE_SIDEBAR_DECK_GALLERY_LARGE 60
+#define IMAGE_SIDEBAR_DECK_GALLERY_SMALL 62
+#define IMAGE_SIDEBAR_DECK_IMGANIM_LARGE 70
+#define IMAGE_SIDEBAR_DECK_IMGANIM_SMALL 72
+#define IMAGE_SIDEBAR_DECK_NAVIGATOR_LARGE 80
+#define IMAGE_SIDEBAR_DECK_NAVIGATOR_SMALL 82
+#define IMAGE_SIDEBAR_PROPERTIES_DECK_LARGE 90
+#define IMAGE_SIDEBAR_PROPERTIES_DECK_SMALL 92
+#define IMAGE_SIDEBAR_DECK_STYLE_LARGE 100
+#define IMAGE_SIDEBAR_DECK_STYLE_SMALL 102
+#define IMAGE_SIDEBAR_DECK_TEMPLATE_LARGE 110
+#define IMAGE_SIDEBAR_DECK_TEMPLATE_SMALL 112
+#define IMAGE_SIDEBAR_DECK_TRANSITION_LARGE 120
+#define IMAGE_SIDEBAR_DECK_TRANSITION_SMALL 122
+#define IMAGE_SIDEBAR_DECK_FUNCTIONS_LARGE 130
+#define IMAGE_SIDEBAR_DECK_FUNCTIONS_SMALL 132
+#define STRING_CUSTOMIZATION 200
+#define STRING_RESTORE 201
diff --git a/sfx2/source/sidebar/Sidebar.hxx b/sfx2/source/sidebar/Sidebar.hxx
new file mode 100644
index 000000000000..e225bdf8aaa8
--- /dev/null
+++ b/sfx2/source/sidebar/Sidebar.hxx
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_HXX
+#define SFX_SIDEBAR_HXX
+
+#include "sfx2/dllapi.h"
+#include <vcl/window.hxx>
+#include <com/sun/star/frame/XFrame.hpp>
+
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+namespace sfx2 { namespace sidebar {
+
+
+/** SFX-less version of a module dependent task pane, filled with tool panels as specified in the respective
+ module's configuration
+*/
+class SFX2_DLLPUBLIC Sidebar
+ : public Window
+{
+public:
+ /** creates a new instance
+ @param i_rParentWindow
+ the parent window
+ @param i_rDocumentFrame
+ the frame to which the task pane belongs. Will be passed to any custom tool panels created
+ via an XUIElementFactory. Also, it is used to determine the module which the task pane is
+ responsible for, thus controlling which tool panels are actually available.
+ */
+ Sidebar(
+ Window& rParentWindow,
+ const cssu::Reference<css::frame::XFrame>& rxDocumentFrame);
+
+
+ virtual ~Sidebar (void);
+
+protected:
+ virtual void Resize (void);
+ virtual void GetFocus (void);
+
+private:
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Sidebar.src b/sfx2/source/sidebar/Sidebar.src
new file mode 100644
index 000000000000..64eef88e3a23
--- /dev/null
+++ b/sfx2/source/sidebar/Sidebar.src
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "Sidebar.hrc"
+
+Resource RID_SIDEBAR_RESOURCE
+{
+ Image IMAGE_SIDEBAR_PLUS
+ {
+ ImageBitmap = Bitmap { File = "plus.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_MINUS
+ {
+ ImageBitmap = Bitmap { File = "minus.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_GRIP
+ {
+ ImageBitmap = Bitmap { File = "grip.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_MENU
+ {
+ ImageBitmap = Bitmap { File = "symphony/open_more.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_DETAIL_DIALOG
+ {
+ ImageBitmap = Bitmap { File = "symphony/morebutton.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_TOOLBOX_SEPARATOR
+ {
+ ImageBitmap = Bitmap { File = "separator.png" ;};
+ };
+
+ Image IMAGE_SIDEBAR_DECK_3D_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-3d-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_3D_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-3d-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_ANIMATION_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-animation-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_ANIMATION_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-animation-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_COLORS_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-colors-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_COLORS_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-colors-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_EYEDROPPER_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-eyedropper-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_EYEDROPPER_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-eyedropper-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_GALLERY_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-gallery-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_GALLERY_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-gallery-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_IMGANIM_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-imganim-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_IMGANIM_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-imganim-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_NAVIGATOR_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-navigator-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_NAVIGATOR_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-navigator-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_PROPERTIES_DECK_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-property-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_PROPERTIES_DECK_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-property-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_STYLE_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-style-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_STYLE_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-style-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_TEMPLATE_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-template-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_TEMPLATE_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-template-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_TRANSITION_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-transition-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_TRANSITION_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-transition-small.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_FUNCTIONS_LARGE
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-functions-large.png" ;};
+ };
+ Image IMAGE_SIDEBAR_DECK_FUNCTIONS_SMALL
+ {
+ ImageBitmap = Bitmap { File = "symphony/sidebar-functions-small.png" ;};
+ };
+ String STRING_CUSTOMIZATION
+ {
+ Text [en-US] = "Customization";
+ };
+ String STRING_RESTORE
+ {
+ Text [en-US] = "Restore Default";
+ };
+};
+
+
diff --git a/sfx2/source/sidebar/SidebarChildWindow.cxx b/sfx2/source/sidebar/SidebarChildWindow.cxx
new file mode 100644
index 000000000000..2fdf0a23d865
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarChildWindow.cxx
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sfx2/sidebar/SidebarChildWindow.hxx"
+#include "SidebarDockingWindow.hxx"
+#include "sfx2/sfxsids.hrc"
+#include "helpid.hrc"
+#include "sfx2/dockwin.hxx"
+#include <sfx2/sidebar/ResourceDefinitions.hrc>
+
+
+namespace sfx2 { namespace sidebar {
+
+
+SFX_IMPL_DOCKINGWINDOW_WITHID(SidebarChildWindow, SID_SIDEBAR);
+
+
+SidebarChildWindow::SidebarChildWindow (
+ Window* pSidebarParent,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo )
+ : SfxChildWindow(pSidebarParent, nId)
+{
+ this->pWindow = new SidebarDockingWindow(
+ pBindings,
+ *this,
+ pSidebarParent,
+ WB_STDDOCKWIN | WB_OWNERDRAWDECORATION | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE);
+ eChildAlignment = SFX_ALIGN_RIGHT;
+
+ this->pWindow->SetHelpId(HID_SIDEBAR_WINDOW);
+ this->pWindow->SetOutputSizePixel(Size(300, 450));
+
+ dynamic_cast<SfxDockingWindow*>(pWindow)->Initialize(pInfo);
+ SetHideNotDelete(sal_True);
+
+ this->pWindow->Show();
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarController.cxx b/sfx2/source/sidebar/SidebarController.cxx
new file mode 100644
index 000000000000..08e1e6d420ff
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarController.cxx
@@ -0,0 +1,927 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "SidebarController.hxx"
+#include "Deck.hxx"
+#include "DeckTitleBar.hxx"
+#include "Panel.hxx"
+#include "SidebarPanel.hxx"
+#include "SidebarResource.hxx"
+#include "TabBar.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "SidebarDockingWindow.hxx"
+#include "Context.hxx"
+#include "Tools.hxx"
+
+#include "sfxresid.hxx"
+#include "sfx2/sfxsids.hrc"
+#include "sfx2/titledockwin.hxx"
+#include "sfxlocal.hrc"
+#include <vcl/floatwin.hxx>
+#include "splitwin.hxx"
+#include <svl/smplhint.hxx>
+#include <tools/link.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
+#include <com/sun/star/ui/ContextChangeEventObject.hpp>
+#include <com/sun/star/ui/XUIElementFactory.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/util/URL.hpp>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/scoped_array.hpp>
+
+
+using namespace css;
+using namespace cssu;
+using ::rtl::OUString;
+
+
+
+namespace sfx2 { namespace sidebar {
+
+namespace {
+ enum MenuId
+ {
+ MID_UNLOCK_TASK_PANEL = 1,
+ MID_LOCK_TASK_PANEL,
+ MID_CUSTOMIZATION,
+ MID_RESTORE_DEFAULT,
+ MID_FIRST_PANEL,
+ MID_FIRST_HIDE = 1000
+ };
+}
+
+
+SidebarController::SidebarController (
+ SidebarDockingWindow* pParentWindow,
+ const cssu::Reference<css::frame::XFrame>& rxFrame)
+ : SidebarControllerInterfaceBase(m_aMutex),
+ mpCurrentDeck(),
+ mpParentWindow(pParentWindow),
+ mpTabBar(new TabBar(
+ mpParentWindow,
+ rxFrame,
+ ::boost::bind(&SidebarController::SwitchToDeck, this, _1),
+ ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2,_3))),
+ mxFrame(rxFrame),
+ maCurrentContext(OUString(), OUString()),
+ msCurrentDeckId(A2S("PropertyDeck")),
+ maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)),
+ mbIsDeckClosed(false),
+ mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width())
+{
+ if (pParentWindow == NULL)
+ {
+ OSL_ASSERT(pParentWindow!=NULL);
+ return;
+ }
+
+ // Listen for context change events.
+ cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
+ css::ui::ContextChangeEventMultiplexer::get(
+ ::comphelper::getProcessComponentContext()));
+ if (xMultiplexer.is())
+ xMultiplexer->addContextChangeEventListener(
+ static_cast<css::ui::XContextChangeEventListener*>(this),
+ mxFrame->getController());
+
+ // Listen for window events.
+ mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
+
+ // Listen for theme property changes.
+ Theme::GetPropertySet()->addPropertyChangeListener(
+ A2S(""),
+ static_cast<css::beans::XPropertyChangeListener*>(this));
+
+ SwitchToDeck(A2S("default"));
+}
+
+
+
+
+SidebarController::~SidebarController (void)
+{
+}
+
+
+
+
+void SAL_CALL SidebarController::disposing (void)
+{
+ maFocusManager.Clear();
+
+ cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
+ css::ui::ContextChangeEventMultiplexer::get(
+ ::comphelper::getProcessComponentContext()));
+ if (xMultiplexer.is())
+ xMultiplexer->removeAllContextChangeEventListeners(
+ static_cast<css::ui::XContextChangeEventListener*>(this));
+
+ if (mpParentWindow != NULL)
+ {
+ mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
+ mpParentWindow = NULL;
+ }
+
+ if (mpCurrentDeck)
+ {
+ mpCurrentDeck->Dispose();
+ OSL_TRACE("deleting deck window subtree");
+ mpCurrentDeck->PrintWindowTree();
+ mpCurrentDeck.reset();
+ }
+
+ mpTabBar.reset();
+
+ Theme::GetPropertySet()->removePropertyChangeListener(
+ A2S(""),
+ static_cast<css::beans::XPropertyChangeListener*>(this));
+}
+
+
+
+
+void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent)
+ throw(cssu::RuntimeException)
+{
+ UpdateConfigurations(
+ Context(
+ rEvent.ApplicationName,
+ rEvent.ContextName));
+}
+
+
+
+
+void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject)
+ throw(cssu::RuntimeException)
+{
+ (void)rEventObject;
+
+ dispose();
+}
+
+
+
+
+void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChangeEvent& rEvent)
+ throw(cssu::RuntimeException)
+{
+ (void)rEvent;
+
+ maPropertyChangeForwarder.RequestCall();
+}
+
+
+
+
+void SAL_CALL SidebarController::requestLayout (void)
+ throw(cssu::RuntimeException)
+{
+ if (mpCurrentDeck)
+ mpCurrentDeck->RequestLayout();
+ RestrictWidth();
+}
+
+
+
+
+void SidebarController::BroadcastPropertyChange (void)
+{
+ DataChangedEvent aEvent (DATACHANGED_USER);
+ mpParentWindow->NotifyAllChildren(aEvent);
+ mpParentWindow->Invalidate(INVALIDATE_CHILDREN);
+}
+
+
+
+
+void SidebarController::NotifyResize (void)
+{
+ if (mpTabBar == NULL)
+ {
+ OSL_ASSERT(mpTabBar!=NULL);
+ return;
+ }
+
+ Window* pParentWindow = mpTabBar->GetParent();
+
+ const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width());
+ const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height());
+
+ // Place the deck.
+ if (mpCurrentDeck)
+ {
+ mpCurrentDeck->setPosSizePixel(0,0, nWidth-TabBar::GetDefaultWidth(), nHeight);
+ mpCurrentDeck->Show();
+ mpCurrentDeck->RequestLayout();
+ }
+
+ // Place the tab bar.
+ mpTabBar->setPosSizePixel(nWidth-TabBar::GetDefaultWidth(),0,TabBar::GetDefaultWidth(),nHeight);
+ mpTabBar->Show();
+
+ // Determine if the closer of the deck can be shown.
+ if (mpCurrentDeck)
+ {
+ DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
+ if (pTitleBar != NULL && pTitleBar->IsVisible())
+ pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
+ }
+
+ if (nWidth > TabBar::GetDefaultWidth())
+ mnSavedSidebarWidth = nWidth;
+
+ RestrictWidth();
+#ifdef DEBUG
+ if (mpCurrentDeck)
+ {
+ 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();
+ }
+ }
+#endif
+}
+
+
+
+
+void SidebarController::UpdateConfigurations (const Context& rContext)
+{
+ if (maCurrentContext != rContext)
+ {
+ maCurrentContext = rContext;
+
+ // Notify the tab bar about the updated set of decks.
+ ResourceManager::IdContainer aDeckIds;
+ ResourceManager::Instance().GetMatchingDecks (
+ aDeckIds,
+ rContext,
+ mxFrame);
+ mpTabBar->SetDecks(aDeckIds);
+
+ // Check if the current deck is among the matching decks.
+ bool bCurrentDeckMatches (false);
+ for (ResourceManager::IdContainer::const_iterator
+ iDeck(aDeckIds.begin()),
+ iEnd(aDeckIds.end());
+ iDeck!=iEnd;
+ ++iDeck)
+ {
+ if (iDeck->equals(msCurrentDeckId))
+ {
+ bCurrentDeckMatches = true;
+ break;
+ }
+ }
+
+ DeckDescriptor const* pDeckDescriptor = NULL;
+ if ( ! bCurrentDeckMatches)
+ pDeckDescriptor = ResourceManager::Instance().GetBestMatchingDeck(rContext, mxFrame);
+ else
+ pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(msCurrentDeckId);
+ if (pDeckDescriptor != NULL)
+ {
+ msCurrentDeckId = pDeckDescriptor->msId;
+ SwitchToDeck(*pDeckDescriptor, rContext);
+ }
+
+#ifdef DEBUG
+ // Show the context name in the deck title bar.
+ if (mpCurrentDeck)
+ {
+ DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
+ if (pTitleBar != NULL)
+ pTitleBar->SetTitle(msCurrentDeckTitle+A2S(" (")+rContext.msContext+A2S(")"));
+ }
+#endif
+ }
+}
+
+
+
+
+void SidebarController::SwitchToDeck (
+ const ::rtl::OUString& rsDeckId)
+{
+ if ( ! msCurrentDeckId.equals(rsDeckId) || mbIsDeckClosed)
+ {
+ const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId);
+ if (pDeckDescriptor != NULL)
+ SwitchToDeck(*pDeckDescriptor, maCurrentContext);
+ }
+}
+
+
+
+
+void SidebarController::SwitchToDeck (
+ const DeckDescriptor& rDeckDescriptor,
+ const Context& rContext)
+{
+ maFocusManager.Clear();
+
+ if ( ! msCurrentDeckId.equals(rDeckDescriptor.msId))
+ {
+ // When the deck changes then destroy the deck and all panels
+ // and create everything new.
+ if (mpCurrentDeck)
+ {
+ mpCurrentDeck->Dispose();
+ mpCurrentDeck.reset();
+ }
+
+ msCurrentDeckId = rDeckDescriptor.msId;
+ }
+
+ // Reopen the deck when necessary.
+ OpenDeck();
+
+ // Determine the panels to display in the deck.
+ ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
+ ResourceManager::Instance().GetMatchingPanels(
+ aPanelContextDescriptors,
+ rContext,
+ rDeckDescriptor.msId,
+ mxFrame);
+
+ if (aPanelContextDescriptors.empty())
+ {
+ // There are no panels to be displayed in the current context.
+ if (EnumContext::GetContextEnum(rContext.msContext) != EnumContext::Context_Empty)
+ {
+ // Switch to the "empty" context and try again.
+ SwitchToDeck(
+ rDeckDescriptor,
+ Context(
+ rContext.msApplication,
+ EnumContext::GetContextName(EnumContext::Context_Empty)));
+ return;
+ }
+ else
+ {
+ // This is already the "empty" context. Looks like we have
+ // to live with an empty deck.
+ }
+ }
+
+ if (mpCurrentDeck
+ && ArePanelSetsEqual(mpCurrentDeck->GetPanels(), aPanelContextDescriptors))
+ {
+ // Requested set of panels is identical to the current set of
+ // panels => Nothing to do.
+ return;
+ }
+
+ // Provide a configuration and Deck object.
+ if ( ! mpCurrentDeck)
+ {
+ mpCurrentDeck.reset(
+ new Deck(
+ rDeckDescriptor,
+ mpParentWindow,
+ ::boost::bind(&SidebarController::CloseDeck, this)));
+ msCurrentDeckTitle = rDeckDescriptor.msTitle;
+ }
+ if ( ! mpCurrentDeck)
+ return;
+
+ // Update the panel list.
+ const sal_Int32 nNewPanelCount (aPanelContextDescriptors.size());
+ SharedPanelContainer aNewPanels;
+ const SharedPanelContainer& rCurrentPanels (mpCurrentDeck->GetPanels());
+ aNewPanels.resize(nNewPanelCount);
+ sal_Int32 nWriteIndex (0);
+ bool bHasPanelSetChanged (false);
+ for (sal_Int32 nReadIndex=0; nReadIndex<nNewPanelCount; ++nReadIndex)
+ {
+ const ResourceManager::PanelContextDescriptor& rPanelContexDescriptor (
+ aPanelContextDescriptors[nReadIndex]);
+
+ // Find the corresponding panel among the currently active
+ // panels.
+ SharedPanelContainer::const_iterator iPanel (::std::find_if(
+ rCurrentPanels.begin(),
+ rCurrentPanels.end(),
+ ::boost::bind(&Panel::HasIdPredicate, _1, ::boost::cref(rPanelContexDescriptor.msId))));
+ if (iPanel != rCurrentPanels.end())
+ {
+ // Panel already exists in current deck. Reuse it.
+ aNewPanels[nWriteIndex] = *iPanel;
+ OSL_TRACE(" reusing panel %s", S2A(rPanelContexDescriptor.msId));
+ }
+ else
+ {
+ // Panel does not yet exist. Create it.
+ aNewPanels[nWriteIndex] = CreatePanel(
+ rPanelContexDescriptor.msId,
+ mpCurrentDeck->GetPanelParentWindow(),
+ rPanelContexDescriptor.msMenuCommand);
+ OSL_TRACE(" creating panel %s", S2A(rPanelContexDescriptor.msId));
+ bHasPanelSetChanged = true;
+ }
+ if (aNewPanels[nWriteIndex] != NULL)
+ {
+ // Depending on the context we have to collapse the panel.
+ aNewPanels[nWriteIndex]->SetExpanded(rPanelContexDescriptor.mbIsInitiallyVisible);
+
+ ++nWriteIndex;
+ }
+
+ }
+ aNewPanels.resize(nWriteIndex);
+
+ // Activate the deck and the new set of panels.
+ mpCurrentDeck->setPosSizePixel(
+ 0,
+ 0,
+ mpParentWindow->GetSizePixel().Width()-TabBar::GetDefaultWidth(),
+ mpParentWindow->GetSizePixel().Height());
+ mpCurrentDeck->SetPanels(aNewPanels);
+ mpCurrentDeck->Show();
+
+ // Tell the tab bar to highlight the button associated with the
+ // deck.
+ mpTabBar->HighlightDeck(rDeckDescriptor.msId);
+
+ mpParentWindow->SetText(rDeckDescriptor.msTitle);
+
+ if (bHasPanelSetChanged)
+ NotifyResize();
+
+ // Tell the focus manager about the new panels and tab bar
+ // buttons.
+ maFocusManager.SetPanels(aNewPanels);
+ mpTabBar->UpdateFocusManager(maFocusManager);
+}
+
+
+
+
+bool SidebarController::ArePanelSetsEqual (
+ const SharedPanelContainer& rCurrentPanels,
+ const ResourceManager::PanelContextDescriptorContainer& rRequestedPanels)
+{
+ 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));
+ }
+
+ if (rCurrentPanels.size() != rRequestedPanels.size())
+ return false;
+ for (sal_Int32 nIndex=0,nCount=rCurrentPanels.size(); nIndex<nCount; ++nIndex)
+ {
+ if (rCurrentPanels[nIndex] == NULL)
+ return false;
+ if ( ! rCurrentPanels[nIndex]->GetId().equals(rRequestedPanels[nIndex].msId))
+ return false;
+ }
+ return true;
+}
+
+
+
+
+SharedPanel SidebarController::CreatePanel (
+ const OUString& rsPanelId,
+ ::Window* pParentWindow,
+ const OUString& rsMenuCommand)
+{
+ const PanelDescriptor* pPanelDescriptor = ResourceManager::Instance().GetPanelDescriptor(rsPanelId);
+ if (pPanelDescriptor == NULL)
+ return SharedPanel();
+
+#ifdef DEBUG
+ // Prevent the panel not being created in the same memory of an old panel.
+ ::boost::scoped_array<char> pUnused (new char[sizeof(Panel)]);
+ OSL_TRACE("allocated memory at %x", pUnused.get());
+#endif
+
+ // Create the panel which is the parent window of the UIElement.
+ SharedPanel pPanel (new Panel(
+ *pPanelDescriptor,
+ pParentWindow,
+ ::boost::bind(&Deck::RequestLayout, mpCurrentDeck.get()),
+ rsMenuCommand.getLength()>0
+ ? ::boost::bind(&SidebarController::ShowDetailMenu,this,rsMenuCommand)
+ : ::boost::function<void(void)>()));
+
+ // Create the XUIElement.
+ Reference<ui::XUIElement> xUIElement (CreateUIElement(
+ pPanel->GetComponentInterface(),
+ pPanelDescriptor->msImplementationURL));
+ if (xUIElement.is())
+ {
+ // Initialize the panel and add it to the active deck.
+ pPanel->SetUIElement(xUIElement);
+ }
+ else
+ {
+ pPanel.reset();
+ }
+
+ return pPanel;
+}
+
+
+
+
+Reference<ui::XUIElement> SidebarController::CreateUIElement (
+ const Reference<awt::XWindowPeer>& rxWindow,
+ const ::rtl::OUString& rsImplementationURL)
+{
+ try
+ {
+ const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory());
+ const Reference<ui::XUIElementFactory> xUIElementFactory (
+ aComponentContext.createComponent("com.sun.star.ui.UIElementFactoryManager"),
+ UNO_QUERY_THROW);
+
+ // Create the XUIElement.
+ ::comphelper::NamedValueCollection aCreationArguments;
+ aCreationArguments.put("Frame", makeAny(mxFrame));
+ aCreationArguments.put("ParentWindow", makeAny(rxWindow));
+ SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(mpParentWindow);
+ if (pSfxDockingWindow != NULL)
+ aCreationArguments.put("SfxBindings", makeAny(sal_uInt64(&pSfxDockingWindow->GetBindings())));
+ aCreationArguments.put("Theme", Theme::GetPropertySet());
+ aCreationArguments.put("Sidebar", makeAny(Reference<ui::XSidebar>(static_cast<ui::XSidebar*>(this))));
+
+ Reference<ui::XUIElement> xUIElement(
+ xUIElementFactory->createUIElement(
+ rsImplementationURL,
+ Sequence<beans::PropertyValue>(aCreationArguments.getPropertyValues())),
+ UNO_QUERY_THROW);
+
+ return xUIElement;
+ }
+ catch(Exception& rException)
+ {
+ OSL_TRACE("caught exception: %s",
+ OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr());
+ // For some reason we can not create the actual panel.
+ // Probably because its factory was not properly registered.
+ // TODO: provide feedback to developer to better pinpoint the
+ // source of the error.
+
+ return NULL;
+ }
+}
+
+
+
+
+IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
+{
+ if (pEvent != NULL)
+ {
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_GETFOCUS:
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ break;
+
+ case VCLEVENT_WINDOW_SHOW:
+ case VCLEVENT_WINDOW_RESIZE:
+ NotifyResize();
+ break;
+
+ case VCLEVENT_WINDOW_DATACHANGED:
+ // Force an update of deck and tab bar to reflect
+ // changes in theme (high contrast mode).
+ Theme::HandleDataChange();
+ mpParentWindow->Invalidate();
+ break;
+
+ case SFX_HINT_DYING:
+ dispose();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return sal_True;
+}
+
+
+
+
+void SidebarController::ShowPopupMenu (
+ const Rectangle& rButtonBox,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const
+{
+ ::boost::shared_ptr<PopupMenu> pMenu = CreatePopupMenu(rDeckSelectionData, rDeckShowData);
+ pMenu->SetSelectHdl(LINK(this, SidebarController, OnMenuItemSelected));
+
+ // pass toolbox button rect so the menu can stay open on button up
+ Rectangle aBox (rButtonBox);
+ aBox.Move(mpTabBar->GetPosPixel().X(), 0);
+ pMenu->Execute(mpParentWindow, aBox, POPUPMENU_EXECUTE_DOWN);
+}
+
+
+
+
+void SidebarController::ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) const
+{
+ 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));
+ if (xDispatch.is())
+ xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
+ }
+ catch(Exception& rException)
+ {
+ OSL_TRACE("caught exception: %s",
+ OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr());
+ }
+}
+
+
+
+
+::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu (
+ const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const
+{
+ ::boost::shared_ptr<PopupMenu> pMenu (new PopupMenu());
+ FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
+ if (pMenuWindow != NULL)
+ {
+ pMenuWindow->SetPopupModeFlags(pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE);
+ }
+
+ SidebarResource aLocalResource;
+
+ // Add one entry for every tool panel element to individually make
+ // them visible or hide them.
+ {
+ sal_Int32 nIndex (MID_FIRST_PANEL);
+ for(::std::vector<TabBar::DeckMenuData>::const_iterator
+ iItem(rDeckSelectionData.begin()),
+ iEnd(rDeckSelectionData.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ pMenu->InsertItem(nIndex, iItem->get<0>(), MIB_RADIOCHECK);
+ pMenu->CheckItem(nIndex, iItem->get<2>());
+ ++nIndex;
+ }
+ }
+
+ pMenu->InsertSeparator();
+
+ // Add entry for docking or un-docking the tool panel.
+ if (mpParentWindow->IsFloatingMode())
+ pMenu->InsertItem(MID_LOCK_TASK_PANEL, String(SfxResId(STR_SFX_DOCK)));
+ else
+ pMenu->InsertItem(MID_UNLOCK_TASK_PANEL, String(SfxResId(STR_SFX_UNDOCK)));
+
+ // Add sub menu for customization (hiding of deck tabs.)
+ PopupMenu* pCustomizationMenu = new PopupMenu();
+ {
+ sal_Int32 nIndex (MID_FIRST_HIDE);
+ for(::std::vector<TabBar::DeckMenuData>::const_iterator
+ iItem(rDeckShowData.begin()),
+ iEnd(rDeckShowData.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ pCustomizationMenu->InsertItem(nIndex, iItem->get<0>(), MIB_CHECKABLE);
+ pCustomizationMenu->CheckItem(nIndex, iItem->get<2>());
+ ++nIndex;
+ }
+ }
+
+ pCustomizationMenu->InsertSeparator();
+ pCustomizationMenu->InsertItem(MID_RESTORE_DEFAULT, String(SfxResId(STRING_RESTORE)));
+
+ pMenu->InsertItem(MID_CUSTOMIZATION, String(SfxResId(STRING_CUSTOMIZATION)));
+ pMenu->SetPopupMenu(MID_CUSTOMIZATION, pCustomizationMenu);
+
+ pMenu->RemoveDisabledEntries(sal_False, sal_False);
+
+ return pMenu;
+}
+
+
+
+
+IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu)
+{
+ if (pMenu == NULL)
+ {
+ OSL_ENSURE(pMenu!=NULL, "sfx2::sidebar::SidebarController::OnMenuItemSelected: illegal menu!");
+ return 0;
+ }
+
+ pMenu->Deactivate();
+ const sal_Int32 nIndex (pMenu->GetCurItemId());
+ switch (nIndex)
+ {
+ case MID_UNLOCK_TASK_PANEL:
+ mpParentWindow->SetFloatingMode(sal_True);
+ break;
+
+ case MID_LOCK_TASK_PANEL:
+ mpParentWindow->SetFloatingMode(sal_False);
+ break;
+
+ case MID_RESTORE_DEFAULT:
+ mpTabBar->RestoreHideFlags();
+ break;
+
+ default:
+ {
+ try
+ {
+ if (nIndex >= MID_FIRST_PANEL && nIndex<MID_FIRST_HIDE)
+ SwitchToDeck(mpTabBar->GetDeckIdForIndex(nIndex - MID_FIRST_PANEL));
+ else if (nIndex >=MID_FIRST_HIDE)
+ mpTabBar->ToggleHideFlag(nIndex-MID_FIRST_HIDE);
+ }
+ catch (RuntimeException&)
+ {
+ }
+ }
+ break;
+ }
+
+ return 1;
+}
+
+
+
+
+void SidebarController::CloseDeck (void)
+{
+ if ( ! mbIsDeckClosed)
+ {
+ mbIsDeckClosed = true;
+ if ( ! mpParentWindow->IsFloatingMode())
+ mnSavedSidebarWidth = SetChildWindowWidth(TabBar::GetDefaultWidth());
+ mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
+
+ if (mpCurrentDeck)
+ mpCurrentDeck->Hide();
+
+ NotifyResize();
+ }
+}
+
+
+
+
+void SidebarController::OpenDeck (void)
+{
+ if (mbIsDeckClosed)
+ {
+ mbIsDeckClosed = false;
+ SetChildWindowWidth(mnSavedSidebarWidth);
+
+ if (mpCurrentDeck)
+ mpCurrentDeck->Show();
+
+ NotifyResize();
+ }
+}
+
+
+
+
+FocusManager& SidebarController::GetFocusManager (void)
+{
+ return maFocusManager;
+}
+
+
+
+
+bool SidebarController::CanModifyChildWindowWidth (void) const
+{
+ SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+ if (pSplitWindow == NULL)
+ {
+ OSL_ASSERT(pSplitWindow!=NULL);
+ return 0;
+ }
+
+ sal_uInt16 nRow (0xffff);
+ sal_uInt16 nColumn (0xffff);
+ pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow);
+
+ sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn));
+
+ return nRowCount == 1;
+}
+
+
+
+
+sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
+{
+ SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+ if (pSplitWindow == NULL)
+ return 0;
+
+ sal_uInt16 nRow (0xffff);
+ sal_uInt16 nColumn (0xffff);
+ pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow);
+ const long nColumnWidth (pSplitWindow->GetLineSize(nColumn));
+
+ Window* pWindow = mpParentWindow;
+ const Point aWindowPosition (pWindow->GetPosPixel());
+ const Size aWindowSize (pWindow->GetSizePixel());
+
+ pSplitWindow->MoveWindow(
+ mpParentWindow,
+ Size(nNewWidth, aWindowSize.Height()),
+ nColumn,
+ nRow);
+
+ return static_cast<sal_Int32>(nColumnWidth);
+}
+
+
+
+
+void SidebarController::RestrictWidth (void)
+{
+ SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
+ 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);
+ }
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarController.hxx b/sfx2/source/sidebar/SidebarController.hxx
new file mode 100644
index 000000000000..8902a73dd883
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarController.hxx
@@ -0,0 +1,165 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_CONTROLLER_HXX
+#define SFX_SIDEBAR_CONTROLLER_HXX
+
+#include "AsynchronousCall.hxx"
+#include "Context.hxx"
+#include "FocusManager.hxx"
+#include "Panel.hxx"
+#include "ResourceManager.hxx"
+#include "TabBar.hxx"
+
+#include <vcl/menu.hxx>
+
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.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 <cppuhelper/basemutex.hxx>
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+
+namespace
+{
+ typedef ::cppu::WeakComponentImplHelper3 <
+ css::ui::XContextChangeEventListener,
+ css::beans::XPropertyChangeListener,
+ css::ui::XSidebar
+ > SidebarControllerInterfaceBase;
+}
+
+namespace sfx2 { namespace sidebar {
+
+class ContentPanelDescriptor;
+class Deck;
+class DeckDescriptor;
+class SidebarDockingWindow;
+class TabBar;
+class TabBarConfiguration;
+
+class SidebarController
+ : private ::boost::noncopyable,
+ private ::cppu::BaseMutex,
+ public SidebarControllerInterfaceBase
+{
+public:
+ SidebarController(
+ SidebarDockingWindow* pParentWindow,
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+ virtual ~SidebarController (void);
+
+ // ui::XContextChangeEventListener
+ virtual void SAL_CALL notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent)
+ throw(cssu::RuntimeException);
+
+ // XEventListener
+ virtual void SAL_CALL disposing (const css::lang::EventObject& rEventObject)
+ throw(cssu::RuntimeException);
+
+ // beans::XPropertyChangeListener
+ virtual void SAL_CALL propertyChange (const css::beans::PropertyChangeEvent& rEvent)
+ throw(cssu::RuntimeException);
+
+ // ui::XSidebar
+ virtual void SAL_CALL requestLayout (void)
+ throw(cssu::RuntimeException);
+
+ void NotifyResize (void);
+
+ void SwitchToDeck (
+ const ::rtl::OUString& rsDeckId);
+
+ /** Show only the tab bar, not the deck.
+ */
+ void CloseDeck (void);
+
+ /** Open the deck area and restore the parent window to its old width.
+ */
+ void OpenDeck (void);
+
+ FocusManager& GetFocusManager (void);
+
+private:
+ ::boost::scoped_ptr<Deck> mpCurrentDeck;
+ SidebarDockingWindow* mpParentWindow;
+ ::boost::scoped_ptr<TabBar> mpTabBar;
+ cssu::Reference<css::frame::XFrame> mxFrame;
+ Context maCurrentContext;
+ ::rtl::OUString msCurrentDeckId;
+ ::rtl::OUString msCurrentDeckTitle;
+ AsynchronousCall maPropertyChangeForwarder;
+ bool mbIsDeckClosed;
+ /** 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;
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent*);
+ void UpdateConfigurations (const Context& rContext);
+ bool ArePanelSetsEqual (
+ const SharedPanelContainer& rCurrentPanels,
+ const ResourceManager::PanelContextDescriptorContainer& rRequestedPanels);
+ cssu::Reference<css::ui::XUIElement> CreateUIElement (
+ const cssu::Reference<css::awt::XWindowPeer>& rxWindow,
+ const ::rtl::OUString& rsImplementationURL);
+ SharedPanel CreatePanel (
+ const ::rtl::OUString& rsPanelId,
+ ::Window* pParentWindow,
+ const ::rtl::OUString& rsMenuCommand);
+ void SwitchToDeck (
+ const DeckDescriptor& rDeckDescriptor,
+ const Context& rContext);
+ void ShowPopupMenu (
+ const Rectangle& rButtonBox,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const;
+ void ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) const;
+ ::boost::shared_ptr<PopupMenu> CreatePopupMenu (
+ const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData,
+ const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const;
+ DECL_LINK(OnMenuItemSelected, Menu*);
+ void BroadcastPropertyChange (void);
+
+ /** The close of the deck changes the width of the child window.
+ 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;
+
+ /** Set the child window container to a new width.
+ Return the old width.
+ */
+ sal_Int32 SetChildWindowWidth (const sal_Int32 nNewWidth);
+
+ void RestrictWidth (void);
+
+ virtual void SAL_CALL disposing (void);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/SidebarDockingWindow.cxx b/sfx2/source/sidebar/SidebarDockingWindow.cxx
new file mode 100644
index 000000000000..ccfdbaaa3705
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarDockingWindow.cxx
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "SidebarDockingWindow.hxx"
+#include "sfx2/sidebar/SidebarChildWindow.hxx"
+#include "SidebarController.hxx"
+
+#include "sfx2/bindings.hxx"
+#include "sfx2/dispatch.hxx"
+#include <tools/link.hxx>
+
+using namespace css;
+using namespace cssu;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+SidebarDockingWindow::SidebarDockingWindow(
+ SfxBindings* pSfxBindings,
+ SidebarChildWindow& rChildWindow,
+ Window* pParent,
+ WinBits nBits)
+ : SfxDockingWindow(pSfxBindings, &rChildWindow, pParent, nBits),
+ mpSidebarController()
+{
+ // Get the XFrame from the bindings.
+ if (pSfxBindings==NULL || pSfxBindings->GetDispatcher()==NULL)
+ {
+ OSL_ASSERT(pSfxBindings!=NULL);
+ OSL_ASSERT(pSfxBindings->GetDispatcher()!=NULL);
+ }
+ else
+ {
+ const SfxViewFrame* pViewFrame = pSfxBindings->GetDispatcher()->GetFrame();
+ const SfxFrame& rFrame = pViewFrame->GetFrame();
+ mpSidebarController.set(new sfx2::sidebar::SidebarController(this, rFrame.GetFrameInterface()));
+ }
+}
+
+
+
+
+SidebarDockingWindow::~SidebarDockingWindow (void)
+{
+ DoDispose();
+}
+
+
+
+
+void SidebarDockingWindow::DoDispose (void)
+{
+}
+
+
+
+
+void SidebarDockingWindow::GetFocus()
+{
+ mpSidebarController->GetFocusManager().GrabFocus();
+}
+
+
+
+
+long SidebarDockingWindow::PreNotify (NotifyEvent& rEvent)
+{
+ switch (rEvent.GetType())
+ {
+ case EVENT_KEYINPUT:
+ {
+ const KeyEvent* pKeyEvent = rEvent.GetKeyEvent();
+ if (pKeyEvent != NULL)
+ return mpSidebarController->GetFocusManager().NotifyDockingWindowEvent(*pKeyEvent);
+ else
+ break;
+ }
+
+ case EVENT_GETFOCUS:
+ OSL_TRACE("");
+ break;
+
+ }
+
+ return SfxDockingWindow::PreNotify(rEvent);
+}
+
+
+
+
+SfxChildWindow* SidebarDockingWindow::GetChildWindow (void)
+{
+ return GetChildWindow_Impl();
+}
+
+
+
+
+sal_Bool SidebarDockingWindow::Close (void)
+{
+ if (mpSidebarController.is())
+ {
+ // Do not close the floating window.
+ // Dock it and close just the deck instead.
+ mpSidebarController->CloseDeck();
+ SetFloatingMode(sal_False);
+ mpSidebarController->NotifyResize();
+ return sal_False;
+ }
+ else
+ return SfxDockingWindow::Close();
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarDockingWindow.hxx b/sfx2/source/sidebar/SidebarDockingWindow.hxx
new file mode 100644
index 000000000000..700ffde16e94
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarDockingWindow.hxx
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_DOCKING_WINDOW_HXX
+#define SFX_SIDEBAR_DOCKING_WINDOW_HXX
+
+#include "sfx2/dockwin.hxx"
+#include "sfx2/dockwin.hxx"
+#include "Sidebar.hxx"
+
+#include <rtl/ref.hxx>
+
+namespace sfx2 { namespace sidebar {
+
+class SidebarChildWindow;
+
+class SidebarController;
+
+class SidebarDockingWindow
+ : public SfxDockingWindow
+{
+public:
+ SidebarDockingWindow(
+ SfxBindings* pBindings,
+ SidebarChildWindow& rChildWindow,
+ Window* pParent,
+ WinBits nBits);
+ virtual ~SidebarDockingWindow (void);
+
+ virtual sal_Bool Close (void);
+
+ SfxChildWindow* GetChildWindow (void);
+
+protected:
+ // Window overridables
+ virtual void GetFocus (void);
+ virtual long PreNotify (NotifyEvent& rEvent);
+
+private:
+ ::rtl::Reference<sfx2::sidebar::SidebarController> mpSidebarController;
+
+ void DoDispose (void);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+
+#endif
diff --git a/sfx2/source/sidebar/SidebarPanel.cxx b/sfx2/source/sidebar/SidebarPanel.cxx
new file mode 100644
index 000000000000..33c3ef6ff7cf
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarPanel.cxx
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "precompiled_sfx2.hxx"
+
+#include "SidebarPanel.hxx"
+
+#include "Panel.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/smplhint.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+
+
+using namespace css;
+using namespace cssu;
+
+namespace sfx2 { namespace sidebar {
+
+Reference<css::ui::XSidebarPanel> SidebarPanel::Create (Panel* pPanel)
+{
+ return Reference<css::ui::XSidebarPanel>(new SidebarPanel(pPanel));
+}
+
+
+
+
+SidebarPanel::SidebarPanel(Panel* pPanel)
+ : SidebarPanelInterfaceBase(m_aMutex),
+ mpPanel(pPanel),
+ mxCanvas()
+{
+ if (mpPanel != NULL)
+ mpPanel->AddEventListener(LINK(this, SidebarPanel, HandleWindowEvent));
+ else
+ {
+ mpPanel = NULL;
+ dispose();
+ }
+}
+
+
+
+
+SidebarPanel::~SidebarPanel (void)
+{
+}
+
+
+
+
+void SAL_CALL SidebarPanel::disposing (const css::lang::EventObject& rEventObject)
+ throw(cssu::RuntimeException)
+{
+ (void)rEventObject;
+}
+
+
+
+
+void SAL_CALL SidebarPanel::disposing (void)
+{
+ if (mpPanel != NULL)
+ {
+ mpPanel->RemoveEventListener(LINK(this, SidebarPanel, HandleWindowEvent));
+ mpPanel = NULL;
+ }
+}
+
+
+
+
+cssu::Reference<css::rendering::XCanvas> SAL_CALL SidebarPanel::getCanvas (void)
+ throw (cssu::RuntimeException)
+{
+ if ( ! mxCanvas.is())
+ {
+ Sequence<Any> aArg (5);
+
+ // common: first any is VCL pointer to window (for VCL canvas)
+ aArg[0] = makeAny(reinterpret_cast<sal_Int64>(mpPanel));
+ aArg[1] = Any();
+ aArg[2] = makeAny(::com::sun::star::awt::Rectangle());
+ aArg[3] = makeAny(sal_False);
+ aArg[4] = makeAny(mpPanel->GetComponentInterface());
+
+ const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory());
+ mxCanvas = Reference<rendering::XCanvas>(
+ aComponentContext.createComponentWithArguments(
+ "com.sun.star.rendering.VCLCanvas",
+ aArg),
+ UNO_QUERY);
+ }
+
+ return mxCanvas;
+
+}
+
+
+
+
+awt::Point SAL_CALL SidebarPanel::getPositionOnScreen (void)
+ throw (cssu::RuntimeException)
+{
+ awt::Point aAwtPoint;
+
+ if (mpPanel != NULL)
+ {
+ ::vos::OGuard aGuard (Application::GetSolarMutex());
+
+ // mpPanel->GetPosPixel()
+ const Point aLocationOnScreen (mpPanel->OutputToAbsoluteScreenPixel(Point(0,0)));
+
+ aAwtPoint.X = aLocationOnScreen.X();
+ aAwtPoint.Y = aLocationOnScreen.Y();
+ }
+
+ return aAwtPoint;
+}
+
+
+
+
+Reference<beans::XPropertySet> SAL_CALL SidebarPanel::getThemeProperties (void)
+ throw (RuntimeException)
+{
+ return Theme::GetPropertySet();
+}
+
+
+
+
+IMPL_LINK(SidebarPanel, HandleWindowEvent, VclWindowEvent*, pEvent)
+{
+ if (pEvent != NULL)
+ {
+ switch (pEvent->GetId())
+ {
+ case SFX_HINT_DYING:
+ dispose();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return sal_True;
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarPanel.hxx b/sfx2/source/sidebar/SidebarPanel.hxx
new file mode 100644
index 000000000000..99a8e8020394
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarPanel.hxx
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_SIDEBAR_PANEL_HXX
+#define SFX_SIDEBAR_SIDEBAR_PANEL_HXX
+
+#include <tools/link.hxx>
+#include <com/sun/star/ui/XSidebarPanel.hpp>
+
+#include <boost/noncopyable.hpp>
+#include <cppuhelper/compbase1.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+namespace
+{
+ typedef ::cppu::WeakComponentImplHelper1 <
+ css::ui::XSidebarPanel
+ > SidebarPanelInterfaceBase;
+}
+
+
+class DockingWindow;
+class VclWindowEvent;
+
+namespace sfx2 { namespace sidebar {
+
+class Panel;
+
+class SidebarPanel
+ : private ::boost::noncopyable,
+ private ::cppu::BaseMutex,
+ public SidebarPanelInterfaceBase
+{
+public:
+ static cssu::Reference<css::ui::XSidebarPanel> Create (Panel* pPanel);
+
+protected:
+ SidebarPanel(
+ Panel* pPanel);
+ virtual ~SidebarPanel (void);
+
+ virtual void SAL_CALL disposing (const css::lang::EventObject& rEventObject)
+ throw(cssu::RuntimeException);
+
+ virtual void SAL_CALL disposing (void);
+
+private:
+ Panel* mpPanel;
+ cssu::Reference<css::rendering::XCanvas> mxCanvas;
+
+ DECL_LINK(HandleWindowEvent, VclWindowEvent*);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/SidebarPanelBase.cxx b/sfx2/source/sidebar/SidebarPanelBase.cxx
new file mode 100644
index 000000000000..6a17fb70dfcf
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarPanelBase.cxx
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sfx2/sidebar/SidebarPanelBase.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "sfx2/sidebar/ILayoutableWindow.hxx"
+#include "sfx2/sidebar/IContextChangeReceiver.hxx"
+#include "sfx2/imagemgr.hxx"
+#include <vcl/ctrl.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
+#include <com/sun/star/ui/UIElementType.hpp>
+
+using namespace css;
+using namespace cssu;
+
+
+namespace sfx2 { namespace sidebar {
+
+Reference<ui::XUIElement> SidebarPanelBase::Create (
+ const ::rtl::OUString& rsResourceURL,
+ const cssu::Reference<css::frame::XFrame>& rxFrame,
+ Window* pWindow,
+ const css::ui::LayoutSize& rLayoutSize)
+{
+ Reference<ui::XUIElement> xUIElement (
+ new SidebarPanelBase(
+ rsResourceURL,
+ rxFrame,
+ pWindow,
+ rLayoutSize));
+ return xUIElement;
+}
+
+
+
+
+SidebarPanelBase::SidebarPanelBase (
+ const ::rtl::OUString& rsResourceURL,
+ const cssu::Reference<css::frame::XFrame>& rxFrame,
+ Window* pWindow,
+ const css::ui::LayoutSize& rLayoutSize)
+ : SidebarPanelBaseInterfaceBase(m_aMutex),
+ mxFrame(rxFrame),
+ mpControl(pWindow),
+ msResourceURL(rsResourceURL),
+ maLayoutSize(rLayoutSize)
+{
+ if (mxFrame.is())
+ {
+ cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
+ css::ui::ContextChangeEventMultiplexer::get(
+ ::comphelper::getProcessComponentContext()));
+ if (xMultiplexer.is())
+ xMultiplexer->addContextChangeEventListener(this, mxFrame->getController());
+ }
+ if (mpControl != NULL)
+ {
+ mpControl->SetBackground(Theme::GetWallpaper(Theme::Paint_PanelBackground));
+ mpControl->Show();
+ }
+}
+
+
+
+
+SidebarPanelBase::~SidebarPanelBase (void)
+{
+}
+
+
+
+
+void SAL_CALL SidebarPanelBase::disposing (void)
+ throw (cssu::RuntimeException)
+{
+ if (mpControl != NULL)
+ {
+ delete mpControl;
+ mpControl = NULL;
+ }
+
+ if (mxFrame.is())
+ {
+ cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
+ css::ui::ContextChangeEventMultiplexer::get(
+ ::comphelper::getProcessComponentContext()));
+ if (xMultiplexer.is())
+ xMultiplexer->removeAllContextChangeEventListeners(this);
+ mxFrame = NULL;
+ }
+}
+
+
+
+
+void SidebarPanelBase::SetControl (::Window* pControl)
+{
+ mpControl = pControl;
+}
+
+
+
+
+::Window* SidebarPanelBase::GetControl (void) const
+{
+ return mpControl;
+}
+
+
+
+
+// XContextChangeEventListener
+void SAL_CALL SidebarPanelBase::notifyContextChangeEvent (
+ const ui::ContextChangeEventObject& rEvent)
+ throw (cssu::RuntimeException)
+{
+ IContextChangeReceiver* pContextChangeReceiver
+ = dynamic_cast<IContextChangeReceiver*>(mpControl);
+ if (pContextChangeReceiver != NULL)
+ {
+ const EnumContext aContext(
+ EnumContext::GetApplicationEnum(rEvent.ApplicationName),
+ EnumContext::GetContextEnum(rEvent.ContextName));
+ pContextChangeReceiver->HandleContextChange(aContext);
+ }
+}
+
+
+
+
+void SAL_CALL SidebarPanelBase::disposing (
+ const css::lang::EventObject& rEvent)
+ throw (cssu::RuntimeException)
+{
+ (void)rEvent;
+
+ mxFrame = NULL;
+ mpControl = NULL;
+}
+
+
+
+
+cssu::Reference<css::frame::XFrame> SAL_CALL SidebarPanelBase::getFrame (void)
+ throw(cssu::RuntimeException)
+{
+ return mxFrame;
+}
+
+
+
+
+::rtl::OUString SAL_CALL SidebarPanelBase::getResourceURL (void)
+ throw(cssu::RuntimeException)
+{
+ return msResourceURL;
+}
+
+
+
+
+sal_Int16 SAL_CALL SidebarPanelBase::getType (void)
+ throw(cssu::RuntimeException)
+{
+ return ui::UIElementType::TOOLPANEL;
+}
+
+
+
+
+Reference<XInterface> SAL_CALL SidebarPanelBase::getRealInterface (void)
+ throw(cssu::RuntimeException)
+{
+ return Reference<XInterface>(static_cast<XWeak*>(this));
+}
+
+
+
+
+Reference<accessibility::XAccessible> SAL_CALL SidebarPanelBase::createAccessible (
+ const Reference<accessibility::XAccessible>& rxParentAccessible)
+ throw(cssu::RuntimeException)
+{
+ (void)rxParentAccessible;
+
+ // Not yet implemented.
+ return NULL;
+}
+
+
+
+
+Reference<awt::XWindow> SAL_CALL SidebarPanelBase::getWindow (void)
+ throw(cssu::RuntimeException)
+{
+ if (mpControl != NULL)
+ return Reference<awt::XWindow>(
+ mpControl->GetComponentInterface(),
+ UNO_QUERY);
+ else
+ return NULL;
+}
+
+
+
+
+ui::LayoutSize SAL_CALL SidebarPanelBase::getHeightForWidth (const sal_Int32 nWidth)
+ throw(cssu::RuntimeException)
+{
+ if (maLayoutSize.Minimum >= 0)
+ return maLayoutSize;
+ else
+ {
+ ILayoutableWindow* pLayoutableWindow = dynamic_cast<ILayoutableWindow*>(mpControl);
+ if (pLayoutableWindow != NULL)
+ return pLayoutableWindow->GetHeightForWidth(nWidth);
+ else if (mpControl != NULL)
+ {
+ const sal_Int32 nHeight (mpControl->GetSizePixel().Height());
+ return ui::LayoutSize(nHeight,nHeight,nHeight);
+ }
+ }
+
+ return ui::LayoutSize(0,0,0);
+}
+
+IContextChangeReceiver::~IContextChangeReceiver()
+{
+}
+
+ILayoutableWindow::~ILayoutableWindow()
+{
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarResource.hxx b/sfx2/source/sidebar/SidebarResource.hxx
new file mode 100644
index 000000000000..be1371ba7ff7
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarResource.hxx
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_RESOURCE_HXX
+#define SFX_SIDEBAR_RESOURCE_HXX
+
+
+#include "Sidebar.hrc"
+#include <sfx2/sfxresid.hxx>
+#include <tools/rc.hxx>
+
+
+class SidebarResource : public Resource
+{
+public:
+ SidebarResource (void) : Resource(SfxResId(RID_SIDEBAR_RESOURCE)){}
+ ~SidebarResource (void) { FreeResource(); }
+};
+
+
+#endif
diff --git a/sfx2/source/sidebar/SidebarToolBox.cxx b/sfx2/source/sidebar/SidebarToolBox.cxx
new file mode 100644
index 000000000000..6a404dfec2c6
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarToolBox.cxx
@@ -0,0 +1,153 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "SidebarToolBox.hxx"
+#include "ToolBoxBackground.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "Tools.hxx"
+
+#include <vcl/gradient.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+SidebarToolBox::SidebarToolBox (
+ Window* pParentWindow,
+ const ResId& rResId)
+ : ToolBox(pParentWindow, rResId),
+ mbParentIsBorder(false),
+ maItemSeparator(Theme::GetImage(Theme::Image_ToolBoxItemSeparator))
+{
+ SetBackground(Wallpaper());
+ SetPaintTransparent(true);
+#ifdef DEBUG
+ SetText(A2S("SidebarToolBox"));
+#endif
+}
+
+
+
+
+SidebarToolBox::~SidebarToolBox (void)
+{
+}
+
+
+
+
+void SidebarToolBox::SetBorderWindow (const Window* pBorderWindow)
+{
+ if (pBorderWindow != GetParent())
+ {
+ OSL_ASSERT("SetBorderWindow can only handle parent as border window");
+ return;
+ }
+
+ if ( ! mbParentIsBorder)
+ {
+ mbParentIsBorder = true;
+
+ setPosSizePixel (
+ GetPosPixel().X(),
+ GetPosPixel().Y(),
+ GetSizePixel().Width(),
+ GetSizePixel().Height(),
+ WINDOW_POSSIZE_ALL);
+ }
+}
+
+
+
+
+void SidebarToolBox::Paint (const Rectangle& rRect)
+{
+ ToolBox::Paint(rRect);
+
+ if (Theme::GetBoolean(Theme::Bool_UseToolBoxItemSeparator))
+ {
+ const sal_Int32 nSeparatorY ((GetSizePixel().Height() - maItemSeparator.GetSizePixel().Height())/2);
+ const sal_uInt16 nItemCount (GetItemCount());
+ int nLastRight (-1);
+ for (sal_uInt16 nIndex=0; nIndex<nItemCount; ++nIndex)
+ {
+ const Rectangle aItemBoundingBox (GetItemPosRect(nIndex));
+ if (nLastRight >= 0)
+ {
+ const int nSeparatorX ((nLastRight + aItemBoundingBox.Left() - 1) / 2);
+ DrawImage(Point(nSeparatorX,nSeparatorY), maItemSeparator);
+ }
+
+ nLastRight = aItemBoundingBox.Right();
+ }
+ }
+}
+
+
+
+
+Point SidebarToolBox::GetPosPixel (void) const
+{
+ if (mbParentIsBorder)
+ {
+ const Point aParentPoint (GetParent()->GetPosPixel());
+ const Point aChildPoint (ToolBox::GetPosPixel());
+ return Point(
+ aParentPoint.X() + aChildPoint.X(),
+ aParentPoint.Y() + aChildPoint.Y());
+ }
+ else
+ return ToolBox::GetPosPixel();
+}
+
+
+
+
+void SidebarToolBox::setPosSizePixel (
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags)
+{
+ if (mbParentIsBorder)
+ {
+ const Point aRelativePosition (static_cast<ToolBoxBackground*>(GetParent())->SetToolBoxChild(
+ this,
+ nX,
+ nY,
+ nWidth,
+ nHeight,
+ nFlags));
+ ToolBox::setPosSizePixel(
+ aRelativePosition.X(),
+ aRelativePosition.Y(),
+ nWidth,
+ nHeight,
+ nFlags);
+ }
+ else
+ ToolBox::setPosSizePixel(nX, nY, nWidth, nHeight, nFlags);
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/SidebarToolBox.hxx b/sfx2/source/sidebar/SidebarToolBox.hxx
new file mode 100644
index 000000000000..125839a8a24d
--- /dev/null
+++ b/sfx2/source/sidebar/SidebarToolBox.hxx
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TOOLBOX_HXX
+#define SFX_SIDEBAR_TOOLBOX_HXX
+
+#include "vcl/toolbox.hxx"
+
+
+namespace sfx2 { namespace sidebar {
+
+class SidebarToolBox
+ : public ToolBox
+{
+public:
+ SidebarToolBox (Window* pParentWindow, const ResId& rResId);
+ virtual ~SidebarToolBox (void);
+
+ void SetBorderWindow (const Window* pBorderWindow);
+ virtual void Paint (const Rectangle& rRect);
+
+ virtual Point GetPosPixel (void) const;
+ virtual void setPosSizePixel (
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags);
+
+private:
+ bool mbParentIsBorder;
+ Image maItemSeparator;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/TabBar.cxx b/sfx2/source/sidebar/TabBar.cxx
new file mode 100644
index 000000000000..c30953bbdd94
--- /dev/null
+++ b/sfx2/source/sidebar/TabBar.cxx
@@ -0,0 +1,385 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * 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 "TabItem.hxx"
+#include "sidebar/ControlFactory.hxx"
+#include "DeckDescriptor.hxx"
+#include "Paint.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+#include "Tools.hxx"
+#include "FocusManager.hxx"
+
+#include <vcl/gradient.hxx>
+#include <vcl/image.hxx>
+#include <vcl/wrkwin.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <tools/svborder.hxx>
+
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+
+
+namespace sfx2 { namespace sidebar {
+
+TabBar::TabBar (
+ Window* pParentWindow,
+ const Reference<frame::XFrame>& rxFrame,
+ const ::boost::function<void(const ::rtl::OUString&)>& rDeckActivationFunctor,
+ const PopupMenuProvider& rPopupMenuProvider)
+ : Window(pParentWindow, WB_DIALOGCONTROL),
+ mxFrame(rxFrame),
+ mpMenuButton(ControlFactory::CreateMenuButton(this)),
+ maItems(),
+ maDeckActivationFunctor(rDeckActivationFunctor),
+ maPopupMenuProvider(rPopupMenuProvider)
+{
+ SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
+
+ mpMenuButton->SetModeImage(Theme::GetImage(Theme::Image_TabBarMenu));
+ mpMenuButton->SetClickHdl(LINK(this, TabBar, OnToolboxClicked));
+ Layout();
+
+#ifdef DEBUG
+ SetText(A2S("TabBar"));
+#endif
+}
+
+
+
+
+TabBar::~TabBar (void)
+{
+}
+
+
+
+
+void TabBar::Paint (const Rectangle& rUpdateArea)
+{
+ Window::Paint(rUpdateArea);
+
+ const sal_Int32 nHorizontalPadding (Theme::GetInteger(Theme::Int_TabMenuSeparatorPadding));
+ SetLineColor(Theme::GetColor(Theme::Color_TabMenuSeparator));
+ DrawLine(
+ Point(nHorizontalPadding, mnMenuSeparatorY),
+ Point(GetSizePixel().Width()-nHorizontalPadding, mnMenuSeparatorY));
+}
+
+
+
+
+sal_Int32 TabBar::GetDefaultWidth (void)
+{
+ return Theme::GetInteger(Theme::Int_TabItemWidth)
+ + Theme::GetInteger(Theme::Int_TabBarLeftPadding)
+ + Theme::GetInteger(Theme::Int_TabBarRightPadding);
+}
+
+
+
+
+void TabBar::SetDecks (
+ const ResourceManager::IdContainer& rDeckIds)
+{
+ // Remove the current buttons.
+ {
+ for(ItemContainer::iterator
+ iItem(maItems.begin()), iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ iItem->mpButton.reset();
+ }
+ maItems.clear();
+ }
+
+ maItems.resize(rDeckIds.size());
+ sal_Int32 nIndex (0);
+ for (ResourceManager::IdContainer::const_iterator
+ iDeckId(rDeckIds.begin()),
+ iEnd(rDeckIds.end());
+ iDeckId!=iEnd;
+ ++iDeckId)
+ {
+ const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(*iDeckId);
+ if (pDescriptor == NULL)
+ {
+ OSL_ASSERT(pDescriptor!=NULL);
+ continue;
+ }
+
+ Item& rItem (maItems[nIndex++]);
+ rItem.msDeckId = pDescriptor->msId;
+ rItem.mpButton.reset(CreateTabItem(*pDescriptor));
+ rItem.mpButton->SetClickHdl(LINK(&rItem, TabBar::Item, HandleClick));
+ rItem.maDeckActivationFunctor = maDeckActivationFunctor;
+ rItem.mbIsHiddenByDefault = false;
+ rItem.mbIsHidden = ! pDescriptor->mbIsEnabled;
+ }
+
+ UpdateButtonIcons();
+ Layout();
+}
+
+
+
+
+void TabBar::UpdateButtonIcons (void)
+{
+ mpMenuButton->SetModeImage(Theme::GetImage(Theme::Image_TabBarMenu));
+
+ for(ItemContainer::const_iterator
+ iItem(maItems.begin()), iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
+ if (pDeckDescriptor != NULL)
+ iItem->mpButton->SetModeImage(GetItemImage(*pDeckDescriptor));
+ }
+
+ Invalidate();
+}
+
+
+
+
+void TabBar::Layout (void)
+{
+ const SvBorder aPadding (
+ Theme::GetInteger(Theme::Int_TabBarLeftPadding),
+ Theme::GetInteger(Theme::Int_TabBarTopPadding),
+ Theme::GetInteger(Theme::Int_TabBarRightPadding),
+ Theme::GetInteger(Theme::Int_TabBarBottomPadding));
+ sal_Int32 nX (aPadding.Top());
+ sal_Int32 nY (aPadding.Left());
+ const Size aTabItemSize (
+ Theme::GetInteger(Theme::Int_TabItemWidth),
+ Theme::GetInteger(Theme::Int_TabItemHeight));
+
+ // Place the menu button and the separator.
+ if (mpMenuButton != NULL)
+ {
+ mpMenuButton->SetPosSizePixel(
+ Point(nX,nY),
+ aTabItemSize);
+ mpMenuButton->Show();
+ nY += mpMenuButton->GetSizePixel().Height() + 1 + Theme::GetInteger(Theme::Int_TabMenuPadding);
+ mnMenuSeparatorY = nY - Theme::GetInteger(Theme::Int_TabMenuPadding)/2 - 1;
+ }
+
+ // Place the deck selection buttons.
+ for(ItemContainer::const_iterator
+ iItem(maItems.begin()), iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ Button& rButton (*iItem->mpButton);
+ rButton.Show( ! iItem->mbIsHidden);
+
+ if (iItem->mbIsHidden)
+ continue;
+
+ // Place and size the icon.
+ rButton.SetPosSizePixel(
+ Point(nX,nY),
+ aTabItemSize);
+ rButton.Show();
+
+ nY += rButton.GetSizePixel().Height() + 1 + aPadding.Bottom();
+ }
+ Invalidate();
+}
+
+
+
+
+void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId)
+{
+ for (ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ if (iItem->msDeckId.equals(rsDeckId))
+ {
+ iItem->mpButton->Check();
+ break;
+ }
+ }
+}
+
+
+
+
+void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent)
+{
+ SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
+ UpdateButtonIcons();
+
+ Window::DataChanged(rDataChangedEvent);
+}
+
+
+
+
+RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor)
+{
+ RadioButton* pItem = ControlFactory::CreateTabItem(this);
+ pItem->SetHelpText(rDeckDescriptor.msHelpText);
+ pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
+
+ return pItem;
+}
+
+
+
+Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const
+{
+ return Tools::GetImage(
+ rDeckDescriptor.msIconURL,
+ rDeckDescriptor.msHighContrastIconURL,
+ mxFrame);
+}
+
+
+
+
+
+IMPL_LINK(TabBar::Item, HandleClick, Button*, EMPTYARG)
+{
+ maDeckActivationFunctor(msDeckId);
+ return 1;
+}
+
+
+
+
+const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
+{
+ if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
+ throw RuntimeException();
+ else
+ return maItems[nIndex].msDeckId;
+}
+
+
+
+
+void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
+{
+ if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
+ throw RuntimeException();
+ else
+ {
+ maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
+ ResourceManager::Instance().SetIsDeckEnabled(
+ maItems[nIndex].msDeckId,
+ maItems[nIndex].mbIsHidden);
+ Layout();
+ }
+}
+
+
+
+
+void TabBar::RestoreHideFlags (void)
+{
+ bool bNeedsLayout (false);
+ for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
+ {
+ iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
+ bNeedsLayout = true;
+ }
+ }
+ if (bNeedsLayout)
+ Layout();
+}
+
+
+
+
+void TabBar::UpdateFocusManager (FocusManager& rFocusManager)
+{
+ ::std::vector<Button*> aButtons;
+ aButtons.reserve(maItems.size()+1);
+
+ aButtons.push_back(mpMenuButton.get());
+ for(ItemContainer::const_iterator
+ iItem(maItems.begin()), iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ aButtons.push_back(iItem->mpButton.get());
+ }
+ rFocusManager.SetButtons(aButtons);
+}
+
+
+
+
+IMPL_LINK(TabBar, OnToolboxClicked, void*, EMPTYARG)
+{
+ ::std::vector<DeckMenuData> aSelectionData;
+ ::std::vector<DeckMenuData> aShowData;
+
+ for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
+ iItem!=iEnd;
+ ++iItem)
+ {
+ const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
+ if (pDeckDescriptor != NULL)
+ {
+ if ( ! iItem->mbIsHidden)
+ aSelectionData.push_back(
+ DeckMenuData(
+ pDeckDescriptor->msTitle,
+ pDeckDescriptor->msId,
+ iItem->mpButton->IsChecked()));
+
+ aShowData.push_back(
+ DeckMenuData(
+ pDeckDescriptor->msTitle,
+ pDeckDescriptor->msId,
+ !iItem->mbIsHidden));
+ }
+ }
+
+ maPopupMenuProvider(
+ Rectangle(
+ mpMenuButton->GetPosPixel(),
+ mpMenuButton->GetSizePixel()),
+ aSelectionData,
+ aShowData);
+
+ return 0;
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/TabBar.hxx b/sfx2/source/sidebar/TabBar.hxx
new file mode 100644
index 000000000000..50ea6f3537d0
--- /dev/null
+++ b/sfx2/source/sidebar/TabBar.hxx
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TAB_BAR_HXX
+#define SFX_SIDEBAR_TAB_BAR_HXX
+
+#include "DeckDescriptor.hxx"
+#include "ResourceManager.hxx"
+
+#include <vcl/menu.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/frame/XFrame.hpp>
+#include <boost/function.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/scoped_ptr.hpp>
+
+class Button;
+class RadioButton;
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+class FocusManager;
+class TabBarConfiguration;
+class TabItem;
+
+/** The tab bar is the container for the individual tabs.
+*/
+class TabBar
+ : public Window
+{
+public:
+ /** DeckMenuData has entries for display name, deck id, and a flag:
+ - isCurrentDeck for the deck selection data
+ - isEnabled for the show/hide menu
+ */
+ typedef ::boost::tuple<rtl::OUString,rtl::OUString,bool> DeckMenuData;
+ typedef ::boost::function<void(
+ const Rectangle&,
+ const ::std::vector<DeckMenuData>& rDeckSelectionData,
+ const ::std::vector<DeckMenuData>& rDeckShowData)> PopupMenuProvider;
+ TabBar (
+ Window* pParentWindow,
+ const cssu::Reference<css::frame::XFrame>& rxFrame,
+ const ::boost::function<void(const ::rtl::OUString&rsDeckId)>& rDeckActivationFunctor,
+ const PopupMenuProvider& rPopupMenuProvider);
+ virtual ~TabBar (void);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void DataChanged (const DataChangedEvent& rDataChangedEvent);
+
+ static sal_Int32 GetDefaultWidth (void);
+
+ void SetDecks (
+ const ResourceManager::IdContainer& rDeckIds);
+ void HighlightDeck (const ::rtl::OUString& rsDeckId);
+ void AddPopupMenuEntries (
+ PopupMenu& rMenu,
+ const sal_Int32 nFirstIndex);
+ void AddCustomizationMenuEntries (
+ PopupMenu& rMenu,
+ const sal_Int32 nFirstIndex);
+ const ::rtl::OUString GetDeckIdForIndex (const sal_Int32 nIndex) const;
+ void ToggleHideFlag (const sal_Int32 nIndex);
+ void RestoreHideFlags (void);
+
+ void UpdateFocusManager (FocusManager& rFocusManager);
+
+private:
+ cssu::Reference<css::frame::XFrame> mxFrame;
+ ::boost::scoped_ptr<Button> mpMenuButton;
+ class Item
+ {
+ public:
+ DECL_LINK(HandleClick, Button*);
+ ::boost::shared_ptr<RadioButton> mpButton;
+ ::rtl::OUString msDeckId;
+ ::boost::function<void(const ::rtl::OUString&rsDeckId)> maDeckActivationFunctor;
+ bool mbIsHidden;
+ bool mbIsHiddenByDefault;
+ };
+ typedef ::std::vector<Item> ItemContainer;
+ ItemContainer maItems;
+ const ::boost::function<void(const ::rtl::OUString&rsDeckId)> maDeckActivationFunctor;
+ sal_Int32 mnMenuSeparatorY;
+ PopupMenuProvider maPopupMenuProvider;
+
+ RadioButton* CreateTabItem (const DeckDescriptor& rDeckDescriptor);
+ Image GetItemImage (const DeckDescriptor& rDeskDescriptor) const;
+ void Layout (void);
+ void UpdateButtonIcons (void);
+
+ ::boost::shared_ptr<PopupMenu> CreatePopupMenu (void) const;
+ void ShowPopupMenu (void) const;
+ DECL_LINK(OnToolboxClicked, void*);
+
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/TabItem.cxx b/sfx2/source/sidebar/TabItem.cxx
new file mode 100644
index 000000000000..059fabdf6d7b
--- /dev/null
+++ b/sfx2/source/sidebar/TabItem.cxx
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TabItem.hxx"
+
+#include "DrawHelper.hxx"
+#include "Paint.hxx"
+#include "Tools.hxx"
+
+#include "sfx2/sidebar/Theme.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+
+TabItem::TabItem (Window* pParentWindow)
+ : ImageRadioButton(pParentWindow),
+ mbIsLeftButtonDown(false),
+ mePaintType(PT_Theme)
+{
+ SetStyle(GetStyle() | WB_TABSTOP | WB_DIALOGCONTROL | WB_NOPOINTERFOCUS);
+ SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
+#ifdef DEBUG
+ SetText(A2S("TabItem"));
+#endif
+}
+
+
+
+
+TabItem::~TabItem (void)
+{
+}
+
+
+
+
+void TabItem::Paint (const Rectangle& rUpdateArea)
+{
+ OSL_TRACE("TabItem::Paint");
+ switch(mePaintType)
+ {
+ case PT_Theme:
+ default:
+ {
+ const bool bIsSelected (IsChecked());
+ const bool bIsHighlighted (IsMouseOver() || HasFocus());
+ DrawHelper::DrawRoundedRectangle(
+ *this,
+ Rectangle(Point(0,0), GetSizePixel()),
+ Theme::GetInteger(Theme::Int_ButtonCornerRadius),
+ bIsHighlighted||bIsSelected
+ ? Theme::GetColor(Theme::Color_TabItemBorder)
+ : Color(0xffffffff),
+ bIsHighlighted
+ ? Theme::GetPaint(Theme::Paint_TabItemBackgroundHighlight)
+ : Theme::GetPaint(Theme::Paint_TabItemBackgroundNormal));
+
+ const Image aIcon(Button::GetModeImage());
+ const Size aIconSize (aIcon.GetSizePixel());
+ const Point aIconLocation(
+ (GetSizePixel().Width() - aIconSize.Width())/2,
+ (GetSizePixel().Height() - aIconSize.Height())/2);
+ DrawImage(
+ aIconLocation,
+ aIcon);
+ break;
+ }
+ case PT_Native:
+ Button::Paint(rUpdateArea);
+ // DrawImage(maIconPosition, maIcon);
+ break;
+ }
+}
+
+
+
+
+void TabItem::MouseMove (const MouseEvent& rEvent)
+{
+ if (rEvent.IsEnterWindow() || rEvent.IsLeaveWindow())
+ Invalidate();
+ ImageRadioButton::MouseMove(rEvent);
+}
+
+
+
+
+void TabItem::MouseButtonDown (const MouseEvent& rMouseEvent)
+{
+ if (rMouseEvent.IsLeft())
+ {
+ mbIsLeftButtonDown = true;
+ CaptureMouse();
+ Invalidate();
+ }
+}
+
+
+
+
+void TabItem::MouseButtonUp (const MouseEvent& rMouseEvent)
+{
+ if (IsMouseCaptured())
+ ReleaseMouse();
+
+ if (rMouseEvent.IsLeft())
+ {
+ if (mbIsLeftButtonDown)
+ {
+ Check();
+ Click();
+ GetParent()->Invalidate();
+ }
+ }
+ if (mbIsLeftButtonDown)
+ {
+ mbIsLeftButtonDown = false;
+ Invalidate();
+ }
+}
+
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/TabItem.hxx b/sfx2/source/sidebar/TabItem.hxx
new file mode 100644
index 000000000000..31898b3e8334
--- /dev/null
+++ b/sfx2/source/sidebar/TabItem.hxx
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TAB_ITEM_HXX
+#define SFX_SIDEBAR_TAB_ITEM_HXX
+
+#include "vcl/button.hxx"
+
+#include "DeckDescriptor.hxx"
+
+class Window;
+
+namespace sfx2 { namespace sidebar {
+
+/** A single button in the The tab bar.
+*/
+class TabItem
+ : public ImageRadioButton
+{
+public:
+ TabItem (Window* pParentWindow);
+ virtual ~TabItem (void);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void MouseMove (const MouseEvent& rEvent);
+ virtual void MouseButtonDown (const MouseEvent& rMouseEvent);
+ virtual void MouseButtonUp (const MouseEvent& rMouseEvent);
+
+private:
+ bool mbIsLeftButtonDown;
+ enum PaintType {
+ PT_Native,
+ PT_Theme
+ } mePaintType;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Theme.cxx b/sfx2/source/sidebar/Theme.cxx
new file mode 100644
index 000000000000..d571885ca525
--- /dev/null
+++ b/sfx2/source/sidebar/Theme.cxx
@@ -0,0 +1,1148 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sfx2/sidebar/Theme.hxx"
+#include "Paint.hxx"
+#include "SidebarResource.hxx"
+#include "Tools.hxx"
+
+#include <tools/svborder.hxx>
+#include <tools/rc.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace css;
+using namespace cssu;
+
+
+namespace sfx2 { namespace sidebar {
+
+::rtl::Reference<Theme> Theme::mpInstance;
+
+
+
+
+Theme& Theme::GetCurrentTheme (void)
+{
+ if ( ! mpInstance.is())
+ {
+ mpInstance.set(new Theme());
+ mpInstance->InitializeTheme();
+ }
+ return *mpInstance;
+}
+
+
+
+
+Theme::Theme (void)
+ : ThemeInterfaceBase(m_aMutex),
+ maImages(),
+ maColors(),
+ maPaints(),
+ maIntegers(),
+ maBooleans(),
+ mbIsHighContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()),
+ mbIsHighContrastModeSetManually(false),
+ maPropertyNameToIdMap(),
+ maPropertyIdToNameMap(),
+ maRawValues(),
+ maChangeListeners(),
+ maVetoableListeners()
+
+{
+ SetupPropertyMaps();
+}
+
+
+
+
+Theme::~Theme (void)
+{
+}
+
+
+
+
+Image Theme::GetImage (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Image);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.maImages[nIndex];
+}
+
+
+
+
+Color Theme::GetColor (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Color || eType==PT_Paint);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ if (eType == PT_Color)
+ return rTheme.maColors[nIndex];
+ else if (eType == PT_Paint)
+ return rTheme.maPaints[nIndex].GetColor();
+ else
+ return COL_WHITE;
+}
+
+
+
+
+const Paint& Theme::GetPaint (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Paint);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.maPaints[nIndex];
+}
+
+
+
+
+const Wallpaper Theme::GetWallpaper (const ThemeItem eItem)
+{
+ return GetPaint(eItem).GetWallpaper();
+}
+
+
+
+
+sal_Int32 Theme::GetInteger (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Integer);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.maIntegers[nIndex];
+}
+
+
+
+
+bool Theme::GetBoolean (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Boolean);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.maBooleans[nIndex];
+}
+
+
+
+
+Rectangle Theme::GetRectangle (const ThemeItem eItem)
+{
+ const PropertyType eType (GetPropertyType(eItem));
+ OSL_ASSERT(eType==PT_Rectangle);
+ const sal_Int32 nIndex (GetIndex(eItem, eType));
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.maRectangles[nIndex];
+}
+
+
+
+
+bool Theme::IsHighContrastMode (void)
+{
+ const Theme& rTheme (GetCurrentTheme());
+ return rTheme.mbIsHighContrastMode;
+}
+
+
+
+
+void Theme::HandleDataChange (void)
+{
+ Theme& rTheme (GetCurrentTheme());
+
+ if ( ! rTheme.mbIsHighContrastModeSetManually)
+ {
+ // Do not modify mbIsHighContrastMode when it was manually set.
+ GetCurrentTheme().mbIsHighContrastMode = Application::GetSettings().GetStyleSettings().GetHighContrastMode();
+ rTheme.maRawValues[Bool_IsHighContrastModeActive] = Any(GetCurrentTheme().mbIsHighContrastMode);
+ }
+
+ GetCurrentTheme().UpdateTheme();
+}
+
+
+
+
+void Theme::InitializeTheme (void)
+{
+ setPropertyValue(
+ maPropertyIdToNameMap[Bool_UseSymphonyIcons],
+ Any(false));
+ setPropertyValue(
+ maPropertyIdToNameMap[Bool_UseSystemColors],
+ Any(false));
+}
+
+
+
+
+void Theme::UpdateTheme (void)
+{
+ SidebarResource aLocalResource;
+
+ try
+ {
+ const StyleSettings& rStyle (Application::GetSettings().GetStyleSettings());
+ const bool bUseSystemColors (GetBoolean(Bool_UseSystemColors));
+
+#define Alternatives(n,hc,sys) (mbIsHighContrastMode ? hc : (bUseSystemColors ? sys : n))
+
+ const Color aBaseBackgroundColor (rStyle.GetDialogColor());
+ Color aBorderColor (aBaseBackgroundColor);
+ aBorderColor.DecreaseLuminance(15);
+ Color aSecondColor (aBaseBackgroundColor);
+ aSecondColor.DecreaseLuminance(15);
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_DeckBackground],
+ Any(sal_Int32(rStyle.GetMenuColor().GetRGBColor())));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_DeckTitleBarBackground],
+ Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckLeftPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckTopPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckRightPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckBottomPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckBorderSize],
+ Any(sal_Int32(1)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckSeparatorHeight],
+ Any(sal_Int32(1)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_ButtonCornerRadius],
+ Any(sal_Int32(3)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_DeckTitleFont],
+ Any(sal_Int32(rStyle.GetFontColor().GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_DeckTitleBarHeight],
+ Any(sal_Int32(Alternatives(
+ 26,
+ 26,
+ rStyle.GetFloatTitleHeight()))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_PanelBackground],
+ Any(sal_Int32(rStyle.GetDialogColor().GetRGBColor())));
+ // Any(sal_Int32(mbIsHighContrastMode ? 0x000000 :
+ // 0xffffff)));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_PanelTitleBarBackground],
+ Any(Tools::VclToAwtGradient(Gradient(
+ GradientStyle_LINEAR,
+ aSecondColor.GetRGBColor(),
+ aBaseBackgroundColor.GetRGBColor()
+ ))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_PanelTitleFont],
+ Any(sal_Int32(mbIsHighContrastMode ? 0x00ff00 : 0x262626)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_PanelTitleBarHeight],
+ Any(sal_Int32(Alternatives(
+ 26,
+ 26,
+ rStyle.GetTitleHeight()))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_TabBarBackground],
+ Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabBarLeftPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabBarTopPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabBarRightPadding],
+ Any(sal_Int32(2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabBarBottomPadding],
+ Any(sal_Int32(2)));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabMenuPadding],
+ Any(sal_Int32(6)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_TabMenuSeparator],
+ Any(sal_Int32(aBorderColor.GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabMenuSeparatorPadding],
+ Any(sal_Int32(7)));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabItemWidth],
+ Any(sal_Int32(32)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Int_TabItemHeight],
+ Any(sal_Int32(32)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_TabItemBorder],
+ Any(sal_Int32(rStyle.GetActiveBorderColor().GetRGBColor())));
+ // mbIsHighContrastMode ? 0x00ff00 : 0xbfbfbf)));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_DropDownBackground],
+ Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_DropDownBorder],
+ Any(sal_Int32(rStyle.GetActiveBorderColor().GetRGBColor())));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_Highlight],
+ Any(sal_Int32(rStyle.GetHighlightColor().GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Color_HighlightText],
+ Any(sal_Int32(rStyle.GetHighlightTextColor().GetRGBColor())));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_TabItemBackgroundNormal],
+ Any());
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_TabItemBackgroundHighlight],
+ Any(sal_Int32(rStyle.GetActiveTabColor().GetRGBColor())));
+ // mbIsHighContrastMode ? 0x000000 : 0x00ffffff)));
+
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_HorizontalBorder],
+ Any(sal_Int32(aBorderColor.GetRGBColor())));
+ // mbIsHighContrastMode ? 0x00ff00 : 0xe4e4e4)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_VerticalBorder],
+ Any(sal_Int32(aBorderColor.GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_Grip],
+ Any(A2S("private:graphicrepository/sfx2/res/grip.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_Expand],
+ Any(A2S("private:graphicrepository/res/plus.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_Collapse],
+ Any(A2S("private:graphicrepository/res/minus.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_TabBarMenu],
+ Any(A2S("private:graphicrepository/sfx2/res/symphony/open_more.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_PanelMenu],
+ Any(A2S("private:graphicrepository/sfx2/res/symphony/morebutton.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_Closer],
+ Any(A2S("private:graphicrepository/sfx2/res/closedoc.png")));
+ setPropertyValue(
+ maPropertyIdToNameMap[Image_ToolBoxItemSeparator],
+ Any(
+ A2S("private:graphicrepository/sfx2/res/separator.png")));
+
+ // ToolBox
+
+ /*
+ // Separator style
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBackground],
+ Any(sal_Int32(rStyle.GetMenuColor().GetRGBColor())));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderTopLeft],
+ Any());
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderCenterCorners],
+ Any());
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderBottomRight],
+ Any());
+ setPropertyValue(
+ maPropertyIdToNameMap[Rect_ToolBoxPadding],
+ Any(awt::Rectangle(2,2,2,2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Rect_ToolBoxBorder],
+ Any(awt::Rectangle(0,0,0,0)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Bool_UseToolBoxItemSeparator],
+ Any(true));
+
+ */
+
+ // Gradient style
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBackground],
+ Any(Tools::VclToAwtGradient(Gradient(
+ GradientStyle_LINEAR,
+ Color(0xf2f2f2),
+ Color(0xfefefe)
+ ))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderTopLeft],
+ mbIsHighContrastMode
+ ? Any(util::Color(sal_uInt32(0x00ff00)))
+ : Any(util::Color(sal_uInt32(0xf2f2f2))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderCenterCorners],
+ mbIsHighContrastMode
+ ? Any(util::Color(sal_uInt32(0x00ff00)))
+ : Any(util::Color(sal_uInt32(0xf2f2f2))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Paint_ToolBoxBorderBottomRight],
+ mbIsHighContrastMode
+ ? Any(util::Color(sal_uInt32(0x00ff00)))
+ : Any(util::Color(sal_uInt32(0xf2f2f2))));
+ setPropertyValue(
+ maPropertyIdToNameMap[Rect_ToolBoxPadding],
+ Any(awt::Rectangle(2,2,2,2)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Rect_ToolBoxBorder],
+ Any(awt::Rectangle(1,1,1,1)));
+ setPropertyValue(
+ maPropertyIdToNameMap[Bool_UseToolBoxItemSeparator],
+ Any(false));
+ }
+ catch(beans::UnknownPropertyException& rException)
+ {
+ OSL_TRACE("unknown property: %s",
+ OUStringToOString(
+ rException.Message,
+ RTL_TEXTENCODING_ASCII_US).getStr());
+ OSL_ASSERT(false);
+ }
+}
+
+
+
+
+void SAL_CALL Theme::disposing (void)
+{
+ ChangeListeners aListeners;
+ maChangeListeners.swap(aListeners);
+
+ const lang::EventObject aEvent (static_cast<XWeak*>(this));
+
+ for (ChangeListeners::const_iterator
+ iContainer(maChangeListeners.begin()),
+ iContainerEnd(maChangeListeners.end());
+ iContainerEnd!=iContainerEnd;
+ ++iContainerEnd)
+ {
+ for (ChangeListenerContainer::const_iterator
+ iListener(iContainer->second.begin()),
+ iEnd(iContainer->second.end());
+ iListener!=iEnd;
+ ++iListener)
+ {
+ try
+ {
+ (*iListener)->disposing(aEvent);
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ }
+}
+
+
+
+
+Reference<beans::XPropertySet> Theme::GetPropertySet (void)
+{
+ return Reference<beans::XPropertySet>(static_cast<XWeak*>(&GetCurrentTheme()), UNO_QUERY);
+}
+
+
+
+
+Reference<beans::XPropertySetInfo> SAL_CALL Theme::getPropertySetInfo (void)
+ throw(cssu::RuntimeException)
+{
+ return Reference<beans::XPropertySetInfo>(this);
+}
+
+
+
+
+void SAL_CALL Theme::setPropertyValue (
+ const ::rtl::OUString& rsPropertyName,
+ const cssu::Any& rValue)
+ throw(cssu::RuntimeException)
+{
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException(rsPropertyName, NULL);
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException(rsPropertyName, NULL);
+
+ const ThemeItem eItem (iId->second);
+
+ if (rValue == maRawValues[eItem])
+ {
+ // Value is not different from the one in the property
+ // set => nothing to do.
+ return;
+ }
+
+ const Any aOldValue (maRawValues[eItem]);
+
+ const beans::PropertyChangeEvent aEvent(
+ static_cast<XWeak*>(this),
+ rsPropertyName,
+ sal_False,
+ eItem,
+ aOldValue,
+ rValue);
+
+ if (DoVetoableListenersVeto(GetVetoableListeners(__AnyItem, false), aEvent))
+ return;
+ if (DoVetoableListenersVeto(GetVetoableListeners(eItem, false), aEvent))
+ return;
+
+ maRawValues[eItem] = rValue;
+ ProcessNewValue(rValue, eItem, eType);
+
+ BroadcastPropertyChange(GetChangeListeners(__AnyItem, false), aEvent);
+ BroadcastPropertyChange(GetChangeListeners(eItem, false), aEvent);
+}
+
+
+
+
+Any SAL_CALL Theme::getPropertyValue (
+ const ::rtl::OUString& rsPropertyName)
+ throw(css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException,
+ cssu::RuntimeException)
+{
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ const ThemeItem eItem (iId->second);
+
+ return maRawValues[eItem];
+}
+
+
+
+
+void SAL_CALL Theme::addPropertyChangeListener(
+ const ::rtl::OUString& rsPropertyName,
+ const cssu::Reference<css::beans::XPropertyChangeListener>& rxListener)
+ throw(css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException,
+ cssu::RuntimeException)
+{
+ ThemeItem eItem (__AnyItem);
+ if (rsPropertyName.getLength() > 0)
+ {
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ eItem = iId->second;
+ }
+ ChangeListenerContainer* pListeners = GetChangeListeners(eItem, true);
+ if (pListeners != NULL)
+ pListeners->push_back(rxListener);
+}
+
+
+
+
+void SAL_CALL Theme::removePropertyChangeListener(
+ const ::rtl::OUString& rsPropertyName,
+ const cssu::Reference<css::beans::XPropertyChangeListener>& rxListener)
+ throw(css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException,
+ cssu::RuntimeException)
+{
+ ThemeItem eItem (__AnyItem);
+ if (rsPropertyName.getLength() > 0)
+ {
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ eItem = iId->second;
+ }
+ ChangeListenerContainer* pContainer = GetChangeListeners(eItem, false);
+ if (pContainer != NULL)
+ {
+ ChangeListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener));
+ if (iListener != pContainer->end())
+ {
+ pContainer->erase(iListener);
+
+ // Remove the listener container when empty.
+ if (pContainer->empty())
+ maChangeListeners.erase(eItem);
+ }
+ }
+}
+
+
+
+
+void SAL_CALL Theme::addVetoableChangeListener(
+ const ::rtl::OUString& rsPropertyName,
+ const cssu::Reference<css::beans::XVetoableChangeListener>& rxListener)
+ throw(css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException,
+ cssu::RuntimeException)
+{
+ ThemeItem eItem (__AnyItem);
+ if (rsPropertyName.getLength() > 0)
+ {
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ eItem = iId->second;
+ }
+ VetoableListenerContainer* pListeners = GetVetoableListeners(eItem, true);
+ if (pListeners != NULL)
+ pListeners->push_back(rxListener);
+}
+
+
+
+
+void SAL_CALL Theme::removeVetoableChangeListener(
+ const ::rtl::OUString& rsPropertyName,
+ const cssu::Reference<css::beans::XVetoableChangeListener>& rxListener)
+ throw(css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException,
+ cssu::RuntimeException)
+{
+ ThemeItem eItem (__AnyItem);
+ if (rsPropertyName.getLength() > 0)
+ {
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ eItem = iId->second;
+ }
+ VetoableListenerContainer* pContainer = GetVetoableListeners(eItem, false);
+ if (pContainer != NULL)
+ {
+ VetoableListenerContainer::iterator iListener (::std::find(pContainer->begin(), pContainer->end(), rxListener));
+ if (iListener != pContainer->end())
+ {
+ pContainer->erase(iListener);
+ // Remove container when empty.
+ if (pContainer->empty())
+ maVetoableListeners.erase(eItem);
+ }
+ }
+}
+
+
+
+
+cssu::Sequence<css::beans::Property> SAL_CALL Theme::getProperties (void)
+ throw(cssu::RuntimeException)
+{
+ ::std::vector<beans::Property> aProperties;
+
+ for (sal_Int32 nItem(__Begin),nEnd(__End); nItem!=nEnd; ++nItem)
+ {
+ const ThemeItem eItem (static_cast<ThemeItem>(nItem));
+ const PropertyType eType (GetPropertyType(eItem));
+ if (eType == PT_Invalid)
+ continue;
+
+ const beans::Property aProperty(
+ maPropertyIdToNameMap[eItem],
+ eItem,
+ GetCppuType(eType),
+ 0);
+ aProperties.push_back(aProperty);
+ }
+
+ return cssu::Sequence<css::beans::Property>(
+ &aProperties.front(),
+ aProperties.size());
+}
+
+
+
+
+beans::Property SAL_CALL Theme::getPropertyByName (const ::rtl::OUString& rsPropertyName)
+ throw(css::beans::UnknownPropertyException,
+ cssu::RuntimeException)
+{
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ throw beans::UnknownPropertyException();
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ throw beans::UnknownPropertyException();
+
+ const ThemeItem eItem (iId->second);
+
+ return beans::Property(
+ rsPropertyName,
+ eItem,
+ GetCppuType(eType),
+ 0);
+}
+
+
+
+
+sal_Bool SAL_CALL Theme::hasPropertyByName (const ::rtl::OUString& rsPropertyName)
+ throw(cssu::RuntimeException)
+{
+ PropertyNameToIdMap::const_iterator iId (maPropertyNameToIdMap.find(rsPropertyName));
+ if (iId == maPropertyNameToIdMap.end())
+ return sal_False;
+
+ const PropertyType eType (GetPropertyType(iId->second));
+ if (eType == PT_Invalid)
+ return sal_False;
+
+ return sal_True;
+}
+
+
+
+
+void Theme::SetupPropertyMaps (void)
+{
+ maPropertyIdToNameMap.resize(__Post_Rect);
+ maImages.resize(__Image_Color - __Pre_Image - 1);
+ maColors.resize(__Color_Paint - __Image_Color - 1);
+ maPaints.resize(__Paint_Int - __Color_Paint - 1);
+ maIntegers.resize(__Int_Bool - __Paint_Int - 1);
+ maBooleans.resize(__Bool_Rect - __Int_Bool - 1);
+ maRectangles.resize(__Post_Rect - __Bool_Rect - 1);
+
+ #define AddEntry(e) maPropertyNameToIdMap[A2S(#e)]=e; maPropertyIdToNameMap[e]=A2S(#e)
+
+ AddEntry(Image_Grip);
+ AddEntry(Image_Expand);
+ AddEntry(Image_Collapse);
+ AddEntry(Image_TabBarMenu);
+ AddEntry(Image_PanelMenu);
+ AddEntry(Image_ToolBoxItemSeparator);
+ AddEntry(Image_Closer);
+
+ AddEntry(Color_DeckTitleFont);
+ AddEntry(Color_PanelTitleFont);
+ AddEntry(Color_TabMenuSeparator);
+ AddEntry(Color_TabItemBorder);
+ AddEntry(Color_DropDownBorder);
+ AddEntry(Color_Highlight);
+ AddEntry(Color_HighlightText);
+
+ AddEntry(Paint_DeckBackground);
+ AddEntry(Paint_DeckTitleBarBackground);
+ AddEntry(Paint_PanelBackground);
+ AddEntry(Paint_PanelTitleBarBackground);
+ AddEntry(Paint_TabBarBackground);
+ AddEntry(Paint_TabItemBackgroundNormal);
+ AddEntry(Paint_TabItemBackgroundHighlight);
+ AddEntry(Paint_HorizontalBorder);
+ AddEntry(Paint_VerticalBorder);
+ AddEntry(Paint_ToolBoxBackground);
+ AddEntry(Paint_ToolBoxBorderTopLeft);
+ AddEntry(Paint_ToolBoxBorderCenterCorners);
+ AddEntry(Paint_ToolBoxBorderBottomRight);
+ AddEntry(Paint_DropDownBackground);
+
+ AddEntry(Int_DeckTitleBarHeight);
+ AddEntry(Int_DeckBorderSize);
+ AddEntry(Int_DeckSeparatorHeight);
+ AddEntry(Int_PanelTitleBarHeight);
+ AddEntry(Int_TabMenuPadding);
+ AddEntry(Int_TabMenuSeparatorPadding);
+ AddEntry(Int_TabItemWidth);
+ AddEntry(Int_TabItemHeight);
+ AddEntry(Int_DeckLeftPadding);
+ AddEntry(Int_DeckTopPadding);
+ AddEntry(Int_DeckRightPadding);
+ AddEntry(Int_DeckBottomPadding);
+ AddEntry(Int_TabBarLeftPadding);
+ AddEntry(Int_TabBarTopPadding);
+ AddEntry(Int_TabBarRightPadding);
+ AddEntry(Int_TabBarBottomPadding);
+ AddEntry(Int_ButtonCornerRadius);
+
+ AddEntry(Bool_UseSymphonyIcons);
+ AddEntry(Bool_UseSystemColors);
+ AddEntry(Bool_UseToolBoxItemSeparator);
+ AddEntry(Bool_IsHighContrastModeActive);
+
+ AddEntry(Rect_ToolBoxPadding);
+ AddEntry(Rect_ToolBoxBorder);
+
+ #undef AddEntry
+
+ maRawValues.resize(maPropertyIdToNameMap.size());
+}
+
+
+
+
+Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem)
+{
+ switch(eItem)
+ {
+ case Image_Grip:
+ case Image_Expand:
+ case Image_Collapse:
+ case Image_TabBarMenu:
+ case Image_PanelMenu:
+ case Image_ToolBoxItemSeparator:
+ case Image_Closer:
+ return PT_Image;
+
+ case Color_DeckTitleFont:
+ case Color_PanelTitleFont:
+ case Color_TabMenuSeparator:
+ case Color_TabItemBorder:
+ case Color_DropDownBorder:
+ case Color_Highlight:
+ case Color_HighlightText:
+ return PT_Color;
+
+ case Paint_DeckBackground:
+ case Paint_DeckTitleBarBackground:
+ case Paint_PanelBackground:
+ case Paint_PanelTitleBarBackground:
+ case Paint_TabBarBackground:
+ case Paint_TabItemBackgroundNormal:
+ case Paint_TabItemBackgroundHighlight:
+ case Paint_HorizontalBorder:
+ case Paint_VerticalBorder:
+ case Paint_ToolBoxBackground:
+ case Paint_ToolBoxBorderTopLeft:
+ case Paint_ToolBoxBorderCenterCorners:
+ case Paint_ToolBoxBorderBottomRight:
+ case Paint_DropDownBackground:
+ return PT_Paint;
+
+ case Int_DeckTitleBarHeight:
+ case Int_DeckBorderSize:
+ case Int_DeckSeparatorHeight:
+ case Int_PanelTitleBarHeight:
+ case Int_TabMenuPadding:
+ case Int_TabMenuSeparatorPadding:
+ case Int_TabItemWidth:
+ case Int_TabItemHeight:
+ case Int_DeckLeftPadding:
+ case Int_DeckTopPadding:
+ case Int_DeckRightPadding:
+ case Int_DeckBottomPadding:
+ case Int_TabBarLeftPadding:
+ case Int_TabBarTopPadding:
+ case Int_TabBarRightPadding:
+ case Int_TabBarBottomPadding:
+ case Int_ButtonCornerRadius:
+ return PT_Integer;
+
+ case Bool_UseSymphonyIcons:
+ case Bool_UseSystemColors:
+ case Bool_UseToolBoxItemSeparator:
+ case Bool_IsHighContrastModeActive:
+ return PT_Boolean;
+
+ case Rect_ToolBoxBorder:
+ case Rect_ToolBoxPadding:
+ return PT_Rectangle;
+
+ default:
+ return PT_Invalid;
+ }
+}
+
+
+
+
+cssu::Type Theme::GetCppuType (const PropertyType eType)
+{
+ switch(eType)
+ {
+ case PT_Image:
+ return getCppuType((rtl::OUString*)NULL);
+
+ case PT_Color:
+ return getCppuType((sal_uInt32*)NULL);
+
+ case PT_Paint:
+ return getCppuVoidType();
+
+ case PT_Integer:
+ return getCppuType((sal_Int32*)NULL);
+
+ case PT_Boolean:
+ return getCppuType((sal_Bool*)NULL);
+
+ case PT_Rectangle:
+ return getCppuType((awt::Rectangle*)NULL);
+
+ case PT_Invalid:
+ default:
+ return getCppuVoidType();
+ }
+}
+
+
+
+
+sal_Int32 Theme::GetIndex (const ThemeItem eItem, const PropertyType eType)
+{
+ switch(eType)
+ {
+ case PT_Image:
+ return eItem - __Pre_Image-1;
+ case PT_Color:
+ return eItem - __Image_Color-1;
+ case PT_Paint:
+ return eItem - __Color_Paint-1;
+ case PT_Integer:
+ return eItem - __Paint_Int-1;
+ case PT_Boolean:
+ return eItem - __Int_Bool-1;
+ case PT_Rectangle:
+ return eItem - __Bool_Rect-1;
+
+ default:
+ OSL_ASSERT(false);
+ return 0;
+ }
+}
+
+
+
+
+Theme::VetoableListenerContainer* Theme::GetVetoableListeners (
+ const ThemeItem eItem,
+ const bool bCreate)
+{
+ VetoableListeners::iterator iContainer (maVetoableListeners.find(eItem));
+ if (iContainer != maVetoableListeners.end())
+ return &iContainer->second;
+ else if (bCreate)
+ {
+ maVetoableListeners[eItem] = VetoableListenerContainer();
+ return &maVetoableListeners[eItem];
+ }
+ else
+ return NULL;
+}
+
+
+
+
+Theme::ChangeListenerContainer* Theme::GetChangeListeners (
+ const ThemeItem eItem,
+ const bool bCreate)
+{
+ ChangeListeners::iterator iContainer (maChangeListeners.find(eItem));
+ if (iContainer != maChangeListeners.end())
+ return &iContainer->second;
+ else if (bCreate)
+ {
+ maChangeListeners[eItem] = ChangeListenerContainer();
+ return &maChangeListeners[eItem];
+ }
+ else
+ return NULL;
+}
+
+
+
+
+bool Theme::DoVetoableListenersVeto (
+ const VetoableListenerContainer* pListeners,
+ const beans::PropertyChangeEvent& rEvent) const
+{
+ if (pListeners == NULL)
+ return false;
+
+ VetoableListenerContainer aListeners (*pListeners);
+ try
+ {
+ for (VetoableListenerContainer::const_iterator
+ iListener(aListeners.begin()),
+ iEnd(aListeners.end());
+ iListener!=iEnd;
+ ++iListener)
+ {
+ (*iListener)->vetoableChange(rEvent);
+ }
+ }
+ catch(const beans::PropertyVetoException&)
+ {
+ return true;
+ }
+ catch(const Exception&)
+ {
+ // Ignore any other errors (such as disposed listeners).
+ }
+ return false;
+}
+
+
+
+
+void Theme::BroadcastPropertyChange (
+ const ChangeListenerContainer* pListeners,
+ const beans::PropertyChangeEvent& rEvent) const
+{
+ if (pListeners == NULL)
+ return;
+
+ const ChangeListenerContainer aListeners (*pListeners);
+ try
+ {
+ for (ChangeListenerContainer::const_iterator
+ iListener(aListeners.begin()),
+ iEnd(aListeners.end());
+ iListener!=iEnd;
+ ++iListener)
+ {
+ (*iListener)->propertyChange(rEvent);
+ }
+ }
+ catch(const Exception&)
+ {
+ // Ignore any errors (such as disposed listeners).
+ }
+}
+
+
+
+
+void Theme::ProcessNewValue (
+ const Any& rValue,
+ const ThemeItem eItem,
+ const PropertyType eType)
+{
+ const sal_Int32 nIndex (GetIndex (eItem, eType));
+ switch (eType)
+ {
+ case PT_Image:
+ {
+ ::rtl::OUString sURL;
+ if (rValue >>= sURL)
+ {
+ maImages[nIndex] = Tools::GetImage(sURL, NULL);
+ }
+ break;
+ }
+ case PT_Color:
+ {
+ sal_Int32 nColorValue (0);
+ if (rValue >>= nColorValue)
+ {
+ maColors[nIndex] = Color(nColorValue);
+ }
+ break;
+ }
+ case PT_Paint:
+ {
+ maPaints[nIndex] = Paint::Create(rValue);
+ break;
+ }
+ case PT_Integer:
+ {
+ sal_Int32 nValue (0);
+ if (rValue >>= nValue)
+ {
+ maIntegers[nIndex] = nValue;
+ }
+ break;
+ }
+ case PT_Boolean:
+ {
+ sal_Bool nValue (0);
+ if (rValue >>= nValue)
+ {
+ maBooleans[nIndex] = (nValue==sal_True);
+ if (eItem == Bool_IsHighContrastModeActive)
+ {
+ mbIsHighContrastModeSetManually = true;
+ mbIsHighContrastMode = maBooleans[nIndex];
+ HandleDataChange();
+ }
+ else if (eItem == Bool_UseSystemColors)
+ {
+ HandleDataChange();
+ }
+ }
+ break;
+ }
+ case PT_Rectangle:
+ {
+ awt::Rectangle aBox;
+ if (rValue >>= aBox)
+ {
+ maRectangles[nIndex] = Rectangle(
+ aBox.X,
+ aBox.Y,
+ aBox.Width,
+ aBox.Height);
+ }
+ break;
+ }
+ case PT_Invalid:
+ OSL_ASSERT(eType != PT_Invalid);
+ throw RuntimeException();
+ }
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/TitleBar.cxx b/sfx2/source/sidebar/TitleBar.cxx
new file mode 100644
index 000000000000..1a48d0308fbf
--- /dev/null
+++ b/sfx2/source/sidebar/TitleBar.cxx
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TitleBar.hxx"
+#include "Paint.hxx"
+
+#include <tools/svborder.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/lineinfo.hxx>
+
+ToolbarValue::~ToolbarValue (void) {}
+
+
+namespace sfx2 { namespace sidebar {
+
+TitleBar::TitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ const sidebar::Paint& rInitialBackgroundPaint)
+ : Window(pParentWindow),
+ maToolBox(this),
+ msTitle(rsTitle)
+{
+ SetBackground(rInitialBackgroundPaint.GetWallpaper());
+
+ maToolBox.SetSelectHdl(LINK(this, TitleBar, SelectionHandler));
+}
+
+
+
+
+TitleBar::~TitleBar (void)
+{
+}
+
+
+
+
+void TitleBar::SetTitle (const ::rtl::OUString& rsTitle)
+{
+ msTitle = rsTitle;
+ Invalidate();
+}
+
+
+
+
+void TitleBar::Paint (const Rectangle& rUpdateArea)
+{
+ (void)rUpdateArea;
+
+ // Paint title bar background.
+ Size aWindowSize (GetOutputSizePixel());
+ Rectangle aTitleBarBox(
+ 0,
+ 0,
+ aWindowSize.Width(),
+ aWindowSize.Height()
+ );
+
+ PaintDecoration(aTitleBarBox);
+ const Rectangle aTitleBox (GetTitleArea(aTitleBarBox));
+ PaintTitle(aTitleBox);
+ if (HasFocus())
+ PaintFocus(aTitleBox);
+}
+
+
+
+
+void TitleBar::DataChanged (const DataChangedEvent& rEvent)
+{
+ (void)rEvent;
+
+ SetBackground(GetBackgroundPaint().GetWallpaper());
+}
+
+
+
+
+void TitleBar::setPosSizePixel (
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags)
+{
+ Window::setPosSizePixel(nX,nY,nWidth,nHeight,nFlags);
+
+ // Place the toolbox.
+ const sal_Int32 nToolBoxWidth (maToolBox.GetItemPosRect(0).GetWidth());
+ maToolBox.setPosSizePixel(nWidth-nToolBoxWidth,0,nToolBoxWidth,nHeight);
+ maToolBox.Show();
+}
+
+
+
+
+ToolBox& TitleBar::GetToolBox (void)
+{
+ return maToolBox;
+}
+
+
+
+
+void TitleBar::HandleToolBoxItemClick (const sal_uInt16 nItemIndex)
+{
+ (void)nItemIndex;
+ // Any real processing has to be done in derived class.
+}
+
+
+
+
+void TitleBar::PaintTitle (const Rectangle& rTitleBox)
+{
+ Push(PUSH_FONT | PUSH_TEXTCOLOR);
+
+ Font aFont(GetFont());
+ SetFont(aFont);
+
+ // Paint title bar text.
+ SetTextColor(GetTextColor());
+ DrawText(
+ rTitleBox,
+ msTitle,
+ TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER);
+
+ Pop();
+}
+
+
+
+
+void TitleBar::PaintFocus (const Rectangle& rFocusBox)
+{
+ Push(PUSH_FONT | PUSH_TEXTCOLOR | PUSH_LINECOLOR | PUSH_FILLCOLOR);
+
+ const Rectangle aTextBox (
+ GetTextRect(
+ rFocusBox,
+ msTitle,
+ TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER));
+ const Rectangle aLargerTextBox (
+ aTextBox.Left() - 2,
+ aTextBox.Top() - 2,
+ aTextBox.Right() + 2,
+ aTextBox.Bottom() + 2);
+
+ LineInfo aDottedStyle (LINE_DASH);
+ aDottedStyle.SetDashCount(0);
+ aDottedStyle.SetDotCount(1);
+ aDottedStyle.SetDotLen(1);
+ aDottedStyle.SetDistance(1);
+
+ SetFillColor();
+ SetLineColor(COL_BLACK);
+ DrawPolyLine(Polygon(aLargerTextBox), aDottedStyle);
+
+ Pop();
+}
+
+
+
+
+IMPL_LINK(TitleBar, SelectionHandler, ToolBox*, pToolBox)
+{
+ (void)pToolBox;
+ OSL_ASSERT(&maToolBox==pToolBox);
+ const sal_uInt16 nItemId (maToolBox.GetHighlightItemId());
+
+ HandleToolBoxItemClick(nItemId);
+
+ return sal_True;
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/TitleBar.hxx b/sfx2/source/sidebar/TitleBar.hxx
new file mode 100644
index 000000000000..4f4f67c8b601
--- /dev/null
+++ b/sfx2/source/sidebar/TitleBar.hxx
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TITLE_BAR_HXX
+#define SFX_SIDEBAR_TITLE_BAR_HXX
+
+#include "Paint.hxx"
+
+#include <vcl/window.hxx>
+#include <vcl/toolbox.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+class TitleBar
+ : public Window
+{
+public:
+ TitleBar (
+ const ::rtl::OUString& rsTitle,
+ Window* pParentWindow,
+ const sidebar::Paint& rInitialBackgroundPaint);
+ virtual ~TitleBar (void);
+
+ void SetTitle (const ::rtl::OUString& rsTitle);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+ virtual void setPosSizePixel (
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags = WINDOW_POSSIZE_ALL);
+
+ ToolBox& GetToolBox (void);
+
+protected:
+ ToolBox maToolBox;
+
+ virtual Rectangle GetTitleArea (const Rectangle& rTitleBarBox) = 0;
+ virtual void PaintDecoration (const Rectangle& rTitleBarBox) = 0;
+ virtual void PaintFocus (const Rectangle& rFocusBox);
+ virtual sidebar::Paint GetBackgroundPaint (void) = 0;
+ virtual Color GetTextColor (void) = 0;
+ virtual void HandleToolBoxItemClick (const sal_uInt16 nItemIndex);
+
+private:
+ ::rtl::OUString msTitle;
+
+ void PaintTitle (const Rectangle& rTitleBox);
+ DECL_LINK(SelectionHandler, ToolBox*);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/ToolBox.hxx b/sfx2/source/sidebar/ToolBox.hxx
new file mode 100644
index 000000000000..8de0a6b003ee
--- /dev/null
+++ b/sfx2/source/sidebar/ToolBox.hxx
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TOOLBOX_HXX
+#define SFX_SIDEBAR_TOOLBOX_HXX
+
+#include "vcl/toolbox.hxx"
+
+
+namespace sfx2 { namespace sidebar {
+
+class ToolBox
+ : public ::ToolBox
+{
+public:
+ MenuButton (Window* pParentWindow);
+ virtual ~MenuButton (void);
+
+ virtual void Paint (const Rectangle& rUpdateArea);
+ virtual void MouseMove (const MouseEvent& rEvent);
+ virtual void MouseButtonDown (const MouseEvent& rMouseEvent);
+ virtual void MouseButtonUp (const MouseEvent& rMouseEvent);
+
+protected:
+ using CheckBox::FillLayoutData;
+
+private:
+ bool mbIsLeftButtonDown;
+ enum PaintType {
+ PT_Native,
+ PT_Theme
+ } mePaintType;
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/ToolBoxBackground.cxx b/sfx2/source/sidebar/ToolBoxBackground.cxx
new file mode 100644
index 000000000000..1336c03478ed
--- /dev/null
+++ b/sfx2/source/sidebar/ToolBoxBackground.cxx
@@ -0,0 +1,148 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "ToolBoxBackground.hxx"
+#include "Paint.hxx"
+#include "DrawHelper.hxx"
+#include "Tools.hxx"
+#include "sfx2/sidebar/Theme.hxx"
+
+#include <vcl/toolbox.hxx>
+#include <vcl/gradient.hxx>
+#include <svl/smplhint.hxx>
+
+
+namespace sfx2 { namespace sidebar {
+
+ToolBoxBackground::ToolBoxBackground (Window* pParentWindow)
+ : Window(pParentWindow, WB_DIALOGCONTROL),
+ maPadding(Tools::RectangleToSvBorder(Theme::GetRectangle(Theme::Rect_ToolBoxPadding)))
+{
+ SetBackground(Theme::GetPaint(Theme::Paint_ToolBoxBackground).GetWallpaper());
+
+#ifdef DEBUG
+ SetText(A2S("ToolBoxBackground"));
+#endif
+}
+
+
+
+
+ToolBoxBackground::~ToolBoxBackground (void)
+{
+ Link aEventListener (LINK(this, ToolBoxBackground, WindowEventHandler));
+ if (GetChildCount() > 0)
+ GetChild(0)->RemoveEventListener(aEventListener);
+}
+
+
+
+
+Point ToolBoxBackground::SetToolBoxChild (
+ ToolBox* pChild,
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags)
+{
+ if (pChild == NULL)
+ {
+ OSL_ASSERT(pChild!=NULL);
+ return Point(nX, nY);
+ }
+
+ Link aEventListener (LINK(this, ToolBoxBackground, WindowEventHandler));
+ pChild->AddEventListener(aEventListener);
+
+ setPosSizePixel(
+ nX - maPadding.Left(),
+ nY - maPadding.Top(),
+ nWidth + maPadding.Left() + maPadding.Right(),
+ nHeight + maPadding.Top() + maPadding.Bottom(),
+ nFlags);
+ return Point(
+ maPadding.Left(),
+ maPadding.Top());
+}
+
+
+
+
+void ToolBoxBackground::Paint (const Rectangle& rRect)
+{
+ Window::Paint(rRect);
+
+ Rectangle aBox (Point(0,0), GetSizePixel());
+
+ const sidebar::Paint aTopLeftBorderPaint (Theme::GetPaint(Theme::Paint_ToolBoxBorderTopLeft));
+ const sidebar::Paint aCenterBorderPaint (Theme::GetPaint(Theme::Paint_ToolBoxBorderCenterCorners));
+ const sidebar::Paint aBottomRightBorderPaint (Theme::GetPaint(Theme::Paint_ToolBoxBorderBottomRight));
+ const Rectangle aBorderSize (Theme::GetRectangle(Theme::Rect_ToolBoxBorder));
+ DrawHelper::DrawBevelBorder (
+ *this,
+ aBox,
+ Tools::RectangleToSvBorder(aBorderSize),
+ aTopLeftBorderPaint,
+ aCenterBorderPaint,
+ aBottomRightBorderPaint);
+}
+
+
+
+
+void ToolBoxBackground::DataChanged (const DataChangedEvent& rEvent)
+{
+ (void)rEvent;
+
+ SetBackground(Theme::GetPaint(Theme::Paint_ToolBoxBackground).GetWallpaper());
+ maPadding = Tools::RectangleToSvBorder(Theme::GetRectangle(Theme::Rect_ToolBoxPadding));
+}
+
+
+
+
+IMPL_LINK(ToolBoxBackground, WindowEventHandler, VclWindowEvent*, pEvent)
+{
+ if (pEvent != NULL)
+ {
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_SHOW:
+ if (GetChild(0)->IsVisible())
+ Show();
+ break;
+
+ case VCLEVENT_WINDOW_HIDE:
+ if ( ! GetChild(0)->IsVisible())
+ Hide();
+ break;
+
+ case SFX_HINT_DYING:
+ doLazyDelete();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return sal_True;
+}
+
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/ToolBoxBackground.hxx b/sfx2/source/sidebar/ToolBoxBackground.hxx
new file mode 100644
index 000000000000..e5204b921204
--- /dev/null
+++ b/sfx2/source/sidebar/ToolBoxBackground.hxx
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TOOLBOX_BACKGROUND_HXX
+#define SFX_SIDEBAR_TOOLBOX_BACKGROUND_HXX
+
+#include "vcl/window.hxx"
+
+#include <tools/svborder.hxx>
+
+
+class ToolBox;
+
+namespace sfx2 { namespace sidebar {
+
+class ToolBoxBackground
+ : public Window
+{
+public:
+ ToolBoxBackground (Window* pParentWindow);
+ virtual ~ToolBoxBackground (void);
+
+ /** Call this method once to
+ a) let the ToolBoxBackground object know which ToolBox to
+ monitor and
+ b) so that position and sizes can be set up.
+ @return
+ The relative position of the child.
+ */
+ Point SetToolBoxChild (
+ ToolBox* pChild,
+ long nX,
+ long nY,
+ long nWidth,
+ long nHeight,
+ sal_uInt16 nFlags);
+
+ virtual void Paint (const Rectangle& rRect);
+ virtual void DataChanged (const DataChangedEvent& rEvent);
+
+private:
+ SvBorder maPadding;
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent*);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif
diff --git a/sfx2/source/sidebar/Tools.cxx b/sfx2/source/sidebar/Tools.cxx
new file mode 100644
index 000000000000..27956cd6670d
--- /dev/null
+++ b/sfx2/source/sidebar/Tools.cxx
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Tools.hxx"
+
+#include "sfx2/sidebar/Theme.hxx"
+
+#include "sfx2/imagemgr.hxx"
+#include <comphelper/processfactory.hxx>
+#include <comphelper/componentcontext.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <vcl/gradient.hxx>
+
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+
+#include <cstring>
+
+using namespace css;
+using namespace cssu;
+
+
+namespace sfx2 { namespace sidebar {
+
+Image Tools::GetImage (
+ const ::rtl::OUString& rsImageURL,
+ const ::rtl::OUString& rsHighContrastImageURL,
+ const Reference<frame::XFrame>& rxFrame)
+{
+ if (Theme::IsHighContrastMode())
+ return GetImage(rsHighContrastImageURL, rxFrame);
+ else
+ return GetImage(rsImageURL, rxFrame);
+}
+
+
+
+
+Image Tools::GetImage (
+ const ::rtl::OUString& rsURL,
+ const Reference<frame::XFrame>& rxFrame)
+{
+ if (rsURL.getLength() > 0)
+ {
+ const sal_Char sUnoCommandPrefix[] = ".uno:";
+ const sal_Char sCommandImagePrefix[] = "private:commandimage/";
+ const sal_Int32 nCommandImagePrefixLength = strlen(sCommandImagePrefix);
+
+ if (rsURL.startsWith(sUnoCommandPrefix))
+ {
+ const Image aPanelImage (::GetImage(rxFrame, rsURL, sal_False));
+ return aPanelImage;
+ }
+ else if (rsURL.startsWith(sCommandImagePrefix))
+ {
+ ::rtl::OUStringBuffer aCommandName;
+ aCommandName.appendAscii(sUnoCommandPrefix);
+ aCommandName.append(rsURL.copy(nCommandImagePrefixLength));
+ const ::rtl::OUString sCommandName (aCommandName.makeStringAndClear());
+
+ const Image aPanelImage (::GetImage(rxFrame, sCommandName, sal_False));
+ return aPanelImage;
+ }
+ else
+ {
+ const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory());
+ const Reference<graphic::XGraphicProvider> xGraphicProvider (
+ aContext.createComponent("com.sun.star.graphic.GraphicProvider"),
+ UNO_QUERY);
+ if ( xGraphicProvider.is())
+ {
+ ::comphelper::NamedValueCollection aMediaProperties;
+ aMediaProperties.put("URL", rsURL);
+ const Reference<graphic::XGraphic> xGraphic (
+ xGraphicProvider->queryGraphic(aMediaProperties.getPropertyValues()),
+ UNO_QUERY);
+ if (xGraphic.is())
+ return Image(xGraphic);
+ }
+ }
+ }
+ return Image();
+}
+
+
+
+
+css::awt::Gradient Tools::VclToAwtGradient (const Gradient aVclGradient)
+{
+ css::awt::Gradient aAwtGradient (
+ awt::GradientStyle(aVclGradient.GetStyle()),
+ aVclGradient.GetStartColor().GetRGBColor(),
+ aVclGradient.GetEndColor().GetRGBColor(),
+ aVclGradient.GetAngle(),
+ aVclGradient.GetBorder(),
+ aVclGradient.GetOfsX(),
+ aVclGradient.GetOfsY(),
+ aVclGradient.GetStartIntensity(),
+ aVclGradient.GetEndIntensity(),
+ aVclGradient.GetSteps());
+ return aAwtGradient;
+}
+
+
+
+
+Gradient Tools::AwtToVclGradient (const css::awt::Gradient aAwtGradient)
+{
+ Gradient aVclGradient (
+ GradientStyle(aAwtGradient.Style),
+ aAwtGradient.StartColor,
+ aAwtGradient.EndColor);
+ aVclGradient.SetAngle(aAwtGradient.Angle);
+ aVclGradient.SetBorder(aAwtGradient.Border);
+ aVclGradient.SetOfsX(aAwtGradient.XOffset);
+ aVclGradient.SetOfsY(aAwtGradient.YOffset);
+ aVclGradient.SetStartIntensity(aAwtGradient.StartIntensity);
+ aVclGradient.SetEndIntensity(aAwtGradient.EndIntensity);
+ aVclGradient.SetSteps(aAwtGradient.StepCount);
+
+ return aVclGradient;
+}
+
+
+
+
+SvBorder Tools::RectangleToSvBorder (const Rectangle aBox)
+{
+ return SvBorder(
+ aBox.Left(),
+ aBox.Top(),
+ aBox.Right(),
+ aBox.Bottom());
+}
+
+} } // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/Tools.hxx b/sfx2/source/sidebar/Tools.hxx
new file mode 100644
index 000000000000..70bc7f995d0c
--- /dev/null
+++ b/sfx2/source/sidebar/Tools.hxx
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef SFX_SIDEBAR_TOOLS_HXX
+#define SFX_SIDEBAR_TOOLS_HXX
+
+#include <vcl/image.hxx>
+#include <vcl/gradient.hxx>
+#include <tools/svborder.hxx>
+
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+
+
+#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)))
+#define S2A(s) rtl::OUStringToOString(s, RTL_TEXTENCODING_ASCII_US).getStr()
+
+namespace css = ::com::sun::star;
+namespace cssu = ::com::sun::star::uno;
+
+
+namespace sfx2 { namespace sidebar {
+
+class Tools
+{
+public:
+ static Image GetImage (
+ const ::rtl::OUString& rsImageURL,
+ const ::rtl::OUString& rsHighContrastImageURL,
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+
+ static Image GetImage (
+ const ::rtl::OUString& rsURL,
+ const cssu::Reference<css::frame::XFrame>& rxFrame);
+
+ static css::awt::Gradient VclToAwtGradient (const Gradient aGradient);
+ static Gradient AwtToVclGradient (const css::awt::Gradient aGradient);
+
+ static SvBorder RectangleToSvBorder (const Rectangle aBox);
+};
+
+
+} } // end of namespace sfx2::sidebar
+
+#endif