Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sd / source / ui / sidebar / MasterPageContainer.cxx
blob2beabbe98cdc80ec032b00bcace684e068effc82
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/io/XStream.hpp>
36 #include <com/sun/star/io/XInputStream.hpp>
37 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/uno/Reference.hxx>
40 #include <com/sun/star/uno/Any.hxx>
41 #include <com/sun/star/util/XCloseable.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <sfx2/app.hxx>
44 #include <svx/svdpage.hxx>
45 #include <DrawDocShell.hxx>
46 #include <drawdoc.hxx>
47 #include <sdpage.hxx>
48 #include <svl/itemset.hxx>
49 #include <svl/eitem.hxx>
50 #include <sdresid.hxx>
51 #include <tools/TimerBasedTaskExecution.hxx>
52 #include <pres.hxx>
53 #include <osl/mutex.hxx>
54 #include <osl/getglobalmutex.hxx>
55 #include <xmloff/autolayout.hxx>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
60 namespace {
62 typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
64 } // end of anonymous namespace
66 namespace sd { namespace sidebar {
68 /** Inner implementation class of the MasterPageContainer.
70 class MasterPageContainer::Implementation
71 : public SdGlobalResource,
72 public MasterPageContainerFiller::ContainerAdapter,
73 public MasterPageContainerQueue::ContainerAdapter
75 public:
76 mutable ::osl::Mutex maMutex;
78 static std::weak_ptr<Implementation> mpInstance;
79 MasterPageContainerType maContainer;
81 static std::shared_ptr<Implementation> Instance();
83 void LateInit();
84 void AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink);
85 void RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink);
86 void UpdatePreviewSizePixel();
87 const Size& GetPreviewSizePixel (PreviewSize eSize) const;
89 bool HasToken (Token aToken) const;
90 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
91 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
92 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor) override;
93 void InvalidatePreview (Token aToken);
94 Image GetPreviewForToken (
95 Token aToken,
96 PreviewSize ePreviewSize);
97 PreviewState GetPreviewState (Token aToken) const;
98 bool RequestPreview (Token aToken);
100 Reference<frame::XModel> GetModel();
101 SdDrawDocument* GetDocument();
103 void FireContainerChange (
104 MasterPageContainerChangeEvent::EventType eType,
105 Token aToken);
107 virtual bool UpdateDescriptor (
108 const SharedMasterPageDescriptor& rpDescriptor,
109 bool bForcePageObject,
110 bool bForcePreview,
111 bool bSendEvents) override;
113 void ReleaseDescriptor (Token aToken);
115 /** Called by the MasterPageContainerFiller to notify that all master
116 pages from template documents have been added.
118 virtual void FillingDone() override;
120 private:
121 Implementation();
122 virtual ~Implementation() override;
124 class Deleter { public:
125 void operator() (Implementation* pObject) { delete pObject; }
127 friend class Deleter;
129 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
131 std::unique_ptr<MasterPageContainerQueue> mpRequestQueue;
132 css::uno::Reference<css::frame::XModel> mxModel;
133 SdDrawDocument* mpDocument;
134 PreviewRenderer maPreviewRenderer;
135 /** Remember whether the first page object has already been used to
136 determine the correct size ratio.
138 bool mbFirstPageObjectSeen;
140 // The widths for the previews contain two pixels for the border that is
141 // painted around the preview.
142 static const int SMALL_PREVIEW_WIDTH = 72 + 2;
143 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
145 /** This substition of page preview shows "Preparing preview" and is
146 shown as long as the actual previews are not being present.
148 Image maLargePreviewBeingCreated;
149 Image maSmallPreviewBeingCreated;
151 /** This substition of page preview is shown when a preview can not be
152 created and thus is not available.
154 Image maLargePreviewNotAvailable;
155 Image maSmallPreviewNotAvailable;
157 ::std::vector<Link<MasterPageContainerChangeEvent&,void>> maChangeListeners;
159 // We have to remember the tasks for initialization and filling in case
160 // a MasterPageContainer object is destroyed before these tasks have
161 // been completed.
162 std::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
164 Size maSmallPreviewSizePixel;
165 Size maLargePreviewSizePixel;
167 Image GetPreviewSubstitution(const char* pId, PreviewSize ePreviewSize);
169 void CleanContainer();
172 //===== MasterPageContainer ===================================================
174 std::weak_ptr<MasterPageContainer::Implementation>
175 MasterPageContainer::Implementation::mpInstance;
177 std::shared_ptr<MasterPageContainer::Implementation>
178 MasterPageContainer::Implementation::Instance()
180 std::shared_ptr<MasterPageContainer::Implementation> pInstance;
182 if (Implementation::mpInstance.expired())
184 ::osl::GetGlobalMutex aMutexFunctor;
185 ::osl::MutexGuard aGuard (aMutexFunctor());
186 if (Implementation::mpInstance.expired())
188 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
189 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
190 new MasterPageContainer::Implementation(),
191 MasterPageContainer::Implementation::Deleter());
192 SdGlobalResourceContainer::Instance().AddResource(pInstance);
193 Implementation::mpInstance = pInstance;
195 else
196 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
197 Implementation::mpInstance);
199 else
201 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
202 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
203 Implementation::mpInstance);
206 DBG_ASSERT (pInstance.get()!=nullptr,
207 "MasterPageContainer::Implementation::Instance(): instance is nullptr");
208 return pInstance;
211 MasterPageContainer::MasterPageContainer()
212 : mpImpl(Implementation::Instance()),
213 mePreviewSize(SMALL)
215 mpImpl->LateInit();
218 MasterPageContainer::~MasterPageContainer()
222 void MasterPageContainer::AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
224 mpImpl->AddChangeListener(rLink);
227 void MasterPageContainer::RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
229 mpImpl->RemoveChangeListener(rLink);
232 void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
234 mePreviewSize = eSize;
235 mpImpl->FireContainerChange(
236 MasterPageContainerChangeEvent::EventType::SIZE_CHANGED,
237 NIL_TOKEN);
240 Size const & MasterPageContainer::GetPreviewSizePixel() const
242 return mpImpl->GetPreviewSizePixel(mePreviewSize);
245 MasterPageContainer::Token MasterPageContainer::PutMasterPage (
246 const SharedMasterPageDescriptor& rDescriptor)
248 return mpImpl->PutMasterPage(rDescriptor);
251 void MasterPageContainer::AcquireToken (Token aToken)
253 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
254 if (pDescriptor.get() != nullptr)
256 ++pDescriptor->mnUseCount;
260 void MasterPageContainer::ReleaseToken (Token aToken)
262 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
263 if (pDescriptor.get() != nullptr)
265 OSL_ASSERT(pDescriptor->mnUseCount>0);
266 --pDescriptor->mnUseCount;
267 if (pDescriptor->mnUseCount <= 0)
269 switch (pDescriptor->meOrigin)
271 case DEFAULT:
272 case TEMPLATE:
273 default:
274 break;
276 case MASTERPAGE:
277 mpImpl->ReleaseDescriptor(aToken);
278 break;
284 int MasterPageContainer::GetTokenCount() const
286 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
288 return mpImpl->maContainer.size();
291 bool MasterPageContainer::HasToken (Token aToken) const
293 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
295 return mpImpl->HasToken(aToken);
298 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
300 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
302 Token aResult (NIL_TOKEN);
303 if (HasToken(nIndex))
304 aResult = mpImpl->maContainer[nIndex]->maToken;
305 return aResult;
308 MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
309 const OUString& sURL)
311 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
313 Token aResult (NIL_TOKEN);
314 if (!sURL.isEmpty())
316 MasterPageContainerType::iterator iEntry (
317 ::std::find_if (
318 mpImpl->maContainer.begin(),
319 mpImpl->maContainer.end(),
320 MasterPageDescriptor::URLComparator(sURL)));
321 if (iEntry != mpImpl->maContainer.end())
322 aResult = (*iEntry)->maToken;
324 return aResult;
327 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const OUString& sStyleName)
329 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
331 Token aResult (NIL_TOKEN);
332 if (!sStyleName.isEmpty())
334 MasterPageContainerType::iterator iEntry (
335 ::std::find_if (
336 mpImpl->maContainer.begin(),
337 mpImpl->maContainer.end(),
338 MasterPageDescriptor::StyleNameComparator(sStyleName)));
339 if (iEntry != mpImpl->maContainer.end())
340 aResult = (*iEntry)->maToken;
342 return aResult;
345 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
346 const SdPage* pPage)
348 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
350 Token aResult (NIL_TOKEN);
351 if (pPage != nullptr)
353 MasterPageContainerType::iterator iEntry (
354 ::std::find_if (
355 mpImpl->maContainer.begin(),
356 mpImpl->maContainer.end(),
357 MasterPageDescriptor::PageObjectComparator(pPage)));
358 if (iEntry != mpImpl->maContainer.end())
359 aResult = (*iEntry)->maToken;
361 return aResult;
364 OUString MasterPageContainer::GetURLForToken (
365 MasterPageContainer::Token aToken)
367 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
369 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
370 if (pDescriptor.get() != nullptr)
371 return pDescriptor->msURL;
372 else
373 return OUString();
376 OUString MasterPageContainer::GetPageNameForToken (
377 MasterPageContainer::Token aToken)
379 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
381 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
382 if (pDescriptor.get() != nullptr)
383 return pDescriptor->msPageName;
384 else
385 return OUString();
388 OUString MasterPageContainer::GetStyleNameForToken (
389 MasterPageContainer::Token aToken)
391 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
393 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
394 if (pDescriptor.get() != nullptr)
395 return pDescriptor->msStyleName;
396 else
397 return OUString();
400 SdPage* MasterPageContainer::GetPageObjectForToken (
401 MasterPageContainer::Token aToken,
402 bool bLoad)
404 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
406 SdPage* pPageObject = nullptr;
407 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
408 if (pDescriptor.get() != nullptr)
410 pPageObject = pDescriptor->mpMasterPage;
411 if (pPageObject == nullptr)
413 // The page object is not (yet) present. Call
414 // UpdateDescriptor() to trigger the PageObjectProvider() to
415 // provide it.
416 if (bLoad)
417 mpImpl->GetModel();
418 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
419 pPageObject = pDescriptor->mpMasterPage;
422 return pPageObject;
425 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken)
427 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
429 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
430 if (pDescriptor.get() != nullptr)
431 return pDescriptor->meOrigin;
432 else
433 return UNKNOWN;
436 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
438 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
440 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
441 if (pDescriptor.get() != nullptr)
442 return pDescriptor->mnTemplateIndex;
443 else
444 return -1;
447 SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
448 MasterPageContainer::Token aToken)
450 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
452 return mpImpl->GetDescriptor(aToken);
455 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
457 mpImpl->InvalidatePreview(aToken);
460 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
462 return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
465 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
467 return mpImpl->GetPreviewState(aToken);
470 bool MasterPageContainer::RequestPreview (Token aToken)
472 return mpImpl->RequestPreview(aToken);
475 //==== Implementation ================================================
477 MasterPageContainer::Implementation::Implementation()
478 : maMutex(),
479 maContainer(),
480 meInitializationState(NOT_INITIALIZED),
481 mpRequestQueue(nullptr),
482 mxModel(nullptr),
483 mpDocument(nullptr),
484 maPreviewRenderer(),
485 mbFirstPageObjectSeen(false),
486 maLargePreviewBeingCreated(),
487 maSmallPreviewBeingCreated(),
488 maLargePreviewNotAvailable(),
489 maSmallPreviewNotAvailable(),
490 maChangeListeners(),
491 maSmallPreviewSizePixel(),
492 maLargePreviewSizePixel()
494 UpdatePreviewSizePixel();
497 MasterPageContainer::Implementation::~Implementation()
499 // When the initializer or filler tasks are still running then we have
500 // to stop them now in order to prevent them from calling us back.
501 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
503 mpRequestQueue.reset();
505 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
506 if (xCloseable.is())
510 xCloseable->close(true);
512 catch (const css::util::CloseVetoException&)
516 mxModel = nullptr;
519 void MasterPageContainer::Implementation::LateInit()
521 const ::osl::MutexGuard aGuard (maMutex);
523 if (meInitializationState == NOT_INITIALIZED)
525 meInitializationState = INITIALIZING;
527 OSL_ASSERT(Instance().get()==this);
528 mpRequestQueue.reset(MasterPageContainerQueue::Create(
529 std::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
531 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
532 std::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
534 50);
536 meInitializationState = INITIALIZED;
540 void MasterPageContainer::Implementation::AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
542 const ::osl::MutexGuard aGuard (maMutex);
544 ::std::vector<Link<MasterPageContainerChangeEvent&,void>>::iterator iListener (
545 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
546 if (iListener == maChangeListeners.end())
547 maChangeListeners.push_back(rLink);
551 void MasterPageContainer::Implementation::RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
553 const ::osl::MutexGuard aGuard (maMutex);
555 ::std::vector<Link<MasterPageContainerChangeEvent&,void>>::iterator iListener (
556 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
557 if (iListener != maChangeListeners.end())
558 maChangeListeners.erase(iListener);
561 void MasterPageContainer::Implementation::UpdatePreviewSizePixel()
563 const ::osl::MutexGuard aGuard (maMutex);
565 // The default aspect ratio is 4:3
566 int nWidth (4);
567 int nHeight (3);
569 // Search for the first entry with an existing master page.
570 MasterPageContainerType::const_iterator iDescriptor;
571 MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
572 for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
573 if (*iDescriptor!=nullptr && (*iDescriptor)->mpMasterPage != nullptr)
575 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
576 OSL_ASSERT(aPageSize.Width() > 0 && aPageSize.Height() > 0);
577 if (aPageSize.Width() > 0)
578 nWidth = aPageSize.Width();
579 if (aPageSize.Height() > 0)
580 nHeight = aPageSize.Height();
581 mbFirstPageObjectSeen = true;
582 break;
585 maSmallPreviewSizePixel.setWidth( SMALL_PREVIEW_WIDTH );
586 maLargePreviewSizePixel.setWidth( LARGE_PREVIEW_WIDTH );
588 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
589 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
591 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
592 || nNewLargeHeight!=maLargePreviewSizePixel.Height())
594 maSmallPreviewSizePixel.setHeight( nNewSmallHeight );
595 maLargePreviewSizePixel.setHeight( nNewLargeHeight );
596 FireContainerChange(
597 MasterPageContainerChangeEvent::EventType::SIZE_CHANGED,
598 NIL_TOKEN);
602 const Size& MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
604 if (eSize == SMALL)
605 return maSmallPreviewSizePixel;
606 else
607 return maLargePreviewSizePixel;
610 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
611 const SharedMasterPageDescriptor& rpDescriptor)
613 const ::osl::MutexGuard aGuard (maMutex);
615 Token aResult (NIL_TOKEN);
617 // Get page object and preview when that is inexpensive.
618 UpdateDescriptor(rpDescriptor,false,false, false);
620 // Look up the new MasterPageDescriptor and either insert it or update
621 // an already existing one.
622 MasterPageContainerType::iterator aEntry (
623 ::std::find_if (
624 maContainer.begin(),
625 maContainer.end(),
626 MasterPageDescriptor::AllComparator(rpDescriptor)));
627 if (aEntry == maContainer.end())
629 // Insert a new MasterPageDescriptor.
630 bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==nullptr
631 && rpDescriptor->msURL.isEmpty());
633 if ( ! bIgnore)
635 CleanContainer();
637 aResult = maContainer.size();
638 rpDescriptor->SetToken(aResult);
640 // Templates are precious, i.e. we lock them so that they will
641 // not be destroyed when (temporarily) no one references them.
642 // They will only be deleted when the container is destroyed.
643 switch (rpDescriptor->meOrigin)
645 case TEMPLATE:
646 case DEFAULT:
647 ++rpDescriptor->mnUseCount;
648 break;
650 default:
651 break;
654 maContainer.push_back(rpDescriptor);
655 aEntry = maContainer.end()-1;
657 FireContainerChange(MasterPageContainerChangeEvent::EventType::CHILD_ADDED,aResult);
660 else
662 // Update an existing MasterPageDescriptor.
663 aResult = (*aEntry)->maToken;
664 std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
665 (*aEntry)->Update(*rpDescriptor));
666 if (pEventTypes.get()!=nullptr && pEventTypes->size()>0)
668 // One or more aspects of the descriptor have changed. Send
669 // appropriate events to the listeners.
670 UpdateDescriptor(*aEntry,false,false, true);
672 std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
673 for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
675 FireContainerChange( *iEventType,(*aEntry)->maToken);
680 return aResult;
683 bool MasterPageContainer::Implementation::HasToken (Token aToken) const
685 return aToken>=0
686 && static_cast<unsigned>(aToken)<maContainer.size()
687 && maContainer[aToken].get()!=nullptr;
690 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
691 Token aToken) const
693 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
694 return maContainer[aToken];
695 else
696 return SharedMasterPageDescriptor();
699 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
701 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
702 return maContainer[aToken];
703 else
704 return SharedMasterPageDescriptor();
707 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
709 const ::osl::MutexGuard aGuard (maMutex);
711 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
712 if (pDescriptor.get() != nullptr)
714 pDescriptor->maSmallPreview = Image();
715 pDescriptor->maLargePreview = Image();
716 RequestPreview(aToken);
720 Image MasterPageContainer::Implementation::GetPreviewForToken (
721 MasterPageContainer::Token aToken,
722 PreviewSize ePreviewSize)
724 const ::osl::MutexGuard aGuard (maMutex);
726 Image aPreview;
727 PreviewState ePreviewState (GetPreviewState(aToken));
729 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
731 // When the preview is missing but inexpensively creatable then do that
732 // now.
733 if (pDescriptor.get()!=nullptr)
735 if (ePreviewState == PS_CREATABLE)
736 if (UpdateDescriptor(pDescriptor, false,false, true))
737 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
738 ePreviewState = PS_AVAILABLE;
740 switch (ePreviewState)
742 case PS_AVAILABLE:
743 aPreview = pDescriptor->GetPreview(ePreviewSize);
744 break;
746 case PS_PREPARING:
747 aPreview = GetPreviewSubstitution(
748 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
749 ePreviewSize);
750 break;
752 case PS_CREATABLE:
753 aPreview = GetPreviewSubstitution(
754 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
755 ePreviewSize);
756 break;
758 case PS_NOT_AVAILABLE:
759 aPreview = GetPreviewSubstitution(
760 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
761 ePreviewSize);
762 if (ePreviewSize == SMALL)
763 pDescriptor->maSmallPreview = aPreview;
764 else
765 pDescriptor->maLargePreview = aPreview;
766 break;
770 return aPreview;
773 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
774 Token aToken) const
776 const ::osl::MutexGuard aGuard (maMutex);
778 PreviewState eState (PS_NOT_AVAILABLE);
780 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
781 if (pDescriptor.get() != nullptr)
783 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
784 eState = PS_AVAILABLE;
785 else if (pDescriptor->mpPreviewProvider.get() != nullptr)
787 // The preview does not exist but can be created. When that is
788 // not expensive then do it at once.
789 if (mpRequestQueue->HasRequest(aToken))
790 eState = PS_PREPARING;
791 else
792 eState = PS_CREATABLE;
794 else
795 eState = PS_NOT_AVAILABLE;
798 return eState;
801 bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
803 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
804 if (pDescriptor.get() != nullptr)
805 return mpRequestQueue->RequestPreview(pDescriptor);
806 else
807 return false;
810 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel()
812 const ::osl::MutexGuard aGuard (maMutex);
814 if ( ! mxModel.is())
816 // Get the desktop a s service factory.
817 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(
818 ::comphelper::getProcessComponentContext() );
820 // Create a new model.
821 mxModel.set(
822 ::comphelper::getProcessServiceFactory()->createInstance(
823 "com.sun.star.presentation.PresentationDocument"),
824 uno::UNO_QUERY);
826 // Initialize the model.
827 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
828 if (xLoadable.is())
829 xLoadable->initNew();
831 // Use its tunnel to get a pointer to its core implementation.
832 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
833 if (xUnoTunnel.is())
835 mpDocument = reinterpret_cast<SdXImpressDocument*>(
836 xUnoTunnel->getSomething(
837 SdXImpressDocument::getUnoTunnelId()))->GetDoc();
840 // Create a default page.
841 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
842 if (xSlideSupplier.is())
844 uno::Reference<drawing::XDrawPages> xSlides (
845 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
846 if (xSlides.is())
848 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(0));
849 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
850 if (xProperties.is())
851 xProperties->setPropertyValue(
852 "Layout",
853 makeAny(sal_Int16(AUTOLAYOUT_TITLE)));
857 return mxModel;
860 SdDrawDocument* MasterPageContainer::Implementation::GetDocument()
862 GetModel();
863 return mpDocument;
866 Image MasterPageContainer::Implementation::GetPreviewSubstitution (
867 const char* pId,
868 PreviewSize ePreviewSize)
870 const ::osl::MutexGuard aGuard (maMutex);
872 Image aPreview;
874 if (strcmp(pId, STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION) == 0)
876 Image& rPreview (ePreviewSize==SMALL
877 ? maSmallPreviewBeingCreated
878 : maLargePreviewBeingCreated);
879 if (rPreview.GetSizePixel().Width() == 0)
881 rPreview = maPreviewRenderer.RenderSubstitution(
882 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
883 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
885 aPreview = rPreview;
887 else if (strcmp(pId, STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION) == 0)
889 Image& rPreview (ePreviewSize==SMALL
890 ? maSmallPreviewNotAvailable
891 : maLargePreviewNotAvailable);
892 if (rPreview.GetSizePixel().Width() == 0)
894 rPreview = maPreviewRenderer.RenderSubstitution(
895 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
896 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
898 aPreview = rPreview;
901 return aPreview;
904 void MasterPageContainer::Implementation::CleanContainer()
906 // Remove the empty elements at the end of the container. The empty
907 // elements in the middle can not be removed because that would
908 // invalidate the references still held by others.
909 int nIndex (maContainer.size()-1);
910 while (nIndex>=0 && maContainer[nIndex].get()==nullptr)
911 --nIndex;
912 maContainer.resize(++nIndex);
915 void MasterPageContainer::Implementation::FireContainerChange (
916 MasterPageContainerChangeEvent::EventType eType,
917 Token aToken)
919 ::std::vector<Link<MasterPageContainerChangeEvent&,void>> aCopy(maChangeListeners.begin(),maChangeListeners.end());
920 ::std::vector<Link<MasterPageContainerChangeEvent&,void>>::iterator iListener;
921 MasterPageContainerChangeEvent aEvent;
922 aEvent.meEventType = eType;
923 aEvent.maChildToken = aToken;
924 for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
925 iListener->Call(aEvent);
928 bool MasterPageContainer::Implementation::UpdateDescriptor (
929 const SharedMasterPageDescriptor& rpDescriptor,
930 bool bForcePageObject,
931 bool bForcePreview,
932 bool bSendEvents)
934 const ::osl::MutexGuard aGuard (maMutex);
936 // We have to create the page object when the preview provider needs it
937 // and the caller needs the preview.
938 bForcePageObject |= (bForcePreview
939 && rpDescriptor->mpPreviewProvider->NeedsPageObject()
940 && rpDescriptor->mpMasterPage==nullptr);
942 // Define a cost threshold so that an update or page object or preview
943 // that is at least this cost are made at once. Updates with higher cost
944 // are scheduled for later.
945 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
947 // Update the page object (which may be used for the preview update).
948 if (bForcePageObject)
949 GetDocument();
950 int nPageObjectModified (rpDescriptor->UpdatePageObject(
951 (bForcePageObject ? -1 : nCostThreshold),
952 mpDocument));
953 if (nPageObjectModified == 1 && bSendEvents)
954 FireContainerChange(
955 MasterPageContainerChangeEvent::EventType::DATA_CHANGED,
956 rpDescriptor->maToken);
957 if (nPageObjectModified == -1 && bSendEvents)
958 FireContainerChange(
959 MasterPageContainerChangeEvent::EventType::CHILD_REMOVED,
960 rpDescriptor->maToken);
961 if (nPageObjectModified && ! mbFirstPageObjectSeen)
962 UpdatePreviewSizePixel();
964 // Update the preview.
965 bool bPreviewModified (rpDescriptor->UpdatePreview(
966 (bForcePreview ? -1 : nCostThreshold),
967 maSmallPreviewSizePixel,
968 maLargePreviewSizePixel,
969 maPreviewRenderer));
971 if (bPreviewModified && bSendEvents)
972 FireContainerChange(
973 MasterPageContainerChangeEvent::EventType::PREVIEW_CHANGED,
974 rpDescriptor->maToken);
976 return nPageObjectModified || bPreviewModified;
979 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
981 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
983 maContainer[aToken].reset();
987 void MasterPageContainer::Implementation::FillingDone()
989 mpRequestQueue->ProcessAllRequests();
992 } } // end of namespace sd::sidebar
994 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */