/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: MasterPageContainer.cxx,v $ * $Revision: 1.20 $ * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sd.hxx" #include "MasterPageContainer.hxx" #include "MasterPageDescriptor.hxx" #include "MasterPageContainerFiller.hxx" #include "MasterPageContainerQueue.hxx" #include "TemplateScanner.hxx" #include "tools/AsynchronousTask.hxx" #include "strings.hrc" #include #include #include #include "unomodel.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DrawDocShell.hxx" #include "drawdoc.hxx" #include "sdpage.hxx" #include #include #include "sdresid.hxx" #include "tools/TimerBasedTaskExecution.hxx" #include "pres.hxx" #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::sd::toolpanel::controls; namespace { typedef ::std::vector MasterPageContainerType; class PreviewCreationRequest { public: PreviewCreationRequest (MasterPageContainer::Token aToken, int nPriority); MasterPageContainer::Token maToken; int mnPriority; class Compare {public: bool operator() (const PreviewCreationRequest& r1,const PreviewCreationRequest& r2); }; class CompareToken {public: MasterPageContainer::Token maToken; CompareToken(MasterPageContainer::Token aToken); bool operator() (const PreviewCreationRequest& rRequest); }; }; } // end of anonymous namespace namespace sd { namespace toolpanel { namespace controls { /** Inner implementation class of the MasterPageContainer. */ class MasterPageContainer::Implementation : public SdGlobalResource, public MasterPageContainerFiller::ContainerAdapter, public MasterPageContainerQueue::ContainerAdapter { public: mutable ::osl::Mutex maMutex; static ::boost::weak_ptr mpInstance; MasterPageContainerType maContainer; static ::boost::shared_ptr Instance (void); void LateInit (void); void AddChangeListener (const Link& rLink); void RemoveChangeListener (const Link& rLink); void UpdatePreviewSizePixel (void); Size GetPreviewSizePixel (PreviewSize eSize) const; bool HasToken (Token aToken) const; const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const; SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken); virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor); void InvalidatePreview (Token aToken); Image GetPreviewForToken ( Token aToken, PreviewSize ePreviewSize); PreviewState GetPreviewState (Token aToken) const; bool RequestPreview (Token aToken); Reference GetModel (void); SdDrawDocument* GetDocument (void); void FireContainerChange ( MasterPageContainerChangeEvent::EventType eType, Token aToken, bool bNotifyAsynchronously = false); virtual bool UpdateDescriptor ( const SharedMasterPageDescriptor& rpDescriptor, bool bForcePageObject, bool bForcePreview, bool bSendEvents); void ReleaseDescriptor (Token aToken); /** Called by the MasterPageContainerFiller to notify that all master pages from template documents have been added. */ virtual void FillingDone (void); private: Implementation (void); virtual ~Implementation (void); class Deleter { public: void operator() (Implementation* pObject) { delete pObject; } }; friend class Deleter; enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState; ::boost::scoped_ptr mpRequestQueue; ::com::sun::star::uno::Reference mxModel; SdDrawDocument* mpDocument; PreviewRenderer maPreviewRenderer; /** Remember whether the first page object has already been used to determine the correct size ratio. */ bool mbFirstPageObjectSeen; // The widths for the previews contain two pixels for the border that is // painted arround the preview. static const int SMALL_PREVIEW_WIDTH = 72 + 2; static const int LARGE_PREVIEW_WIDTH = 2*72 + 2; /** This substition of page preview shows "Preparing preview" and is shown as long as the actual previews are not being present. */ Image maLargePreviewBeingCreated; Image maSmallPreviewBeingCreated; /** This substition of page preview is shown when a preview can not be created and thus is not available. */ Image maLargePreviewNotAvailable; Image maSmallPreviewNotAvailable; ::std::vector maChangeListeners; // We have to remember the tasks for initialization and filling in case // a MasterPageContainer object is destroyed before these tasks have // been completed. ::boost::weak_ptr mpFillerTask; Size maSmallPreviewSizePixel; Size maLargePreviewSizePixel; bool mbPageRatioKnown; bool mbContainerCleaningPending; typedef ::std::pair EventData; DECL_LINK(AsynchronousNotifyCallback, EventData*); ::sd::DrawDocShell* LoadDocument ( const String& sFileName, SfxObjectShellLock& rxDocumentShell); Image GetPreviewSubstitution (USHORT nId, PreviewSize ePreviewSize); void CleanContainer (void); }; //===== MasterPageContainer =================================================== ::boost::weak_ptr MasterPageContainer::Implementation::mpInstance; static const MasterPageContainer::Token NIL_TOKEN (-1); ::boost::shared_ptr MasterPageContainer::Implementation::Instance (void) { ::boost::shared_ptr pInstance; if (Implementation::mpInstance.expired()) { ::osl::GetGlobalMutex aMutexFunctor; ::osl::MutexGuard aGuard (aMutexFunctor()); if (Implementation::mpInstance.expired()) { OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); pInstance = ::boost::shared_ptr( new MasterPageContainer::Implementation(), MasterPageContainer::Implementation::Deleter()); SdGlobalResourceContainer::Instance().AddResource(pInstance); Implementation::mpInstance = pInstance; } else pInstance = ::boost::shared_ptr( Implementation::mpInstance); } else { OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); pInstance = ::boost::shared_ptr( Implementation::mpInstance); } DBG_ASSERT (pInstance.get()!=NULL, "MasterPageContainer::Implementation::Instance(): instance is NULL"); return pInstance; } MasterPageContainer::MasterPageContainer (void) : mpImpl(Implementation::Instance()), mePreviewSize(SMALL) { mpImpl->LateInit(); } MasterPageContainer::~MasterPageContainer (void) { } void MasterPageContainer::AddChangeListener (const Link& rLink) { mpImpl->AddChangeListener(rLink); } void MasterPageContainer::RemoveChangeListener (const Link& rLink) { mpImpl->RemoveChangeListener(rLink); } void MasterPageContainer::SetPreviewSize (PreviewSize eSize) { mePreviewSize = eSize; mpImpl->FireContainerChange( MasterPageContainerChangeEvent::SIZE_CHANGED, NIL_TOKEN); } MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const { return mePreviewSize; } Size MasterPageContainer::GetPreviewSizePixel (void) const { return mpImpl->GetPreviewSizePixel(mePreviewSize); } MasterPageContainer::Token MasterPageContainer::PutMasterPage ( const SharedMasterPageDescriptor& rDescriptor) { return mpImpl->PutMasterPage(rDescriptor); } void MasterPageContainer::AcquireToken (Token aToken) { SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) { ++pDescriptor->mnUseCount; } } void MasterPageContainer::ReleaseToken (Token aToken) { SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) { OSL_ASSERT(pDescriptor->mnUseCount>0); --pDescriptor->mnUseCount; if (pDescriptor->mnUseCount <= 0) { switch (pDescriptor->meOrigin) { case DEFAULT: case TEMPLATE: default: break; case MASTERPAGE: mpImpl->ReleaseDescriptor(aToken); break; } } } } int MasterPageContainer::GetTokenCount (void) const { const ::osl::MutexGuard aGuard (mpImpl->maMutex); return mpImpl->maContainer.size(); } bool MasterPageContainer::HasToken (Token aToken) const { const ::osl::MutexGuard aGuard (mpImpl->maMutex); return mpImpl->HasToken(aToken); } MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); Token aResult (NIL_TOKEN); if (HasToken(nIndex)) aResult = mpImpl->maContainer[nIndex]->maToken; return aResult; } MasterPageContainer::Token MasterPageContainer::GetTokenForURL ( const String& sURL) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); Token aResult (NIL_TOKEN); if (sURL.Len() > 0) { MasterPageContainerType::iterator iEntry ( ::std::find_if ( mpImpl->maContainer.begin(), mpImpl->maContainer.end(), MasterPageDescriptor::URLComparator(sURL))); if (iEntry != mpImpl->maContainer.end()) aResult = (*iEntry)->maToken; } return aResult; } MasterPageContainer::Token MasterPageContainer::GetTokenForPageName ( const String& sPageName) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); Token aResult (NIL_TOKEN); if (sPageName.Len() > 0) { MasterPageContainerType::iterator iEntry ( ::std::find_if ( mpImpl->maContainer.begin(), mpImpl->maContainer.end(), MasterPageDescriptor::PageNameComparator(sPageName))); if (iEntry != mpImpl->maContainer.end()) aResult = (*iEntry)->maToken; } return aResult; } MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); Token aResult (NIL_TOKEN); if (sStyleName.Len() > 0) { MasterPageContainerType::iterator iEntry ( ::std::find_if ( mpImpl->maContainer.begin(), mpImpl->maContainer.end(), MasterPageDescriptor::StyleNameComparator(sStyleName))); if (iEntry != mpImpl->maContainer.end()) aResult = (*iEntry)->maToken; } return aResult; } MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject ( const SdPage* pPage) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); Token aResult (NIL_TOKEN); if (pPage != NULL) { MasterPageContainerType::iterator iEntry ( ::std::find_if ( mpImpl->maContainer.begin(), mpImpl->maContainer.end(), MasterPageDescriptor::PageObjectComparator(pPage))); if (iEntry != mpImpl->maContainer.end()) aResult = (*iEntry)->maToken; } return aResult; } String MasterPageContainer::GetURLForToken ( MasterPageContainer::Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) return pDescriptor->msURL; else return String(); } String MasterPageContainer::GetPageNameForToken ( MasterPageContainer::Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) return pDescriptor->msPageName; else return String(); } String MasterPageContainer::GetStyleNameForToken ( MasterPageContainer::Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) return pDescriptor->msStyleName; else return String(); } SdPage* MasterPageContainer::GetPageObjectForToken ( MasterPageContainer::Token aToken, bool bLoad) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SdPage* pPageObject = NULL; SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) { pPageObject = pDescriptor->mpMasterPage; if (pPageObject == NULL) { // The page object is not (yet) present. Call // UpdateDescriptor() to trigger the PageObjectProvider() to // provide it. if (bLoad) mpImpl->GetModel(); if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true)) pPageObject = pDescriptor->mpMasterPage; } } return pPageObject; } MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) return pDescriptor->meOrigin; else return UNKNOWN; } sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) return pDescriptor->mnTemplateIndex; else return -1; } void MasterPageContainer::SetPreviewProviderForToken ( Token aToken, const ::boost::shared_ptr& rpPreviewProvider) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get()!=NULL) { pDescriptor->mpPreviewProvider = rpPreviewProvider; mpImpl->InvalidatePreview(aToken); } } SdPage* MasterPageContainer::GetSlideForToken ( MasterPageContainer::Token aToken, bool bLoad) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); SdPage* pSlide = NULL; SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); if (pDescriptor.get() != NULL) { pSlide = pDescriptor->mpSlide; if (pSlide==NULL && bLoad) { GetPageObjectForToken(aToken, bLoad); pSlide = pDescriptor->mpSlide; } } return pSlide; } SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken ( MasterPageContainer::Token aToken) { const ::osl::MutexGuard aGuard (mpImpl->maMutex); return mpImpl->GetDescriptor(aToken); } bool MasterPageContainer::UpdateDescriptor ( const SharedMasterPageDescriptor& rpDescriptor, bool bForcePageObject, bool bForcePreview, bool bSendEvents) { return mpImpl->UpdateDescriptor(rpDescriptor, bForcePageObject, bForcePreview, bSendEvents); } void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken) { mpImpl->InvalidatePreview(aToken); } Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken) { return mpImpl->GetPreviewForToken(aToken,mePreviewSize); } MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken) { return mpImpl->GetPreviewState(aToken); } bool MasterPageContainer::RequestPreview (Token aToken) { return mpImpl->RequestPreview(aToken); } //==== Implementation ================================================ MasterPageContainer::Implementation::Implementation (void) : maMutex(), maContainer(), meInitializationState(NOT_INITIALIZED), mpRequestQueue(NULL), mxModel(NULL), mpDocument(NULL), maPreviewRenderer(), mbFirstPageObjectSeen(false), maLargePreviewBeingCreated(), maSmallPreviewBeingCreated(), maLargePreviewNotAvailable(), maSmallPreviewNotAvailable(), maChangeListeners(), maSmallPreviewSizePixel(), maLargePreviewSizePixel(), mbPageRatioKnown(false), mbContainerCleaningPending(true) { UpdatePreviewSizePixel(); } MasterPageContainer::Implementation::~Implementation (void) { // When the initializer or filler tasks are still running then we have // to stop them now in order to prevent them from calling us back. tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask); mpRequestQueue.reset(); uno::Reference xCloseable (mxModel, uno::UNO_QUERY); if (xCloseable.is()) { try { xCloseable->close(true); } catch (::com::sun::star::util::CloseVetoException aException) { } } mxModel = NULL; } void MasterPageContainer::Implementation::LateInit (void) { const ::osl::MutexGuard aGuard (maMutex); if (meInitializationState == NOT_INITIALIZED) { meInitializationState = INITIALIZING; OSL_ASSERT(Instance().get()==this); mpRequestQueue.reset(MasterPageContainerQueue::Create( ::boost::shared_ptr(Instance()))); mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create( ::boost::shared_ptr(new MasterPageContainerFiller(*this)), 5, 50); meInitializationState = INITIALIZED; } } void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink) { const ::osl::MutexGuard aGuard (maMutex); ::std::vector::iterator iListener ( ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); if (iListener == maChangeListeners.end()) maChangeListeners.push_back(rLink); } void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink) { const ::osl::MutexGuard aGuard (maMutex); ::std::vector::iterator iListener ( ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); if (iListener != maChangeListeners.end()) maChangeListeners.erase(iListener); } void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void) { const ::osl::MutexGuard aGuard (maMutex); // The default aspect ratio is 4:3 int nWidth (4); int nHeight (3); // Search for the first entry with an existing master page. MasterPageContainerType::const_iterator iDescriptor; MasterPageContainerType::const_iterator iContainerEnd(maContainer.end()); for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor) if (*iDescriptor!=NULL && (*iDescriptor)->mpMasterPage != NULL) { Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize()); nWidth = aPageSize.Width(); nHeight = aPageSize.Height(); mbFirstPageObjectSeen = true; break; } maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH; maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH; int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2); int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2); if (nNewSmallHeight!=maSmallPreviewSizePixel.Height() || nNewLargeHeight!=maLargePreviewSizePixel.Height()) { maSmallPreviewSizePixel.Height() = nNewSmallHeight; maLargePreviewSizePixel.Height() = nNewLargeHeight; FireContainerChange( MasterPageContainerChangeEvent::SIZE_CHANGED, NIL_TOKEN); } } Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const { if (eSize == SMALL) return maSmallPreviewSizePixel; else return maLargePreviewSizePixel; } IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData) { const ::osl::MutexGuard aGuard (maMutex); if (pData != NULL) { FireContainerChange(pData->first, pData->second, false); delete pData; } return 0; } MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage ( const SharedMasterPageDescriptor& rpDescriptor) { const ::osl::MutexGuard aGuard (maMutex); Token aResult (NIL_TOKEN); // Get page object and preview when that is inexpensive. UpdateDescriptor(rpDescriptor,false,false, false); // Look up the new MasterPageDescriptor and either insert it or update // an already existing one. MasterPageContainerType::iterator aEntry ( ::std::find_if ( maContainer.begin(), maContainer.end(), MasterPageDescriptor::AllComparator(rpDescriptor))); if (aEntry == maContainer.end()) { // Insert a new MasterPageDescriptor. bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL && rpDescriptor->msURL.getLength()==0); if ( ! bIgnore) { if (mbContainerCleaningPending) CleanContainer(); aResult = maContainer.size(); rpDescriptor->SetToken(aResult); // Templates are precious, i.e. we lock them so that they will // not be destroyed when (temporarily) no one references them. // They will only be deleted when the container is destroyed. switch (rpDescriptor->meOrigin) { case TEMPLATE: case DEFAULT: ++rpDescriptor->mnUseCount; break; default: break; } maContainer.push_back(rpDescriptor); aEntry = maContainer.end()-1; FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult); } } else { // Update an existing MasterPageDescriptor. aResult = (*aEntry)->maToken; ::std::auto_ptr > pEventTypes( (*aEntry)->Update(*rpDescriptor)); if (pEventTypes.get()!=NULL && pEventTypes->size()>0) { // One or more aspects of the descriptor have changed. Send // appropriate events to the listeners. UpdateDescriptor(*aEntry,false,false, true); std::vector::const_iterator iEventType; for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType) { FireContainerChange( *iEventType, (*aEntry)->maToken, false); } } } return aResult; } bool MasterPageContainer::Implementation::HasToken (Token aToken) const { return aToken>=0 && (unsigned)aToken=0 && (unsigned)aToken=0 && (unsigned)aTokenmaSmallPreview = Image(); pDescriptor->maLargePreview = Image(); RequestPreview(aToken); } } Image MasterPageContainer::Implementation::GetPreviewForToken ( MasterPageContainer::Token aToken, PreviewSize ePreviewSize) { const ::osl::MutexGuard aGuard (maMutex); Image aPreview; PreviewState ePreviewState (GetPreviewState(aToken)); SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); // When the preview is missing but inexpensively creatable then do that // now. if (pDescriptor.get()!=NULL) { if (ePreviewState == PS_CREATABLE) if (UpdateDescriptor(pDescriptor, false,false, true)) if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) ePreviewState = PS_AVAILABLE; switch (ePreviewState) { case PS_AVAILABLE: aPreview = pDescriptor->GetPreview(ePreviewSize); break; case PS_PREPARING: aPreview = GetPreviewSubstitution( STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, ePreviewSize); break; case PS_CREATABLE: aPreview = GetPreviewSubstitution( STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, ePreviewSize); break; case PS_NOT_AVAILABLE: aPreview = GetPreviewSubstitution( STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION, ePreviewSize); if (ePreviewSize == SMALL) pDescriptor->maSmallPreview = aPreview; else pDescriptor->maLargePreview = aPreview; break; } } return aPreview; } MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState ( Token aToken) const { const ::osl::MutexGuard aGuard (maMutex); PreviewState eState (PS_NOT_AVAILABLE); SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); if (pDescriptor.get() != NULL) { if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) eState = PS_AVAILABLE; else if (pDescriptor->mpPreviewProvider.get() != NULL) { // The preview does not exist but can be created. When that is // not expensive then do it at once. if (mpRequestQueue->HasRequest(aToken)) eState = PS_PREPARING; else eState = PS_CREATABLE; } else eState = PS_NOT_AVAILABLE; } return eState; } bool MasterPageContainer::Implementation::RequestPreview (Token aToken) { SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); if (pDescriptor.get() != NULL) return mpRequestQueue->RequestPreview(pDescriptor); else return false; } Reference MasterPageContainer::Implementation::GetModel (void) { const ::osl::MutexGuard aGuard (maMutex); if ( ! mxModel.is()) { // Get the desktop a s service factory. ::rtl::OUString sDesktopServiceName ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")); uno::Reference xDesktop ( ::comphelper::getProcessServiceFactory()->createInstance( sDesktopServiceName), uno::UNO_QUERY); // Create a new model. ::rtl::OUString sModelServiceName ( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument")); mxModel = uno::Reference( ::comphelper::getProcessServiceFactory()->createInstance( sModelServiceName), uno::UNO_QUERY); // Initialize the model. uno::Reference xLoadable (mxModel,uno::UNO_QUERY); if (xLoadable.is()) xLoadable->initNew(); // Use its tunnel to get a pointer to its core implementation. uno::Reference xUnoTunnel (mxModel, uno::UNO_QUERY); if (xUnoTunnel.is()) { mpDocument = reinterpret_cast( xUnoTunnel->getSomething( SdXImpressDocument::getUnoTunnelId()))->GetDoc(); } // Create a default page. uno::Reference xSlideSupplier (mxModel, uno::UNO_QUERY); if (xSlideSupplier.is()) { uno::Reference xSlides ( xSlideSupplier->getDrawPages(), uno::UNO_QUERY); if (xSlides.is()) { sal_Int32 nIndex (0); uno::Reference xNewPage (xSlides->insertNewByIndex(nIndex)); uno::Reference xProperties(xNewPage, uno::UNO_QUERY); if (xProperties.is()) xProperties->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")), makeAny((sal_Int16)AUTOLAYOUT_TITLE)); } } } return mxModel; } SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void) { GetModel(); return mpDocument; } Image MasterPageContainer::Implementation::GetPreviewSubstitution ( USHORT nId, PreviewSize ePreviewSize) { const ::osl::MutexGuard aGuard (maMutex); Image aPreview; switch (nId) { case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION: { Image& rPreview (ePreviewSize==SMALL ? maSmallPreviewBeingCreated : maLargePreviewBeingCreated); if (rPreview.GetSizePixel().Width() == 0) { rPreview = maPreviewRenderer.RenderSubstitution( ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION)); } aPreview = rPreview; } break; case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION: { Image& rPreview (ePreviewSize==SMALL ? maSmallPreviewNotAvailable : maLargePreviewNotAvailable); if (rPreview.GetSizePixel().Width() == 0) { rPreview = maPreviewRenderer.RenderSubstitution( ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION)); } aPreview = rPreview; } break; } return aPreview; } void MasterPageContainer::Implementation::CleanContainer (void) { // Remove the empty elements at the end of the container. The empty // elements in the middle can not be removed because that would // invalidate the references still held by others. int nIndex (maContainer.size()-1); while (nIndex>=0 && maContainer[nIndex].get()==NULL) --nIndex; maContainer.resize(++nIndex); } void MasterPageContainer::Implementation::FireContainerChange ( MasterPageContainerChangeEvent::EventType eType, Token aToken, bool bNotifyAsynchronously) { if (bNotifyAsynchronously) { Application::PostUserEvent( LINK(this,Implementation,AsynchronousNotifyCallback), new EventData(eType,aToken)); } else { ::std::vector aCopy(maChangeListeners.begin(),maChangeListeners.end()); ::std::vector::iterator iListener; MasterPageContainerChangeEvent aEvent; aEvent.meEventType = eType; aEvent.maChildToken = aToken; for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener) iListener->Call(&aEvent); } } bool MasterPageContainer::Implementation::UpdateDescriptor ( const SharedMasterPageDescriptor& rpDescriptor, bool bForcePageObject, bool bForcePreview, bool bSendEvents) { const ::osl::MutexGuard aGuard (maMutex); // We have to create the page object when the preview provider needs it // and the caller needs the preview. bForcePageObject |= (bForcePreview && rpDescriptor->mpPreviewProvider->NeedsPageObject() && rpDescriptor->mpMasterPage==NULL); // Define a cost threshold so that an update or page object or preview // that is at least this cost are made at once. Updates with higher cost // are scheduled for later. sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0); // Update the page object (which may be used for the preview update). if (bForcePageObject) GetDocument(); bool bPageObjectModified (rpDescriptor->UpdatePageObject( (bForcePageObject ? -1 : nCostThreshold), mpDocument)); if (bPageObjectModified && bSendEvents) FireContainerChange( MasterPageContainerChangeEvent::DATA_CHANGED, rpDescriptor->maToken); if (bPageObjectModified && ! mbFirstPageObjectSeen) UpdatePreviewSizePixel(); // Update the preview. bool bPreviewModified (rpDescriptor->UpdatePreview( (bForcePreview ? -1 : nCostThreshold), maSmallPreviewSizePixel, maLargePreviewSizePixel, maPreviewRenderer)); if (bPreviewModified && bSendEvents) FireContainerChange( MasterPageContainerChangeEvent::PREVIEW_CHANGED, rpDescriptor->maToken); return bPageObjectModified || bPreviewModified; } void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken) { if (aToken>=0 && (unsigned)aTokenProcessAllRequests(); } } } } // end of namespace ::sd::toolpanel::controls namespace { //===== PreviewCreationRequest ================================================ PreviewCreationRequest::PreviewCreationRequest ( MasterPageContainer::Token aToken, int nPriority) : maToken(aToken), mnPriority(nPriority) { } bool PreviewCreationRequest::Compare::operator() ( const PreviewCreationRequest& aRequest1, const PreviewCreationRequest& aRequest2) { if (aRequest1.mnPriority != aRequest2.mnPriority) { // Prefer requests with higher priority. return aRequest1.mnPriority > aRequest2.mnPriority; } else { // Prefer tokens that have been earlier created (those with lower // value). return aRequest1.maToken < aRequest2.maToken; } } PreviewCreationRequest::CompareToken::CompareToken (MasterPageContainer::Token aToken) : maToken(aToken) { } bool PreviewCreationRequest::CompareToken::operator() (const PreviewCreationRequest& aRequest) { return maToken==aRequest.maToken; } } // end of anonymous namespace