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