1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
52 #include <svl/itemset.hxx>
53 #include <svl/eitem.hxx>
54 #include <sdresid.hxx>
55 #include <tools/TimerBasedTaskExecution.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
;
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
81 mutable ::osl::Mutex maMutex
;
83 static std::weak_ptr
<Implementation
> mpInstance
;
84 MasterPageContainerType maContainer
;
86 static std::shared_ptr
<Implementation
> Instance();
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 (
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
,
112 virtual bool UpdateDescriptor (
113 const SharedMasterPageDescriptor
& rpDescriptor
,
114 bool bForcePageObject
,
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
;
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
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
;
201 pInstance
= std::shared_ptr
<MasterPageContainer::Implementation
>(
202 Implementation::mpInstance
);
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");
216 MasterPageContainer::MasterPageContainer()
217 : mpImpl(Implementation::Instance()),
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
,
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)
271 OSL_ASSERT(pDescriptor
->mnUseCount
>0);
272 --pDescriptor
->mnUseCount
;
273 if (pDescriptor
->mnUseCount
> 0)
276 switch (pDescriptor
->meOrigin
)
284 mpImpl
->ReleaseDescriptor(aToken
);
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
;
313 MasterPageContainer::Token
MasterPageContainer::GetTokenForURL (
314 const OUString
& sURL
)
316 const ::osl::MutexGuard
aGuard (mpImpl
->maMutex
);
318 Token
aResult (NIL_TOKEN
);
321 MasterPageContainerType::iterator
iEntry (
323 mpImpl
->maContainer
.begin(),
324 mpImpl
->maContainer
.end(),
325 MasterPageDescriptor::URLComparator(sURL
)));
326 if (iEntry
!= mpImpl
->maContainer
.end())
327 aResult
= (*iEntry
)->maToken
;
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 (
341 mpImpl
->maContainer
.begin(),
342 mpImpl
->maContainer
.end(),
343 MasterPageDescriptor::StyleNameComparator(sStyleName
)));
344 if (iEntry
!= mpImpl
->maContainer
.end())
345 aResult
= (*iEntry
)->maToken
;
350 MasterPageContainer::Token
MasterPageContainer::GetTokenForPageObject (
353 const ::osl::MutexGuard
aGuard (mpImpl
->maMutex
);
355 Token
aResult (NIL_TOKEN
);
356 if (pPage
!= nullptr)
358 MasterPageContainerType::iterator
iEntry (
360 mpImpl
->maContainer
.begin(),
361 mpImpl
->maContainer
.end(),
362 MasterPageDescriptor::PageObjectComparator(pPage
)));
363 if (iEntry
!= mpImpl
->maContainer
.end())
364 aResult
= (*iEntry
)->maToken
;
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
;
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
;
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
;
405 SdPage
* MasterPageContainer::GetPageObjectForToken (
406 MasterPageContainer::Token aToken
,
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
423 if (mpImpl
->UpdateDescriptor(pDescriptor
,bLoad
,false, true))
424 pPageObject
= pDescriptor
->mpMasterPage
;
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
;
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
;
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()
485 meInitializationState(NOT_INITIALIZED
),
488 mbFirstPageObjectSeen(false),
489 maLargePreviewBeingCreated(),
490 maSmallPreviewBeingCreated(),
491 maLargePreviewNotAvailable(),
492 maSmallPreviewNotAvailable(),
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
);
513 xCloseable
->close(true);
515 catch (const css::util::CloseVetoException
&)
522 void MasterPageContainer::Implementation::LateInit()
524 const ::osl::MutexGuard
aGuard (maMutex
);
526 if (meInitializationState
!= NOT_INITIALIZED
)
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)),
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
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
);
600 MasterPageContainerChangeEvent::EventType::SIZE_CHANGED
,
605 const Size
& MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize
) const
608 return maSmallPreviewSizePixel
;
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 (
629 MasterPageDescriptor::AllComparator(rpDescriptor
)));
630 if (aEntry
== maContainer
.end())
632 // Insert a new MasterPageDescriptor.
633 bool bIgnore(rpDescriptor
->mpPageObjectProvider
== nullptr
634 && rpDescriptor
->msURL
.isEmpty());
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
)
650 ++rpDescriptor
->mnUseCount
;
657 maContainer
.push_back(rpDescriptor
);
658 aEntry
= maContainer
.end()-1;
660 FireContainerChange(MasterPageContainerChangeEvent::EventType::CHILD_ADDED
,aResult
);
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
);
685 bool MasterPageContainer::Implementation::HasToken (Token aToken
) const
688 && static_cast<unsigned>(aToken
)<maContainer
.size()
689 && maContainer
[aToken
].get()!=nullptr;
692 const SharedMasterPageDescriptor
MasterPageContainer::Implementation::GetDescriptor (
695 if (aToken
>=0 && static_cast<unsigned>(aToken
)<maContainer
.size())
696 return maContainer
[aToken
];
698 return SharedMasterPageDescriptor();
701 SharedMasterPageDescriptor
MasterPageContainer::Implementation::GetDescriptor (Token aToken
)
703 if (aToken
>=0 && static_cast<unsigned>(aToken
)<maContainer
.size())
704 return maContainer
[aToken
];
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
);
729 PreviewState
ePreviewState (GetPreviewState(aToken
));
731 SharedMasterPageDescriptor pDescriptor
= GetDescriptor(aToken
);
733 // When the preview is missing but inexpensively creatable then do that
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
)
745 aPreview
= pDescriptor
->GetPreview(ePreviewSize
);
749 aPreview
= GetPreviewSubstitution(
750 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION
,
755 aPreview
= GetPreviewSubstitution(
756 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION
,
760 case PS_NOT_AVAILABLE
:
761 aPreview
= GetPreviewSubstitution(
762 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION
,
764 if (ePreviewSize
== SMALL
)
765 pDescriptor
->maSmallPreview
= aPreview
;
767 pDescriptor
->maLargePreview
= aPreview
;
775 MasterPageContainer::PreviewState
MasterPageContainer::Implementation::GetPreviewState (
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
;
794 eState
= PS_CREATABLE
;
797 eState
= PS_NOT_AVAILABLE
;
803 bool MasterPageContainer::Implementation::RequestPreview (Token aToken
)
805 SharedMasterPageDescriptor pDescriptor
= GetDescriptor(aToken
);
806 if (pDescriptor
.get() != nullptr)
807 return mpRequestQueue
->RequestPreview(pDescriptor
);
812 Reference
<frame::XModel
> MasterPageContainer::Implementation::GetModel()
814 const ::osl::MutexGuard
aGuard (maMutex
);
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.
824 ::comphelper::getProcessServiceFactory()->createInstance(
825 "com.sun.star.presentation.PresentationDocument"),
828 // Initialize the model.
829 uno::Reference
<frame::XLoadable
> xLoadable (mxModel
,uno::UNO_QUERY
);
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
);
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
);
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(
855 makeAny(sal_Int16(AUTOLAYOUT_TITLE
)));
862 SdDrawDocument
* MasterPageContainer::Implementation::GetDocument()
868 Image
MasterPageContainer::Implementation::GetPreviewSubstitution (
870 PreviewSize ePreviewSize
)
872 const ::osl::MutexGuard
aGuard (maMutex
);
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
));
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
));
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)
914 maContainer
.resize(++nIndex
);
917 void MasterPageContainer::Implementation::FireContainerChange (
918 MasterPageContainerChangeEvent::EventType eType
,
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
,
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
)
951 int nPageObjectModified (rpDescriptor
->UpdatePageObject(
952 (bForcePageObject
? -1 : nCostThreshold
),
954 if (nPageObjectModified
== 1 && bSendEvents
)
956 MasterPageContainerChangeEvent::EventType::DATA_CHANGED
,
957 rpDescriptor
->maToken
);
958 if (nPageObjectModified
== -1 && bSendEvents
)
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
,
972 if (bPreviewModified
&& bSendEvents
)
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: */