summaryrefslogtreecommitdiff
path: root/sd/source/ui/framework/configuration
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/framework/configuration')
-rw-r--r--sd/source/ui/framework/configuration/ChangeRequestQueue.cxx38
-rw-r--r--sd/source/ui/framework/configuration/ChangeRequestQueue.hxx55
-rwxr-xr-xsd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx237
-rwxr-xr-xsd/source/ui/framework/configuration/ChangeRequestQueueProcessor.hxx136
-rw-r--r--sd/source/ui/framework/configuration/Configuration.cxx420
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationClassifier.cxx238
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationClassifier.hxx183
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationController.cxx726
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx231
-rw-r--r--sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.hxx151
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx352
-rw-r--r--sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.hxx145
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationTracer.cxx83
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationTracer.hxx57
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationUpdater.cxx468
-rwxr-xr-xsd/source/ui/framework/configuration/ConfigurationUpdater.hxx215
-rw-r--r--sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.cxx104
-rw-r--r--sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.hxx123
-rw-r--r--sd/source/ui/framework/configuration/ResourceFactoryManager.cxx230
-rw-r--r--sd/source/ui/framework/configuration/ResourceFactoryManager.hxx128
-rwxr-xr-xsd/source/ui/framework/configuration/ResourceId.cxx626
-rw-r--r--sd/source/ui/framework/configuration/UpdateRequest.cxx86
-rw-r--r--sd/source/ui/framework/configuration/UpdateRequest.hxx93
-rw-r--r--sd/source/ui/framework/configuration/makefile.mk63
24 files changed, 5188 insertions, 0 deletions
diff --git a/sd/source/ui/framework/configuration/ChangeRequestQueue.cxx b/sd/source/ui/framework/configuration/ChangeRequestQueue.cxx
new file mode 100644
index 000000000000..c46a89df8ee8
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ChangeRequestQueue.cxx
@@ -0,0 +1,38 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ChangeRequestQueue.hxx"
+
+namespace sd { namespace framework {
+
+ChangeRequestQueue::ChangeRequestQueue (void)
+{
+}
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ChangeRequestQueue.hxx b/sd/source/ui/framework/configuration/ChangeRequestQueue.hxx
new file mode 100644
index 000000000000..bad80ff50d69
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ChangeRequestQueue.hxx
@@ -0,0 +1,55 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CHANGE_OPERATION_QUEUE_HXX
+#define SD_FRAMEWORK_CHANGE_OPERATION_QUEUE_HXX
+
+#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
+
+#include <list>
+
+namespace sd { namespace framework {
+
+
+/** The ChangeRequestQueue stores the pending requests for changes to the
+ requested configuration. It is the task of the
+ ChangeRequestQueueProcessor to process these requests.
+*/
+class ChangeRequestQueue
+ : public ::std::list<com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfigurationChangeRequest> >
+{
+public:
+ /** Create an empty queue.
+ */
+ ChangeRequestQueue (void);
+};
+
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx
new file mode 100755
index 000000000000..bf3571cbd8f4
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ChangeRequestQueueProcessor.hxx"
+#include "ConfigurationTracer.hxx"
+
+#include "framework/ConfigurationController.hxx"
+#include "ConfigurationUpdater.hxx"
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+#undef VERBOSE
+//#define VERBOSE 1
+
+namespace {
+
+#ifdef VERBOSE
+
+void TraceRequest (const Reference<XConfigurationChangeRequest>& rxRequest)
+{
+ Reference<container::XNamed> xNamed (rxRequest, UNO_QUERY);
+ if (xNamed.is())
+ OSL_TRACE(" %s\n",
+ ::rtl::OUStringToOString(xNamed->getName(), RTL_TEXTENCODING_UTF8).getStr());
+}
+
+#endif
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace framework {
+
+ChangeRequestQueueProcessor::ChangeRequestQueueProcessor (
+ const ::rtl::Reference<ConfigurationController>& rpConfigurationController,
+ const ::boost::shared_ptr<ConfigurationUpdater>& rpConfigurationUpdater)
+ : maMutex(),
+ maQueue(),
+ mnUserEventId(0),
+ mxConfiguration(),
+ mpConfigurationController(rpConfigurationController),
+ mpConfigurationUpdater(rpConfigurationUpdater)
+{
+}
+
+
+
+
+ChangeRequestQueueProcessor::~ChangeRequestQueueProcessor (void)
+{
+ if (mnUserEventId != 0)
+ Application::RemoveUserEvent(mnUserEventId);
+}
+
+
+
+
+void ChangeRequestQueueProcessor::SetConfiguration (
+ const Reference<XConfiguration>& rxConfiguration)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mxConfiguration = rxConfiguration;
+ StartProcessing();
+}
+
+
+
+
+void ChangeRequestQueueProcessor::AddRequest (
+ const Reference<XConfigurationChangeRequest>& rxRequest)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+#ifdef VERBOSE
+ if (maQueue.empty())
+ {
+ OSL_TRACE("Adding requests to empty queue\n");
+ ConfigurationTracer::TraceConfiguration(
+ mxConfiguration, "current configuration of queue processor");
+ }
+ OSL_TRACE("Adding request\n");
+ TraceRequest(rxRequest);
+#endif
+
+ maQueue.push_back(rxRequest);
+ StartProcessing();
+}
+
+
+
+
+void ChangeRequestQueueProcessor::StartProcessing (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mnUserEventId == 0
+ && mxConfiguration.is()
+ && ! maQueue.empty())
+ {
+#ifdef VERBOSE
+ OSL_TRACE("ChangeRequestQueueProcessor scheduling processing\n");
+#endif
+ mnUserEventId = Application::PostUserEvent(
+ LINK(this,ChangeRequestQueueProcessor,ProcessEvent));
+ }
+}
+
+
+
+
+IMPL_LINK(ChangeRequestQueueProcessor, ProcessEvent, void*, pUnused)
+{
+ (void)pUnused;
+
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mnUserEventId = 0;
+
+ ProcessOneEvent();
+
+ if ( ! maQueue.empty())
+ {
+ // Schedule the processing of the next event.
+ StartProcessing();
+ }
+
+ return 0;
+}
+
+
+
+
+void ChangeRequestQueueProcessor::ProcessOneEvent (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+#ifdef VERBOSE
+ OSL_TRACE("ProcessOneEvent\n");
+#endif
+
+ if (mxConfiguration.is()
+ && ! maQueue.empty())
+ {
+ // Get and remove the first entry from the queue.
+ Reference<XConfigurationChangeRequest> xRequest (maQueue.front());
+ maQueue.pop_front();
+
+ // Execute the change request.
+ if (xRequest.is())
+ {
+#ifdef VERBOSE
+ TraceRequest(xRequest);
+#endif
+ xRequest->execute(mxConfiguration);
+ }
+
+ if (maQueue.empty())
+ {
+#ifdef VERBOSE
+ OSL_TRACE("All requests are processed\n");
+#endif
+ // The queue is empty so tell the ConfigurationManager to update
+ // its state.
+ if (mpConfigurationUpdater.get() != NULL)
+ {
+#ifdef VERBOSE
+ ConfigurationTracer::TraceConfiguration (
+ mxConfiguration, "updating to configuration");
+#endif
+ mpConfigurationUpdater->RequestUpdate(mxConfiguration);
+ }
+ }
+ }
+}
+
+
+
+
+bool ChangeRequestQueueProcessor::IsEmpty (void) const
+{
+ return maQueue.empty();
+}
+
+
+
+
+void ChangeRequestQueueProcessor::ProcessUntilEmpty (void)
+{
+ while ( ! IsEmpty())
+ ProcessOneEvent();
+}
+
+
+
+
+void ChangeRequestQueueProcessor::Clear (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ maQueue.clear();
+}
+
+
+} } // end of namespace sd::framework::configuration
diff --git a/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.hxx b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.hxx
new file mode 100755
index 000000000000..3dd151ae3d29
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ChangeRequestQueueProcessor.hxx
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX
+#define SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX
+
+#include "ChangeRequestQueue.hxx"
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
+#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
+
+#include <cppuhelper/interfacecontainer.hxx>
+#include <tools/link.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+namespace sd { namespace framework {
+
+class ConfigurationController;
+class ConfigurationUpdater;
+
+/** The ChangeRequestQueueProcessor ownes the ChangeRequestQueue and
+ processes the configuration change requests.
+
+ When after processing one entry the queue is empty then the
+ XConfigurationController::update() method is called so that the changes
+ made to the local XConfiguration reference are reflected by the UI.
+
+ Queue entries are processed asynchronously by calling PostUserEvent().
+*/
+class ChangeRequestQueueProcessor
+{
+public:
+ /** The queue processor is created with a reference to an
+ ConfigurationController so that its UpdateConfiguration() method can
+ be called when the queue becomes empty.
+ */
+ ChangeRequestQueueProcessor (
+ const ::rtl::Reference<ConfigurationController>& rxController,
+ const ::boost::shared_ptr<ConfigurationUpdater>& rpUpdater);
+ ~ChangeRequestQueueProcessor (void);
+
+ /** Sets the configuration who will be changed by subsequent change
+ requests. This method should be called only by the configuration
+ controller who owns the configuration.
+ */
+ void SetConfiguration (
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration);
+
+ /** The given request is appended to the end of the queue and will
+ eventually be processed when all other entries in front of it have
+ been processed.
+ */
+ void AddRequest (const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfigurationChangeRequest>& rxRequest);
+
+ /** Returns </sal_True> when the queue is empty.
+ */
+ bool IsEmpty (void) const;
+
+ /** Process all events in the queue synchronously.
+
+ <p>This method is typically called when the framework is shut down
+ to establish an empty configuration.</p>
+ */
+ void ProcessUntilEmpty (void);
+
+ /** Process the first event in queue.
+ */
+ void ProcessOneEvent (void);
+
+ /** Remove all events from the queue.
+
+ <p>This method is typically called when the framework is shut down
+ to avoid the processing of still pending activation requests.</p>
+ */
+ void Clear (void);
+
+private:
+ mutable ::osl::Mutex maMutex;
+
+ ChangeRequestQueue maQueue;
+
+ /** The id returned by the last PostUserEvent() call. This id is stored
+ so that a pending user event can be removed whent he queue processor
+ is destroyed.
+ */
+ sal_uIntPtr mnUserEventId;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration> mxConfiguration;
+
+ ::rtl::Reference<ConfigurationController> mpConfigurationController;
+
+ ::boost::shared_ptr<ConfigurationUpdater> mpConfigurationUpdater;
+
+ /** Initiate the processing of the entries in the queue. The actual
+ processing starts asynchronously.
+ */
+ void StartProcessing (void);
+
+ /** Callback function for the PostUserEvent() call.
+ */
+ DECL_LINK(ProcessEvent,void*);
+};
+
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/Configuration.cxx b/sd/source/ui/framework/configuration/Configuration.cxx
new file mode 100644
index 000000000000..2637a9ac1413
--- /dev/null
+++ b/sd/source/ui/framework/configuration/Configuration.cxx
@@ -0,0 +1,420 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "framework/Configuration.hxx"
+
+#include "framework/FrameworkHelper.hxx"
+#include <comphelper/stl_types.hxx>
+
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::sd::framework::FrameworkHelper;
+using ::rtl::OUString;
+
+#undef VERBOSE
+
+namespace {
+/** Use the XResourceId::compareTo() method to implement a compare operator
+ for STL containers.
+*/
+class XResourceIdLess
+ : public ::std::binary_function <Reference<XResourceId>, Reference<XResourceId>, bool>
+{
+public:
+ bool operator () (const Reference<XResourceId>& rId1, const Reference<XResourceId>& rId2) const
+ {
+ return rId1->compareTo(rId2) == -1;
+ }
+};
+
+} // end of anonymous namespace
+
+
+
+
+namespace sd { namespace framework {
+
+
+class Configuration::ResourceContainer
+ : public ::std::set<Reference<XResourceId>, XResourceIdLess>
+{
+public:
+ ResourceContainer (void) {}
+};
+
+
+
+
+//----- Service ---------------------------------------------------------------
+
+Reference<XInterface> SAL_CALL Configuration_createInstance (
+ const Reference<XComponentContext>& rxContext)
+{
+ (void)rxContext;
+ return Reference<XInterface>(static_cast<XWeak*>(new Configuration(NULL,false)));
+}
+
+
+
+
+OUString Configuration_getImplementationName (void) throw(RuntimeException)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.Draw.framework.configuration.Configuration"));
+}
+
+
+
+
+Sequence<rtl::OUString> SAL_CALL Configuration_getSupportedServiceNames (void)
+ throw (RuntimeException)
+{
+ static const OUString sServiceName(OUString::createFromAscii(
+ "com.sun.star.drawing.framework.Configuration"));
+ return Sequence<rtl::OUString>(&sServiceName, 1);
+}
+
+
+
+
+//===== Configuration =========================================================
+
+Configuration::Configuration (
+ const Reference<XConfigurationControllerBroadcaster>& rxBroadcaster,
+ bool bBroadcastRequestEvents)
+ : ConfigurationInterfaceBase(MutexOwner::maMutex),
+ mpResourceContainer(new ResourceContainer()),
+ mxBroadcaster(rxBroadcaster),
+ mbBroadcastRequestEvents(bBroadcastRequestEvents)
+{
+}
+
+
+
+Configuration::Configuration (
+ const Reference<XConfigurationControllerBroadcaster>& rxBroadcaster,
+ bool bBroadcastRequestEvents,
+ const ResourceContainer& rResourceContainer)
+ : ConfigurationInterfaceBase(MutexOwner::maMutex),
+ mpResourceContainer(new ResourceContainer(rResourceContainer)),
+ mxBroadcaster(rxBroadcaster),
+ mbBroadcastRequestEvents(bBroadcastRequestEvents)
+{
+}
+
+
+
+
+Configuration::~Configuration (void)
+{
+}
+
+
+
+
+void SAL_CALL Configuration::disposing (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ mpResourceContainer->clear();
+ mxBroadcaster = NULL;
+}
+
+
+
+
+//----- XConfiguration --------------------------------------------------------
+
+void SAL_CALL Configuration::addResource (const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+
+ if ( ! rxResourceId.is() || rxResourceId->getResourceURL().getLength()==0)
+ throw ::com::sun::star::lang::IllegalArgumentException();
+
+ if (mpResourceContainer->find(rxResourceId) == mpResourceContainer->end())
+ {
+#ifdef VERBOSE
+ OSL_TRACE("Configuration::addResource() %s",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ mpResourceContainer->insert(rxResourceId);
+ PostEvent(rxResourceId, true);
+ }
+}
+
+
+
+
+void SAL_CALL Configuration::removeResource (const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+
+ if ( ! rxResourceId.is() || rxResourceId->getResourceURL().getLength()==0)
+ throw ::com::sun::star::lang::IllegalArgumentException();
+
+ ResourceContainer::iterator iResource (mpResourceContainer->find(rxResourceId));
+ if (iResource != mpResourceContainer->end())
+ {
+#ifdef VERBOSE
+ OSL_TRACE("Configuration::removeResource() %s",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ PostEvent(rxResourceId,false);
+ mpResourceContainer->erase(iResource);
+ }
+}
+
+
+
+
+Sequence<Reference<XResourceId> > SAL_CALL Configuration::getResources (
+ const Reference<XResourceId>& rxAnchorId,
+ const ::rtl::OUString& rsResourceURLPrefix,
+ AnchorBindingMode eMode)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ bool bFilterResources (rsResourceURLPrefix.getLength() > 0);
+
+ // Collect the matching resources in a vector.
+ ::std::vector<Reference<XResourceId> > aResources;
+ ResourceContainer::const_iterator iResource;
+ for (iResource=mpResourceContainer->begin();
+ iResource!=mpResourceContainer->end();
+ ++iResource)
+ {
+ if ( ! (*iResource)->isBoundTo(rxAnchorId,eMode))
+ continue;
+
+
+ if (bFilterResources)
+ {
+ // Apply the given resource prefix as filter.
+
+ // Make sure that the resource is bound directly to the anchor.
+ if (eMode != AnchorBindingMode_DIRECT
+ && ! (*iResource)->isBoundTo(rxAnchorId, AnchorBindingMode_DIRECT))
+ {
+ continue;
+ }
+
+ // Make sure that the resource URL matches the given prefix.
+ if ( ! (*iResource)->getResourceURL().match(rsResourceURLPrefix))
+ {
+ continue;
+ }
+ }
+
+ aResources.push_back(*iResource);
+ }
+
+ // Copy the resources from the vector into a new sequence.
+ Sequence<Reference<XResourceId> > aResult (aResources.size());
+ for (sal_uInt32 nIndex=0; nIndex<aResources.size(); ++nIndex)
+ aResult[nIndex] = aResources[nIndex];
+
+ return aResult;
+}
+
+
+
+
+sal_Bool SAL_CALL Configuration::hasResource (const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ return rxResourceId.is()
+ && mpResourceContainer->find(rxResourceId) != mpResourceContainer->end();
+}
+
+
+
+
+//----- XCloneable ------------------------------------------------------------
+
+Reference<util::XCloneable> SAL_CALL Configuration::createClone (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ Configuration* pConfiguration = new Configuration(
+ mxBroadcaster,
+ mbBroadcastRequestEvents,
+ *mpResourceContainer);
+
+ return Reference<util::XCloneable>(pConfiguration);
+}
+
+
+
+
+//----- XNamed ----------------------------------------------------------------
+
+OUString SAL_CALL Configuration::getName (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ OUString aString;
+
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ aString += OUString::createFromAscii("DISPOSED ");
+ aString += OUString::createFromAscii("Configuration[");
+
+ ResourceContainer::const_iterator iResource;
+ for (iResource=mpResourceContainer->begin();
+ iResource!=mpResourceContainer->end();
+ ++iResource)
+ {
+ if (iResource != mpResourceContainer->begin())
+ aString += OUString::createFromAscii(", ");
+ aString += FrameworkHelper::ResourceIdToString(*iResource);
+ }
+ aString += OUString::createFromAscii("]");
+
+ return aString;
+}
+
+
+
+
+void SAL_CALL Configuration::setName (const OUString& rsName)
+ throw (RuntimeException)
+{
+ (void)rsName; // rsName is ignored.
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+
+void Configuration::PostEvent (
+ const Reference<XResourceId>& rxResourceId,
+ const bool bActivation)
+{
+ OSL_ASSERT(rxResourceId.is());
+
+ if (mxBroadcaster.is())
+ {
+ ConfigurationChangeEvent aEvent;
+ aEvent.ResourceId = rxResourceId;
+ if (bActivation)
+ if (mbBroadcastRequestEvents)
+ aEvent.Type = FrameworkHelper::msResourceActivationRequestEvent;
+ else
+ aEvent.Type = FrameworkHelper::msResourceActivationEvent;
+ else
+ if (mbBroadcastRequestEvents)
+ aEvent.Type = FrameworkHelper::msResourceDeactivationRequestEvent;
+ else
+ aEvent.Type = FrameworkHelper::msResourceDeactivationEvent;
+ aEvent.Configuration = this;
+
+ mxBroadcaster->notifyEvent(aEvent);
+ }
+}
+
+
+
+
+void Configuration::ThrowIfDisposed (void) const
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ throw lang::DisposedException (
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "Configuration object has already been disposed")),
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+
+
+
+//=============================================================================
+
+bool AreConfigurationsEquivalent (
+ const Reference<XConfiguration>& rxConfiguration1,
+ const Reference<XConfiguration>& rxConfiguration2)
+{
+ if (rxConfiguration1.is() != rxConfiguration2.is())
+ return false;
+ if ( ! rxConfiguration1.is() && ! rxConfiguration2.is())
+ return true;
+
+ // Get the lists of resources from the two given configurations.
+ const Sequence<Reference<XResourceId> > aResources1(
+ rxConfiguration1->getResources(
+ NULL, OUString(), AnchorBindingMode_INDIRECT));
+ const Sequence<Reference<XResourceId> > aResources2(
+ rxConfiguration2->getResources(
+ NULL, OUString(), AnchorBindingMode_INDIRECT));
+
+ // When the number of resources differ then the configurations can not
+ // be equivalent.
+ const sal_Int32 nCount (aResources1.getLength());
+ const sal_Int32 nCount2 (aResources2.getLength());
+ if (nCount != nCount2)
+ return false;
+
+ // Comparison of the two lists of resource ids relies on their
+ // ordering.
+ for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
+ {
+ const Reference<XResourceId> xResource1 (aResources1[nIndex]);
+ const Reference<XResourceId> xResource2 (aResources2[nIndex]);
+ if (xResource1.is() && xResource2.is())
+ {
+ if (xResource1->compareTo(xResource2) != 0)
+ return false;
+ }
+ else if (xResource1.is() != xResource2.is())
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx b/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx
new file mode 100755
index 000000000000..55e22361ad3a
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationClassifier.cxx
@@ -0,0 +1,238 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ConfigurationClassifier.hxx"
+
+#include "framework/FrameworkHelper.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::rtl::OUString;
+
+#undef VERBOSE
+//#define VERBOSE 2
+
+
+namespace sd { namespace framework {
+
+ConfigurationClassifier::ConfigurationClassifier (
+ const Reference<XConfiguration>& rxConfiguration1,
+ const Reference<XConfiguration>& rxConfiguration2)
+ : mxConfiguration1(rxConfiguration1),
+ mxConfiguration2(rxConfiguration2),
+ maC1minusC2(),
+ maC2minusC1(),
+ maC1andC2()
+{
+}
+
+
+
+
+bool ConfigurationClassifier::Partition (void)
+{
+ maC1minusC2.clear();
+ maC2minusC1.clear();
+ maC1andC2.clear();
+
+ PartitionResources(
+ mxConfiguration1->getResources(NULL, OUString(), AnchorBindingMode_DIRECT),
+ mxConfiguration2->getResources(NULL, OUString(), AnchorBindingMode_DIRECT));
+
+ return !maC1minusC2.empty() || !maC2minusC1.empty();
+}
+
+
+
+
+const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC1minusC2 (void) const
+{
+ return maC1minusC2;
+}
+
+
+
+
+const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC2minusC1 (void) const
+{
+ return maC2minusC1;
+}
+
+
+
+const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC1andC2 (void) const
+{
+ return maC1andC2;
+}
+
+
+void ConfigurationClassifier::PartitionResources (
+ const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS1,
+ const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS2)
+{
+ ResourceIdVector aC1minusC2;
+ ResourceIdVector aC2minusC1;
+ ResourceIdVector aC1andC2;
+
+ // Classify the resources in the configurations that are not bound to
+ // other resources.
+ ClassifyResources(
+ rS1,
+ rS2,
+ aC1minusC2,
+ aC2minusC1,
+ aC1andC2);
+
+#if defined VERBOSE && VERBOSE >= 2
+ OSL_TRACE("copying resource ids to C1-C2\r");
+#endif
+ CopyResources(aC1minusC2, mxConfiguration1, maC1minusC2);
+#if defined VERBOSE && VERBOSE >= 2
+ OSL_TRACE("copying resource ids to C2-C1\r");
+#endif
+ CopyResources(aC2minusC1, mxConfiguration2, maC2minusC1);
+
+ // Process the unique resources that belong to both configurations.
+ ResourceIdVector::const_iterator iResource;
+ for (iResource=aC1andC2.begin(); iResource!=aC1andC2.end(); ++iResource)
+ {
+ maC1andC2.push_back(*iResource);
+ PartitionResources(
+ mxConfiguration1->getResources(*iResource, OUString(), AnchorBindingMode_DIRECT),
+ mxConfiguration2->getResources(*iResource, OUString(), AnchorBindingMode_DIRECT));
+ }
+}
+
+
+
+
+void ConfigurationClassifier::ClassifyResources (
+ const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS1,
+ const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS2,
+ ResourceIdVector& rS1minusS2,
+ ResourceIdVector& rS2minusS1,
+ ResourceIdVector& rS1andS2)
+{
+ // Get arrays from the sequences for faster iteration.
+ const Reference<XResourceId>* aA1 = rS1.getConstArray();
+ const Reference<XResourceId>* aA2 = rS2.getConstArray();
+ sal_Int32 nL1 (rS1.getLength());
+ sal_Int32 nL2 (rS2.getLength());
+
+ // Find all elements in rS1 and place them in rS1minusS2 or rS1andS2
+ // depending on whether they are in rS2 or not.
+ for (sal_Int32 i=0; i<nL1; ++i)
+ {
+ bool bFound (false);
+ for (sal_Int32 j=0; j<nL2 && !bFound; ++j)
+ if (aA1[i]->getResourceURL().equals(aA2[j]->getResourceURL()))
+ bFound = true;
+
+ if (bFound)
+ rS1andS2.push_back(aA1[i]);
+ else
+ rS1minusS2.push_back(aA1[i]);
+ }
+
+ // Find all elements in rS2 that are not in rS1. The elements that are
+ // in both rS1 and rS2 have been handled above and are therefore ignored
+ // here.
+ for (sal_Int32 j=0; j<nL2; ++j)
+ {
+ bool bFound (false);
+ for (sal_Int32 i=0; i<nL1 && !bFound; ++i)
+ if (aA2[j]->getResourceURL().equals(aA1[i]->getResourceURL()))
+ bFound = true;
+
+ if ( ! bFound)
+ rS2minusS1.push_back(aA2[j]);
+ }
+}
+
+
+
+
+void ConfigurationClassifier::CopyResources (
+ const ResourceIdVector& rSource,
+ const Reference<XConfiguration>& rxConfiguration,
+ ResourceIdVector& rTarget)
+{
+ // Copy all resources bound to the ones in aC1minusC2Unique to rC1minusC2.
+ ResourceIdVector::const_iterator iResource (rSource.begin());
+ ResourceIdVector::const_iterator iEnd(rSource.end());
+ for ( ; iResource!=iEnd; ++iResource)
+ {
+ const Sequence<Reference<XResourceId> > aBoundResources (
+ rxConfiguration->getResources(
+ *iResource,
+ OUString(),
+ AnchorBindingMode_INDIRECT));
+ const sal_Int32 nL (aBoundResources.getLength());
+
+ rTarget.reserve(rTarget.size() + 1 + nL);
+ rTarget.push_back(*iResource);
+
+#if defined VERBOSE && VERBOSE >= 2
+ OSL_TRACE(" copying %s\r",
+ OUStringToOString(FrameworkHelper::ResourceIdToString(*iResource),
+ RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ const Reference<XResourceId>* aA = aBoundResources.getConstArray();
+ for (sal_Int32 i=0; i<nL; ++i)
+ {
+ rTarget.push_back(aA[i]);
+#if defined VERBOSE && VERBOSE >= 2
+ OSL_TRACE(" copying %s\r",
+ OUStringToOString(FrameworkHelper::ResourceIdToString(aA[i]),
+ RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ }
+ }
+}
+
+
+void ConfigurationClassifier::TraceResourceIdVector (
+ const sal_Char* pMessage,
+ const ResourceIdVector& rResources) const
+{
+
+ OSL_TRACE(pMessage);
+ ResourceIdVector::const_iterator iResource;
+ for (iResource=rResources.begin(); iResource!=rResources.end(); ++iResource)
+ {
+ OUString sResource (FrameworkHelper::ResourceIdToString(*iResource));
+ OSL_TRACE(" %s\r",
+ OUStringToOString(sResource, RTL_TEXTENCODING_UTF8).getStr());
+ }
+}
+
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ConfigurationClassifier.hxx b/sd/source/ui/framework/configuration/ConfigurationClassifier.hxx
new file mode 100755
index 000000000000..b19f8c1459a5
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationClassifier.hxx
@@ -0,0 +1,183 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CONFIGURATION_CLASSIFIER_HXX
+#define SD_FRAMEWORK_CONFIGURATION_CLASSIFIER_HXX
+
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+
+#include <vector>
+
+namespace sd { namespace framework {
+
+/** A ConfigurationClassifier object compares two configurations of
+ resources and gives access to the differences. It is used mainly when
+ changes to the current configuration have been requested and the various
+ resource controllers have to be supplied with the set of resources that
+ are to be activated or deactivated.
+*/
+class ConfigurationClassifier
+{
+public:
+ /** Create a new ConfigurationClassifier object that will compare the
+ two given configurations.
+ */
+ ConfigurationClassifier (
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration1,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration2);
+
+ /** Calculate three lists of resource ids. These contain the resources
+ that belong to one configuration but not the other, or that belong
+ to both configurations.
+ @return
+ When the two configurations differ then return <TRUE/>. When
+ they are equivalent then return <FALSE/>.
+ */
+ bool Partition (void);
+
+ typedef ::std::vector<com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId> > ResourceIdVector;
+
+ /** Return the resources that belong to the configuration given as
+ rxConfiguration1 to the constructor but that do not belong to
+ rxConfiguration2.
+ @return
+ A reference to the, possibly empty, list of resources is
+ returned. This reference remains valid as long as the called
+ ConfigurationClassifier object stays alive.
+ */
+ const ResourceIdVector& GetC1minusC2 (void) const;
+
+ /** Return the resources that belong to the configuration given as
+ rxConfiguration2 to the constructor but that do not belong to
+ rxConfiguration1.
+ @return
+ A reference to the, possibly empty, list of resources is
+ returned. This reference remains valid as long as the called
+ ConfigurationClassifier object stays alive.
+ */
+ const ResourceIdVector& GetC2minusC1 (void) const;
+
+ /** Return the resources that belong to both the configurations that
+ where given to the constructor.
+ @return
+ A reference to the, possibly empty, list of resources is
+ returned. This reference remains valid as long as the called
+ ConfigurationClassifier object stays alive.
+ */
+ const ResourceIdVector& GetC1andC2 (void) const;
+
+ void TraceResourceIdVector (
+ const sal_Char* pMessage,
+ const ResourceIdVector& rResources) const;
+
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration> mxConfiguration1;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration> mxConfiguration2;
+
+ /** After the call to Classify() this vector holds all elements from
+ mxConfiguration1 that are not in mxConfiguration2.
+ */
+ ResourceIdVector maC1minusC2;
+
+ /** After the call to Classify() this vector holds all elements from
+ mxConfiguration2 that are not in mxConfiguration1.
+ */
+ ResourceIdVector maC2minusC1;
+
+ /** After the call to Classify() this vector holds all elements that are
+ member both of mxConfiguration1 and mxConfiguration2.
+ */
+ ResourceIdVector maC1andC2;
+
+ /** Put all the elements in the two gven sequences of resource ids and
+ copy them into one of the resource id result vectors maC1minusC2,
+ maC2minusC1, and maC1andC2. This is done by using only the resource
+ URLs for classification. Therefor this method calls itself
+ recursively.
+ @param rS1
+ One sequence of XResourceId objects.
+ @param rS2
+ Another sequence of XResourceId objects.
+ */
+ void PartitionResources (
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId> >& rS1,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId> >& rS2);
+
+ /** Compare the given sequences of resource ids and put their elements
+ in one of three vectors depending on whether an element belongs to
+ both sequences or to one but not the other. Note that only the
+ resource URLs of the XResourceId objects are used for the
+ classification.
+ @param rS1
+ One sequence of XResourceId objects.
+ @param rS2
+ Another sequence of XResourceId objects.
+ */
+ void ClassifyResources (
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId> >& rS1,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId> >& rS2,
+ ResourceIdVector& rS1minusS2,
+ ResourceIdVector& rS2minusS1,
+ ResourceIdVector& rS1andS2);
+
+
+ /** Copy the resources given in rSource to the list of resources
+ specified by rTarget. Resources bound to the ones in rSource,
+ either directly or indirectly, are copied as well.
+ @param rSource
+ All resources and the ones bound to them, either directly or
+ indirectly, are copied.
+ @param rxConfiguration
+ This configuration is used to determine the resources bound to
+ the ones in rSource.
+ @param rTarget
+ This list is filled with resources from rSource and the ones
+ bound to them.
+ */
+ void CopyResources (
+ const ResourceIdVector& rSource,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration,
+ ResourceIdVector& rTarget);
+};
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ConfigurationController.cxx b/sd/source/ui/framework/configuration/ConfigurationController.cxx
new file mode 100755
index 000000000000..2f846e50be25
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationController.cxx
@@ -0,0 +1,726 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "framework/ConfigurationController.hxx"
+
+#include "framework/Configuration.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "ConfigurationUpdater.hxx"
+#include "ConfigurationControllerBroadcaster.hxx"
+#include "ConfigurationTracer.hxx"
+#include "GenericConfigurationChangeRequest.hxx"
+#include "ResourceFactoryManager.hxx"
+#include "UpdateRequest.hxx"
+#include "ChangeRequestQueueProcessor.hxx"
+#include "ConfigurationClassifier.hxx"
+#include "ViewShellBase.hxx"
+#include "UpdateLockManager.hxx"
+#include "DrawController.hxx"
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <comphelper/stl_types.hxx>
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using rtl::OUString;
+using ::sd::framework::FrameworkHelper;
+
+#undef VERBOSE
+//#define VERBOSE 3
+
+
+namespace sd { namespace framework {
+
+Reference<XInterface> SAL_CALL ConfigurationController_createInstance (
+ const Reference<XComponentContext>& rxContext)
+{
+ (void)rxContext;
+ return static_cast<XWeak*>(new ConfigurationController());
+}
+
+
+
+
+OUString ConfigurationController_getImplementationName (void) throw(RuntimeException)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.Draw.framework.configuration.ConfigurationController"));
+}
+
+
+
+
+Sequence<rtl::OUString> SAL_CALL ConfigurationController_getSupportedServiceNames (void)
+ throw (RuntimeException)
+{
+ static const OUString sServiceName(OUString::createFromAscii(
+ "com.sun.star.drawing.framework.ConfigurationController"));
+ return Sequence<rtl::OUString>(&sServiceName, 1);
+}
+
+
+
+
+//----- ConfigurationController::Implementation -------------------------------
+
+class ConfigurationController::Implementation
+{
+public:
+ Implementation (
+ ConfigurationController& rController,
+ const Reference<frame::XController>& rxController);
+ ~Implementation (void);
+
+ Reference<XControllerManager> mxControllerManager;
+
+ /** The Broadcaster class implements storing and calling of listeners.
+ */
+ ::boost::shared_ptr<ConfigurationControllerBroadcaster> mpBroadcaster;
+
+ /** The requested configuration which is modifed (asynchronously) by
+ calls to requestResourceActivation() and
+ requestResourceDeactivation(). The mpConfigurationUpdater makes the
+ current configuration reflect the content of this one.
+ */
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration> mxRequestedConfiguration;
+
+ ViewShellBase* mpBase;
+
+ ::boost::shared_ptr<ResourceFactoryManager> mpResourceFactoryContainer;
+
+ ::boost::shared_ptr<ConfigurationControllerResourceManager> mpResourceManager;
+
+ ::boost::shared_ptr<ConfigurationUpdater> mpConfigurationUpdater;
+
+ /** The queue processor ownes the queue of configuration change request
+ objects and processes the objects.
+ */
+ ::boost::scoped_ptr<ChangeRequestQueueProcessor> mpQueueProcessor;
+
+ ::boost::shared_ptr<ConfigurationUpdaterLock> mpConfigurationUpdaterLock;
+
+ sal_Int32 mnLockCount;
+};
+
+
+
+
+//===== ConfigurationController::Lock =========================================
+
+ConfigurationController::Lock::Lock (const Reference<XConfigurationController>& rxController)
+ : mxController(rxController)
+{
+ OSL_ASSERT(mxController.is());
+
+ if (mxController.is())
+ mxController->lock();
+}
+
+
+
+
+ConfigurationController::Lock::~Lock (void)
+{
+ if (mxController.is())
+ mxController->unlock();
+}
+
+
+
+
+//===== ConfigurationController ===============================================
+
+ConfigurationController::ConfigurationController (void) throw()
+ : ConfigurationControllerInterfaceBase(MutexOwner::maMutex),
+ mpImplementation(),
+ mbIsDisposed(false)
+{
+}
+
+
+
+
+ConfigurationController::~ConfigurationController (void) throw()
+{
+}
+
+
+
+
+void SAL_CALL ConfigurationController::disposing (void)
+{
+ if (mpImplementation.get() == NULL)
+ return;
+
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("ConfigurationController::disposing\n");
+ OSL_TRACE(" requesting empty configuration\n");
+#endif
+ // To destroy all resources an empty configuration is requested and then,
+ // synchronously, all resulting requests are processed.
+ mpImplementation->mpQueueProcessor->Clear();
+ restoreConfiguration(new Configuration(this,false));
+ mpImplementation->mpQueueProcessor->ProcessUntilEmpty();
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE(" all requests processed\n");
+#endif
+
+ // Now that all resources have been deactivated, mark the controller as
+ // disposed.
+ mbIsDisposed = true;
+
+ // Release the listeners.
+ lang::EventObject aEvent;
+ aEvent.Source = uno::Reference<uno::XInterface>((cppu::OWeakObject*)this);
+
+ {
+ const ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
+ mpImplementation->mpBroadcaster->DisposeAndClear();
+ }
+
+ mpImplementation->mpQueueProcessor.reset();
+ mpImplementation->mxRequestedConfiguration = NULL;
+ mpImplementation.reset();
+}
+
+
+
+
+void ConfigurationController::ProcessEvent (void)
+{
+ if (mpImplementation.get() != NULL)
+ {
+ OSL_ASSERT(mpImplementation->mpQueueProcessor.get()!=NULL);
+
+ mpImplementation->mpQueueProcessor->ProcessOneEvent();
+ }
+}
+
+
+
+
+void ConfigurationController::RequestSynchronousUpdate (void)
+{
+ if (mpImplementation.get() == NULL)
+ return;
+ if (mpImplementation->mpQueueProcessor.get() == 0)
+ return;
+ mpImplementation->mpQueueProcessor->ProcessUntilEmpty();
+}
+
+
+
+
+//----- XConfigurationControllerBroadcaster -----------------------------------
+
+void SAL_CALL ConfigurationController::addConfigurationChangeListener (
+ const Reference<XConfigurationChangeListener>& rxListener,
+ const ::rtl::OUString& rsEventType,
+ const Any& rUserData)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ ThrowIfDisposed();
+ OSL_ASSERT(mpImplementation.get()!=NULL);
+ mpImplementation->mpBroadcaster->AddListener(rxListener, rsEventType, rUserData);
+}
+
+
+
+
+void SAL_CALL ConfigurationController::removeConfigurationChangeListener (
+ const Reference<XConfigurationChangeListener>& rxListener)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ ThrowIfDisposed();
+ mpImplementation->mpBroadcaster->RemoveListener(rxListener);
+}
+
+
+
+
+void SAL_CALL ConfigurationController::notifyEvent (
+ const ConfigurationChangeEvent& rEvent)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ mpImplementation->mpBroadcaster->NotifyListeners(rEvent);
+}
+
+
+
+
+
+//----- XConfigurationController ----------------------------------------------
+
+void SAL_CALL ConfigurationController::lock (void)
+ throw (RuntimeException)
+{
+ OSL_ASSERT(mpImplementation.get()!=NULL);
+ OSL_ASSERT(mpImplementation->mpConfigurationUpdater.get()!=NULL);
+
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+
+ ++mpImplementation->mnLockCount;
+ if (mpImplementation->mpConfigurationUpdaterLock.get()==NULL)
+ mpImplementation->mpConfigurationUpdaterLock
+ = mpImplementation->mpConfigurationUpdater->GetLock();
+}
+
+
+
+
+void SAL_CALL ConfigurationController::unlock (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Allow unlocking while the ConfigurationController is being disposed
+ // (but not when that is done and the controller is disposed.)
+ if (rBHelper.bDisposed)
+ ThrowIfDisposed();
+
+ OSL_ASSERT(mpImplementation->mnLockCount>0);
+ --mpImplementation->mnLockCount;
+ if (mpImplementation->mnLockCount == 0)
+ mpImplementation->mpConfigurationUpdaterLock.reset();
+}
+
+
+
+
+void SAL_CALL ConfigurationController::requestResourceActivation (
+ const Reference<XResourceId>& rxResourceId,
+ ResourceActivationMode eMode)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ // Check whether we are being disposed. This is handled differently
+ // then being completely disposed because the first thing disposing()
+ // does is to deactivate all remaining resources. This is done via
+ // regular methods which must not throw DisposedExceptions. Therefore
+ // we just return silently during that stage.
+ if (rBHelper.bInDispose)
+ {
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("ConfigurationController::requestResourceActivation(): ignoring %s\n",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ return;
+ }
+
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationController::requestResourceActivation() %s\n",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ if (rxResourceId.is())
+ {
+ if (eMode == ResourceActivationMode_REPLACE)
+ {
+ // Get a list of the matching resources and create deactivation
+ // requests for them.
+ Sequence<Reference<XResourceId> > aResourceList (
+ mpImplementation->mxRequestedConfiguration->getResources(
+ rxResourceId->getAnchor(),
+ rxResourceId->getResourceTypePrefix(),
+ AnchorBindingMode_DIRECT));
+
+ for (sal_Int32 nIndex=0; nIndex<aResourceList.getLength(); ++nIndex)
+ {
+ // Do not request the deactivation of the resource for which
+ // this method was called. Doing it would not change the
+ // outcome but would result in unnecessary work.
+ if (rxResourceId->compareTo(aResourceList[nIndex]) == 0)
+ continue;
+
+ // Request the deactivation of a resource and all resources
+ // linked to it.
+ requestResourceDeactivation(aResourceList[nIndex]);
+ }
+ }
+
+ Reference<XConfigurationChangeRequest> xRequest(
+ new GenericConfigurationChangeRequest(
+ rxResourceId,
+ GenericConfigurationChangeRequest::Activation));
+ postChangeRequest(xRequest);
+ }
+}
+
+
+
+
+void SAL_CALL ConfigurationController::requestResourceDeactivation (
+ const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationController::requestResourceDeactivation() %s\n",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ if (rxResourceId.is())
+ {
+ // Request deactivation of all resources linked to the specified one
+ // as well.
+ const Sequence<Reference<XResourceId> > aLinkedResources (
+ mpImplementation->mxRequestedConfiguration->getResources(
+ rxResourceId,
+ OUString(),
+ AnchorBindingMode_DIRECT));
+ const sal_Int32 nCount (aLinkedResources.getLength());
+ for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
+ {
+ // We do not add deactivation requests directly but call this
+ // method recursively, so that when one time there are resources
+ // linked to linked resources, these are handled correctly, too.
+ requestResourceDeactivation(aLinkedResources[nIndex]);
+ }
+
+ // Add a deactivation request for the specified resource.
+ Reference<XConfigurationChangeRequest> xRequest(
+ new GenericConfigurationChangeRequest(
+ rxResourceId,
+ GenericConfigurationChangeRequest::Deactivation));
+ postChangeRequest(xRequest);
+ }
+}
+
+
+
+
+Reference<XResource> SAL_CALL ConfigurationController::getResource (
+ const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ ConfigurationControllerResourceManager::ResourceDescriptor aDescriptor (
+ mpImplementation->mpResourceManager->GetResource(rxResourceId));
+ return aDescriptor.mxResource;
+}
+
+
+
+
+void SAL_CALL ConfigurationController::update (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ if (mpImplementation->mpQueueProcessor->IsEmpty())
+ {
+ // The queue is empty. Add another request that does nothing but
+ // asynchronously trigger a request for an update.
+ mpImplementation->mpQueueProcessor->AddRequest(new UpdateRequest());
+ }
+ else
+ {
+ // The queue is not empty, so we rely on the queue processor to
+ // request an update automatically when the queue becomes empty.
+ }
+}
+
+
+
+
+sal_Bool SAL_CALL ConfigurationController::hasPendingRequests (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ return ! mpImplementation->mpQueueProcessor->IsEmpty();
+}
+
+
+
+
+
+void SAL_CALL ConfigurationController::postChangeRequest (
+ const Reference<XConfigurationChangeRequest>& rxRequest)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ mpImplementation->mpQueueProcessor->AddRequest(rxRequest);
+}
+
+
+
+
+Reference<XConfiguration> SAL_CALL ConfigurationController::getRequestedConfiguration (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ if (mpImplementation->mxRequestedConfiguration.is())
+ return Reference<XConfiguration>(
+ mpImplementation->mxRequestedConfiguration->createClone(), UNO_QUERY);
+ else
+ return Reference<XConfiguration>();
+}
+
+
+
+
+Reference<XConfiguration> SAL_CALL ConfigurationController::getCurrentConfiguration (void)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ Reference<XConfiguration> xCurrentConfiguration(
+ mpImplementation->mpConfigurationUpdater->GetCurrentConfiguration());
+ if (xCurrentConfiguration.is())
+ return Reference<XConfiguration>(xCurrentConfiguration->createClone(), UNO_QUERY);
+ else
+ return Reference<XConfiguration>();
+}
+
+
+
+
+/** The given configuration is restored by generating the appropriate set of
+ activation and deactivation requests.
+*/
+void SAL_CALL ConfigurationController::restoreConfiguration (
+ const Reference<XConfiguration>& rxNewConfiguration)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ // We will probably be making a couple of activation and deactivation
+ // requests so lock the configuration controller and let it later update
+ // all changes at once.
+ ::boost::shared_ptr<ConfigurationUpdaterLock> pLock (
+ mpImplementation->mpConfigurationUpdater->GetLock());
+
+ // Get lists of resources that are to be activated or deactivated.
+ Reference<XConfiguration> xCurrentConfiguration (mpImplementation->mxRequestedConfiguration);
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("ConfigurationController::restoreConfiguration(\n");
+ ConfigurationTracer::TraceConfiguration(rxNewConfiguration, "requested configuration");
+ ConfigurationTracer::TraceConfiguration(xCurrentConfiguration, "current configuration");
+#endif
+ ConfigurationClassifier aClassifier (rxNewConfiguration, xCurrentConfiguration);
+ aClassifier.Partition();
+#if defined VERBOSE && VERBOSE>=3
+ aClassifier.TraceResourceIdVector(
+ "requested but not current resources:\n", aClassifier.GetC1minusC2());
+ aClassifier.TraceResourceIdVector(
+ "current but not requested resources:\n", aClassifier.GetC2minusC1());
+ aClassifier.TraceResourceIdVector(
+ "requested and current resources:\n", aClassifier.GetC1andC2());
+#endif
+
+ ConfigurationClassifier::ResourceIdVector::const_iterator iResource;
+
+ // Request the deactivation of resources that are not requested in the
+ // new configuration.
+ const ConfigurationClassifier::ResourceIdVector& rResourcesToDeactivate (
+ aClassifier.GetC2minusC1());
+ for (iResource=rResourcesToDeactivate.begin();
+ iResource!=rResourcesToDeactivate.end();
+ ++iResource)
+ {
+ requestResourceDeactivation(*iResource);
+ }
+
+ // Request the activation of resources that are requested in the
+ // new configuration but are not part of the current configuration.
+ const ConfigurationClassifier::ResourceIdVector& rResourcesToActivate (
+ aClassifier.GetC1minusC2());
+ for (iResource=rResourcesToActivate.begin();
+ iResource!=rResourcesToActivate.end();
+ ++iResource)
+ {
+ requestResourceActivation(*iResource, ResourceActivationMode_ADD);
+ }
+
+ pLock.reset();
+}
+
+
+
+
+//----- XResourceFactoryManager -----------------------------------------------
+
+void SAL_CALL ConfigurationController::addResourceFactory(
+ const OUString& sResourceURL,
+ const Reference<XResourceFactory>& rxResourceFactory)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+ mpImplementation->mpResourceFactoryContainer->AddFactory(sResourceURL, rxResourceFactory);
+}
+
+
+
+
+void SAL_CALL ConfigurationController::removeResourceFactoryForURL(
+ const OUString& sResourceURL)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+ mpImplementation->mpResourceFactoryContainer->RemoveFactoryForURL(sResourceURL);
+}
+
+
+
+
+void SAL_CALL ConfigurationController::removeResourceFactoryForReference(
+ const Reference<XResourceFactory>& rxResourceFactory)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+ mpImplementation->mpResourceFactoryContainer->RemoveFactoryForReference(rxResourceFactory);
+}
+
+
+
+
+Reference<XResourceFactory> SAL_CALL ConfigurationController::getResourceFactory (
+ const OUString& sResourceURL)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ThrowIfDisposed();
+
+ return mpImplementation->mpResourceFactoryContainer->GetFactory(sResourceURL);
+}
+
+
+
+
+//----- XInitialization -------------------------------------------------------
+
+void SAL_CALL ConfigurationController::initialize (const Sequence<Any>& aArguments)
+ throw (Exception, RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (aArguments.getLength() == 1)
+ {
+ const ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
+
+ mpImplementation.reset(new Implementation(
+ *this,
+ Reference<frame::XController>(aArguments[0], UNO_QUERY_THROW)));
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+
+void ConfigurationController::ThrowIfDisposed (void) const
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (mbIsDisposed)
+ {
+ throw lang::DisposedException (
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "ConfigurationController object has already been disposed")),
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+
+ if (mpImplementation.get() == NULL)
+ {
+ OSL_ASSERT(mpImplementation.get() != NULL);
+ throw RuntimeException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "ConfigurationController not initialized")),
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+
+
+
+//===== ConfigurationController::Implementation ===============================
+
+ConfigurationController::Implementation::Implementation (
+ ConfigurationController& rController,
+ const Reference<frame::XController>& rxController)
+ : mxControllerManager(rxController, UNO_QUERY_THROW),
+ mpBroadcaster(new ConfigurationControllerBroadcaster(&rController)),
+ mxRequestedConfiguration(new Configuration(&rController, true)),
+ mpBase(NULL),
+ mpResourceFactoryContainer(new ResourceFactoryManager(mxControllerManager)),
+ mpResourceManager(
+ new ConfigurationControllerResourceManager(mpResourceFactoryContainer,mpBroadcaster)),
+ mpConfigurationUpdater(
+ new ConfigurationUpdater(mpBroadcaster, mpResourceManager,mxControllerManager)),
+ mpQueueProcessor(new ChangeRequestQueueProcessor(&rController,mpConfigurationUpdater)),
+ mpConfigurationUpdaterLock(),
+ mnLockCount(0)
+{
+ mpQueueProcessor->SetConfiguration(mxRequestedConfiguration);
+}
+
+
+
+
+ConfigurationController::Implementation::~Implementation (void)
+{
+}
+
+
+
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx
new file mode 100755
index 000000000000..ff167f07520a
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.cxx
@@ -0,0 +1,231 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ConfigurationControllerBroadcaster.hxx"
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using rtl::OUString;
+
+namespace sd { namespace framework {
+
+ConfigurationControllerBroadcaster::ConfigurationControllerBroadcaster (
+ const Reference<XConfigurationController>& rxController)
+ : mxConfigurationController(rxController),
+ maListenerMap()
+{
+}
+
+
+
+
+void ConfigurationControllerBroadcaster::AddListener(
+ const Reference<XConfigurationChangeListener>& rxListener,
+ const ::rtl::OUString& rsEventType,
+ const Any& rUserData)
+{
+ if ( ! rxListener.is())
+ throw lang::IllegalArgumentException(
+ OUString::createFromAscii("invalid listener"),
+ mxConfigurationController,
+ 0);
+
+ if (maListenerMap.find(rsEventType) == maListenerMap.end())
+ maListenerMap[rsEventType] = ListenerList();
+ ListenerDescriptor aDescriptor;
+ aDescriptor.mxListener = rxListener;
+ aDescriptor.maUserData = rUserData;
+ maListenerMap[rsEventType].push_back(aDescriptor);
+}
+
+
+
+
+void ConfigurationControllerBroadcaster::RemoveListener(
+ const Reference<XConfigurationChangeListener>& rxListener)
+{
+ if ( ! rxListener.is())
+ throw lang::IllegalArgumentException(
+ OUString::createFromAscii("invalid listener"),
+ mxConfigurationController,
+ 0);
+
+ ListenerMap::iterator iMap;
+ ListenerList::iterator iList;
+ for (iMap=maListenerMap.begin(); iMap!=maListenerMap.end(); ++iMap)
+ {
+ for (iList=iMap->second.begin(); iList!=iMap->second.end(); ++iList)
+ {
+ if (iList->mxListener == rxListener)
+ {
+ iMap->second.erase(iList);
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+void ConfigurationControllerBroadcaster::NotifyListeners (
+ const ListenerList& rList,
+ const ConfigurationChangeEvent& rEvent)
+{
+ // Create a local copy of the event in which the user data is modified
+ // for every listener.
+ ConfigurationChangeEvent aEvent (rEvent);
+
+ ListenerList::const_iterator iListener;
+ for (iListener=rList.begin(); iListener!=rList.end(); ++iListener)
+ {
+ try
+ {
+ aEvent.UserData = iListener->maUserData;
+ iListener->mxListener->notifyConfigurationChange(aEvent);
+ }
+ catch (lang::DisposedException& rException)
+ {
+ // When the exception comes from the listener itself then
+ // unregister it.
+ if (rException.Context == iListener->mxListener)
+ RemoveListener(iListener->mxListener);
+ }
+ catch(RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+}
+
+
+
+
+void ConfigurationControllerBroadcaster::NotifyListeners (const ConfigurationChangeEvent& rEvent)
+{
+ // Notify the specialized listeners.
+ ListenerMap::const_iterator iMap (maListenerMap.find(rEvent.Type));
+ if (iMap != maListenerMap.end())
+ {
+ // Create a local list of the listeners to avoid problems with
+ // concurrent changes and to be able to remove disposed listeners.
+ ListenerList aList (iMap->second.begin(), iMap->second.end());
+ NotifyListeners(aList,rEvent);
+ }
+
+ // Notify the universal listeners.
+ iMap = maListenerMap.find(OUString());
+ if (iMap != maListenerMap.end())
+ {
+ // Create a local list of the listeners to avoid problems with
+ // concurrent changes and to be able to remove disposed listeners.
+ ListenerList aList (iMap->second.begin(), iMap->second.end());
+ NotifyListeners(aList,rEvent);
+ }
+}
+
+
+
+
+void ConfigurationControllerBroadcaster::NotifyListeners (
+ const OUString& rsEventType,
+ const Reference<XResourceId>& rxResourceId,
+ const Reference<XResource>& rxResourceObject)
+{
+ ConfigurationChangeEvent aEvent;
+ aEvent.Type = rsEventType;
+ aEvent.ResourceId = rxResourceId;
+ aEvent.ResourceObject = rxResourceObject;
+ try
+ {
+ NotifyListeners(aEvent);
+ }
+ catch (lang::DisposedException)
+ {
+ }
+}
+
+
+
+
+
+void ConfigurationControllerBroadcaster::DisposeAndClear (void)
+{
+ lang::EventObject aEvent;
+ aEvent.Source = mxConfigurationController;
+ while (maListenerMap.size() > 0)
+ {
+ ListenerMap::iterator iMap (maListenerMap.begin());
+ if (iMap == maListenerMap.end())
+ break;
+
+ // When the first vector is empty then remove it from the map.
+ if (iMap->second.size() == 0)
+ {
+ maListenerMap.erase(iMap);
+ continue;
+ }
+ else
+ {
+ Reference<lang::XEventListener> xListener (
+ iMap->second.front().mxListener, UNO_QUERY);
+ if (xListener.is())
+ {
+ // Tell the listener that the configuration controller is
+ // being disposed and remove the listener (for all event
+ // types).
+ try
+ {
+ RemoveListener(iMap->second.front().mxListener);
+ xListener->disposing(aEvent);
+ }
+ catch (RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ else
+ {
+ // Remove just this reference to the listener.
+ iMap->second.erase(iMap->second.begin());
+ }
+ }
+ }
+}
+
+
+
+
+} } // end of namespace sd::framework
+
diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.hxx b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.hxx
new file mode 100644
index 000000000000..a5939386d7b7
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationControllerBroadcaster.hxx
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX
+#define SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX
+
+#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
+#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
+#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
+
+#include <comphelper/stl_types.hxx>
+#include <vector>
+#include <hash_map>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace framework {
+
+/** This class manages the set of XConfigurationChangeListeners and
+ calls them when the ConfigurationController wants to broadcast an
+ event.
+
+ For every registered combination of listener and event type a user data
+ object is stored. This user data object is then given to the listener
+ whenever it is called for an event. With this the listener can use
+ a switch statement to handle different event types.
+*/
+class ConfigurationControllerBroadcaster
+{
+public:
+ /** The given controller is used as origin of thrown exceptions.
+ */
+ ConfigurationControllerBroadcaster (
+ const css::uno::Reference<
+ css::drawing::framework::XConfigurationController>& rxController);
+
+ /** Add a listener for one type of event. When one listener is
+ interested in more than one event type this method has to be called
+ once for every event type. Alternatively it can register as
+ universal listener that will be called for all event types.
+ @param rxListener
+ A valid reference to a listener.
+ @param rsEventType
+ The type of event that the listener will be called for. The
+ empty string is a special value in that the listener will be
+ called for all event types.
+ @param rUserData
+ This object is passed to the listener whenever it is called for
+ the specified event type. For different event types different
+ user data objects can be provided.
+ @throws IllegalArgumentException
+ when an empty listener reference is given.
+ */
+ void AddListener(
+ const css::uno::Reference<
+ css::drawing::framework::XConfigurationChangeListener>& rxListener,
+ const ::rtl::OUString& rsEventType,
+ const css::uno::Any& rUserData);
+
+ /** Remove all references to the given listener. When one listener has
+ been registered for more than one type of event then it is removed
+ for all of them.
+ @param rxListener
+ A valid reference to a listener.
+ @throws IllegalArgumentException
+ when an empty listener reference is given.
+ */
+ void RemoveListener(
+ const css::uno::Reference<
+ css::drawing::framework::XConfigurationChangeListener>& rxListener);
+
+ /** Broadcast the given event to all listeners that have been registered
+ for its type of event as well as all universal listeners.
+
+ When calling a listener results in a DisposedException being thrown
+ the listener is unregistered automatically.
+ */
+ void NotifyListeners (
+ const css::drawing::framework::ConfigurationChangeEvent& rEvent);
+
+ /** This convenience variant of NotifyListeners create the event from
+ the given arguments.
+ */
+ void NotifyListeners (
+ const ::rtl::OUString& rsEventType,
+ const ::css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
+ const ::css::uno::Reference<css::drawing::framework::XResource>& rxResourceObject);
+
+ /** Call all listeners and inform them that the
+ ConfigurationController is being disposed. When this method returns
+ the list of registered listeners is empty. Further calls to
+ RemoveListener() are not necessary but do not result in an error.
+ */
+ void DisposeAndClear (void);
+
+private:
+ css::uno::Reference<
+ com::sun::star::drawing::framework::XConfigurationController> mxConfigurationController;
+ class ListenerDescriptor {public:
+ css::uno::Reference<
+ css::drawing::framework::XConfigurationChangeListener> mxListener;
+ css::uno::Any maUserData;
+ };
+ typedef ::std::vector<ListenerDescriptor> ListenerList;
+ typedef ::std::hash_map
+ <rtl::OUString,
+ ListenerList,
+ ::comphelper::UStringHash,
+ ::comphelper::UStringEqual> ListenerMap;
+ ListenerMap maListenerMap;
+
+ /** Broadcast the given event to all listeners in the given list.
+
+ When calling a listener results in a DisposedException being thrown
+ the listener is unregistered automatically.
+ */
+ void NotifyListeners (
+ const ListenerList& rList,
+ const css::drawing::framework::ConfigurationChangeEvent& rEvent);
+};
+
+
+
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx
new file mode 100755
index 000000000000..93ff7ee54e00
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.cxx
@@ -0,0 +1,352 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ConfigurationControllerResourceManager.hxx"
+#include "ConfigurationControllerBroadcaster.hxx"
+#include "ResourceFactoryManager.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <tools/diagnose_ex.h>
+#include <algorithm>
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::rtl::OUString;
+
+#undef VERBOSE
+//#define VERBOSE 1
+
+namespace sd { namespace framework {
+
+//===== ConfigurationControllerResourceManager ================================
+
+ConfigurationControllerResourceManager::ConfigurationControllerResourceManager (
+ const ::boost::shared_ptr<ResourceFactoryManager>& rpResourceFactoryContainer,
+ const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster)
+ : maResourceMap(ResourceComparator()),
+ mpResourceFactoryContainer(rpResourceFactoryContainer),
+ mpBroadcaster(rpBroadcaster)
+{
+}
+
+
+
+
+ConfigurationControllerResourceManager::~ConfigurationControllerResourceManager (void)
+{
+}
+
+
+
+
+ConfigurationControllerResourceManager::ResourceDescriptor
+ ConfigurationControllerResourceManager::GetResource (
+ const Reference<XResourceId>& rxResourceId)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ResourceMap::const_iterator iResource (maResourceMap.find(rxResourceId));
+ if (iResource != maResourceMap.end())
+ return iResource->second;
+ else
+ return ResourceDescriptor();
+}
+
+
+
+
+void ConfigurationControllerResourceManager::ActivateResources (
+ const ::std::vector<Reference<XResourceId> >& rResources,
+ const Reference<XConfiguration>& rxConfiguration)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ // Iterate in normal order over the resources that are to be
+ // activated so that resources on which others depend are activated
+ // beforet the depending resources are activated.
+ ::std::for_each(
+ rResources.begin(),
+ rResources.end(),
+ ::boost::bind(&ConfigurationControllerResourceManager::ActivateResource,
+ this, _1, rxConfiguration));
+}
+
+
+
+
+void ConfigurationControllerResourceManager::DeactivateResources (
+ const ::std::vector<Reference<XResourceId> >& rResources,
+ const Reference<XConfiguration>& rxConfiguration)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ // Iterate in reverese order over the resources that are to be
+ // deactivated so that resources on which others depend are deactivated
+ // only when the depending resources have already been deactivated.
+ ::std::for_each(
+ rResources.rbegin(),
+ rResources.rend(),
+ ::boost::bind(&ConfigurationControllerResourceManager::DeactivateResource,
+ this, _1, rxConfiguration));
+}
+
+
+
+
+/* In this method we do following steps.
+ 1. Get the factory with which the resource will be created.
+ 2. Create the resource.
+ 3. Add the resource to the URL->Object map of the configuration
+ controller.
+ 4. Add the resource id to the current configuration.
+ 5. Notify listeners.
+*/
+void ConfigurationControllerResourceManager::ActivateResource (
+ const Reference<XResourceId>& rxResourceId,
+ const Reference<XConfiguration>& rxConfiguration)
+{
+ if ( ! rxResourceId.is())
+ {
+ OSL_ASSERT(rxResourceId.is());
+ return;
+ }
+
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("activating resource %s\n", OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ // 1. Get the factory.
+ const OUString sResourceURL (rxResourceId->getResourceURL());
+ Reference<XResourceFactory> xFactory (mpResourceFactoryContainer->GetFactory(sResourceURL));
+ if ( ! xFactory.is())
+ {
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE(" no factory found fo %s\n",
+ OUStringToOString(sResourceURL, RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ return;
+ }
+
+ try
+ {
+ // 2. Create the resource.
+ Reference<XResource> xResource;
+ try
+ {
+ xResource = xFactory->createResource(rxResourceId);
+ }
+ catch (lang::DisposedException&)
+ {
+ // The factory is disposed and can be removed from the list
+ // of registered factories.
+ mpResourceFactoryContainer->RemoveFactoryForReference(xFactory);
+ }
+ catch(Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ if (xResource.is())
+ {
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE(" successfully created\n");
+#endif
+ // 3. Add resource to URL->Object map.
+ AddResource(xResource, xFactory);
+
+ // 4. Add resource id to current configuration.
+ rxConfiguration->addResource(rxResourceId);
+
+ // 5. Notify the new resource to listeners of the ConfigurationController.
+ mpBroadcaster->NotifyListeners(
+ FrameworkHelper::msResourceActivationEvent,
+ rxResourceId,
+ xResource);
+ }
+ else
+ {
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE(" resource creation failed\n");
+#endif
+ }
+ }
+ catch (RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+
+
+
+/* In this method we do following steps.
+ 1. Remove the resource from the URL->Object map of the configuration
+ controller.
+ 2. Notify listeners.
+ 3. Remove the resource id from the current configuration.
+ 4. Release the resource.
+*/
+void ConfigurationControllerResourceManager::DeactivateResource (
+ const Reference<XResourceId>& rxResourceId,
+ const Reference<XConfiguration>& rxConfiguration)
+{
+ if ( ! rxResourceId.is())
+ return;
+
+ bool bSuccess (false);
+ try
+ {
+ // 1. Remove resource from URL->Object map.
+ ResourceDescriptor aDescriptor (RemoveResource(rxResourceId));
+
+ if (aDescriptor.mxResource.is() && aDescriptor.mxResourceFactory.is())
+ {
+ // 2. Notifiy listeners that the resource is being deactivated.
+ mpBroadcaster->NotifyListeners(
+ FrameworkHelper::msResourceDeactivationEvent,
+ rxResourceId,
+ aDescriptor.mxResource);
+
+ // 3. Remove resource id from current configuration.
+ rxConfiguration->removeResource(rxResourceId);
+
+ // 4. Release the resource.
+ try
+ {
+ aDescriptor.mxResourceFactory->releaseResource(aDescriptor.mxResource);
+ }
+ catch (lang::DisposedException& rException)
+ {
+ if ( ! rException.Context.is()
+ || rException.Context == aDescriptor.mxResourceFactory)
+ {
+ // The factory is disposed and can be removed from the
+ // list of registered factories.
+ mpResourceFactoryContainer->RemoveFactoryForReference(
+ aDescriptor.mxResourceFactory);
+ }
+ }
+
+ bSuccess = true;
+ }
+ }
+ catch (RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+#if defined VERBOSE && VERBOSE>=1
+ if (bSuccess)
+ OSL_TRACE("successfully deactivated %s\n", OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+ else
+ OSL_TRACE("activating resource %s failed\n", OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
+#endif
+}
+
+
+
+
+void ConfigurationControllerResourceManager::AddResource (
+ const Reference<XResource>& rxResource,
+ const Reference<XResourceFactory>& rxFactory)
+{
+ if ( ! rxResource.is())
+ {
+ OSL_ASSERT(rxResource.is());
+ return;
+ }
+
+ // Add the resource to the resource container.
+ ResourceDescriptor aDescriptor;
+ aDescriptor.mxResource = rxResource;
+ aDescriptor.mxResourceFactory = rxFactory;
+ maResourceMap[rxResource->getResourceId()] = aDescriptor;
+
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationControllerResourceManager::AddResource(): added %s -> %x\n",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResource->getResourceId()),
+ RTL_TEXTENCODING_UTF8).getStr(),
+ rxResource.get());
+#endif
+}
+
+
+
+
+ConfigurationControllerResourceManager::ResourceDescriptor
+ ConfigurationControllerResourceManager::RemoveResource (
+ const Reference<XResourceId>& rxResourceId)
+{
+ ResourceDescriptor aDescriptor;
+
+ ResourceMap::iterator iResource (maResourceMap.find(rxResourceId));
+ if (iResource != maResourceMap.end())
+ {
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationControllerResourceManager::RemoveResource(): removing %s -> %x\n",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(rxResourceId),
+ RTL_TEXTENCODING_UTF8).getStr(),
+ *iResource);
+#endif
+
+ aDescriptor = iResource->second;
+ maResourceMap.erase(rxResourceId);
+ }
+
+ return aDescriptor;
+}
+
+
+
+
+//===== ConfigurationControllerResourceManager::ResourceComparator ============
+
+bool ConfigurationControllerResourceManager::ResourceComparator::operator() (
+ const Reference<XResourceId>& rxId1,
+ const Reference<XResourceId>& rxId2) const
+{
+ if (rxId1.is() && rxId2.is())
+ return rxId1->compareTo(rxId2)<0;
+ else if (rxId1.is())
+ return true;
+ else if (rxId2.is())
+ return false;
+ else
+ return false;
+}
+
+
+
+
+} } // end of namespace sd::framework
+
diff --git a/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.hxx b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.hxx
new file mode 100644
index 000000000000..0c095df50fdf
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationControllerResourceManager.hxx
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_RESOURCE_MANAGER_HXX
+#define SD_FRAMEWORK_RESOURCE_MANAGER_HXX
+
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <com/sun/star/drawing/framework/XResource.hpp>
+#include <com/sun/star/drawing/framework/XResourceFactory.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <vector>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace framework {
+
+class ConfigurationControllerBroadcaster;
+class ResourceFactoryManager;
+
+/** Manage the set of active resources. Activate and deactivate resources.
+*/
+class ConfigurationControllerResourceManager
+ : ::boost::noncopyable
+{
+public:
+ /** For every active resource both the resource itself as well as its
+ creating factory are remembered, so that on deactivation, the
+ resource can be deactivated by this factory.
+ */
+ class ResourceDescriptor
+ {
+ public:
+ css::uno::Reference<css::drawing::framework::XResource> mxResource;
+ css::uno::Reference<css::drawing::framework::XResourceFactory> mxResourceFactory;
+ };
+
+ /** A new ResourceManager object is created with the resource factory
+ container for creating resources and the event broadcaster for
+ notifying ConfigurationChangeListeners of activated or deactivated
+ resources.
+ */
+ ConfigurationControllerResourceManager (
+ const ::boost::shared_ptr<ResourceFactoryManager>& rpResourceFactoryContainer,
+ const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster);
+
+ ~ConfigurationControllerResourceManager (void);
+
+ /** Activate all the resources that are specified by resource ids in
+ rResources. The resource ids of activated resources are added to
+ the given configuration. Activated resources are notified to all
+ interested ConfigurationChangeListeners.
+ */
+ void ActivateResources (
+ const ::std::vector<
+ css::uno::Reference<css::drawing::framework::XResourceId> >& rResources,
+ const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration);
+
+ /** Deactivate all the resources that are specified by resource ids in
+ rResources. The resource ids of deactivated resources are removed
+ from the given configuration. Activated resources are notified to all
+ interested ConfigurationChangeListeners.
+ */
+ void DeactivateResources (
+ const ::std::vector<
+ css::uno::Reference<css::drawing::framework::XResourceId> >& rResources,
+ const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration);
+
+ /** Return the descriptor for the specified resource.
+ @return
+ When there is no active resource for the given resource id then
+ an empty descriptor is returned.
+ */
+ ResourceDescriptor GetResource (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId);
+
+private:
+ osl::Mutex maMutex;
+
+ class ResourceComparator
+ {
+ public:
+ bool operator() (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxId1,
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxId2) const;
+ };
+
+ typedef ::std::map<
+ css::uno::Reference<css::drawing::framework::XResourceId>,
+ ResourceDescriptor,
+ ResourceComparator> ResourceMap;
+ ResourceMap maResourceMap;
+
+ ::boost::shared_ptr<ResourceFactoryManager> mpResourceFactoryContainer;
+
+ /** This broadcaster is used to notify the activation and deactivation
+ of resources.
+ */
+ ::boost::shared_ptr<ConfigurationControllerBroadcaster> mpBroadcaster;
+
+ void ActivateResource (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
+ const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration);
+
+ void DeactivateResource (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
+ const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration);
+
+ void AddResource (
+ const css::uno::Reference<css::drawing::framework::XResource>& rxResource,
+ const css::uno::Reference<css::drawing::framework::XResourceFactory>& rxFactory);
+
+ ResourceDescriptor RemoveResource (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId);
+};
+
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ConfigurationTracer.cxx b/sd/source/ui/framework/configuration/ConfigurationTracer.cxx
new file mode 100755
index 000000000000..b9552940060e
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationTracer.cxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ConfigurationTracer.hxx"
+
+#include <cstdio>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd { namespace framework {
+
+void ConfigurationTracer::TraceConfiguration (
+ const Reference<XConfiguration>& rxConfiguration,
+ const char* pMessage)
+{
+#ifdef DEBUG
+ OSL_TRACE("%s at %p {", pMessage, rxConfiguration.get());
+ if (rxConfiguration.is())
+ {
+ TraceBoundResources(rxConfiguration, NULL, 0);
+ }
+ else
+ {
+ OSL_TRACE(" empty");
+ }
+ OSL_TRACE("}");
+#else
+ (void)rxConfiguration;
+ (void)pMessage;
+#endif
+}
+
+
+
+
+#ifdef DEBUG
+void ConfigurationTracer::TraceBoundResources (
+ const Reference<XConfiguration>& rxConfiguration,
+ const Reference<XResourceId>& rxResourceId,
+ const int nIndentation)
+{
+ Sequence<Reference<XResourceId> > aResourceList (
+ rxConfiguration->getResources(rxResourceId, ::rtl::OUString(), AnchorBindingMode_DIRECT));
+ const ::rtl::OUString sIndentation (::rtl::OUString::createFromAscii(" "));
+ for (sal_Int32 nIndex=0; nIndex<aResourceList.getLength(); ++nIndex)
+ {
+ ::rtl::OUString sLine (aResourceList[nIndex]->getResourceURL());
+ for (int i=0; i<nIndentation; ++i)
+ sLine = sIndentation + sLine;
+ OSL_TRACE("%s", OUStringToOString(sLine, RTL_TEXTENCODING_UTF8).getStr());
+ TraceBoundResources(rxConfiguration, aResourceList[nIndex], nIndentation+1);
+ }
+}
+#endif
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ConfigurationTracer.hxx b/sd/source/ui/framework/configuration/ConfigurationTracer.hxx
new file mode 100755
index 000000000000..b04206fd65e1
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationTracer.hxx
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CONFIGURATION_TRACER_HXX
+#define SD_FRAMEWORK_CONFIGURATION_TRACER_HXX
+
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+
+namespace sd { namespace framework {
+
+/** Print debug information about configurations to the standard error
+ output channel.
+*/
+class ConfigurationTracer
+{
+public:
+ static void TraceConfiguration (
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration,
+ const char* pMessage);
+#ifdef DEBUG
+ static void TraceBoundResources (
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::framework::XResourceId>& rxResourceId,
+ const int nIndentation);
+#endif
+};
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx b/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx
new file mode 100755
index 000000000000..4ab361a9490d
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationUpdater.cxx
@@ -0,0 +1,468 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ConfigurationUpdater.hxx"
+#include "ConfigurationTracer.hxx"
+#include "ConfigurationClassifier.hxx"
+#include "ConfigurationControllerBroadcaster.hxx"
+#include "framework/Configuration.hxx"
+#include "framework/FrameworkHelper.hxx"
+
+#include <comphelper/scopeguard.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::sd::framework::FrameworkHelper;
+using ::rtl::OUString;
+using ::std::vector;
+
+#undef VERBOSE
+//#define VERBOSE 2
+
+namespace {
+static const sal_Int32 snShortTimeout (100);
+static const sal_Int32 snNormalTimeout (1000);
+static const sal_Int32 snLongTimeout (10000);
+static const sal_Int32 snShortTimeoutCountThreshold (1);
+static const sal_Int32 snNormalTimeoutCountThreshold (5);
+}
+
+namespace sd { namespace framework {
+
+
+//===== ConfigurationUpdaterLock ==============================================
+
+class ConfigurationUpdaterLock
+{
+public:
+ ConfigurationUpdaterLock (ConfigurationUpdater& rUpdater)
+ : mrUpdater(rUpdater) { mrUpdater.LockUpdates(); }
+ ~ConfigurationUpdaterLock(void) { mrUpdater.UnlockUpdates(); }
+private:
+ ConfigurationUpdater& mrUpdater;
+};
+
+
+
+
+//===== ConfigurationUpdater ==================================================
+
+ConfigurationUpdater::ConfigurationUpdater (
+ const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster,
+ const ::boost::shared_ptr<ConfigurationControllerResourceManager>& rpResourceManager,
+ const Reference<XControllerManager>& rxControllerManager)
+ : mxControllerManager(),
+ mpBroadcaster(rpBroadcaster),
+ mxCurrentConfiguration(Reference<XConfiguration>(new Configuration(NULL, false))),
+ mxRequestedConfiguration(),
+ mbUpdatePending(false),
+ mbUpdateBeingProcessed(false),
+ mnLockCount(0),
+ maUpdateTimer(),
+ mnFailedUpdateCount(0),
+ mpResourceManager(rpResourceManager)
+{
+ // Prepare the timer that is started when after an update the current
+ // and the requested configuration differ. With the timer we try
+ // updates until the two configurations are the same.
+ maUpdateTimer.SetTimeout(snNormalTimeout);
+ maUpdateTimer.SetTimeoutHdl(LINK(this,ConfigurationUpdater,TimeoutHandler));
+ SetControllerManager(rxControllerManager);
+}
+
+
+
+
+ConfigurationUpdater::~ConfigurationUpdater (void)
+{
+ maUpdateTimer.Stop();
+}
+
+
+
+
+void ConfigurationUpdater::SetControllerManager(
+ const Reference<XControllerManager>& rxControllerManager)
+{
+ mxControllerManager = rxControllerManager;
+}
+
+
+
+
+void ConfigurationUpdater::RequestUpdate (
+ const Reference<XConfiguration>& rxRequestedConfiguration)
+{
+ mxRequestedConfiguration = rxRequestedConfiguration;
+
+ // Find out whether we really can update the configuration.
+ if (IsUpdatePossible())
+ {
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("UpdateConfiguration start");
+#endif
+
+ // Call UpdateConfiguration while that is possible and while someone
+ // set mbUpdatePending to true in the middle of it.
+ do
+ {
+ UpdateConfiguration();
+
+ if (mbUpdatePending && IsUpdatePossible())
+ continue;
+ }
+ while (false);
+ }
+ else
+ {
+ mbUpdatePending = true;
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("scheduling update for later");
+#endif
+ }
+}
+
+
+
+
+Reference<XConfiguration> ConfigurationUpdater::GetCurrentConfiguration (void) const
+{
+ return mxCurrentConfiguration;
+}
+
+
+
+
+bool ConfigurationUpdater::IsUpdatePossible (void)
+{
+ return ! mbUpdateBeingProcessed
+ && mxControllerManager.is()
+ && mnLockCount==0
+ && mxRequestedConfiguration.is()
+ && mxCurrentConfiguration.is();
+}
+
+
+
+
+void ConfigurationUpdater::UpdateConfiguration (void)
+{
+#if defined VERBOSE && VERBOSE>=1
+ OSL_TRACE("UpdateConfiguration update");
+#endif
+ SetUpdateBeingProcessed(true);
+ comphelper::ScopeGuard aScopeGuard (
+ ::boost::bind(&ConfigurationUpdater::SetUpdateBeingProcessed, this, false));
+
+ try
+ {
+ mbUpdatePending = false;
+
+ CleanRequestedConfiguration();
+ ConfigurationClassifier aClassifier(mxRequestedConfiguration, mxCurrentConfiguration);
+ if (aClassifier.Partition())
+ {
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationUpdater::UpdateConfiguration(");
+ ConfigurationTracer::TraceConfiguration(
+ mxRequestedConfiguration, "requested configuration");
+ ConfigurationTracer::TraceConfiguration(
+ mxCurrentConfiguration, "current configuration");
+#endif
+ // Notify the begining of the update.
+ ConfigurationChangeEvent aEvent;
+ aEvent.Type = FrameworkHelper::msConfigurationUpdateStartEvent;
+ aEvent.Configuration = mxRequestedConfiguration;
+ mpBroadcaster->NotifyListeners(aEvent);
+
+ // Do the actual update. All exceptions are caught and ignored,
+ // so that the the end of the update is notified always.
+ try
+ {
+ if (mnLockCount == 0)
+ UpdateCore(aClassifier);
+ }
+ catch(RuntimeException)
+ {
+ }
+
+ // Notify the end of the update.
+ aEvent.Type = FrameworkHelper::msConfigurationUpdateEndEvent;
+ mpBroadcaster->NotifyListeners(aEvent);
+
+ CheckUpdateSuccess();
+ }
+ else
+ {
+#if defined VERBOSE && VERBOSE>0
+ OSL_TRACE("nothing to do");
+#if defined VERBOSE && VERBOSE>=2
+ ConfigurationTracer::TraceConfiguration(
+ mxRequestedConfiguration, "requested configuration");
+ ConfigurationTracer::TraceConfiguration(
+ mxCurrentConfiguration, "current configuration");
+#endif
+#endif
+ }
+ }
+ catch (RuntimeException e)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+#if defined VERBOSE && VERBOSE>0
+ OSL_TRACE("ConfigurationUpdater::UpdateConfiguration)");
+ OSL_TRACE("UpdateConfiguration end");
+#endif
+}
+
+
+
+
+void ConfigurationUpdater::CleanRequestedConfiguration (void)
+{
+ if (mxControllerManager.is())
+ {
+ // Request the deactivation of pure anchors that have no child.
+ vector<Reference<XResourceId> > aResourcesToDeactivate;
+ CheckPureAnchors(mxRequestedConfiguration, aResourcesToDeactivate);
+ if (aResourcesToDeactivate.size() > 0)
+ {
+ Reference<XConfigurationController> xCC (
+ mxControllerManager->getConfigurationController());
+ vector<Reference<XResourceId> >::iterator iId;
+ for (iId=aResourcesToDeactivate.begin(); iId!=aResourcesToDeactivate.end(); ++iId)
+ if (iId->is())
+ xCC->requestResourceDeactivation(*iId);
+ }
+ }
+}
+
+
+
+
+void ConfigurationUpdater::CheckUpdateSuccess (void)
+{
+ // When the two configurations differ then start the timer to call
+ // another update later.
+ if ( ! AreConfigurationsEquivalent(mxCurrentConfiguration, mxRequestedConfiguration))
+ {
+ if (mnFailedUpdateCount <= snShortTimeoutCountThreshold)
+ maUpdateTimer.SetTimeout(snShortTimeout);
+ else if (mnFailedUpdateCount < snNormalTimeoutCountThreshold)
+ maUpdateTimer.SetTimeout(snNormalTimeout);
+ else
+ maUpdateTimer.SetTimeout(snLongTimeout);
+ ++mnFailedUpdateCount;
+ maUpdateTimer.Start();
+ }
+ else
+ {
+ // Update was successfull. Reset the failed update count.
+ mnFailedUpdateCount = 0;
+ }
+}
+
+
+
+
+void ConfigurationUpdater::UpdateCore (const ConfigurationClassifier& rClassifier)
+{
+ try
+ {
+#if defined VERBOSE && VERBOSE>=2
+ rClassifier.TraceResourceIdVector(
+ "requested but not current resources:", rClassifier.GetC1minusC2());
+ rClassifier.TraceResourceIdVector(
+ "current but not requested resources:", rClassifier.GetC2minusC1());
+ rClassifier.TraceResourceIdVector(
+ "requested and current resources:", rClassifier.GetC1andC2());
+#endif
+
+ // Updating of the sub controllers is done in two steps. In the
+ // first the sub controllers typically shut down resources that are
+ // not requested anymore. In the second the sub controllers
+ // typically set up resources that have been newly requested.
+ mpResourceManager->DeactivateResources(rClassifier.GetC2minusC1(), mxCurrentConfiguration);
+ mpResourceManager->ActivateResources(rClassifier.GetC1minusC2(), mxCurrentConfiguration);
+
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("ConfigurationController::UpdateConfiguration)");
+ ConfigurationTracer::TraceConfiguration(
+ mxRequestedConfiguration, "requested configuration");
+ ConfigurationTracer::TraceConfiguration(
+ mxCurrentConfiguration, "current configuration");
+#endif
+
+ // Deactivate pure anchors that have no child.
+ vector<Reference<XResourceId> > aResourcesToDeactivate;
+ CheckPureAnchors(mxCurrentConfiguration, aResourcesToDeactivate);
+ if (aResourcesToDeactivate.size() > 0)
+ mpResourceManager->DeactivateResources(aResourcesToDeactivate, mxCurrentConfiguration);
+ }
+ catch(RuntimeException)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+
+
+
+void ConfigurationUpdater::CheckPureAnchors (
+ const Reference<XConfiguration>& rxConfiguration,
+ vector<Reference<XResourceId> >& rResourcesToDeactivate)
+{
+ if ( ! rxConfiguration.is())
+ return;
+
+ // Get a list of all resources in the configuration.
+ Sequence<Reference<XResourceId> > aResources(
+ rxConfiguration->getResources(
+ NULL, OUString(), AnchorBindingMode_INDIRECT));
+ sal_Int32 nCount (aResources.getLength());
+
+ // Prepare the list of pure anchors that have to be deactivated.
+ rResourcesToDeactivate.clear();
+
+ // Iterate over the list in reverse order because when there is a chain
+ // of pure anchors with only the last one having no child then the whole
+ // list has to be deactivated.
+ sal_Int32 nIndex (nCount-1);
+ while (nIndex >= 0)
+ {
+ const Reference<XResourceId> xResourceId (aResources[nIndex]);
+ const Reference<XResource> xResource (
+ mpResourceManager->GetResource(xResourceId).mxResource);
+ bool bDeactiveCurrentResource (false);
+
+ // Skip all resources that are no pure anchors.
+ if (xResource.is() && xResource->isAnchorOnly())
+ {
+ // When xResource is not an anchor of the the next resource in
+ // the list then it is the anchor of no resource at all.
+ if (nIndex == nCount-1)
+ {
+ // No following anchors, deactivate this one, then remove it
+ // from the list.
+ bDeactiveCurrentResource = true;
+ }
+ else
+ {
+ const Reference<XResourceId> xPrevResourceId (aResources[nIndex+1]);
+ if ( ! xPrevResourceId.is()
+ || ! xPrevResourceId->isBoundTo(xResourceId, AnchorBindingMode_DIRECT))
+ {
+ // The previous resource (id) does not exist or is not bound to
+ // the current anchor.
+ bDeactiveCurrentResource = true;
+ }
+ }
+ }
+
+ if (bDeactiveCurrentResource)
+ {
+#if defined VERBOSE && VERBOSE>=2
+ OSL_TRACE("deactiving pure anchor %s because it has no children",
+ OUStringToOString(
+ FrameworkHelper::ResourceIdToString(xResourceId),
+ RTL_TEXTENCODING_UTF8).getStr());
+#endif
+ // Erase element from current configuration.
+ for (sal_Int32 nI=nIndex; nI<nCount-2; ++nI)
+ aResources[nI] = aResources[nI+1];
+ nCount -= 1;
+
+ rResourcesToDeactivate.push_back(xResourceId);
+ }
+ nIndex -= 1;
+ }
+}
+
+
+
+
+void ConfigurationUpdater::LockUpdates (void)
+{
+ ++mnLockCount;
+}
+
+
+
+
+void ConfigurationUpdater::UnlockUpdates (void)
+{
+ --mnLockCount;
+ if (mnLockCount == 0 && mbUpdatePending)
+ {
+ RequestUpdate(mxRequestedConfiguration);
+ }
+}
+
+
+
+
+::boost::shared_ptr<ConfigurationUpdaterLock> ConfigurationUpdater::GetLock (void)
+{
+ return ::boost::shared_ptr<ConfigurationUpdaterLock>(new ConfigurationUpdaterLock(*this));
+}
+
+
+
+
+void ConfigurationUpdater::SetUpdateBeingProcessed (bool bValue)
+{
+ mbUpdateBeingProcessed = bValue;
+}
+
+
+
+
+IMPL_LINK(ConfigurationUpdater, TimeoutHandler, Timer*, EMPTYARG)
+{
+ OSL_TRACE("configuration update timer");
+ if ( ! mbUpdateBeingProcessed
+ && mxCurrentConfiguration.is()
+ && mxRequestedConfiguration.is())
+ {
+ if ( ! AreConfigurationsEquivalent(mxCurrentConfiguration, mxRequestedConfiguration))
+ {
+ OSL_TRACE("configurations differ, requesting update");
+ RequestUpdate(mxRequestedConfiguration);
+ }
+ }
+ return 0;
+}
+
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ConfigurationUpdater.hxx b/sd/source/ui/framework/configuration/ConfigurationUpdater.hxx
new file mode 100755
index 000000000000..8e59c3ec8585
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ConfigurationUpdater.hxx
@@ -0,0 +1,215 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_CONFIGURATION_UPDATER_HXX
+#define SD_FRAMEWORK_CONFIGURATION_UPDATER_HXX
+
+#include "ConfigurationControllerResourceManager.hxx"
+#include <com/sun/star/drawing/framework/XResourceId.hpp>
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <vcl/timer.hxx>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace framework {
+
+class ConfigurationClassifier;
+class ConfigurationUpdaterLock;
+
+/** This is a helper class for the ConfigurationController. It handles the
+ update of the current configuration so that it looks like a requested
+ configuration. An update is made by activating or deactivating drawing
+ framework resources.
+
+ When an update is not successfull, i.e. after the update the current
+ configuration is not equivalent to the requested configuration, then a
+ timer is started to repeat the update after a short time.
+*/
+class ConfigurationUpdater
+{
+public:
+ /** Create a new ConfigurationUpdater object that notifies configuration
+ changes and the start and end of updates via the given broadcaster.
+ */
+ ConfigurationUpdater (
+ const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster,
+ const ::boost::shared_ptr<ConfigurationControllerResourceManager>& rpResourceManager,
+ const css::uno::Reference<
+ css::drawing::framework::XControllerManager>& rxControllerManager);
+ ~ConfigurationUpdater (void);
+
+ /** This method is typically called once, when the controller manager is
+ accessible to the caller.
+ */
+ void SetControllerManager(
+ const css::uno::Reference<
+ css::drawing::framework::XControllerManager>& rxControllerManager);
+
+ /** Request an update of the current configuration so that it looks like
+ the given requested configuration. It checks whether an update of
+ the current configuration can be done. Calls UpdateConfiguration()
+ if that is the case. Otherwise it schedules a later call to
+ UpdateConfiguration().
+ */
+ void RequestUpdate (const css::uno::Reference<
+ css::drawing::framework::XConfiguration>& rxRequestedConfiguration);
+
+ css::uno::Reference<
+ css::drawing::framework::XConfiguration> GetCurrentConfiguration (void) const;
+
+ friend class ConfigurationUpdaterLock;
+ /** Return a lock of the called ConfigurationUpdater. While the
+ returned object exists no update of the current configuration is
+ made.
+ */
+ ::boost::shared_ptr<ConfigurationUpdaterLock> GetLock (void);
+
+private:
+ /** A reference to the XControllerManager is kept so that
+ UpdateConfiguration() has access to the other sub controllers.
+ */
+ css::uno::Reference<
+ css::drawing::framework::XControllerManager> mxControllerManager;
+
+ ::boost::shared_ptr<ConfigurationControllerBroadcaster> mpBroadcaster;
+
+ /** The current configuration holds the resources that are currently
+ active. It is modified during an update.
+ */
+ css::uno::Reference<
+ css::drawing::framework::XConfiguration> mxCurrentConfiguration;
+
+ /** The requested configuration holds the resources that have been
+ requested to activate or to deactivate since the last update. It is
+ (usually) not modified during an update. This configuration is
+ maintained by the ConfigurationController and given to the
+ ConfigurationUpdater in the RequestUpdate() method.
+ */
+ css::uno::Reference<
+ css::drawing::framework::XConfiguration> mxRequestedConfiguration;
+
+ /** This flag is set to </sal_True> when an update of the current
+ configurtion was requested (because the last request in the queue
+ was processed) but could not be exected because the
+ ConfigurationController was locked. A call to UpdateConfiguration()
+ resets the flag to </sal_False>.
+ */
+ bool mbUpdatePending;
+
+ /** This flag is set to </sal_True> while the UpdateConfiguration() method
+ is running. It is used to prevent reentrance problems with this
+ method.
+ */
+ bool mbUpdateBeingProcessed;
+
+ /** The ConfigurationController is locked when this count has a value
+ larger then zero. If the controller is locked then updates of the
+ current configuration are not made.
+ */
+ sal_Int32 mnLockCount;
+
+ /** This timer is used to check from time to time whether the requested
+ configuration and the current configuration are identcal and request
+ an update when they are not.
+ This is used to overcome problems with resources that become
+ available asynchronously.
+ */
+ Timer maUpdateTimer;
+
+ /** The number of failed updates (those after which the current
+ configuration is not equivalent to the requested configuration) is
+ used to determine how long to wait before another update is made.
+ */
+ sal_Int32 mnFailedUpdateCount;
+
+ ::boost::shared_ptr<ConfigurationControllerResourceManager> mpResourceManager;
+
+ /** This method does the main work of an update. It calls the sub
+ controllers that are responsible for the various types of resources
+ and tells them to update their active resources. It notifies
+ listeners about the start and end of the configuration update.
+ */
+ void UpdateConfiguration (void);
+
+ /** Basically calls UpdaterStart() andUpdateEnd() and makes some debug
+ output.
+ */
+ void UpdateCore (const ConfigurationClassifier& rClassifier);
+
+ /** Check for all pure anchors if they have at least one child.
+ Childless pure anchors are deactivated.
+ This affects only the current configuration.
+ */
+ void CheckPureAnchors (
+ const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration,
+ ::std::vector<css::uno::Reference<css::drawing::framework::XResourceId> >&
+ rResourcesToDeactivate);
+
+ /** Remove from the requested configration all pure anchors that have no
+ child. Requested but not yet activated anchors can not be removed
+ because without the actual resource the 'pureness' of an anchor can
+ not be determined.
+ */
+ void CleanRequestedConfiguration (void);
+
+ /** Check the success of a recently executed configuration update.
+ When the update failed then start the timer.
+ */
+ void CheckUpdateSuccess (void);
+
+ /** This method sets the mbUpdateBeingProcessed member that is used to
+ prevent reentrance problems. This method allows function objects
+ easyly and safely to modify the variable.
+ */
+ void SetUpdateBeingProcessed (bool bValue);
+
+ /** Return whether it is possible to do an update of the configuration.
+ This takes into account whether another update is currently being
+ executed, the lock count, and whether the configuration controller
+ is still valid.
+ */
+ bool IsUpdatePossible (void);
+
+ /** Lock updates of the current configuration. For intermediate requests
+ for updates mbUpdatePending is set to <TRUE/>.
+ */
+ void LockUpdates (void);
+
+ /** When an update was requested since the last LockUpdates() call then
+ RequestUpdate() is called.
+ */
+ void UnlockUpdates (void);
+
+ DECL_LINK(TimeoutHandler, Timer*);
+};
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.cxx b/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.cxx
new file mode 100644
index 000000000000..18c80b8b1243
--- /dev/null
+++ b/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.cxx
@@ -0,0 +1,104 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "GenericConfigurationChangeRequest.hxx"
+
+#include "framework/FrameworkHelper.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::rtl::OUString;
+
+namespace sd { namespace framework {
+
+GenericConfigurationChangeRequest::GenericConfigurationChangeRequest (
+ const Reference<XResourceId>& rxResourceId,
+ const Mode eMode) throw(::com::sun::star::lang::IllegalArgumentException)
+ : GenericConfigurationChangeRequestInterfaceBase(MutexOwner::maMutex),
+ mxResourceId(rxResourceId),
+ meMode(eMode)
+{
+ if ( ! rxResourceId.is() || rxResourceId->getResourceURL().getLength()==0)
+ throw ::com::sun::star::lang::IllegalArgumentException();
+}
+
+
+
+
+GenericConfigurationChangeRequest::~GenericConfigurationChangeRequest (void) throw()
+{
+}
+
+
+
+
+void SAL_CALL GenericConfigurationChangeRequest::execute (
+ const Reference<XConfiguration>& rxConfiguration)
+ throw (RuntimeException)
+{
+ if (rxConfiguration.is())
+ {
+ switch (meMode)
+ {
+ case Activation:
+ rxConfiguration->addResource(mxResourceId);
+ break;
+
+ case Deactivation:
+ rxConfiguration->removeResource(mxResourceId);
+ break;
+ }
+ }
+}
+
+
+
+
+OUString SAL_CALL GenericConfigurationChangeRequest::getName (void)
+ throw (RuntimeException)
+{
+ return OUString::createFromAscii("GenericConfigurationChangeRequest ")
+ + OUString::createFromAscii(meMode==Activation ? "activate " : "deactivate ")
+ + FrameworkHelper::ResourceIdToString(mxResourceId);
+}
+
+
+
+
+void SAL_CALL GenericConfigurationChangeRequest::setName (const OUString& rsName)
+ throw (RuntimeException)
+{
+ (void)rsName;
+ // Ignored.
+}
+
+} } // end of namespace sd::framework
+
diff --git a/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.hxx b/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.hxx
new file mode 100644
index 000000000000..ce708e1fa71a
--- /dev/null
+++ b/sd/source/ui/framework/configuration/GenericConfigurationChangeRequest.hxx
@@ -0,0 +1,123 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_GENERIC_CONFIGURATTION_CHANGE_REQUEST_HXX
+#define SD_FRAMEWORK_GENERIC_CONFIGURATTION_CHANGE_REQUEST_HXX
+
+#include "MutexOwner.hxx"
+#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <com/sun/star/drawing/framework/XResourceId.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <cppuhelper/compbase2.hxx>
+
+namespace css = ::com::sun::star;
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper2 <
+ ::com::sun::star::drawing::framework::XConfigurationChangeRequest,
+ ::com::sun::star::container::XNamed
+ > GenericConfigurationChangeRequestInterfaceBase;
+
+} // end of anonymous namespace.
+
+
+namespace sd { namespace framework {
+
+/** This implementation of the XConfigurationChangeRequest interface
+ represents a single explicit request for a configuration change. On its
+ execution it may result in other, implicit, configuration changes. For
+ example this is the case when the deactivation of a unique resource is
+ requested: the resources linked to it have to be deactivated as well.
+*/
+class GenericConfigurationChangeRequest
+ : private MutexOwner,
+ public GenericConfigurationChangeRequestInterfaceBase
+{
+public:
+ /** This enum specified whether the activation or deactivation of a
+ resource is requested.
+ */
+ enum Mode { Activation, Deactivation };
+
+ /** Create a new object that represents the request for activation or
+ deactivation of the specified resource.
+ @param rxsResourceId
+ Id of the resource that is to be activated or deactivated.
+ @param eMode
+ The mode specifies whether to activate or to deactivate the
+ resource.
+ */
+ GenericConfigurationChangeRequest (
+ const ::com::sun::star::uno::Reference<com::sun::star::drawing::framework::XResourceId>&
+ rxResourceId,
+ const Mode eMode)
+ throw (::com::sun::star::lang::IllegalArgumentException);
+
+ virtual ~GenericConfigurationChangeRequest (void) throw();
+
+
+ // XConfigurationChangeOperation
+
+ /** The requested configuration change is executed on the given
+ configuration. Additionally to the explicitly requested change
+ other changes have to be made as well. See class description for an
+ example.
+ @param rxConfiguration
+ The configuration to which the requested change is made.
+ */
+ virtual void SAL_CALL execute (
+ const ::com::sun::star::uno::Reference<
+ com::sun::star::drawing::framework::XConfiguration>& rxConfiguration)
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ // XNamed
+
+ /** Return a human readable string representation. This is used for
+ debugging purposes.
+ */
+ virtual ::rtl::OUString SAL_CALL getName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** This call is ignored because the XNamed interface is (mis)used to
+ give access to a human readable name for debugging purposes.
+ */
+ virtual void SAL_CALL setName (const ::rtl::OUString& rName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ const css::uno::Reference<css::drawing::framework::XResourceId> mxResourceId;
+ const Mode meMode;
+};
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ResourceFactoryManager.cxx b/sd/source/ui/framework/configuration/ResourceFactoryManager.cxx
new file mode 100644
index 000000000000..1df3c77d78ba
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ResourceFactoryManager.cxx
@@ -0,0 +1,230 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "ResourceFactoryManager.hxx"
+#include <tools/wldcrd.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <boost/bind.hpp>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::rtl::OUString;
+
+namespace sd { namespace framework {
+
+ResourceFactoryManager::ResourceFactoryManager (const Reference<XControllerManager>& rxManager)
+ : maMutex(),
+ maFactoryMap(),
+ maFactoryPatternList(),
+ mxControllerManager(rxManager),
+ mxURLTransformer()
+{
+ // Create the URL transformer.
+ Reference<lang::XMultiServiceFactory> xServiceManager (
+ ::comphelper::getProcessServiceFactory());
+ mxURLTransformer = Reference<util::XURLTransformer>(
+ xServiceManager->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
+ UNO_QUERY);
+}
+
+
+
+
+ResourceFactoryManager::~ResourceFactoryManager (void)
+{
+ Reference<lang::XComponent> xComponent (mxURLTransformer, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+}
+
+
+
+
+void ResourceFactoryManager::AddFactory (
+ const OUString& rsURL,
+ const Reference<XResourceFactory>& rxFactory)
+ throw (RuntimeException)
+{
+ if ( ! rxFactory.is())
+ throw lang::IllegalArgumentException();
+ if (rsURL.getLength() == 0)
+ throw lang::IllegalArgumentException();
+
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (rsURL.indexOf('*') >= 0 || rsURL.indexOf('?') >= 0)
+ {
+ // The URL is a URL pattern not an single URL.
+ maFactoryPatternList.push_back(FactoryPatternList::value_type(rsURL, rxFactory));
+ }
+ else
+ {
+ maFactoryMap[rsURL] = rxFactory;
+ }
+}
+
+
+
+
+void ResourceFactoryManager::RemoveFactoryForURL (
+ const OUString& rsURL)
+ throw (RuntimeException)
+{
+ if (rsURL.getLength() == 0)
+ throw lang::IllegalArgumentException();
+
+ ::osl::MutexGuard aGuard (maMutex);
+
+ FactoryMap::iterator iFactory (maFactoryMap.find(rsURL));
+ if (iFactory != maFactoryMap.end())
+ {
+ maFactoryMap.erase(iFactory);
+ }
+ else
+ {
+ // The URL may be a pattern. Look that up.
+ FactoryPatternList::iterator iPattern;
+ for (iPattern=maFactoryPatternList.begin();
+ iPattern!=maFactoryPatternList.end();
+ ++iPattern)
+ {
+ if (iPattern->first == rsURL)
+ {
+ // Found the pattern. Remove it.
+ maFactoryPatternList.erase(iPattern);
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+
+void ResourceFactoryManager::RemoveFactoryForReference(
+ const Reference<XResourceFactory>& rxFactory)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Collect a list with all keys that map to the given factory.
+ ::std::vector<OUString> aKeys;
+ FactoryMap::const_iterator iFactory;
+ for (iFactory=maFactoryMap.begin(); iFactory!=maFactoryMap.end(); ++iFactory)
+ if (iFactory->second == rxFactory)
+ aKeys.push_back(iFactory->first);
+
+ // Remove the entries whose keys we just have collected.
+ ::std::vector<OUString>::const_iterator iKey;
+ for (iKey=aKeys.begin(); iKey!=aKeys.end(); ++iKey)
+ maFactoryMap.erase(maFactoryMap.find(*iKey));
+
+ // Remove the pattern entries whose factories are identical to the given
+ // factory.
+ FactoryPatternList::iterator iNewEnd (
+ std::remove_if(
+ maFactoryPatternList.begin(),
+ maFactoryPatternList.end(),
+ ::boost::bind(
+ std::equal_to<Reference<XResourceFactory> >(),
+ ::boost::bind(&FactoryPatternList::value_type::second, _1),
+ rxFactory)));
+ if (iNewEnd != maFactoryPatternList.end())
+ maFactoryPatternList.erase(iNewEnd, maFactoryPatternList.end());
+}
+
+
+
+
+Reference<XResourceFactory> ResourceFactoryManager::GetFactory (
+ const OUString& rsCompleteURL)
+ throw (RuntimeException)
+{
+ OUString sURLBase (rsCompleteURL);
+ if (mxURLTransformer.is())
+ {
+ util::URL aURL;
+ aURL.Complete = rsCompleteURL;
+ if (mxURLTransformer->parseStrict(aURL))
+ sURLBase = aURL.Main;
+ }
+
+ Reference<XResourceFactory> xFactory = FindFactory(sURLBase);
+
+ if ( ! xFactory.is() && mxControllerManager.is())
+ {
+ Reference<XModuleController> xModuleController(mxControllerManager->getModuleController());
+ if (xModuleController.is())
+ {
+ // Ask the module controller to provide a factory of the
+ // requested view type. Note that this can (and should) cause
+ // intermediate calls to AddFactory().
+ xModuleController->requestResource(sURLBase);
+
+ xFactory = FindFactory(sURLBase);
+ }
+ }
+
+ return xFactory;
+}
+
+
+
+
+Reference<XResourceFactory> ResourceFactoryManager::FindFactory (const OUString& rsURLBase)
+ throw (RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ FactoryMap::const_iterator iFactory (maFactoryMap.find(rsURLBase));
+ if (iFactory != maFactoryMap.end())
+ return iFactory->second;
+ else
+ {
+ // Check the URL patterns.
+ FactoryPatternList::const_iterator iPattern;
+ for (iPattern=maFactoryPatternList.begin();
+ iPattern!=maFactoryPatternList.end();
+ ++iPattern)
+ {
+ WildCard aWildCard (iPattern->first);
+ if (aWildCard.Matches(rsURLBase))
+ return iPattern->second;
+ }
+ }
+ return NULL;
+}
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/ResourceFactoryManager.hxx b/sd/source/ui/framework/configuration/ResourceFactoryManager.hxx
new file mode 100644
index 000000000000..dc7d2574dbfc
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ResourceFactoryManager.hxx
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_RESOURCE_FACTORY_MANAGER_HXX
+#define SD_FRAMEWORK_RESOURCE_FACTORY_MANAGER_HXX
+
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/drawing/framework/XModuleController.hpp>
+#include <com/sun/star/drawing/framework/XResourceFactoryManager.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <osl/mutex.hxx>
+#include <comphelper/stl_types.hxx>
+#include <hash_map>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace framework {
+
+/** Container of resource factories of the drawing framework.
+*/
+class ResourceFactoryManager
+{
+public:
+ ResourceFactoryManager (
+ const css::uno::Reference<css::drawing::framework::XControllerManager>& rxManager);
+
+ ~ResourceFactoryManager (void);
+
+ /** Register a resource factory for one type of resource.
+ @param rsURL
+ The type of the resource that will be created by the factory.
+ @param rxFactory
+ The factory that will create resource objects of the specfied type.
+ */
+ void AddFactory (
+ const ::rtl::OUString& rsURL,
+ const css::uno::Reference<css::drawing::framework::XResourceFactory>& rxFactory)
+ throw (css::uno::RuntimeException);
+
+ /** Unregister the specifed factory.
+ @param rsURL
+ Unregister only the factory for this URL. When the same factory
+ is registered for other URLs then these remain registered.
+ */
+ void RemoveFactoryForURL(
+ const ::rtl::OUString& rsURL)
+ throw (css::uno::RuntimeException);
+
+ /** Unregister the specified factory.
+ @param rxFactory
+ Unregister the this factory for all URLs that it has been
+ registered for.
+ */
+ void RemoveFactoryForReference(
+ const css::uno::Reference<css::drawing::framework::XResourceFactory>& rxFactory)
+ throw (css::uno::RuntimeException);
+
+ /** Return a factory that can create resources specified by the given URL.
+ @param rsCompleteURL
+ This URL specifies the type of the resource. It may contain arguments.
+ @return
+ When a factory for the specified URL has been registered by a
+ previous call to AddFactory() then a reference to that factory
+ is returned. Otherwise an empty reference is returned.
+ */
+ css::uno::Reference<css::drawing::framework::XResourceFactory> GetFactory (
+ const ::rtl::OUString& rsURL)
+ throw (css::uno::RuntimeException);
+
+private:
+ ::osl::Mutex maMutex;
+ typedef ::std::hash_map<
+ ::rtl::OUString,
+ css::uno::Reference<css::drawing::framework::XResourceFactory>,
+ ::comphelper::UStringHash,
+ ::comphelper::UStringEqual> FactoryMap;
+ FactoryMap maFactoryMap;
+
+ typedef ::std::vector<
+ ::std::pair<
+ rtl::OUString,
+ css::uno::Reference<css::drawing::framework::XResourceFactory> > >
+ FactoryPatternList;
+ FactoryPatternList maFactoryPatternList;
+
+ css::uno::Reference<css::drawing::framework::XControllerManager> mxControllerManager;
+ css::uno::Reference<css::util::XURLTransformer> mxURLTransformer;
+
+ /** Look up the factory for the given URL.
+ @param rsURLBase
+ The css::tools::URL.Main part of a URL. Arguments have to be
+ stripped off by the caller.
+ @return
+ When the factory has not yet been added then return NULL.
+ */
+ css::uno::Reference<css::drawing::framework::XResourceFactory> FindFactory (
+ const ::rtl::OUString& rsURLBase)
+ throw (css::uno::RuntimeException);
+};
+
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/ResourceId.cxx b/sd/source/ui/framework/configuration/ResourceId.cxx
new file mode 100755
index 000000000000..15d7c3a6f4ec
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ResourceId.cxx
@@ -0,0 +1,626 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "framework/ResourceId.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "tools/SdGlobalResourceContainer.hxx"
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/processfactory.hxx>
+#include <rtl/ref.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing::framework;
+using ::rtl::OUString;
+
+/** When the USE_OPTIMIZATIONS symbol is defined then at some optimizations
+ are activated that work only together with XResourceId objects that are
+ implemented by the ResourceId class. For other implementations of when
+ the USE_OPTIMIZATIONS symbol is not defined then alternative code is
+ used instead.
+*/
+#define USE_OPTIMIZATIONS
+
+namespace sd { namespace framework {
+
+Reference<XInterface> SAL_CALL ResourceId_createInstance (
+ const Reference<XComponentContext>& rxContext)
+{
+ (void)rxContext;
+ return Reference<XInterface>(static_cast<XWeak*>(new ::sd::framework::ResourceId()));
+}
+
+
+
+
+::rtl::OUString ResourceId_getImplementationName (void) throw(RuntimeException)
+{
+ return ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.ResourceId"));
+}
+
+
+
+
+Sequence<rtl::OUString> SAL_CALL ResourceId_getSupportedServiceNames (void)
+ throw (RuntimeException)
+{
+ static const ::rtl::OUString sServiceName(
+ ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.ResourceId"));
+ return Sequence<rtl::OUString>(&sServiceName, 1);
+}
+
+
+
+
+//===== ResourceId ============================================================
+
+WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
+
+ResourceId::ResourceId (void)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(0),
+ mpURL()
+{
+}
+
+
+
+
+ResourceId::ResourceId (
+ const std::vector<OUString>& rResourceURLs)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(rResourceURLs),
+ mpURL()
+{
+ ParseResourceURL();
+}
+
+
+
+
+ResourceId::ResourceId (
+ const OUString& rsResourceURL)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(1, rsResourceURL),
+ mpURL()
+{
+ // Handle the special case of an empty resource URL.
+ if (rsResourceURL.getLength() == 0)
+ maResourceURLs.clear();
+ ParseResourceURL();
+}
+
+
+
+
+ResourceId::ResourceId (
+ const OUString& rsResourceURL,
+ const OUString& rsAnchorURL)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(2),
+ mpURL()
+{
+ maResourceURLs[0] = rsResourceURL;
+ maResourceURLs[1] = rsAnchorURL;
+ ParseResourceURL();
+}
+
+
+
+
+ResourceId::ResourceId (
+ const OUString& rsResourceURL,
+ const ::std::vector<OUString>& rAnchorURLs)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(1+rAnchorURLs.size()),
+ mpURL()
+{
+ maResourceURLs[0] = rsResourceURL;
+ for (sal_uInt32 nIndex=0; nIndex<rAnchorURLs.size(); ++nIndex)
+ maResourceURLs[nIndex+1] = rAnchorURLs[nIndex];
+ ParseResourceURL();
+}
+
+
+
+
+ResourceId::ResourceId (
+ const OUString& rsResourceURL,
+ const OUString& rsFirstAnchorURL,
+ const Sequence<OUString>& rAnchorURLs)
+ : ResourceIdInterfaceBase(),
+ maResourceURLs(2+rAnchorURLs.getLength()),
+ mpURL()
+{
+ maResourceURLs[0] = rsResourceURL;
+ maResourceURLs[1] = rsFirstAnchorURL;
+ for (sal_Int32 nIndex=0; nIndex<rAnchorURLs.getLength(); ++nIndex)
+ maResourceURLs[nIndex+2] = rAnchorURLs[nIndex];
+ ParseResourceURL();
+}
+
+
+
+
+ResourceId::~ResourceId (void)
+{
+ mpURL.reset();
+}
+
+
+
+
+OUString SAL_CALL
+ ResourceId::getResourceURL (void)
+ throw(com::sun::star::uno::RuntimeException)
+{
+ if (maResourceURLs.size() > 0)
+ return maResourceURLs[0];
+ else
+ return OUString();
+}
+
+
+
+
+util::URL SAL_CALL
+ ResourceId::getFullResourceURL (void)
+ throw(com::sun::star::uno::RuntimeException)
+{
+ if (mpURL.get() != NULL)
+ return *mpURL;
+
+ Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
+ if (xURLTransformer.is() && maResourceURLs.size() > 0)
+ {
+ mpURL.reset(new util::URL);
+ mpURL->Complete = maResourceURLs[0];
+ xURLTransformer->parseStrict(*mpURL);
+ return *mpURL;
+ }
+
+ util::URL aURL;
+ if (maResourceURLs.size() > 0)
+ aURL.Complete = maResourceURLs[0];
+ return aURL;
+}
+
+
+
+
+sal_Bool SAL_CALL
+ ResourceId::hasAnchor (void)
+ throw (RuntimeException)
+{
+ return maResourceURLs.size()>1;
+}
+
+
+
+
+Reference<XResourceId> SAL_CALL
+ ResourceId::getAnchor (void)
+ throw (RuntimeException)
+{
+ ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
+ const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
+ if (nAnchorCount > 0)
+ {
+ rResourceId->maResourceURLs.resize(nAnchorCount);
+ for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
+ rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
+ }
+ return Reference<XResourceId>(rResourceId.get());
+}
+
+
+
+
+Sequence<OUString> SAL_CALL
+ ResourceId::getAnchorURLs (void)
+ throw (RuntimeException)
+{
+ const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
+ if (nAnchorCount > 0)
+ {
+ Sequence<OUString> aAnchorURLs (nAnchorCount);
+ for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
+ aAnchorURLs[nIndex] = maResourceURLs[nIndex+1];
+ return aAnchorURLs;
+ }
+ else
+ return Sequence<OUString>();
+}
+
+
+
+
+OUString SAL_CALL
+ ResourceId::getResourceTypePrefix (void)
+ throw (RuntimeException)
+{
+ if (maResourceURLs.size() > 0)
+ {
+ // Return the "private:resource/<type>/" prefix.
+
+ // Get the the prefix that ends with the second "/".
+ const OUString& rsResourceURL (maResourceURLs[0]);
+ sal_Int32 nPrefixEnd (rsResourceURL.indexOf(sal_Unicode('/'), 0));
+ if (nPrefixEnd >= 0)
+ nPrefixEnd = rsResourceURL.indexOf(sal_Unicode('/'), nPrefixEnd+1) + 1;
+ else
+ nPrefixEnd = 0;
+
+ return rsResourceURL.copy(0,nPrefixEnd);
+ }
+ else
+ return OUString();
+}
+
+
+
+
+sal_Int16 SAL_CALL
+ ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
+ throw (RuntimeException)
+{
+ sal_Int16 nResult (0);
+
+ if ( ! rxResourceId.is())
+ {
+ // The empty reference is interpreted as empty resource id object.
+ if (maResourceURLs.size() > 0)
+ nResult = +1;
+ else
+ nResult = 0;
+ }
+ else
+ {
+ ResourceId* pId = NULL;
+#ifdef USE_OPTIMIZATIONS
+ pId = dynamic_cast<ResourceId*>(rxResourceId.get());
+#endif
+ if (pId != NULL)
+ {
+ // We have direct access to the implementation of the given
+ // resource id object.
+ nResult = CompareToLocalImplementation(*pId);
+ }
+ else
+ {
+ // We have to do the comparison via the UNO interface of the
+ // given resource id object.
+ nResult = CompareToExternalImplementation(rxResourceId);
+ }
+ }
+
+ return nResult;
+}
+
+
+
+
+sal_Int16 ResourceId::CompareToLocalImplementation (const ResourceId& rId) const
+{
+ sal_Int16 nResult (0);
+
+ const sal_uInt32 nLocalURLCount (maResourceURLs.size());
+ const sal_uInt32 nURLCount(rId.maResourceURLs.size());
+
+ // Start comparison with the top most anchors.
+ for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
+ nIndex>=0 && nLocalIndex>=0;
+ --nIndex,--nLocalIndex)
+ {
+ const OUString sLocalURL (maResourceURLs[nLocalIndex]);
+ const OUString sURL (rId.maResourceURLs[nIndex]);
+ const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
+ if (nLocalResult != 0)
+ {
+ if (nLocalResult < 0)
+ nResult = -1;
+ else
+ nResult = +1;
+ break;
+ }
+ }
+
+ if (nResult == 0)
+ {
+ // No difference found yet. When the lengths are the same then the
+ // two resource ids are equivalent. Otherwise the shorter comes
+ // first.
+ if (nLocalURLCount != nURLCount)
+ {
+ if (nLocalURLCount < nURLCount)
+ nResult = -1;
+ else
+ nResult = +1;
+ }
+ }
+
+ return nResult;
+}
+
+
+
+
+sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
+{
+ sal_Int16 nResult (0);
+
+ const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
+ const sal_uInt32 nLocalURLCount (maResourceURLs.size());
+ const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
+
+ // Start comparison with the top most anchors.
+ sal_Int32 nLocalResult (0);
+ for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
+ nIndex>=0&&nLocalIndex>=0;
+ --nIndex,--nLocalIndex)
+ {
+ if (nIndex == 0 )
+ nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
+ else
+ nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
+ if (nLocalResult != 0)
+ {
+ if (nLocalResult < 0)
+ nResult = -1;
+ else
+ nResult = +1;
+ break;
+ }
+ }
+
+ if (nResult == 0)
+ {
+ // No difference found yet. When the lengths are the same then the
+ // two resource ids are equivalent. Otherwise the shorter comes
+ // first.
+ if (nLocalURLCount != nURLCount)
+ {
+ if (nLocalURLCount < nURLCount)
+ nResult = -1;
+ else
+ nResult = +1;
+ }
+ }
+
+ return nResult;
+}
+
+
+
+
+sal_Bool SAL_CALL
+ ResourceId::isBoundTo (
+ const Reference<XResourceId>& rxResourceId,
+ AnchorBindingMode eMode)
+ throw (RuntimeException)
+{
+ if ( ! rxResourceId.is())
+ {
+ // An empty reference is interpreted as empty resource id.
+ return IsBoundToAnchor(NULL, NULL, eMode);
+ }
+
+ ResourceId* pId = NULL;
+#ifdef USE_OPTIMIZATIONS
+ pId = dynamic_cast<ResourceId*>(rxResourceId.get());
+#endif
+ if (pId != NULL)
+ {
+ return IsBoundToAnchor(pId->maResourceURLs, eMode);
+ }
+ else
+ {
+ const OUString sResourceURL (rxResourceId->getResourceURL());
+ const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
+ return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
+ }
+}
+
+
+
+
+sal_Bool SAL_CALL
+ ResourceId::isBoundToURL (
+ const OUString& rsAnchorURL,
+ AnchorBindingMode eMode)
+ throw (RuntimeException)
+{
+ return IsBoundToAnchor(&rsAnchorURL, NULL, eMode);
+}
+
+
+
+
+Reference<XResourceId> SAL_CALL
+ ResourceId::clone (void)
+ throw(RuntimeException)
+{
+ return new ResourceId(maResourceURLs);
+}
+
+
+
+
+//----- XInitialization -------------------------------------------------------
+
+void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
+ throw (RuntimeException)
+{
+ sal_uInt32 nCount (aArguments.getLength());
+ for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
+ {
+ OUString sResourceURL;
+ if (aArguments[nIndex] >>= sResourceURL)
+ maResourceURLs.push_back(sResourceURL);
+ else
+ {
+ Reference<XResourceId> xAnchor;
+ if (aArguments[nIndex] >>= xAnchor)
+ {
+ if (xAnchor.is())
+ {
+ maResourceURLs.push_back(xAnchor->getResourceURL());
+ Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
+ for (sal_Int32 nURLIndex=0; nURLIndex<aAnchorURLs.getLength(); ++nURLIndex)
+ {
+ maResourceURLs.push_back(aAnchorURLs[nURLIndex]);
+ }
+ }
+ }
+ }
+ }
+ ParseResourceURL();
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+
+/** When eMode is DIRECTLY then the anchor of the called object and the
+ anchor represented by the given sequence of anchor URLs have to be
+ identical. When eMode is RECURSIVE then the anchor of the called
+ object has to start with the given anchor URLs.
+*/
+bool ResourceId::IsBoundToAnchor (
+ const OUString* psFirstAnchorURL,
+ const Sequence<OUString>* paAnchorURLs,
+ AnchorBindingMode eMode) const
+{
+ const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
+ const bool bHasFirstAnchorURL (psFirstAnchorURL!=NULL);
+ const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
+ + (paAnchorURLs!=NULL ? paAnchorURLs->getLength() : 0));
+
+ // Check the lengths.
+ if (nLocalAnchorURLCount<nAnchorURLCount ||
+ (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
+ {
+ return false;
+ }
+
+ // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
+ // id and the given anchor.
+ sal_uInt32 nOffset = 0;
+ if (paAnchorURLs != NULL)
+ {
+ sal_uInt32 nCount = paAnchorURLs->getLength();
+ while (nOffset < nCount)
+ {
+ if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
+ (*paAnchorURLs)[nCount - 1 - nOffset]))
+ {
+ return false;
+ }
+ ++nOffset;
+ }
+ }
+ if (bHasFirstAnchorURL)
+ {
+ if ( ! psFirstAnchorURL->equals(maResourceURLs[nLocalAnchorURLCount - nOffset]))
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+bool ResourceId::IsBoundToAnchor (
+ const ::std::vector<OUString>& rAnchorURLs,
+ AnchorBindingMode eMode) const
+{
+ const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
+ const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
+
+ // Check the lengths.
+ if (nLocalAnchorURLCount<nAnchorURLCount ||
+ (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
+ {
+ return false;
+ }
+
+ // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
+ // id and the given anchor.
+ for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
+ {
+ if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
+ rAnchorURLs[nAnchorURLCount - 1 - nOffset]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+void ResourceId::ParseResourceURL (void)
+{
+ ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
+ Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
+ if ( ! xURLTransformer.is())
+ {
+ // Create the URL transformer.
+ Reference<lang::XMultiServiceFactory> xServiceManager (
+ ::comphelper::getProcessServiceFactory());
+ xURLTransformer = Reference<util::XURLTransformer>(
+ xServiceManager->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
+ UNO_QUERY);
+ mxURLTransformerWeak = xURLTransformer;
+ SdGlobalResourceContainer::Instance().AddResource(
+ Reference<XInterface>(xURLTransformer,UNO_QUERY));
+ }
+
+ if (xURLTransformer.is() && maResourceURLs.size() > 0)
+ {
+ mpURL.reset(new util::URL);
+ mpURL->Complete = maResourceURLs[0];
+ xURLTransformer->parseStrict(*mpURL);
+ if (mpURL->Main == maResourceURLs[0])
+ mpURL.reset();
+ else
+ maResourceURLs[0] = mpURL->Main;
+ }
+}
+
+
+} } // end of namespace sd::framework
diff --git a/sd/source/ui/framework/configuration/UpdateRequest.cxx b/sd/source/ui/framework/configuration/UpdateRequest.cxx
new file mode 100644
index 000000000000..1c39006b29c7
--- /dev/null
+++ b/sd/source/ui/framework/configuration/UpdateRequest.cxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "UpdateRequest.hxx"
+
+#include "framework/FrameworkHelper.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::rtl::OUString;
+
+namespace sd { namespace framework {
+
+UpdateRequest::UpdateRequest (void)
+ throw()
+ : UpdateRequestInterfaceBase(MutexOwner::maMutex)
+{
+}
+
+
+
+
+UpdateRequest::~UpdateRequest (void) throw()
+{
+}
+
+
+
+
+void SAL_CALL UpdateRequest::execute (const Reference<XConfiguration>& rxConfiguration)
+ throw (RuntimeException)
+{
+ (void)rxConfiguration;
+ // Do nothing here. The configuration is updated when the request queue
+ // becomes empty.
+}
+
+
+
+
+OUString SAL_CALL UpdateRequest::getName (void)
+ throw (RuntimeException)
+{
+ return OUString::createFromAscii("UpdateRequest");
+}
+
+
+
+
+void SAL_CALL UpdateRequest::setName (const OUString& rsName)
+ throw (RuntimeException)
+{
+ (void)rsName;
+ // Ignored.
+}
+
+} } // end of namespace sd::framework
+
diff --git a/sd/source/ui/framework/configuration/UpdateRequest.hxx b/sd/source/ui/framework/configuration/UpdateRequest.hxx
new file mode 100644
index 000000000000..e3fc159d4b11
--- /dev/null
+++ b/sd/source/ui/framework/configuration/UpdateRequest.hxx
@@ -0,0 +1,93 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_FRAMEWORK_UPDATE_REQUEST_HXX
+#define SD_FRAMEWORK_UPDATE_REQUEST_HXX
+
+#include "MutexOwner.hxx"
+#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <cppuhelper/compbase2.hxx>
+
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper2 <
+ ::com::sun::star::drawing::framework::XConfigurationChangeRequest,
+ ::com::sun::star::container::XNamed
+ > UpdateRequestInterfaceBase;
+
+} // end of anonymous namespace.
+
+
+
+namespace sd { namespace framework {
+
+/** This update request is used to request configuration updates
+ asynchronous when no other requests are being processed. When there are
+ other requests then we can simply wait until the last one is executed:
+ the configuration is updated when the request queue becomes empty. This
+ is use by this implementation as well. The execute() method does not
+ really do anything. This request just triggers the update of the
+ configuration when it is removed as last request from the queue.
+*/
+class UpdateRequest
+ : private MutexOwner,
+ public UpdateRequestInterfaceBase
+{
+public:
+ UpdateRequest (void) throw();
+ virtual ~UpdateRequest (void) throw();
+
+
+ // XConfigurationChangeOperation
+
+ virtual void SAL_CALL execute (
+ const ::com::sun::star::uno::Reference<
+ com::sun::star::drawing::framework::XConfiguration>& rxConfiguration)
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ // XNamed
+
+ /** Return a human readable string representation. This is used for
+ debugging purposes.
+ */
+ virtual ::rtl::OUString SAL_CALL getName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** This call is ignored because the XNamed interface is (mis)used to
+ give access to a human readable name for debugging purposes.
+ */
+ virtual void SAL_CALL setName (const ::rtl::OUString& rName)
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+} } // end of namespace sd::framework
+
+#endif
diff --git a/sd/source/ui/framework/configuration/makefile.mk b/sd/source/ui/framework/configuration/makefile.mk
new file mode 100644
index 000000000000..cdc41491b307
--- /dev/null
+++ b/sd/source/ui/framework/configuration/makefile.mk
@@ -0,0 +1,63 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=framework_configuration
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/ChangeRequestQueue.obj \
+ $(SLO)$/ChangeRequestQueueProcessor.obj \
+ $(SLO)$/Configuration.obj \
+ $(SLO)$/ConfigurationClassifier.obj \
+ $(SLO)$/ConfigurationController.obj \
+ $(SLO)$/ConfigurationControllerBroadcaster.obj \
+ $(SLO)$/ConfigurationControllerResourceManager.obj \
+ $(SLO)$/ConfigurationTracer.obj \
+ $(SLO)$/ConfigurationUpdater.obj \
+ $(SLO)$/GenericConfigurationChangeRequest.obj \
+ $(SLO)$/ResourceId.obj \
+ $(SLO)$/ResourceFactoryManager.obj \
+ $(SLO)$/UpdateRequest.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+