| /************************************************************** |
| * |
| * 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 "MasterPageContainer.hxx" |
| |
| #include "MasterPageDescriptor.hxx" |
| #include "MasterPageContainerFiller.hxx" |
| #include "MasterPageContainerQueue.hxx" |
| #include "TemplateScanner.hxx" |
| #include "tools/AsynchronousTask.hxx" |
| #include "strings.hrc" |
| #include <algorithm> |
| #include <list> |
| #include <set> |
| |
| #include "unomodel.hxx" |
| #include <com/sun/star/frame/XComponentLoader.hpp> |
| #include <com/sun/star/io/XStream.hpp> |
| #include <com/sun/star/io/XInputStream.hpp> |
| #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/uno/Reference.hxx> |
| #include <com/sun/star/uno/Any.hxx> |
| #include <com/sun/star/uno/Sequence.hxx> |
| #include <com/sun/star/util/XCloseable.hpp> |
| #include <comphelper/processfactory.hxx> |
| #include <tools/urlobj.hxx> |
| #include <sfx2/app.hxx> |
| #include <svx/svdpage.hxx> |
| #include "DrawDocShell.hxx" |
| #include "drawdoc.hxx" |
| #include "sdpage.hxx" |
| #include <svl/itemset.hxx> |
| #include <svl/eitem.hxx> |
| #include "sdresid.hxx" |
| #include "tools/TimerBasedTaskExecution.hxx" |
| #include "pres.hxx" |
| #include <osl/mutex.hxx> |
| #include <boost/weak_ptr.hpp> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| |
| namespace { |
| |
| typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType; |
| |
| } // end of anonymous namespace |
| |
| |
| namespace sd { namespace sidebar { |
| |
| |
| /** 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<Implementation> mpInstance; |
| MasterPageContainerType maContainer; |
| |
| static ::boost::shared_ptr<Implementation> 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<frame::XModel> 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<MasterPageContainerQueue> mpRequestQueue; |
| ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> 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<Link> 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<sd::tools::TimerBasedTaskExecution> mpFillerTask; |
| |
| Size maSmallPreviewSizePixel; |
| Size maLargePreviewSizePixel; |
| bool mbPageRatioKnown; |
| |
| bool mbContainerCleaningPending; |
| |
| typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData; |
| DECL_LINK(AsynchronousNotifyCallback, EventData*); |
| ::sd::DrawDocShell* LoadDocument ( |
| const String& sFileName, |
| SfxObjectShellLock& rxDocumentShell); |
| |
| Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize); |
| |
| void CleanContainer (void); |
| }; |
| |
| |
| |
| |
| //===== MasterPageContainer =================================================== |
| |
| ::boost::weak_ptr<MasterPageContainer::Implementation> |
| MasterPageContainer::Implementation::mpInstance; |
| static const MasterPageContainer::Token NIL_TOKEN (-1); |
| |
| |
| |
| |
| ::boost::shared_ptr<MasterPageContainer::Implementation> |
| MasterPageContainer::Implementation::Instance (void) |
| { |
| ::boost::shared_ptr<MasterPageContainer::Implementation> 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<MasterPageContainer::Implementation>( |
| new MasterPageContainer::Implementation(), |
| MasterPageContainer::Implementation::Deleter()); |
| SdGlobalResourceContainer::Instance().AddResource(pInstance); |
| Implementation::mpInstance = pInstance; |
| } |
| else |
| pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( |
| Implementation::mpInstance); |
| } |
| else |
| { |
| OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); |
| pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( |
| 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::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; |
| } |
| |
| |
| |
| |
| SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken ( |
| MasterPageContainer::Token aToken) |
| { |
| const ::osl::MutexGuard aGuard (mpImpl->maMutex); |
| |
| return mpImpl->GetDescriptor(aToken); |
| } |
| |
| |
| |
| 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<util::XCloseable> 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<MasterPageContainerQueue::ContainerAdapter>(Instance()))); |
| |
| mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create( |
| ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)), |
| 5, |
| 50); |
| |
| meInitializationState = INITIALIZED; |
| } |
| } |
| |
| |
| |
| |
| void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink) |
| { |
| const ::osl::MutexGuard aGuard (maMutex); |
| |
| ::std::vector<Link>::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<Link>::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( bool(*iDescriptor) && (*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<std::vector<MasterPageContainerChangeEvent::EventType> > 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<MasterPageContainerChangeEvent::EventType>::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<maContainer.size() |
| && maContainer[aToken].get()!=NULL; |
| } |
| |
| |
| |
| |
| const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor ( |
| Token aToken) const |
| { |
| if (aToken>=0 && (unsigned)aToken<maContainer.size()) |
| return maContainer[aToken]; |
| else |
| return SharedMasterPageDescriptor(); |
| } |
| |
| |
| |
| |
| SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken) |
| { |
| if (aToken>=0 && (unsigned)aToken<maContainer.size()) |
| return maContainer[aToken]; |
| else |
| return SharedMasterPageDescriptor(); |
| } |
| |
| |
| |
| |
| void MasterPageContainer::Implementation::InvalidatePreview (Token aToken) |
| { |
| const ::osl::MutexGuard aGuard (maMutex); |
| |
| SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken)); |
| if (pDescriptor.get() != NULL) |
| { |
| pDescriptor->maSmallPreview = 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<frame::XModel> 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<frame::XComponentLoader> 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<frame::XModel>( |
| ::comphelper::getProcessServiceFactory()->createInstance( |
| sModelServiceName), |
| uno::UNO_QUERY); |
| |
| // Initialize the model. |
| uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY); |
| if (xLoadable.is()) |
| xLoadable->initNew(); |
| |
| // Use its tunnel to get a pointer to its core implementation. |
| uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY); |
| if (xUnoTunnel.is()) |
| { |
| mpDocument = reinterpret_cast<SdXImpressDocument*>( |
| xUnoTunnel->getSomething( |
| SdXImpressDocument::getUnoTunnelId()))->GetDoc(); |
| } |
| |
| // Create a default page. |
| uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY); |
| if (xSlideSupplier.is()) |
| { |
| uno::Reference<drawing::XDrawPages> xSlides ( |
| xSlideSupplier->getDrawPages(), uno::UNO_QUERY); |
| if (xSlides.is()) |
| { |
| sal_Int32 nIndex (0); |
| uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex)); |
| uno::Reference<beans::XPropertySet> 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 ( |
| sal_uInt16 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<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end()); |
| ::std::vector<Link>::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)aToken<maContainer.size()) |
| { |
| maContainer[aToken].reset(); |
| mbContainerCleaningPending = true; |
| } |
| } |
| |
| |
| |
| |
| void MasterPageContainer::Implementation::FillingDone (void) |
| { |
| mpRequestQueue->ProcessAllRequests(); |
| } |
| |
| |
| |
| } } // end of namespace sd::sidebar |