bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / sidebar / MasterPageContainer.cxx
blob3cce7291df9c02c49f66b2bd173bcb8eabc1a1b0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "MasterPageContainer.hxx"
22 #include "MasterPageDescriptor.hxx"
23 #include "MasterPageContainerFiller.hxx"
24 #include "MasterPageContainerQueue.hxx"
25 #include "TemplateScanner.hxx"
26 #include "tools/AsynchronousTask.hxx"
27 #include "strings.hrc"
28 #include <algorithm>
29 #include <list>
30 #include <memory>
31 #include <set>
33 #include "unomodel.hxx"
34 #include <com/sun/star/frame/Desktop.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/io/XStream.hpp>
37 #include <com/sun/star/io/XInputStream.hpp>
38 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/uno/Reference.hxx>
41 #include <com/sun/star/uno/Any.hxx>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include <com/sun/star/util/XCloseable.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <sfx2/app.hxx>
46 #include <svx/svdpage.hxx>
47 #include "DrawDocShell.hxx"
48 #include "drawdoc.hxx"
49 #include "sdpage.hxx"
50 #include <svl/itemset.hxx>
51 #include <svl/eitem.hxx>
52 #include "sdresid.hxx"
53 #include "tools/TimerBasedTaskExecution.hxx"
54 #include "pres.hxx"
55 #include <osl/mutex.hxx>
56 #include <osl/getglobalmutex.hxx>
57 #include <boost/scoped_ptr.hpp>
58 #include <boost/weak_ptr.hpp>
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::uno;
63 namespace {
65 typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
67 } // end of anonymous namespace
69 namespace sd { namespace sidebar {
71 /** Inner implementation class of the MasterPageContainer.
73 class MasterPageContainer::Implementation
74 : public SdGlobalResource,
75 public MasterPageContainerFiller::ContainerAdapter,
76 public MasterPageContainerQueue::ContainerAdapter
78 public:
79 mutable ::osl::Mutex maMutex;
81 static ::boost::weak_ptr<Implementation> mpInstance;
82 MasterPageContainerType maContainer;
84 static ::boost::shared_ptr<Implementation> Instance();
86 void LateInit();
87 void AddChangeListener (const Link<>& rLink);
88 void RemoveChangeListener (const Link<>& rLink);
89 void UpdatePreviewSizePixel();
90 Size GetPreviewSizePixel (PreviewSize eSize) const;
92 bool HasToken (Token aToken) const;
93 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
94 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
95 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor) SAL_OVERRIDE;
96 void InvalidatePreview (Token aToken);
97 Image GetPreviewForToken (
98 Token aToken,
99 PreviewSize ePreviewSize);
100 PreviewState GetPreviewState (Token aToken) const;
101 bool RequestPreview (Token aToken);
103 Reference<frame::XModel> GetModel();
104 SdDrawDocument* GetDocument();
106 void FireContainerChange (
107 MasterPageContainerChangeEvent::EventType eType,
108 Token aToken,
109 bool bNotifyAsynchronously = false);
111 virtual bool UpdateDescriptor (
112 const SharedMasterPageDescriptor& rpDescriptor,
113 bool bForcePageObject,
114 bool bForcePreview,
115 bool bSendEvents) SAL_OVERRIDE;
117 void ReleaseDescriptor (Token aToken);
119 /** Called by the MasterPageContainerFiller to notify that all master
120 pages from template documents have been added.
122 virtual void FillingDone() SAL_OVERRIDE;
124 private:
125 Implementation();
126 virtual ~Implementation();
128 class Deleter { public:
129 void operator() (Implementation* pObject) { delete pObject; }
131 friend class Deleter;
133 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
135 ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue;
136 ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> mxModel;
137 SdDrawDocument* mpDocument;
138 PreviewRenderer maPreviewRenderer;
139 /** Remember whether the first page object has already been used to
140 determine the correct size ratio.
142 bool mbFirstPageObjectSeen;
144 // The widths for the previews contain two pixels for the border that is
145 // painted around the preview.
146 static const int SMALL_PREVIEW_WIDTH = 72 + 2;
147 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
149 /** This substition of page preview shows "Preparing preview" and is
150 shown as long as the actual previews are not being present.
152 Image maLargePreviewBeingCreated;
153 Image maSmallPreviewBeingCreated;
155 /** This substition of page preview is shown when a preview can not be
156 created and thus is not available.
158 Image maLargePreviewNotAvailable;
159 Image maSmallPreviewNotAvailable;
161 ::std::vector<Link<>> maChangeListeners;
163 // We have to remember the tasks for initialization and filling in case
164 // a MasterPageContainer object is destroyed before these tasks have
165 // been completed.
166 ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
168 Size maSmallPreviewSizePixel;
169 Size maLargePreviewSizePixel;
171 bool mbContainerCleaningPending;
173 typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData;
174 DECL_LINK(AsynchronousNotifyCallback, EventData*);
176 Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize);
178 void CleanContainer();
181 //===== MasterPageContainer ===================================================
183 ::boost::weak_ptr<MasterPageContainer::Implementation>
184 MasterPageContainer::Implementation::mpInstance;
186 ::boost::shared_ptr<MasterPageContainer::Implementation>
187 MasterPageContainer::Implementation::Instance()
189 ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance;
191 if (Implementation::mpInstance.expired())
193 ::osl::GetGlobalMutex aMutexFunctor;
194 ::osl::MutexGuard aGuard (aMutexFunctor());
195 if (Implementation::mpInstance.expired())
197 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
198 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
199 new MasterPageContainer::Implementation(),
200 MasterPageContainer::Implementation::Deleter());
201 SdGlobalResourceContainer::Instance().AddResource(pInstance);
202 Implementation::mpInstance = pInstance;
204 else
205 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
206 Implementation::mpInstance);
208 else
210 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
211 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
212 Implementation::mpInstance);
215 DBG_ASSERT (pInstance.get()!=NULL,
216 "MasterPageContainer::Implementation::Instance(): instance is NULL");
217 return pInstance;
220 MasterPageContainer::MasterPageContainer()
221 : mpImpl(Implementation::Instance()),
222 mePreviewSize(SMALL)
224 mpImpl->LateInit();
227 MasterPageContainer::~MasterPageContainer()
231 void MasterPageContainer::AddChangeListener (const Link<>& rLink)
233 mpImpl->AddChangeListener(rLink);
236 void MasterPageContainer::RemoveChangeListener (const Link<>& rLink)
238 mpImpl->RemoveChangeListener(rLink);
241 void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
243 mePreviewSize = eSize;
244 mpImpl->FireContainerChange(
245 MasterPageContainerChangeEvent::SIZE_CHANGED,
246 NIL_TOKEN);
249 Size MasterPageContainer::GetPreviewSizePixel() const
251 return mpImpl->GetPreviewSizePixel(mePreviewSize);
254 MasterPageContainer::Token MasterPageContainer::PutMasterPage (
255 const SharedMasterPageDescriptor& rDescriptor)
257 return mpImpl->PutMasterPage(rDescriptor);
260 void MasterPageContainer::AcquireToken (Token aToken)
262 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
263 if (pDescriptor.get() != NULL)
265 ++pDescriptor->mnUseCount;
269 void MasterPageContainer::ReleaseToken (Token aToken)
271 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
272 if (pDescriptor.get() != NULL)
274 OSL_ASSERT(pDescriptor->mnUseCount>0);
275 --pDescriptor->mnUseCount;
276 if (pDescriptor->mnUseCount <= 0)
278 switch (pDescriptor->meOrigin)
280 case DEFAULT:
281 case TEMPLATE:
282 default:
283 break;
285 case MASTERPAGE:
286 mpImpl->ReleaseDescriptor(aToken);
287 break;
293 int MasterPageContainer::GetTokenCount() const
295 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
297 return mpImpl->maContainer.size();
300 bool MasterPageContainer::HasToken (Token aToken) const
302 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
304 return mpImpl->HasToken(aToken);
307 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
309 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
311 Token aResult (NIL_TOKEN);
312 if (HasToken(nIndex))
313 aResult = mpImpl->maContainer[nIndex]->maToken;
314 return aResult;
317 MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
318 const OUString& sURL)
320 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
322 Token aResult (NIL_TOKEN);
323 if (!sURL.isEmpty())
325 MasterPageContainerType::iterator iEntry (
326 ::std::find_if (
327 mpImpl->maContainer.begin(),
328 mpImpl->maContainer.end(),
329 MasterPageDescriptor::URLComparator(sURL)));
330 if (iEntry != mpImpl->maContainer.end())
331 aResult = (*iEntry)->maToken;
333 return aResult;
336 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const OUString& sStyleName)
338 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
340 Token aResult (NIL_TOKEN);
341 if (!sStyleName.isEmpty())
343 MasterPageContainerType::iterator iEntry (
344 ::std::find_if (
345 mpImpl->maContainer.begin(),
346 mpImpl->maContainer.end(),
347 MasterPageDescriptor::StyleNameComparator(sStyleName)));
348 if (iEntry != mpImpl->maContainer.end())
349 aResult = (*iEntry)->maToken;
351 return aResult;
354 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
355 const SdPage* pPage)
357 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
359 Token aResult (NIL_TOKEN);
360 if (pPage != NULL)
362 MasterPageContainerType::iterator iEntry (
363 ::std::find_if (
364 mpImpl->maContainer.begin(),
365 mpImpl->maContainer.end(),
366 MasterPageDescriptor::PageObjectComparator(pPage)));
367 if (iEntry != mpImpl->maContainer.end())
368 aResult = (*iEntry)->maToken;
370 return aResult;
373 OUString MasterPageContainer::GetURLForToken (
374 MasterPageContainer::Token aToken)
376 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
378 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
379 if (pDescriptor.get() != NULL)
380 return pDescriptor->msURL;
381 else
382 return OUString();
385 OUString MasterPageContainer::GetPageNameForToken (
386 MasterPageContainer::Token aToken)
388 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
390 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
391 if (pDescriptor.get() != NULL)
392 return pDescriptor->msPageName;
393 else
394 return OUString();
397 OUString MasterPageContainer::GetStyleNameForToken (
398 MasterPageContainer::Token aToken)
400 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
402 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
403 if (pDescriptor.get() != NULL)
404 return pDescriptor->msStyleName;
405 else
406 return OUString();
409 SdPage* MasterPageContainer::GetPageObjectForToken (
410 MasterPageContainer::Token aToken,
411 bool bLoad)
413 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
415 SdPage* pPageObject = NULL;
416 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
417 if (pDescriptor.get() != NULL)
419 pPageObject = pDescriptor->mpMasterPage;
420 if (pPageObject == NULL)
422 // The page object is not (yet) present. Call
423 // UpdateDescriptor() to trigger the PageObjectProvider() to
424 // provide it.
425 if (bLoad)
426 mpImpl->GetModel();
427 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
428 pPageObject = pDescriptor->mpMasterPage;
431 return pPageObject;
434 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken)
436 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
438 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
439 if (pDescriptor.get() != NULL)
440 return pDescriptor->meOrigin;
441 else
442 return UNKNOWN;
445 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
447 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
449 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
450 if (pDescriptor.get() != NULL)
451 return pDescriptor->mnTemplateIndex;
452 else
453 return -1;
456 SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
457 MasterPageContainer::Token aToken)
459 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
461 return mpImpl->GetDescriptor(aToken);
464 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
466 mpImpl->InvalidatePreview(aToken);
469 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
471 return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
474 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
476 return mpImpl->GetPreviewState(aToken);
479 bool MasterPageContainer::RequestPreview (Token aToken)
481 return mpImpl->RequestPreview(aToken);
484 //==== Implementation ================================================
486 MasterPageContainer::Implementation::Implementation()
487 : maMutex(),
488 maContainer(),
489 meInitializationState(NOT_INITIALIZED),
490 mpRequestQueue(NULL),
491 mxModel(NULL),
492 mpDocument(NULL),
493 maPreviewRenderer(),
494 mbFirstPageObjectSeen(false),
495 maLargePreviewBeingCreated(),
496 maSmallPreviewBeingCreated(),
497 maLargePreviewNotAvailable(),
498 maSmallPreviewNotAvailable(),
499 maChangeListeners(),
500 maSmallPreviewSizePixel(),
501 maLargePreviewSizePixel(),
502 mbContainerCleaningPending(true)
505 UpdatePreviewSizePixel();
508 MasterPageContainer::Implementation::~Implementation()
510 // When the initializer or filler tasks are still running then we have
511 // to stop them now in order to prevent them from calling us back.
512 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
514 mpRequestQueue.reset();
516 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
517 if (xCloseable.is())
521 xCloseable->close(true);
523 catch (const ::com::sun::star::util::CloseVetoException&)
527 mxModel = NULL;
530 void MasterPageContainer::Implementation::LateInit()
532 const ::osl::MutexGuard aGuard (maMutex);
534 if (meInitializationState == NOT_INITIALIZED)
536 meInitializationState = INITIALIZING;
538 OSL_ASSERT(Instance().get()==this);
539 mpRequestQueue.reset(MasterPageContainerQueue::Create(
540 ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
542 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
543 ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
545 50);
547 meInitializationState = INITIALIZED;
551 void MasterPageContainer::Implementation::AddChangeListener (const Link<>& rLink)
553 const ::osl::MutexGuard aGuard (maMutex);
555 ::std::vector<Link<>>::iterator iListener (
556 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
557 if (iListener == maChangeListeners.end())
558 maChangeListeners.push_back(rLink);
562 void MasterPageContainer::Implementation::RemoveChangeListener (const Link<>& rLink)
564 const ::osl::MutexGuard aGuard (maMutex);
566 ::std::vector<Link<>>::iterator iListener (
567 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
568 if (iListener != maChangeListeners.end())
569 maChangeListeners.erase(iListener);
572 void MasterPageContainer::Implementation::UpdatePreviewSizePixel()
574 const ::osl::MutexGuard aGuard (maMutex);
576 // The default aspect ratio is 4:3
577 int nWidth (4);
578 int nHeight (3);
580 // Search for the first entry with an existing master page.
581 MasterPageContainerType::const_iterator iDescriptor;
582 MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
583 for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
584 if (*iDescriptor!=0 && (*iDescriptor)->mpMasterPage != NULL)
586 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
587 OSL_ASSERT(aPageSize.Width() > 0 && aPageSize.Height() > 0);
588 if (aPageSize.Width() > 0)
589 nWidth = aPageSize.Width();
590 if (aPageSize.Height() > 0)
591 nHeight = aPageSize.Height();
592 mbFirstPageObjectSeen = true;
593 break;
596 maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH;
597 maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH;
599 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
600 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
602 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
603 || nNewLargeHeight!=maLargePreviewSizePixel.Height())
605 maSmallPreviewSizePixel.Height() = nNewSmallHeight;
606 maLargePreviewSizePixel.Height() = nNewLargeHeight;
607 FireContainerChange(
608 MasterPageContainerChangeEvent::SIZE_CHANGED,
609 NIL_TOKEN);
613 Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
615 if (eSize == SMALL)
616 return maSmallPreviewSizePixel;
617 else
618 return maLargePreviewSizePixel;
621 IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData)
623 const ::osl::MutexGuard aGuard (maMutex);
625 if (pData != NULL)
627 FireContainerChange(pData->first, pData->second, false);
628 delete pData;
631 return 0;
634 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
635 const SharedMasterPageDescriptor& rpDescriptor)
637 const ::osl::MutexGuard aGuard (maMutex);
639 Token aResult (NIL_TOKEN);
641 // Get page object and preview when that is inexpensive.
642 UpdateDescriptor(rpDescriptor,false,false, false);
644 // Look up the new MasterPageDescriptor and either insert it or update
645 // an already existing one.
646 MasterPageContainerType::iterator aEntry (
647 ::std::find_if (
648 maContainer.begin(),
649 maContainer.end(),
650 MasterPageDescriptor::AllComparator(rpDescriptor)));
651 if (aEntry == maContainer.end())
653 // Insert a new MasterPageDescriptor.
654 bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL
655 && rpDescriptor->msURL.isEmpty());
657 if ( ! bIgnore)
659 if (mbContainerCleaningPending)
660 CleanContainer();
662 aResult = maContainer.size();
663 rpDescriptor->SetToken(aResult);
665 // Templates are precious, i.e. we lock them so that they will
666 // not be destroyed when (temporarily) no one references them.
667 // They will only be deleted when the container is destroyed.
668 switch (rpDescriptor->meOrigin)
670 case TEMPLATE:
671 case DEFAULT:
672 ++rpDescriptor->mnUseCount;
673 break;
675 default:
676 break;
679 maContainer.push_back(rpDescriptor);
680 aEntry = maContainer.end()-1;
682 FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult);
685 else
687 // Update an existing MasterPageDescriptor.
688 aResult = (*aEntry)->maToken;
689 std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
690 (*aEntry)->Update(*rpDescriptor));
691 if (pEventTypes.get()!=NULL && pEventTypes->size()>0)
693 // One or more aspects of the descriptor have changed. Send
694 // appropriate events to the listeners.
695 UpdateDescriptor(*aEntry,false,false, true);
697 std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
698 for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
700 FireContainerChange(
701 *iEventType,
702 (*aEntry)->maToken,
703 false);
708 return aResult;
711 bool MasterPageContainer::Implementation::HasToken (Token aToken) const
713 return aToken>=0
714 && (unsigned)aToken<maContainer.size()
715 && maContainer[aToken].get()!=NULL;
718 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
719 Token aToken) const
721 if (aToken>=0 && (unsigned)aToken<maContainer.size())
722 return maContainer[aToken];
723 else
724 return SharedMasterPageDescriptor();
727 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
729 if (aToken>=0 && (unsigned)aToken<maContainer.size())
730 return maContainer[aToken];
731 else
732 return SharedMasterPageDescriptor();
735 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
737 const ::osl::MutexGuard aGuard (maMutex);
739 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
740 if (pDescriptor.get() != NULL)
742 pDescriptor->maSmallPreview = Image();
743 pDescriptor->maLargePreview = Image();
744 RequestPreview(aToken);
748 Image MasterPageContainer::Implementation::GetPreviewForToken (
749 MasterPageContainer::Token aToken,
750 PreviewSize ePreviewSize)
752 const ::osl::MutexGuard aGuard (maMutex);
754 Image aPreview;
755 PreviewState ePreviewState (GetPreviewState(aToken));
757 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
759 // When the preview is missing but inexpensively creatable then do that
760 // now.
761 if (pDescriptor.get()!=NULL)
763 if (ePreviewState == PS_CREATABLE)
764 if (UpdateDescriptor(pDescriptor, false,false, true))
765 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
766 ePreviewState = PS_AVAILABLE;
768 switch (ePreviewState)
770 case PS_AVAILABLE:
771 aPreview = pDescriptor->GetPreview(ePreviewSize);
772 break;
774 case PS_PREPARING:
775 aPreview = GetPreviewSubstitution(
776 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
777 ePreviewSize);
778 break;
780 case PS_CREATABLE:
781 aPreview = GetPreviewSubstitution(
782 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
783 ePreviewSize);
784 break;
786 case PS_NOT_AVAILABLE:
787 aPreview = GetPreviewSubstitution(
788 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
789 ePreviewSize);
790 if (ePreviewSize == SMALL)
791 pDescriptor->maSmallPreview = aPreview;
792 else
793 pDescriptor->maLargePreview = aPreview;
794 break;
798 return aPreview;
801 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
802 Token aToken) const
804 const ::osl::MutexGuard aGuard (maMutex);
806 PreviewState eState (PS_NOT_AVAILABLE);
808 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
809 if (pDescriptor.get() != NULL)
811 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
812 eState = PS_AVAILABLE;
813 else if (pDescriptor->mpPreviewProvider.get() != NULL)
815 // The preview does not exist but can be created. When that is
816 // not expensive then do it at once.
817 if (mpRequestQueue->HasRequest(aToken))
818 eState = PS_PREPARING;
819 else
820 eState = PS_CREATABLE;
822 else
823 eState = PS_NOT_AVAILABLE;
826 return eState;
829 bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
831 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
832 if (pDescriptor.get() != NULL)
833 return mpRequestQueue->RequestPreview(pDescriptor);
834 else
835 return false;
838 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel()
840 const ::osl::MutexGuard aGuard (maMutex);
842 if ( ! mxModel.is())
844 // Get the desktop a s service factory.
845 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(
846 ::comphelper::getProcessComponentContext() );
848 // Create a new model.
849 OUString sModelServiceName ( "com.sun.star.presentation.PresentationDocument");
850 mxModel = uno::Reference<frame::XModel>(
851 ::comphelper::getProcessServiceFactory()->createInstance(
852 sModelServiceName),
853 uno::UNO_QUERY);
855 // Initialize the model.
856 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
857 if (xLoadable.is())
858 xLoadable->initNew();
860 // Use its tunnel to get a pointer to its core implementation.
861 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
862 if (xUnoTunnel.is())
864 mpDocument = reinterpret_cast<SdXImpressDocument*>(
865 xUnoTunnel->getSomething(
866 SdXImpressDocument::getUnoTunnelId()))->GetDoc();
869 // Create a default page.
870 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
871 if (xSlideSupplier.is())
873 uno::Reference<drawing::XDrawPages> xSlides (
874 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
875 if (xSlides.is())
877 sal_Int32 nIndex (0);
878 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex));
879 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
880 if (xProperties.is())
881 xProperties->setPropertyValue(
882 "Layout",
883 makeAny((sal_Int16)AUTOLAYOUT_TITLE));
887 return mxModel;
890 SdDrawDocument* MasterPageContainer::Implementation::GetDocument()
892 GetModel();
893 return mpDocument;
896 Image MasterPageContainer::Implementation::GetPreviewSubstitution (
897 sal_uInt16 nId,
898 PreviewSize ePreviewSize)
900 const ::osl::MutexGuard aGuard (maMutex);
902 Image aPreview;
904 switch (nId)
906 case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION:
908 Image& rPreview (ePreviewSize==SMALL
909 ? maSmallPreviewBeingCreated
910 : maLargePreviewBeingCreated);
911 if (rPreview.GetSizePixel().Width() == 0)
913 rPreview = maPreviewRenderer.RenderSubstitution(
914 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
915 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
917 aPreview = rPreview;
919 break;
921 case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION:
923 Image& rPreview (ePreviewSize==SMALL
924 ? maSmallPreviewNotAvailable
925 : maLargePreviewNotAvailable);
926 if (rPreview.GetSizePixel().Width() == 0)
928 rPreview = maPreviewRenderer.RenderSubstitution(
929 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
930 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
932 aPreview = rPreview;
934 break;
937 return aPreview;
940 void MasterPageContainer::Implementation::CleanContainer()
942 // Remove the empty elements at the end of the container. The empty
943 // elements in the middle can not be removed because that would
944 // invalidate the references still held by others.
945 int nIndex (maContainer.size()-1);
946 while (nIndex>=0 && maContainer[nIndex].get()==NULL)
947 --nIndex;
948 maContainer.resize(++nIndex);
951 void MasterPageContainer::Implementation::FireContainerChange (
952 MasterPageContainerChangeEvent::EventType eType,
953 Token aToken,
954 bool bNotifyAsynchronously)
956 if (bNotifyAsynchronously)
958 Application::PostUserEvent(
959 LINK(this,Implementation,AsynchronousNotifyCallback),
960 new EventData(eType,aToken));
962 else
964 ::std::vector<Link<>> aCopy(maChangeListeners.begin(),maChangeListeners.end());
965 ::std::vector<Link<>>::iterator iListener;
966 MasterPageContainerChangeEvent aEvent;
967 aEvent.meEventType = eType;
968 aEvent.maChildToken = aToken;
969 for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
970 iListener->Call(&aEvent);
974 bool MasterPageContainer::Implementation::UpdateDescriptor (
975 const SharedMasterPageDescriptor& rpDescriptor,
976 bool bForcePageObject,
977 bool bForcePreview,
978 bool bSendEvents)
980 const ::osl::MutexGuard aGuard (maMutex);
982 // We have to create the page object when the preview provider needs it
983 // and the caller needs the preview.
984 bForcePageObject |= (bForcePreview
985 && rpDescriptor->mpPreviewProvider->NeedsPageObject()
986 && rpDescriptor->mpMasterPage==NULL);
988 // Define a cost threshold so that an update or page object or preview
989 // that is at least this cost are made at once. Updates with higher cost
990 // are scheduled for later.
991 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
993 // Update the page object (which may be used for the preview update).
994 if (bForcePageObject)
995 GetDocument();
996 int nPageObjectModified (rpDescriptor->UpdatePageObject(
997 (bForcePageObject ? -1 : nCostThreshold),
998 mpDocument));
999 if (nPageObjectModified == 1 && bSendEvents)
1000 FireContainerChange(
1001 MasterPageContainerChangeEvent::DATA_CHANGED,
1002 rpDescriptor->maToken);
1003 if (nPageObjectModified == -1 && bSendEvents)
1004 FireContainerChange(
1005 MasterPageContainerChangeEvent::CHILD_REMOVED,
1006 rpDescriptor->maToken);
1007 if (nPageObjectModified && ! mbFirstPageObjectSeen)
1008 UpdatePreviewSizePixel();
1010 // Update the preview.
1011 bool bPreviewModified (rpDescriptor->UpdatePreview(
1012 (bForcePreview ? -1 : nCostThreshold),
1013 maSmallPreviewSizePixel,
1014 maLargePreviewSizePixel,
1015 maPreviewRenderer));
1017 if (bPreviewModified && bSendEvents)
1018 FireContainerChange(
1019 MasterPageContainerChangeEvent::PREVIEW_CHANGED,
1020 rpDescriptor->maToken);
1022 return nPageObjectModified || bPreviewModified;
1025 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
1027 if (aToken>=0 && (unsigned)aToken<maContainer.size())
1029 maContainer[aToken].reset();
1030 mbContainerCleaningPending = true;
1034 void MasterPageContainer::Implementation::FillingDone()
1036 mpRequestQueue->ProcessAllRequests();
1039 } } // end of namespace sd::sidebar
1041 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */