diff options
Diffstat (limited to 'sd/source/ui/framework/configuration/ResourceId.cxx')
-rwxr-xr-x | sd/source/ui/framework/configuration/ResourceId.cxx | 626 |
1 files changed, 626 insertions, 0 deletions
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 |