/************************************************************** * * 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 #include #include #include "unomodel.hxx" #include #include #include #include #include #include #include #include #include #include #include #include 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 { 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(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 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 aKeys (xSet->getElementNames()); mpMasterPages->clear(); mpMasterPages->reserve(aKeys.getLength()); for (int i=0; i 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( new TemplatePageObjectProvider(sURL)), ::boost::shared_ptr( 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( 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 xSet ( aConfiguration.GetConfigurationNode(GetPathToSetNode()), UNO_QUERY); if ( ! xSet.is()) break; // Clear the set. Sequence aKeys (xSet->getElementNames()); sal_Int32 i; for (i=0; iremoveByName (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 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 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(nIndexsize()) return (*mpMasterPages)[nIndex].maToken; else return MasterPageContainer::NIL_TOKEN; } void RecentlyUsedMasterPages::SendEvent (void) { ::std::vector::iterator aLink (maListeners.begin()); ::std::vector::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