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