diff options
Diffstat (limited to 'sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx')
-rw-r--r-- | sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx b/sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx new file mode 100644 index 000000000000..9c71f68f4b10 --- /dev/null +++ b/sd/source/ui/sidebar/RecentlyUsedMasterPages.cxx @@ -0,0 +1,494 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#include "precompiled_sd.hxx" + +#include "RecentlyUsedMasterPages.hxx" +#include "MasterPageObserver.hxx" +#include "MasterPagesSelector.hxx" +#include "MasterPageDescriptor.hxx" +#include "tools/ConfigurationAccess.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" + +#include <algorithm> +#include <vector> + +#include <comphelper/processfactory.hxx> +#include "unomodel.hxx" +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <tools/urlobj.hxx> +#include <unotools/confignode.hxx> +#include <osl/doublecheckedlocking.h> +#include <osl/getglobalmutex.hxx> + +using namespace ::std; +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +namespace { + +static const OUString& GetPathToImpressConfigurationRoot (void) +{ + static const OUString sPathToImpressConfigurationRoot ( + RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/")); + return sPathToImpressConfigurationRoot; +} +static const OUString& GetPathToSetNode (void) +{ + static const OUString sPathToSetNode( + RTL_CONSTASCII_USTRINGPARAM( + "MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages")); + return sPathToSetNode; +} + + +class Descriptor +{ +public: + ::rtl::OUString msURL; + ::rtl::OUString msName; + ::sd::sidebar::MasterPageContainer::Token maToken; + Descriptor (const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName) + : msURL(rsURL), + msName(rsName), + maToken(::sd::sidebar::MasterPageContainer::NIL_TOKEN) + {} + Descriptor (::sd::sidebar::MasterPageContainer::Token aToken, + const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName) + : msURL(rsURL), + msName(rsName), + maToken(aToken) + {} + class TokenComparator + { public: + TokenComparator(::sd::sidebar::MasterPageContainer::Token aToken) + : maToken(aToken) {} + bool operator () (const Descriptor& rDescriptor) + { return maToken==rDescriptor.maToken; } + private: ::sd::sidebar::MasterPageContainer::Token maToken; + }; +}; + +} // end of anonymous namespace + + + + +namespace sd { namespace sidebar { + +class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor> +{ +public: + MasterPageList (void) {} +}; + + +RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL; + + +RecentlyUsedMasterPages& RecentlyUsedMasterPages::Instance (void) +{ + if (mpInstance == NULL) + { + ::osl::GetGlobalMutex aMutexFunctor; + ::osl::MutexGuard aGuard (aMutexFunctor()); + if (mpInstance == NULL) + { + RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages(); + pInstance->LateInit(); + SdGlobalResourceContainer::Instance().AddResource ( + ::std::auto_ptr<SdGlobalResource>(pInstance)); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + mpInstance = pInstance; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + + return *mpInstance; +} + + + + +RecentlyUsedMasterPages::RecentlyUsedMasterPages (void) + : maListeners(), + mpMasterPages(new MasterPageList()), + mnMaxListSize(8), + mpContainer(new MasterPageContainer()) +{ +} + + + + +RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void) +{ + Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); + mpContainer->RemoveChangeListener(aLink); + + MasterPageObserver::Instance().RemoveEventListener( + LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); +} + + + + +void RecentlyUsedMasterPages::LateInit (void) +{ + Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); + mpContainer->AddChangeListener(aLink); + + LoadPersistentValues (); + MasterPageObserver::Instance().AddEventListener( + LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); +} + + + + +void RecentlyUsedMasterPages::LoadPersistentValues (void) +{ + try + { + do + { + tools::ConfigurationAccess aConfiguration ( + GetPathToImpressConfigurationRoot(), + tools::ConfigurationAccess::READ_ONLY); + Reference<container::XNameAccess> xSet ( + aConfiguration.GetConfigurationNode(GetPathToSetNode()), + UNO_QUERY); + if ( ! xSet.is()) + break; + + const String sURLMemberName (OUString::createFromAscii("URL")); + const String sNameMemberName (OUString::createFromAscii("Name")); + OUString sURL; + OUString sName; + + // Read the names and URLs of the master pages. + Sequence<OUString> aKeys (xSet->getElementNames()); + mpMasterPages->clear(); + mpMasterPages->reserve(aKeys.getLength()); + for (int i=0; i<aKeys.getLength(); i++) + { + Reference<container::XNameAccess> xSetItem ( + xSet->getByName(aKeys[i]), UNO_QUERY); + if (xSetItem.is()) + { + Any aURL (xSetItem->getByName(sURLMemberName)); + Any aName (xSetItem->getByName(sNameMemberName)); + aURL >>= sURL; + aName >>= sName; + SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( + MasterPageContainer::TEMPLATE, + -1, + sURL, + String(), + sName, + false, + ::boost::shared_ptr<PageObjectProvider>( + new TemplatePageObjectProvider(sURL)), + ::boost::shared_ptr<PreviewProvider>( + new TemplatePreviewProvider(sURL)))); + // For user supplied templates we use a different + // preview provider: The preview in the document shows + // not only shapes on the master page but also shapes on + // the foreground. This is misleading and therefore + // these previews are discarded and created directly + // from the page objects. + if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER) + pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>( + new PagePreviewProvider()); + MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor)); + mpMasterPages->push_back(Descriptor(aToken,sURL,sName)); + } + } + + ResolveList(); + } + while (false); + } + catch (Exception&) + { + // Ignore exception. + } +} + + + + +void RecentlyUsedMasterPages::SavePersistentValues (void) +{ + try + { + do + { + tools::ConfigurationAccess aConfiguration ( + GetPathToImpressConfigurationRoot(), + tools::ConfigurationAccess::READ_WRITE); + Reference<container::XNameContainer> xSet ( + aConfiguration.GetConfigurationNode(GetPathToSetNode()), + UNO_QUERY); + if ( ! xSet.is()) + break; + + // Clear the set. + Sequence<OUString> aKeys (xSet->getElementNames()); + sal_Int32 i; + for (i=0; i<aKeys.getLength(); i++) + xSet->removeByName (aKeys[i]); + + // Fill it with the URLs of this object. + const String sURLMemberName (OUString::createFromAscii("URL")); + const String sNameMemberName (OUString::createFromAscii("Name")); + Any aValue; + Reference<lang::XSingleServiceFactory> xChildFactory ( + xSet, UNO_QUERY); + if ( ! xChildFactory.is()) + break; + MasterPageList::const_iterator iDescriptor; + sal_Int32 nIndex(0); + for (iDescriptor=mpMasterPages->begin(); + iDescriptor!=mpMasterPages->end(); + ++iDescriptor,++nIndex) + { + // Create new child. + OUString sKey (OUString::createFromAscii("index_")); + sKey += OUString::valueOf(nIndex); + Reference<container::XNameReplace> xChild( + xChildFactory->createInstance(), UNO_QUERY); + if (xChild.is()) + { + xSet->insertByName (sKey, makeAny(xChild)); + + aValue <<= OUString(iDescriptor->msURL); + xChild->replaceByName (sURLMemberName, aValue); + + aValue <<= OUString(iDescriptor->msName); + xChild->replaceByName (sNameMemberName, aValue); + } + } + + // Write the data back to disk. + aConfiguration.CommitChanges(); + } + while (false); + } + catch (Exception&) + { + // Ignore exception. + } +} + + + + +void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener) +{ + if (::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener) == maListeners.end()) + { + maListeners.push_back (rEventListener); + } +} + + + + +void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener) +{ + maListeners.erase ( + ::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener)); +} + + + + +int RecentlyUsedMasterPages::GetMasterPageCount (void) const +{ + return mpMasterPages->size(); +} + + + + +MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const +{ + if(nIndex<mpMasterPages->size()) + return (*mpMasterPages)[nIndex].maToken; + else + return MasterPageContainer::NIL_TOKEN; +} + + + + +void RecentlyUsedMasterPages::SendEvent (void) +{ + ::std::vector<Link>::iterator aLink (maListeners.begin()); + ::std::vector<Link>::iterator aEnd (maListeners.end()); + while (aLink!=aEnd) + { + aLink->Call (NULL); + ++aLink; + } +} + + + + +IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener, + MasterPageObserverEvent*, pEvent) +{ + switch (pEvent->meType) + { + case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED: + case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS: + AddMasterPage( + mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName)); + break; + + case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED: + // Do not change the list of recently master pages (the deleted + // page was recently used) but tell the listeners. They may want + // to update their lists. + SendEvent(); + break; + } + return 0; +} + + + + +IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener, + MasterPageContainerChangeEvent*, pEvent) +{ + if (pEvent != NULL) + switch (pEvent->meEventType) + { + case MasterPageContainerChangeEvent::CHILD_ADDED: + case MasterPageContainerChangeEvent::CHILD_REMOVED: + case MasterPageContainerChangeEvent::INDEX_CHANGED: + case MasterPageContainerChangeEvent::INDEXES_CHANGED: + ResolveList(); + break; + + default: + // Ignored. + break; + } + return 0; +} + + + + +void RecentlyUsedMasterPages::AddMasterPage ( + MasterPageContainer::Token aToken, + bool bMakePersistent) +{ + // For the page to be inserted the token has to be valid and the page + // has to have a valid URL. This excludes master pages that do not come + // from template files. + if (aToken != MasterPageContainer::NIL_TOKEN + && mpContainer->GetURLForToken(aToken).Len()>0) + { + + MasterPageList::iterator aIterator ( + ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(), + Descriptor::TokenComparator(aToken))); + if (aIterator != mpMasterPages->end()) + { + // When an entry for the given token already exists then remove + // it now and insert it later at the head of the list. + mpMasterPages->erase (aIterator); + } + + mpMasterPages->insert(mpMasterPages->begin(), + Descriptor( + aToken, + mpContainer->GetURLForToken(aToken), + mpContainer->GetStyleNameForToken(aToken))); + + // Shorten list to maximal size. + while (mpMasterPages->size() > mnMaxListSize) + { + mpMasterPages->pop_back (); + } + + if (bMakePersistent) + SavePersistentValues (); + SendEvent(); + } +} + + + + +void RecentlyUsedMasterPages::ResolveList (void) +{ + bool bNotify (false); + + MasterPageList::iterator iDescriptor; + for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor) + { + if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN) + { + MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL)); + iDescriptor->maToken = aToken; + if (aToken != MasterPageContainer::NIL_TOKEN) + bNotify = true; + } + else + { + if ( ! mpContainer->HasToken(iDescriptor->maToken)) + { + iDescriptor->maToken = MasterPageContainer::NIL_TOKEN; + bNotify = true; + } + } + } + + if (bNotify) + SendEvent(); +} + + +} } // end of namespace sd::sidebar |