bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / sidebar / MasterPageContainer.cxx
blobdd6b65cef5d683cea68abbfe99d61cc73f96b561
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 "MasterPageContainerProviders.hxx"
23 #include "MasterPageDescriptor.hxx"
24 #include "MasterPageContainerFiller.hxx"
25 #include "MasterPageContainerQueue.hxx"
26 #include <TemplateScanner.hxx>
27 #include <PreviewRenderer.hxx>
28 #include <tools/AsynchronousTask.hxx>
29 #include <tools/SdGlobalResourceContainer.hxx>
30 #include <strings.hrc>
31 #include <algorithm>
32 #include <list>
33 #include <memory>
34 #include <set>
36 #include <unomodel.hxx>
37 #include <com/sun/star/frame/Desktop.hpp>
38 #include <com/sun/star/io/XStream.hpp>
39 #include <com/sun/star/io/XInputStream.hpp>
40 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/uno/Reference.hxx>
43 #include <com/sun/star/uno/Any.hxx>
44 #include <com/sun/star/util/XCloseable.hpp>
45 #include <com/sun/star/util/CloseVetoException.hpp>
46 #include <comphelper/processfactory.hxx>
47 #include <sfx2/app.hxx>
48 #include <svx/svdpage.hxx>
49 #include <DrawDocShell.hxx>
50 #include <drawdoc.hxx>
51 #include <sdpage.hxx>
52 #include <svl/itemset.hxx>
53 #include <svl/eitem.hxx>
54 #include <sdresid.hxx>
55 #include <tools/TimerBasedTaskExecution.hxx>
56 #include <pres.hxx>
57 #include <osl/mutex.hxx>
58 #include <osl/getglobalmutex.hxx>
59 #include <xmloff/autolayout.hxx>
60 #include <tools/debug.hxx>
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::uno;
65 namespace {
67 typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
69 } // end of anonymous namespace
71 namespace sd { namespace sidebar {
73 /** Inner implementation class of the MasterPageContainer.
75 class MasterPageContainer::Implementation
76 : public SdGlobalResource,
77 public MasterPageContainerFiller::ContainerAdapter,
78 public MasterPageContainerQueue::ContainerAdapter
80 public:
81 mutable ::osl::Mutex maMutex;
83 static std::weak_ptr<Implementation> mpInstance;
84 MasterPageContainerType maContainer;
86 static std::shared_ptr<Implementation> Instance();
88 void LateInit();
89 void AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink);
90 void RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink);
91 void UpdatePreviewSizePixel();
92 const Size& GetPreviewSizePixel (PreviewSize eSize) const;
94 bool HasToken (Token aToken) const;
95 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
96 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
97 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor) override;
98 void InvalidatePreview (Token aToken);
99 Image GetPreviewForToken (
100 Token aToken,
101 PreviewSize ePreviewSize);
102 PreviewState GetPreviewState (Token aToken) const;
103 bool RequestPreview (Token aToken);
105 Reference<frame::XModel> GetModel();
106 SdDrawDocument* GetDocument();
108 void FireContainerChange (
109 MasterPageContainerChangeEvent::EventType eType,
110 Token aToken);
112 virtual bool UpdateDescriptor (
113 const SharedMasterPageDescriptor& rpDescriptor,
114 bool bForcePageObject,
115 bool bForcePreview,
116 bool bSendEvents) override;
118 void ReleaseDescriptor (Token aToken);
120 /** Called by the MasterPageContainerFiller to notify that all master
121 pages from template documents have been added.
123 virtual void FillingDone() override;
125 private:
126 Implementation();
127 virtual ~Implementation() override;
129 class Deleter { public:
130 void operator() (Implementation* pObject) { delete pObject; }
132 friend class Deleter;
134 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
136 std::unique_ptr<MasterPageContainerQueue> mpRequestQueue;
137 css::uno::Reference<css::frame::XModel> mxModel;
138 SdDrawDocument* mpDocument;
139 PreviewRenderer maPreviewRenderer;
140 /** Remember whether the first page object has already been used to
141 determine the correct size ratio.
143 bool mbFirstPageObjectSeen;
145 // The widths for the previews contain two pixels for the border that is
146 // painted around the preview.
147 static const int SMALL_PREVIEW_WIDTH = 72 + 2;
148 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
150 /** This substition of page preview shows "Preparing preview" and is
151 shown as long as the actual previews are not being present.
153 Image maLargePreviewBeingCreated;
154 Image maSmallPreviewBeingCreated;
156 /** This substition of page preview is shown when a preview can not be
157 created and thus is not available.
159 Image maLargePreviewNotAvailable;
160 Image maSmallPreviewNotAvailable;
162 ::std::vector<Link<MasterPageContainerChangeEvent&,void>> maChangeListeners;
164 // We have to remember the tasks for initialization and filling in case
165 // a MasterPageContainer object is destroyed before these tasks have
166 // been completed.
167 std::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
169 Size maSmallPreviewSizePixel;
170 Size maLargePreviewSizePixel;
172 Image GetPreviewSubstitution(const char* pId, PreviewSize ePreviewSize);
174 void CleanContainer();
177 //===== MasterPageContainer ===================================================
179 std::weak_ptr<MasterPageContainer::Implementation>
180 MasterPageContainer::Implementation::mpInstance;
182 std::shared_ptr<MasterPageContainer::Implementation>
183 MasterPageContainer::Implementation::Instance()
185 std::shared_ptr<MasterPageContainer::Implementation> pInstance;
187 if (Implementation::mpInstance.expired())
189 ::osl::GetGlobalMutex aMutexFunctor;
190 ::osl::MutexGuard aGuard (aMutexFunctor());
191 if (Implementation::mpInstance.expired())
193 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
194 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
195 new MasterPageContainer::Implementation(),
196 MasterPageContainer::Implementation::Deleter());
197 SdGlobalResourceContainer::Instance().AddResource(pInstance);
198 Implementation::mpInstance = pInstance;
200 else
201 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
202 Implementation::mpInstance);
204 else
206 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
207 pInstance = std::shared_ptr<MasterPageContainer::Implementation>(
208 Implementation::mpInstance);
211 DBG_ASSERT(pInstance != nullptr,
212 "MasterPageContainer::Implementation::Instance(): instance is nullptr");
213 return pInstance;
216 MasterPageContainer::MasterPageContainer()
217 : mpImpl(Implementation::Instance()),
218 mePreviewSize(SMALL)
220 mpImpl->LateInit();
223 MasterPageContainer::~MasterPageContainer()
227 void MasterPageContainer::AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
229 mpImpl->AddChangeListener(rLink);
232 void MasterPageContainer::RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
234 mpImpl->RemoveChangeListener(rLink);
237 void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
239 mePreviewSize = eSize;
240 mpImpl->FireContainerChange(
241 MasterPageContainerChangeEvent::EventType::SIZE_CHANGED,
242 NIL_TOKEN);
245 Size const & MasterPageContainer::GetPreviewSizePixel() const
247 return mpImpl->GetPreviewSizePixel(mePreviewSize);
250 MasterPageContainer::Token MasterPageContainer::PutMasterPage (
251 const std::shared_ptr<MasterPageDescriptor>& rDescriptor)
253 return mpImpl->PutMasterPage(rDescriptor);
256 void MasterPageContainer::AcquireToken (Token aToken)
258 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
259 if (pDescriptor.get() != nullptr)
261 ++pDescriptor->mnUseCount;
265 void MasterPageContainer::ReleaseToken (Token aToken)
267 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
268 if (pDescriptor.get() == nullptr)
269 return;
271 OSL_ASSERT(pDescriptor->mnUseCount>0);
272 --pDescriptor->mnUseCount;
273 if (pDescriptor->mnUseCount > 0)
274 return;
276 switch (pDescriptor->meOrigin)
278 case DEFAULT:
279 case TEMPLATE:
280 default:
281 break;
283 case MASTERPAGE:
284 mpImpl->ReleaseDescriptor(aToken);
285 break;
289 int MasterPageContainer::GetTokenCount() const
291 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
293 return mpImpl->maContainer.size();
296 bool MasterPageContainer::HasToken (Token aToken) const
298 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
300 return mpImpl->HasToken(aToken);
303 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
305 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
307 Token aResult (NIL_TOKEN);
308 if (HasToken(nIndex))
309 aResult = mpImpl->maContainer[nIndex]->maToken;
310 return aResult;
313 MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
314 const OUString& sURL)
316 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
318 Token aResult (NIL_TOKEN);
319 if (!sURL.isEmpty())
321 MasterPageContainerType::iterator iEntry (
322 ::std::find_if (
323 mpImpl->maContainer.begin(),
324 mpImpl->maContainer.end(),
325 MasterPageDescriptor::URLComparator(sURL)));
326 if (iEntry != mpImpl->maContainer.end())
327 aResult = (*iEntry)->maToken;
329 return aResult;
332 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const OUString& sStyleName)
334 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
336 Token aResult (NIL_TOKEN);
337 if (!sStyleName.isEmpty())
339 MasterPageContainerType::iterator iEntry (
340 ::std::find_if (
341 mpImpl->maContainer.begin(),
342 mpImpl->maContainer.end(),
343 MasterPageDescriptor::StyleNameComparator(sStyleName)));
344 if (iEntry != mpImpl->maContainer.end())
345 aResult = (*iEntry)->maToken;
347 return aResult;
350 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
351 const SdPage* pPage)
353 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
355 Token aResult (NIL_TOKEN);
356 if (pPage != nullptr)
358 MasterPageContainerType::iterator iEntry (
359 ::std::find_if (
360 mpImpl->maContainer.begin(),
361 mpImpl->maContainer.end(),
362 MasterPageDescriptor::PageObjectComparator(pPage)));
363 if (iEntry != mpImpl->maContainer.end())
364 aResult = (*iEntry)->maToken;
366 return aResult;
369 OUString MasterPageContainer::GetURLForToken (
370 MasterPageContainer::Token aToken)
372 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
374 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
375 if (pDescriptor.get() != nullptr)
376 return pDescriptor->msURL;
377 else
378 return OUString();
381 OUString MasterPageContainer::GetPageNameForToken (
382 MasterPageContainer::Token aToken)
384 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
386 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
387 if (pDescriptor.get() != nullptr)
388 return pDescriptor->msPageName;
389 else
390 return OUString();
393 OUString MasterPageContainer::GetStyleNameForToken (
394 MasterPageContainer::Token aToken)
396 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
398 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
399 if (pDescriptor.get() != nullptr)
400 return pDescriptor->msStyleName;
401 else
402 return OUString();
405 SdPage* MasterPageContainer::GetPageObjectForToken (
406 MasterPageContainer::Token aToken,
407 bool bLoad)
409 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
411 SdPage* pPageObject = nullptr;
412 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
413 if (pDescriptor.get() != nullptr)
415 pPageObject = pDescriptor->mpMasterPage;
416 if (pPageObject == nullptr)
418 // The page object is not (yet) present. Call
419 // UpdateDescriptor() to trigger the PageObjectProvider() to
420 // provide it.
421 if (bLoad)
422 mpImpl->GetModel();
423 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
424 pPageObject = pDescriptor->mpMasterPage;
427 return pPageObject;
430 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken)
432 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
434 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
435 if (pDescriptor.get() != nullptr)
436 return pDescriptor->meOrigin;
437 else
438 return UNKNOWN;
441 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
443 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
445 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
446 if (pDescriptor.get() != nullptr)
447 return pDescriptor->mnTemplateIndex;
448 else
449 return -1;
452 std::shared_ptr<MasterPageDescriptor> MasterPageContainer::GetDescriptorForToken (
453 MasterPageContainer::Token aToken)
455 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
457 return mpImpl->GetDescriptor(aToken);
460 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
462 mpImpl->InvalidatePreview(aToken);
465 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
467 return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
470 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
472 return mpImpl->GetPreviewState(aToken);
475 bool MasterPageContainer::RequestPreview (Token aToken)
477 return mpImpl->RequestPreview(aToken);
480 //==== Implementation ================================================
482 MasterPageContainer::Implementation::Implementation()
483 : maMutex(),
484 maContainer(),
485 meInitializationState(NOT_INITIALIZED),
486 mpDocument(nullptr),
487 maPreviewRenderer(),
488 mbFirstPageObjectSeen(false),
489 maLargePreviewBeingCreated(),
490 maSmallPreviewBeingCreated(),
491 maLargePreviewNotAvailable(),
492 maSmallPreviewNotAvailable(),
493 maChangeListeners(),
494 maSmallPreviewSizePixel(),
495 maLargePreviewSizePixel()
497 UpdatePreviewSizePixel();
500 MasterPageContainer::Implementation::~Implementation()
502 // When the initializer or filler tasks are still running then we have
503 // to stop them now in order to prevent them from calling us back.
504 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
506 mpRequestQueue.reset();
508 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
509 if (xCloseable.is())
513 xCloseable->close(true);
515 catch (const css::util::CloseVetoException&)
519 mxModel = nullptr;
522 void MasterPageContainer::Implementation::LateInit()
524 const ::osl::MutexGuard aGuard (maMutex);
526 if (meInitializationState != NOT_INITIALIZED)
527 return;
529 meInitializationState = INITIALIZING;
531 OSL_ASSERT(Instance().get()==this);
532 mpRequestQueue.reset(MasterPageContainerQueue::Create(
533 std::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
535 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
536 std::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
538 50);
540 meInitializationState = INITIALIZED;
543 void MasterPageContainer::Implementation::AddChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
545 const ::osl::MutexGuard aGuard (maMutex);
547 ::std::vector<Link<MasterPageContainerChangeEvent&,void>>::iterator iListener (
548 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
549 if (iListener == maChangeListeners.end())
550 maChangeListeners.push_back(rLink);
554 void MasterPageContainer::Implementation::RemoveChangeListener (const Link<MasterPageContainerChangeEvent&,void>& rLink)
556 const ::osl::MutexGuard aGuard (maMutex);
558 ::std::vector<Link<MasterPageContainerChangeEvent&,void>>::iterator iListener (
559 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
560 if (iListener != maChangeListeners.end())
561 maChangeListeners.erase(iListener);
564 void MasterPageContainer::Implementation::UpdatePreviewSizePixel()
566 const ::osl::MutexGuard aGuard (maMutex);
568 // The default aspect ratio is 4:3
569 int nWidth (4);
570 int nHeight (3);
572 // Search for the first entry with an existing master page.
573 auto iDescriptor = std::find_if(maContainer.begin(), maContainer.end(),
574 [](const SharedMasterPageDescriptor& rxDescriptor) {
575 return rxDescriptor != nullptr && rxDescriptor->mpMasterPage != nullptr;
577 if (iDescriptor != maContainer.end())
579 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
580 OSL_ASSERT(aPageSize.Width() > 0 && aPageSize.Height() > 0);
581 if (aPageSize.Width() > 0)
582 nWidth = aPageSize.Width();
583 if (aPageSize.Height() > 0)
584 nHeight = aPageSize.Height();
585 mbFirstPageObjectSeen = true;
588 maSmallPreviewSizePixel.setWidth( SMALL_PREVIEW_WIDTH );
589 maLargePreviewSizePixel.setWidth( LARGE_PREVIEW_WIDTH );
591 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
592 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
594 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
595 || nNewLargeHeight!=maLargePreviewSizePixel.Height())
597 maSmallPreviewSizePixel.setHeight( nNewSmallHeight );
598 maLargePreviewSizePixel.setHeight( nNewLargeHeight );
599 FireContainerChange(
600 MasterPageContainerChangeEvent::EventType::SIZE_CHANGED,
601 NIL_TOKEN);
605 const Size& MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
607 if (eSize == SMALL)
608 return maSmallPreviewSizePixel;
609 else
610 return maLargePreviewSizePixel;
613 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
614 const SharedMasterPageDescriptor& rpDescriptor)
616 const ::osl::MutexGuard aGuard (maMutex);
618 Token aResult (NIL_TOKEN);
620 // Get page object and preview when that is inexpensive.
621 UpdateDescriptor(rpDescriptor,false,false, false);
623 // Look up the new MasterPageDescriptor and either insert it or update
624 // an already existing one.
625 MasterPageContainerType::iterator aEntry (
626 ::std::find_if (
627 maContainer.begin(),
628 maContainer.end(),
629 MasterPageDescriptor::AllComparator(rpDescriptor)));
630 if (aEntry == maContainer.end())
632 // Insert a new MasterPageDescriptor.
633 bool bIgnore(rpDescriptor->mpPageObjectProvider == nullptr
634 && rpDescriptor->msURL.isEmpty());
636 if ( ! bIgnore)
638 CleanContainer();
640 aResult = maContainer.size();
641 rpDescriptor->SetToken(aResult);
643 // Templates are precious, i.e. we lock them so that they will
644 // not be destroyed when (temporarily) no one references them.
645 // They will only be deleted when the container is destroyed.
646 switch (rpDescriptor->meOrigin)
648 case TEMPLATE:
649 case DEFAULT:
650 ++rpDescriptor->mnUseCount;
651 break;
653 default:
654 break;
657 maContainer.push_back(rpDescriptor);
658 aEntry = maContainer.end()-1;
660 FireContainerChange(MasterPageContainerChangeEvent::EventType::CHILD_ADDED,aResult);
663 else
665 // Update an existing MasterPageDescriptor.
666 aResult = (*aEntry)->maToken;
667 std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
668 (*aEntry)->Update(*rpDescriptor));
669 if (pEventTypes != nullptr && !pEventTypes->empty())
671 // One or more aspects of the descriptor have changed. Send
672 // appropriate events to the listeners.
673 UpdateDescriptor(*aEntry,false,false, true);
675 for (auto& rEventType : *pEventTypes)
677 FireContainerChange(rEventType, (*aEntry)->maToken);
682 return aResult;
685 bool MasterPageContainer::Implementation::HasToken (Token aToken) const
687 return aToken>=0
688 && static_cast<unsigned>(aToken)<maContainer.size()
689 && maContainer[aToken].get()!=nullptr;
692 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
693 Token aToken) const
695 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
696 return maContainer[aToken];
697 else
698 return SharedMasterPageDescriptor();
701 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
703 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
704 return maContainer[aToken];
705 else
706 return SharedMasterPageDescriptor();
709 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
711 const ::osl::MutexGuard aGuard (maMutex);
713 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
714 if (pDescriptor.get() != nullptr)
716 pDescriptor->maSmallPreview = Image();
717 pDescriptor->maLargePreview = Image();
718 RequestPreview(aToken);
722 Image MasterPageContainer::Implementation::GetPreviewForToken (
723 MasterPageContainer::Token aToken,
724 PreviewSize ePreviewSize)
726 const ::osl::MutexGuard aGuard (maMutex);
728 Image aPreview;
729 PreviewState ePreviewState (GetPreviewState(aToken));
731 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
733 // When the preview is missing but inexpensively creatable then do that
734 // now.
735 if (pDescriptor.get()!=nullptr)
737 if (ePreviewState == PS_CREATABLE)
738 if (UpdateDescriptor(pDescriptor, false,false, true))
739 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
740 ePreviewState = PS_AVAILABLE;
742 switch (ePreviewState)
744 case PS_AVAILABLE:
745 aPreview = pDescriptor->GetPreview(ePreviewSize);
746 break;
748 case PS_PREPARING:
749 aPreview = GetPreviewSubstitution(
750 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
751 ePreviewSize);
752 break;
754 case PS_CREATABLE:
755 aPreview = GetPreviewSubstitution(
756 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
757 ePreviewSize);
758 break;
760 case PS_NOT_AVAILABLE:
761 aPreview = GetPreviewSubstitution(
762 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
763 ePreviewSize);
764 if (ePreviewSize == SMALL)
765 pDescriptor->maSmallPreview = aPreview;
766 else
767 pDescriptor->maLargePreview = aPreview;
768 break;
772 return aPreview;
775 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
776 Token aToken) const
778 const ::osl::MutexGuard aGuard (maMutex);
780 PreviewState eState (PS_NOT_AVAILABLE);
782 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
783 if (pDescriptor.get() != nullptr)
785 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
786 eState = PS_AVAILABLE;
787 else if (pDescriptor->mpPreviewProvider != nullptr)
789 // The preview does not exist but can be created. When that is
790 // not expensive then do it at once.
791 if (mpRequestQueue->HasRequest(aToken))
792 eState = PS_PREPARING;
793 else
794 eState = PS_CREATABLE;
796 else
797 eState = PS_NOT_AVAILABLE;
800 return eState;
803 bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
805 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
806 if (pDescriptor.get() != nullptr)
807 return mpRequestQueue->RequestPreview(pDescriptor);
808 else
809 return false;
812 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel()
814 const ::osl::MutexGuard aGuard (maMutex);
816 if ( ! mxModel.is())
818 // Get the desktop a s service factory.
819 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(
820 ::comphelper::getProcessComponentContext() );
822 // Create a new model.
823 mxModel.set(
824 ::comphelper::getProcessServiceFactory()->createInstance(
825 "com.sun.star.presentation.PresentationDocument"),
826 uno::UNO_QUERY);
828 // Initialize the model.
829 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
830 if (xLoadable.is())
831 xLoadable->initNew();
833 // Use its tunnel to get a pointer to its core implementation.
834 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
835 if (xUnoTunnel.is())
837 mpDocument = reinterpret_cast<SdXImpressDocument*>(
838 xUnoTunnel->getSomething(
839 SdXImpressDocument::getUnoTunnelId()))->GetDoc();
842 // Create a default page.
843 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
844 if (xSlideSupplier.is())
846 uno::Reference<drawing::XDrawPages> xSlides (
847 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
848 if (xSlides.is())
850 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(0));
851 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
852 if (xProperties.is())
853 xProperties->setPropertyValue(
854 "Layout",
855 makeAny(sal_Int16(AUTOLAYOUT_TITLE)));
859 return mxModel;
862 SdDrawDocument* MasterPageContainer::Implementation::GetDocument()
864 GetModel();
865 return mpDocument;
868 Image MasterPageContainer::Implementation::GetPreviewSubstitution (
869 const char* pId,
870 PreviewSize ePreviewSize)
872 const ::osl::MutexGuard aGuard (maMutex);
874 Image aPreview;
876 if (strcmp(pId, STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION) == 0)
878 Image& rPreview (ePreviewSize==SMALL
879 ? maSmallPreviewBeingCreated
880 : maLargePreviewBeingCreated);
881 if (rPreview.GetSizePixel().Width() == 0)
883 rPreview = maPreviewRenderer.RenderSubstitution(
884 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
885 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
887 aPreview = rPreview;
889 else if (strcmp(pId, STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION) == 0)
891 Image& rPreview (ePreviewSize==SMALL
892 ? maSmallPreviewNotAvailable
893 : maLargePreviewNotAvailable);
894 if (rPreview.GetSizePixel().Width() == 0)
896 rPreview = maPreviewRenderer.RenderSubstitution(
897 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
898 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
900 aPreview = rPreview;
903 return aPreview;
906 void MasterPageContainer::Implementation::CleanContainer()
908 // Remove the empty elements at the end of the container. The empty
909 // elements in the middle can not be removed because that would
910 // invalidate the references still held by others.
911 int nIndex (maContainer.size()-1);
912 while (nIndex>=0 && maContainer[nIndex].get()==nullptr)
913 --nIndex;
914 maContainer.resize(++nIndex);
917 void MasterPageContainer::Implementation::FireContainerChange (
918 MasterPageContainerChangeEvent::EventType eType,
919 Token aToken)
921 ::std::vector<Link<MasterPageContainerChangeEvent&,void>> aCopy(maChangeListeners);
922 MasterPageContainerChangeEvent aEvent;
923 aEvent.meEventType = eType;
924 aEvent.maChildToken = aToken;
925 for (auto& rListener : aCopy)
926 rListener.Call(aEvent);
929 bool MasterPageContainer::Implementation::UpdateDescriptor (
930 const SharedMasterPageDescriptor& rpDescriptor,
931 bool bForcePageObject,
932 bool bForcePreview,
933 bool bSendEvents)
935 const ::osl::MutexGuard aGuard (maMutex);
937 // We have to create the page object when the preview provider needs it
938 // and the caller needs the preview.
939 bForcePageObject |= (bForcePreview
940 && rpDescriptor->mpPreviewProvider->NeedsPageObject()
941 && rpDescriptor->mpMasterPage==nullptr);
943 // Define a cost threshold so that an update or page object or preview
944 // that is at least this cost are made at once. Updates with higher cost
945 // are scheduled for later.
946 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
948 // Update the page object (which may be used for the preview update).
949 if (bForcePageObject)
950 GetDocument();
951 int nPageObjectModified (rpDescriptor->UpdatePageObject(
952 (bForcePageObject ? -1 : nCostThreshold),
953 mpDocument));
954 if (nPageObjectModified == 1 && bSendEvents)
955 FireContainerChange(
956 MasterPageContainerChangeEvent::EventType::DATA_CHANGED,
957 rpDescriptor->maToken);
958 if (nPageObjectModified == -1 && bSendEvents)
959 FireContainerChange(
960 MasterPageContainerChangeEvent::EventType::CHILD_REMOVED,
961 rpDescriptor->maToken);
962 if (nPageObjectModified && ! mbFirstPageObjectSeen)
963 UpdatePreviewSizePixel();
965 // Update the preview.
966 bool bPreviewModified (rpDescriptor->UpdatePreview(
967 (bForcePreview ? -1 : nCostThreshold),
968 maSmallPreviewSizePixel,
969 maLargePreviewSizePixel,
970 maPreviewRenderer));
972 if (bPreviewModified && bSendEvents)
973 FireContainerChange(
974 MasterPageContainerChangeEvent::EventType::PREVIEW_CHANGED,
975 rpDescriptor->maToken);
977 return nPageObjectModified || bPreviewModified;
980 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
982 if (aToken>=0 && static_cast<unsigned>(aToken)<maContainer.size())
984 maContainer[aToken].reset();
988 void MasterPageContainer::Implementation::FillingDone()
990 mpRequestQueue->ProcessAllRequests();
993 } } // end of namespace sd::sidebar
995 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */