1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include "precompiled_sd.hxx"
23
24 #include "MasterPageContainer.hxx"
25
26 #include "MasterPageDescriptor.hxx"
27 #include "MasterPageContainerFiller.hxx"
28 #include "MasterPageContainerQueue.hxx"
29 #include "TemplateScanner.hxx"
30 #include "tools/AsynchronousTask.hxx"
31 #include "strings.hrc"
32 #include <algorithm>
33 #include <list>
34 #include <set>
35
36 #include "unomodel.hxx"
37 #include <com/sun/star/frame/XComponentLoader.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/uno/Sequence.hxx>
45 #include <com/sun/star/util/XCloseable.hpp>
46 #include <comphelper/processfactory.hxx>
47 #include <tools/urlobj.hxx>
48 #include <sfx2/app.hxx>
49 #include <svx/svdpage.hxx>
50 #include "DrawDocShell.hxx"
51 #include "drawdoc.hxx"
52 #include "sdpage.hxx"
53 #include <svl/itemset.hxx>
54 #include <svl/eitem.hxx>
55 #include "sdresid.hxx"
56 #include "tools/TimerBasedTaskExecution.hxx"
57 #include "pres.hxx"
58 #include <osl/mutex.hxx>
59 #include <boost/weak_ptr.hpp>
60
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::uno;
63
64 namespace {
65
66 typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
67
68 } // end of anonymous namespace
69
70
71 namespace sd { namespace sidebar {
72
73
74 /** Inner implementation class of the MasterPageContainer.
75 */
76 class MasterPageContainer::Implementation
77 : public SdGlobalResource,
78 public MasterPageContainerFiller::ContainerAdapter,
79 public MasterPageContainerQueue::ContainerAdapter
80 {
81 public:
82 mutable ::osl::Mutex maMutex;
83
84 static ::boost::weak_ptr<Implementation> mpInstance;
85 MasterPageContainerType maContainer;
86
87 static ::boost::shared_ptr<Implementation> Instance (void);
88
89 void LateInit (void);
90 void AddChangeListener (const Link& rLink);
91 void RemoveChangeListener (const Link& rLink);
92 void UpdatePreviewSizePixel (void);
93 Size GetPreviewSizePixel (PreviewSize eSize) const;
94
95 bool HasToken (Token aToken) const;
96 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
97 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
98 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor);
99 void InvalidatePreview (Token aToken);
100 Image GetPreviewForToken (
101 Token aToken,
102 PreviewSize ePreviewSize);
103 PreviewState GetPreviewState (Token aToken) const;
104 bool RequestPreview (Token aToken);
105
106 Reference<frame::XModel> GetModel (void);
107 SdDrawDocument* GetDocument (void);
108
109 void FireContainerChange (
110 MasterPageContainerChangeEvent::EventType eType,
111 Token aToken,
112 bool bNotifyAsynchronously = false);
113
114 virtual bool UpdateDescriptor (
115 const SharedMasterPageDescriptor& rpDescriptor,
116 bool bForcePageObject,
117 bool bForcePreview,
118 bool bSendEvents);
119
120 void ReleaseDescriptor (Token aToken);
121
122 /** Called by the MasterPageContainerFiller to notify that all master
123 pages from template documents have been added.
124 */
125 virtual void FillingDone (void);
126
127 private:
128 Implementation (void);
129 virtual ~Implementation (void);
130
131 class Deleter { public:
operator ()(Implementation * pObject)132 void operator() (Implementation* pObject) { delete pObject; }
133 };
134 friend class Deleter;
135
136 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
137
138 ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue;
139 ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> mxModel;
140 SdDrawDocument* mpDocument;
141 PreviewRenderer maPreviewRenderer;
142 /** Remember whether the first page object has already been used to
143 determine the correct size ratio.
144 */
145 bool mbFirstPageObjectSeen;
146
147 // The widths for the previews contain two pixels for the border that is
148 // painted around the preview.
149 static const int SMALL_PREVIEW_WIDTH = 72 + 2;
150 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
151
152 /** This substition of page preview shows "Preparing preview" and is
153 shown as long as the actual previews are not being present.
154 */
155 Image maLargePreviewBeingCreated;
156 Image maSmallPreviewBeingCreated;
157
158 /** This substition of page preview is shown when a preview can not be
159 created and thus is not available.
160 */
161 Image maLargePreviewNotAvailable;
162 Image maSmallPreviewNotAvailable;
163
164 ::std::vector<Link> maChangeListeners;
165
166 // We have to remember the tasks for initialization and filling in case
167 // a MasterPageContainer object is destroyed before these tasks have
168 // been completed.
169 ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
170
171 Size maSmallPreviewSizePixel;
172 Size maLargePreviewSizePixel;
173 bool mbPageRatioKnown;
174
175 bool mbContainerCleaningPending;
176
177 typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData;
178 DECL_LINK(AsynchronousNotifyCallback, EventData*);
179 ::sd::DrawDocShell* LoadDocument (
180 const String& sFileName,
181 SfxObjectShellLock& rxDocumentShell);
182
183 Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize);
184
185 void CleanContainer (void);
186 };
187
188
189
190
191 //===== MasterPageContainer ===================================================
192
193 ::boost::weak_ptr<MasterPageContainer::Implementation>
194 MasterPageContainer::Implementation::mpInstance;
195 static const MasterPageContainer::Token NIL_TOKEN (-1);
196
197
198
199
200 ::boost::shared_ptr<MasterPageContainer::Implementation>
Instance(void)201 MasterPageContainer::Implementation::Instance (void)
202 {
203 ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance;
204
205 if (Implementation::mpInstance.expired())
206 {
207 ::osl::GetGlobalMutex aMutexFunctor;
208 ::osl::MutexGuard aGuard (aMutexFunctor());
209 if (Implementation::mpInstance.expired())
210 {
211 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
212 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
213 new MasterPageContainer::Implementation(),
214 MasterPageContainer::Implementation::Deleter());
215 SdGlobalResourceContainer::Instance().AddResource(pInstance);
216 Implementation::mpInstance = pInstance;
217 }
218 else
219 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
220 Implementation::mpInstance);
221 }
222 else
223 {
224 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
225 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
226 Implementation::mpInstance);
227 }
228
229 DBG_ASSERT (pInstance.get()!=NULL,
230 "MasterPageContainer::Implementation::Instance(): instance is NULL");
231 return pInstance;
232 }
233
234
235
236
MasterPageContainer(void)237 MasterPageContainer::MasterPageContainer (void)
238 : mpImpl(Implementation::Instance()),
239 mePreviewSize(SMALL)
240 {
241 mpImpl->LateInit();
242 }
243
244
245
246
~MasterPageContainer(void)247 MasterPageContainer::~MasterPageContainer (void)
248 {
249 }
250
251
252
253
AddChangeListener(const Link & rLink)254 void MasterPageContainer::AddChangeListener (const Link& rLink)
255 {
256 mpImpl->AddChangeListener(rLink);
257 }
258
259
260
261
RemoveChangeListener(const Link & rLink)262 void MasterPageContainer::RemoveChangeListener (const Link& rLink)
263 {
264 mpImpl->RemoveChangeListener(rLink);
265 }
266
267
268
269
SetPreviewSize(PreviewSize eSize)270 void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
271 {
272 mePreviewSize = eSize;
273 mpImpl->FireContainerChange(
274 MasterPageContainerChangeEvent::SIZE_CHANGED,
275 NIL_TOKEN);
276 }
277
278
279
280
GetPreviewSize(void) const281 MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const
282 {
283 return mePreviewSize;
284 }
285
286
287
288
GetPreviewSizePixel(void) const289 Size MasterPageContainer::GetPreviewSizePixel (void) const
290 {
291 return mpImpl->GetPreviewSizePixel(mePreviewSize);
292 }
293
294
295
296
PutMasterPage(const SharedMasterPageDescriptor & rDescriptor)297 MasterPageContainer::Token MasterPageContainer::PutMasterPage (
298 const SharedMasterPageDescriptor& rDescriptor)
299 {
300 return mpImpl->PutMasterPage(rDescriptor);
301 }
302
303
304
305
AcquireToken(Token aToken)306 void MasterPageContainer::AcquireToken (Token aToken)
307 {
308 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
309 if (pDescriptor.get() != NULL)
310 {
311 ++pDescriptor->mnUseCount;
312 }
313 }
314
315
316
317
ReleaseToken(Token aToken)318 void MasterPageContainer::ReleaseToken (Token aToken)
319 {
320 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
321 if (pDescriptor.get() != NULL)
322 {
323 OSL_ASSERT(pDescriptor->mnUseCount>0);
324 --pDescriptor->mnUseCount;
325 if (pDescriptor->mnUseCount <= 0)
326 {
327 switch (pDescriptor->meOrigin)
328 {
329 case DEFAULT:
330 case TEMPLATE:
331 default:
332 break;
333
334 case MASTERPAGE:
335 mpImpl->ReleaseDescriptor(aToken);
336 break;
337 }
338 }
339 }
340 }
341
342
343
344
GetTokenCount(void) const345 int MasterPageContainer::GetTokenCount (void) const
346 {
347 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
348
349 return mpImpl->maContainer.size();
350 }
351
352
353
354
HasToken(Token aToken) const355 bool MasterPageContainer::HasToken (Token aToken) const
356 {
357 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
358
359 return mpImpl->HasToken(aToken);
360 }
361
362
363
364
GetTokenForIndex(int nIndex)365 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
366 {
367 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
368
369 Token aResult (NIL_TOKEN);
370 if (HasToken(nIndex))
371 aResult = mpImpl->maContainer[nIndex]->maToken;
372 return aResult;
373 }
374
375
376
377
GetTokenForURL(const String & sURL)378 MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
379 const String& sURL)
380 {
381 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
382
383 Token aResult (NIL_TOKEN);
384 if (sURL.Len() > 0)
385 {
386 MasterPageContainerType::iterator iEntry (
387 ::std::find_if (
388 mpImpl->maContainer.begin(),
389 mpImpl->maContainer.end(),
390 MasterPageDescriptor::URLComparator(sURL)));
391 if (iEntry != mpImpl->maContainer.end())
392 aResult = (*iEntry)->maToken;
393 }
394 return aResult;
395 }
396
397
398
399
GetTokenForStyleName(const String & sStyleName)400 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName)
401 {
402 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
403
404 Token aResult (NIL_TOKEN);
405 if (sStyleName.Len() > 0)
406 {
407 MasterPageContainerType::iterator iEntry (
408 ::std::find_if (
409 mpImpl->maContainer.begin(),
410 mpImpl->maContainer.end(),
411 MasterPageDescriptor::StyleNameComparator(sStyleName)));
412 if (iEntry != mpImpl->maContainer.end())
413 aResult = (*iEntry)->maToken;
414 }
415 return aResult;
416 }
417
418
419
420
GetTokenForPageObject(const SdPage * pPage)421 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
422 const SdPage* pPage)
423 {
424 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
425
426 Token aResult (NIL_TOKEN);
427 if (pPage != NULL)
428 {
429 MasterPageContainerType::iterator iEntry (
430 ::std::find_if (
431 mpImpl->maContainer.begin(),
432 mpImpl->maContainer.end(),
433 MasterPageDescriptor::PageObjectComparator(pPage)));
434 if (iEntry != mpImpl->maContainer.end())
435 aResult = (*iEntry)->maToken;
436 }
437 return aResult;
438 }
439
440
441
442
GetURLForToken(MasterPageContainer::Token aToken)443 String MasterPageContainer::GetURLForToken (
444 MasterPageContainer::Token aToken)
445 {
446 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
447
448 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
449 if (pDescriptor.get() != NULL)
450 return pDescriptor->msURL;
451 else
452 return String();
453 }
454
455
456
457
GetPageNameForToken(MasterPageContainer::Token aToken)458 String MasterPageContainer::GetPageNameForToken (
459 MasterPageContainer::Token aToken)
460 {
461 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
462
463 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
464 if (pDescriptor.get() != NULL)
465 return pDescriptor->msPageName;
466 else
467 return String();
468 }
469
470
471
472
GetStyleNameForToken(MasterPageContainer::Token aToken)473 String MasterPageContainer::GetStyleNameForToken (
474 MasterPageContainer::Token aToken)
475 {
476 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
477
478 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
479 if (pDescriptor.get() != NULL)
480 return pDescriptor->msStyleName;
481 else
482 return String();
483 }
484
485
486
487
GetPageObjectForToken(MasterPageContainer::Token aToken,bool bLoad)488 SdPage* MasterPageContainer::GetPageObjectForToken (
489 MasterPageContainer::Token aToken,
490 bool bLoad)
491 {
492 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
493
494 SdPage* pPageObject = NULL;
495 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
496 if (pDescriptor.get() != NULL)
497 {
498 pPageObject = pDescriptor->mpMasterPage;
499 if (pPageObject == NULL)
500 {
501 // The page object is not (yet) present. Call
502 // UpdateDescriptor() to trigger the PageObjectProvider() to
503 // provide it.
504 if (bLoad)
505 mpImpl->GetModel();
506 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
507 pPageObject = pDescriptor->mpMasterPage;
508 }
509 }
510 return pPageObject;
511 }
512
513
514
515
GetOriginForToken(Token aToken)516 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken)
517 {
518 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
519
520 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
521 if (pDescriptor.get() != NULL)
522 return pDescriptor->meOrigin;
523 else
524 return UNKNOWN;
525 }
526
527
528
529
GetTemplateIndexForToken(Token aToken)530 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
531 {
532 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
533
534 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
535 if (pDescriptor.get() != NULL)
536 return pDescriptor->mnTemplateIndex;
537 else
538 return -1;
539 }
540
541
542
543
GetDescriptorForToken(MasterPageContainer::Token aToken)544 SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
545 MasterPageContainer::Token aToken)
546 {
547 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
548
549 return mpImpl->GetDescriptor(aToken);
550 }
551
552
553
InvalidatePreview(MasterPageContainer::Token aToken)554 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
555 {
556 mpImpl->InvalidatePreview(aToken);
557 }
558
559
560
561
GetPreviewForToken(MasterPageContainer::Token aToken)562 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
563 {
564 return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
565 }
566
567
568
569
GetPreviewState(Token aToken)570 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
571 {
572 return mpImpl->GetPreviewState(aToken);
573 }
574
575
576
577
RequestPreview(Token aToken)578 bool MasterPageContainer::RequestPreview (Token aToken)
579 {
580 return mpImpl->RequestPreview(aToken);
581 }
582
583
584
585
586 //==== Implementation ================================================
587
Implementation(void)588 MasterPageContainer::Implementation::Implementation (void)
589 : maMutex(),
590 maContainer(),
591 meInitializationState(NOT_INITIALIZED),
592 mpRequestQueue(NULL),
593 mxModel(NULL),
594 mpDocument(NULL),
595 maPreviewRenderer(),
596 mbFirstPageObjectSeen(false),
597 maLargePreviewBeingCreated(),
598 maSmallPreviewBeingCreated(),
599 maLargePreviewNotAvailable(),
600 maSmallPreviewNotAvailable(),
601 maChangeListeners(),
602 maSmallPreviewSizePixel(),
603 maLargePreviewSizePixel(),
604 mbPageRatioKnown(false),
605 mbContainerCleaningPending(true)
606
607 {
608 UpdatePreviewSizePixel();
609 }
610
611
612
613
~Implementation(void)614 MasterPageContainer::Implementation::~Implementation (void)
615 {
616 // When the initializer or filler tasks are still running then we have
617 // to stop them now in order to prevent them from calling us back.
618 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
619
620 mpRequestQueue.reset();
621
622 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
623 if (xCloseable.is())
624 {
625 try
626 {
627 xCloseable->close(true);
628 }
629 catch (::com::sun::star::util::CloseVetoException aException)
630 {
631 }
632 }
633 mxModel = NULL;
634 }
635
636
637
638
LateInit(void)639 void MasterPageContainer::Implementation::LateInit (void)
640 {
641 const ::osl::MutexGuard aGuard (maMutex);
642
643 if (meInitializationState == NOT_INITIALIZED)
644 {
645 meInitializationState = INITIALIZING;
646
647 OSL_ASSERT(Instance().get()==this);
648 mpRequestQueue.reset(MasterPageContainerQueue::Create(
649 ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
650
651 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
652 ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
653 5,
654 50);
655
656 meInitializationState = INITIALIZED;
657 }
658 }
659
660
661
662
AddChangeListener(const Link & rLink)663 void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink)
664 {
665 const ::osl::MutexGuard aGuard (maMutex);
666
667 ::std::vector<Link>::iterator iListener (
668 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
669 if (iListener == maChangeListeners.end())
670 maChangeListeners.push_back(rLink);
671
672 }
673
674
675
676
RemoveChangeListener(const Link & rLink)677 void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink)
678 {
679 const ::osl::MutexGuard aGuard (maMutex);
680
681 ::std::vector<Link>::iterator iListener (
682 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
683 if (iListener != maChangeListeners.end())
684 maChangeListeners.erase(iListener);
685 }
686
687
688
689
UpdatePreviewSizePixel(void)690 void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void)
691 {
692 const ::osl::MutexGuard aGuard (maMutex);
693
694 // The default aspect ratio is 4:3
695 int nWidth (4);
696 int nHeight (3);
697
698 // Search for the first entry with an existing master page.
699 MasterPageContainerType::const_iterator iDescriptor;
700 MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
701 for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
702 if( bool(*iDescriptor) && (*iDescriptor)->mpMasterPage != NULL)
703 {
704 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
705 nWidth = aPageSize.Width();
706 nHeight = aPageSize.Height();
707 mbFirstPageObjectSeen = true;
708 break;
709 }
710
711 maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH;
712 maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH;
713
714 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
715 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
716
717 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
718 || nNewLargeHeight!=maLargePreviewSizePixel.Height())
719 {
720 maSmallPreviewSizePixel.Height() = nNewSmallHeight;
721 maLargePreviewSizePixel.Height() = nNewLargeHeight;
722 FireContainerChange(
723 MasterPageContainerChangeEvent::SIZE_CHANGED,
724 NIL_TOKEN);
725 }
726 }
727
728
729
730
GetPreviewSizePixel(PreviewSize eSize) const731 Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
732 {
733 if (eSize == SMALL)
734 return maSmallPreviewSizePixel;
735 else
736 return maLargePreviewSizePixel;
737 }
738
739
740
741
IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback,EventData *,pData)742 IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData)
743 {
744 const ::osl::MutexGuard aGuard (maMutex);
745
746 if (pData != NULL)
747 {
748 FireContainerChange(pData->first, pData->second, false);
749 delete pData;
750 }
751
752 return 0;
753 }
754
755
756
757
PutMasterPage(const SharedMasterPageDescriptor & rpDescriptor)758 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
759 const SharedMasterPageDescriptor& rpDescriptor)
760 {
761 const ::osl::MutexGuard aGuard (maMutex);
762
763 Token aResult (NIL_TOKEN);
764
765 // Get page object and preview when that is inexpensive.
766 UpdateDescriptor(rpDescriptor,false,false, false);
767
768 // Look up the new MasterPageDescriptor and either insert it or update
769 // an already existing one.
770 MasterPageContainerType::iterator aEntry (
771 ::std::find_if (
772 maContainer.begin(),
773 maContainer.end(),
774 MasterPageDescriptor::AllComparator(rpDescriptor)));
775 if (aEntry == maContainer.end())
776 {
777 // Insert a new MasterPageDescriptor.
778 bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL
779 && rpDescriptor->msURL.getLength()==0);
780
781 if ( ! bIgnore)
782 {
783 if (mbContainerCleaningPending)
784 CleanContainer();
785
786 aResult = maContainer.size();
787 rpDescriptor->SetToken(aResult);
788
789 // Templates are precious, i.e. we lock them so that they will
790 // not be destroyed when (temporarily) no one references them.
791 // They will only be deleted when the container is destroyed.
792 switch (rpDescriptor->meOrigin)
793 {
794 case TEMPLATE:
795 case DEFAULT:
796 ++rpDescriptor->mnUseCount;
797 break;
798
799 default:
800 break;
801 }
802
803 maContainer.push_back(rpDescriptor);
804 aEntry = maContainer.end()-1;
805
806 FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult);
807 }
808 }
809 else
810 {
811 // Update an existing MasterPageDescriptor.
812 aResult = (*aEntry)->maToken;
813 ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
814 (*aEntry)->Update(*rpDescriptor));
815 if (pEventTypes.get()!=NULL && pEventTypes->size()>0)
816 {
817 // One or more aspects of the descriptor have changed. Send
818 // appropriate events to the listeners.
819 UpdateDescriptor(*aEntry,false,false, true);
820
821 std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
822 for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
823 {
824 FireContainerChange(
825 *iEventType,
826 (*aEntry)->maToken,
827 false);
828 }
829 }
830 }
831
832 return aResult;
833 }
834
835
836
837
HasToken(Token aToken) const838 bool MasterPageContainer::Implementation::HasToken (Token aToken) const
839 {
840 return aToken>=0
841 && (unsigned)aToken<maContainer.size()
842 && maContainer[aToken].get()!=NULL;
843 }
844
845
846
847
GetDescriptor(Token aToken) const848 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
849 Token aToken) const
850 {
851 if (aToken>=0 && (unsigned)aToken<maContainer.size())
852 return maContainer[aToken];
853 else
854 return SharedMasterPageDescriptor();
855 }
856
857
858
859
GetDescriptor(Token aToken)860 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
861 {
862 if (aToken>=0 && (unsigned)aToken<maContainer.size())
863 return maContainer[aToken];
864 else
865 return SharedMasterPageDescriptor();
866 }
867
868
869
870
InvalidatePreview(Token aToken)871 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
872 {
873 const ::osl::MutexGuard aGuard (maMutex);
874
875 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
876 if (pDescriptor.get() != NULL)
877 {
878 pDescriptor->maSmallPreview = Image();
879 pDescriptor->maLargePreview = Image();
880 RequestPreview(aToken);
881 }
882 }
883
884
885
886
GetPreviewForToken(MasterPageContainer::Token aToken,PreviewSize ePreviewSize)887 Image MasterPageContainer::Implementation::GetPreviewForToken (
888 MasterPageContainer::Token aToken,
889 PreviewSize ePreviewSize)
890 {
891 const ::osl::MutexGuard aGuard (maMutex);
892
893 Image aPreview;
894 PreviewState ePreviewState (GetPreviewState(aToken));
895
896 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
897
898 // When the preview is missing but inexpensively creatable then do that
899 // now.
900 if (pDescriptor.get()!=NULL)
901 {
902 if (ePreviewState == PS_CREATABLE)
903 if (UpdateDescriptor(pDescriptor, false,false, true))
904 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
905 ePreviewState = PS_AVAILABLE;
906
907 switch (ePreviewState)
908 {
909 case PS_AVAILABLE:
910 aPreview = pDescriptor->GetPreview(ePreviewSize);
911 break;
912
913 case PS_PREPARING:
914 aPreview = GetPreviewSubstitution(
915 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
916 ePreviewSize);
917 break;
918
919 case PS_CREATABLE:
920 aPreview = GetPreviewSubstitution(
921 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
922 ePreviewSize);
923 break;
924
925 case PS_NOT_AVAILABLE:
926 aPreview = GetPreviewSubstitution(
927 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
928 ePreviewSize);
929 if (ePreviewSize == SMALL)
930 pDescriptor->maSmallPreview = aPreview;
931 else
932 pDescriptor->maLargePreview = aPreview;
933 break;
934 }
935 }
936
937 return aPreview;
938 }
939
940
941
942
GetPreviewState(Token aToken) const943 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
944 Token aToken) const
945 {
946 const ::osl::MutexGuard aGuard (maMutex);
947
948 PreviewState eState (PS_NOT_AVAILABLE);
949
950 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
951 if (pDescriptor.get() != NULL)
952 {
953 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
954 eState = PS_AVAILABLE;
955 else if (pDescriptor->mpPreviewProvider.get() != NULL)
956 {
957 // The preview does not exist but can be created. When that is
958 // not expensive then do it at once.
959 if (mpRequestQueue->HasRequest(aToken))
960 eState = PS_PREPARING;
961 else
962 eState = PS_CREATABLE;
963 }
964 else
965 eState = PS_NOT_AVAILABLE;
966 }
967
968 return eState;
969 }
970
971
972
973
RequestPreview(Token aToken)974 bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
975 {
976 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
977 if (pDescriptor.get() != NULL)
978 return mpRequestQueue->RequestPreview(pDescriptor);
979 else
980 return false;
981 }
982
983
984
985
GetModel(void)986 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void)
987 {
988 const ::osl::MutexGuard aGuard (maMutex);
989
990 if ( ! mxModel.is())
991 {
992 // Get the desktop a s service factory.
993 ::rtl::OUString sDesktopServiceName (
994 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"));
995 uno::Reference<frame::XComponentLoader> xDesktop (
996 ::comphelper::getProcessServiceFactory()->createInstance(
997 sDesktopServiceName),
998 uno::UNO_QUERY);
999
1000 // Create a new model.
1001 ::rtl::OUString sModelServiceName (
1002 RTL_CONSTASCII_USTRINGPARAM(
1003 "com.sun.star.presentation.PresentationDocument"));
1004 mxModel = uno::Reference<frame::XModel>(
1005 ::comphelper::getProcessServiceFactory()->createInstance(
1006 sModelServiceName),
1007 uno::UNO_QUERY);
1008
1009 // Initialize the model.
1010 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
1011 if (xLoadable.is())
1012 xLoadable->initNew();
1013
1014 // Use its tunnel to get a pointer to its core implementation.
1015 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
1016 if (xUnoTunnel.is())
1017 {
1018 mpDocument = reinterpret_cast<SdXImpressDocument*>(
1019 xUnoTunnel->getSomething(
1020 SdXImpressDocument::getUnoTunnelId()))->GetDoc();
1021 }
1022
1023 // Create a default page.
1024 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
1025 if (xSlideSupplier.is())
1026 {
1027 uno::Reference<drawing::XDrawPages> xSlides (
1028 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
1029 if (xSlides.is())
1030 {
1031 sal_Int32 nIndex (0);
1032 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex));
1033 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
1034 if (xProperties.is())
1035 xProperties->setPropertyValue(
1036 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")),
1037 makeAny((sal_Int16)AUTOLAYOUT_TITLE));
1038 }
1039 }
1040 }
1041 return mxModel;
1042 }
1043
1044
1045
1046
GetDocument(void)1047 SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void)
1048 {
1049 GetModel();
1050 return mpDocument;
1051 }
1052
1053
1054
1055
GetPreviewSubstitution(sal_uInt16 nId,PreviewSize ePreviewSize)1056 Image MasterPageContainer::Implementation::GetPreviewSubstitution (
1057 sal_uInt16 nId,
1058 PreviewSize ePreviewSize)
1059 {
1060 const ::osl::MutexGuard aGuard (maMutex);
1061
1062 Image aPreview;
1063
1064 switch (nId)
1065 {
1066 case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION:
1067 {
1068 Image& rPreview (ePreviewSize==SMALL
1069 ? maSmallPreviewBeingCreated
1070 : maLargePreviewBeingCreated);
1071 if (rPreview.GetSizePixel().Width() == 0)
1072 {
1073 rPreview = maPreviewRenderer.RenderSubstitution(
1074 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
1075 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
1076 }
1077 aPreview = rPreview;
1078 }
1079 break;
1080
1081 case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION:
1082 {
1083 Image& rPreview (ePreviewSize==SMALL
1084 ? maSmallPreviewNotAvailable
1085 : maLargePreviewNotAvailable);
1086 if (rPreview.GetSizePixel().Width() == 0)
1087 {
1088 rPreview = maPreviewRenderer.RenderSubstitution(
1089 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
1090 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
1091 }
1092 aPreview = rPreview;
1093 }
1094 break;
1095 }
1096
1097 return aPreview;
1098 }
1099
1100
1101
1102
CleanContainer(void)1103 void MasterPageContainer::Implementation::CleanContainer (void)
1104 {
1105 // Remove the empty elements at the end of the container. The empty
1106 // elements in the middle can not be removed because that would
1107 // invalidate the references still held by others.
1108 int nIndex (maContainer.size()-1);
1109 while (nIndex>=0 && maContainer[nIndex].get()==NULL)
1110 --nIndex;
1111 maContainer.resize(++nIndex);
1112 }
1113
1114
1115
1116
FireContainerChange(MasterPageContainerChangeEvent::EventType eType,Token aToken,bool bNotifyAsynchronously)1117 void MasterPageContainer::Implementation::FireContainerChange (
1118 MasterPageContainerChangeEvent::EventType eType,
1119 Token aToken,
1120 bool bNotifyAsynchronously)
1121 {
1122 if (bNotifyAsynchronously)
1123 {
1124 Application::PostUserEvent(
1125 LINK(this,Implementation,AsynchronousNotifyCallback),
1126 new EventData(eType,aToken));
1127 }
1128 else
1129 {
1130 ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end());
1131 ::std::vector<Link>::iterator iListener;
1132 MasterPageContainerChangeEvent aEvent;
1133 aEvent.meEventType = eType;
1134 aEvent.maChildToken = aToken;
1135 for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
1136 iListener->Call(&aEvent);
1137 }
1138 }
1139
1140
1141
1142
UpdateDescriptor(const SharedMasterPageDescriptor & rpDescriptor,bool bForcePageObject,bool bForcePreview,bool bSendEvents)1143 bool MasterPageContainer::Implementation::UpdateDescriptor (
1144 const SharedMasterPageDescriptor& rpDescriptor,
1145 bool bForcePageObject,
1146 bool bForcePreview,
1147 bool bSendEvents)
1148 {
1149 const ::osl::MutexGuard aGuard (maMutex);
1150
1151 // We have to create the page object when the preview provider needs it
1152 // and the caller needs the preview.
1153 bForcePageObject |= (bForcePreview
1154 && rpDescriptor->mpPreviewProvider->NeedsPageObject()
1155 && rpDescriptor->mpMasterPage==NULL);
1156
1157 // Define a cost threshold so that an update or page object or preview
1158 // that is at least this cost are made at once. Updates with higher cost
1159 // are scheduled for later.
1160 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
1161
1162 // Update the page object (which may be used for the preview update).
1163 if (bForcePageObject)
1164 GetDocument();
1165 bool bPageObjectModified (rpDescriptor->UpdatePageObject(
1166 (bForcePageObject ? -1 : nCostThreshold),
1167 mpDocument));
1168 if (bPageObjectModified && bSendEvents)
1169 FireContainerChange(
1170 MasterPageContainerChangeEvent::DATA_CHANGED,
1171 rpDescriptor->maToken);
1172 if (bPageObjectModified && ! mbFirstPageObjectSeen)
1173 UpdatePreviewSizePixel();
1174
1175 // Update the preview.
1176 bool bPreviewModified (rpDescriptor->UpdatePreview(
1177 (bForcePreview ? -1 : nCostThreshold),
1178 maSmallPreviewSizePixel,
1179 maLargePreviewSizePixel,
1180 maPreviewRenderer));
1181
1182 if (bPreviewModified && bSendEvents)
1183 FireContainerChange(
1184 MasterPageContainerChangeEvent::PREVIEW_CHANGED,
1185 rpDescriptor->maToken);
1186
1187 return bPageObjectModified || bPreviewModified;
1188 }
1189
1190
1191
1192
ReleaseDescriptor(Token aToken)1193 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
1194 {
1195 if (aToken>=0 && (unsigned)aToken<maContainer.size())
1196 {
1197 maContainer[aToken].reset();
1198 mbContainerCleaningPending = true;
1199 }
1200 }
1201
1202
1203
1204
FillingDone(void)1205 void MasterPageContainer::Implementation::FillingDone (void)
1206 {
1207 mpRequestQueue->ProcessAllRequests();
1208 }
1209
1210
1211
1212 } } // end of namespace sd::sidebar
1213