summaryrefslogtreecommitdiff
path: root/sd/source/ui/framework/configuration/ResourceId.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/framework/configuration/ResourceId.cxx')
-rw-r--r--sd/source/ui/framework/configuration/ResourceId.cxx629
1 files changed, 629 insertions, 0 deletions
diff --git a/sd/source/ui/framework/configuration/ResourceId.cxx b/sd/source/ui/framework/configuration/ResourceId.cxx
new file mode 100644
index 000000000000..ce56cf0f0704
--- /dev/null
+++ b/sd/source/ui/framework/configuration/ResourceId.cxx
@@ -0,0 +1,629 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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(RTL_CONSTASCII_USTRINGPARAM("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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */