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 <memory>
31 : #include <set>
32 :
33 : #include "unomodel.hxx"
34 : #include <com/sun/star/frame/Desktop.hpp>
35 : #include <com/sun/star/frame/XComponentLoader.hpp>
36 : #include <com/sun/star/io/XStream.hpp>
37 : #include <com/sun/star/io/XInputStream.hpp>
38 : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
39 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 : #include <com/sun/star/uno/Reference.hxx>
41 : #include <com/sun/star/uno/Any.hxx>
42 : #include <com/sun/star/uno/Sequence.hxx>
43 : #include <com/sun/star/util/XCloseable.hpp>
44 : #include <comphelper/processfactory.hxx>
45 : #include <sfx2/app.hxx>
46 : #include <svx/svdpage.hxx>
47 : #include "DrawDocShell.hxx"
48 : #include "drawdoc.hxx"
49 : #include "sdpage.hxx"
50 : #include <svl/itemset.hxx>
51 : #include <svl/eitem.hxx>
52 : #include "sdresid.hxx"
53 : #include "tools/TimerBasedTaskExecution.hxx"
54 : #include "pres.hxx"
55 : #include <osl/mutex.hxx>
56 : #include <boost/scoped_ptr.hpp>
57 : #include <boost/weak_ptr.hpp>
58 :
59 : using namespace ::com::sun::star;
60 : using namespace ::com::sun::star::uno;
61 :
62 : namespace {
63 :
64 : typedef ::std::vector<sd::sidebar::SharedMasterPageDescriptor> MasterPageContainerType;
65 :
66 : } // end of anonymous namespace
67 :
68 : namespace sd { namespace sidebar {
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) SAL_OVERRIDE;
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) SAL_OVERRIDE;
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) SAL_OVERRIDE;
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 around 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 :
170 : bool mbContainerCleaningPending;
171 :
172 : typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData;
173 : DECL_LINK(AsynchronousNotifyCallback, EventData*);
174 :
175 : Image GetPreviewSubstitution (sal_uInt16 nId, PreviewSize ePreviewSize);
176 :
177 : void CleanContainer (void);
178 : };
179 :
180 : //===== MasterPageContainer ===================================================
181 :
182 : ::boost::weak_ptr<MasterPageContainer::Implementation>
183 38 : MasterPageContainer::Implementation::mpInstance;
184 :
185 : ::boost::shared_ptr<MasterPageContainer::Implementation>
186 0 : MasterPageContainer::Implementation::Instance (void)
187 : {
188 0 : ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance;
189 :
190 0 : if (Implementation::mpInstance.expired())
191 : {
192 : ::osl::GetGlobalMutex aMutexFunctor;
193 0 : ::osl::MutexGuard aGuard (aMutexFunctor());
194 0 : if (Implementation::mpInstance.expired())
195 : {
196 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
197 0 : pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
198 0 : new MasterPageContainer::Implementation(),
199 0 : MasterPageContainer::Implementation::Deleter());
200 0 : SdGlobalResourceContainer::Instance().AddResource(pInstance);
201 0 : Implementation::mpInstance = pInstance;
202 : }
203 : else
204 0 : pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
205 0 : Implementation::mpInstance);
206 : }
207 : else
208 : {
209 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
210 0 : pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
211 0 : Implementation::mpInstance);
212 : }
213 :
214 : DBG_ASSERT (pInstance.get()!=NULL,
215 : "MasterPageContainer::Implementation::Instance(): instance is NULL");
216 0 : return pInstance;
217 : }
218 :
219 0 : MasterPageContainer::MasterPageContainer (void)
220 : : mpImpl(Implementation::Instance()),
221 0 : mePreviewSize(SMALL)
222 : {
223 0 : mpImpl->LateInit();
224 0 : }
225 :
226 0 : MasterPageContainer::~MasterPageContainer (void)
227 : {
228 0 : }
229 :
230 0 : void MasterPageContainer::AddChangeListener (const Link& rLink)
231 : {
232 0 : mpImpl->AddChangeListener(rLink);
233 0 : }
234 :
235 0 : void MasterPageContainer::RemoveChangeListener (const Link& rLink)
236 : {
237 0 : mpImpl->RemoveChangeListener(rLink);
238 0 : }
239 :
240 0 : void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
241 : {
242 0 : mePreviewSize = eSize;
243 : mpImpl->FireContainerChange(
244 : MasterPageContainerChangeEvent::SIZE_CHANGED,
245 0 : NIL_TOKEN);
246 0 : }
247 :
248 0 : Size MasterPageContainer::GetPreviewSizePixel (void) const
249 : {
250 0 : return mpImpl->GetPreviewSizePixel(mePreviewSize);
251 : }
252 :
253 0 : MasterPageContainer::Token MasterPageContainer::PutMasterPage (
254 : const SharedMasterPageDescriptor& rDescriptor)
255 : {
256 0 : return mpImpl->PutMasterPage(rDescriptor);
257 : }
258 :
259 0 : void MasterPageContainer::AcquireToken (Token aToken)
260 : {
261 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
262 0 : if (pDescriptor.get() != NULL)
263 : {
264 0 : ++pDescriptor->mnUseCount;
265 0 : }
266 0 : }
267 :
268 0 : void MasterPageContainer::ReleaseToken (Token aToken)
269 : {
270 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
271 0 : if (pDescriptor.get() != NULL)
272 : {
273 : OSL_ASSERT(pDescriptor->mnUseCount>0);
274 0 : --pDescriptor->mnUseCount;
275 0 : if (pDescriptor->mnUseCount <= 0)
276 : {
277 0 : switch (pDescriptor->meOrigin)
278 : {
279 : case DEFAULT:
280 : case TEMPLATE:
281 : default:
282 0 : break;
283 :
284 : case MASTERPAGE:
285 0 : mpImpl->ReleaseDescriptor(aToken);
286 0 : break;
287 : }
288 : }
289 0 : }
290 0 : }
291 :
292 0 : int MasterPageContainer::GetTokenCount (void) const
293 : {
294 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
295 :
296 0 : return mpImpl->maContainer.size();
297 : }
298 :
299 0 : bool MasterPageContainer::HasToken (Token aToken) const
300 : {
301 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
302 :
303 0 : return mpImpl->HasToken(aToken);
304 : }
305 :
306 0 : MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
307 : {
308 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
309 :
310 0 : Token aResult (NIL_TOKEN);
311 0 : if (HasToken(nIndex))
312 0 : aResult = mpImpl->maContainer[nIndex]->maToken;
313 0 : return aResult;
314 : }
315 :
316 0 : MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
317 : const OUString& sURL)
318 : {
319 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
320 :
321 0 : Token aResult (NIL_TOKEN);
322 0 : if (!sURL.isEmpty())
323 : {
324 : MasterPageContainerType::iterator iEntry (
325 : ::std::find_if (
326 0 : mpImpl->maContainer.begin(),
327 0 : mpImpl->maContainer.end(),
328 0 : MasterPageDescriptor::URLComparator(sURL)));
329 0 : if (iEntry != mpImpl->maContainer.end())
330 0 : aResult = (*iEntry)->maToken;
331 : }
332 0 : return aResult;
333 : }
334 :
335 0 : MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const OUString& sStyleName)
336 : {
337 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
338 :
339 0 : Token aResult (NIL_TOKEN);
340 0 : if (!sStyleName.isEmpty())
341 : {
342 : MasterPageContainerType::iterator iEntry (
343 : ::std::find_if (
344 0 : mpImpl->maContainer.begin(),
345 0 : mpImpl->maContainer.end(),
346 0 : MasterPageDescriptor::StyleNameComparator(sStyleName)));
347 0 : if (iEntry != mpImpl->maContainer.end())
348 0 : aResult = (*iEntry)->maToken;
349 : }
350 0 : return aResult;
351 : }
352 :
353 0 : MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
354 : const SdPage* pPage)
355 : {
356 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
357 :
358 0 : Token aResult (NIL_TOKEN);
359 0 : if (pPage != NULL)
360 : {
361 : MasterPageContainerType::iterator iEntry (
362 : ::std::find_if (
363 0 : mpImpl->maContainer.begin(),
364 0 : mpImpl->maContainer.end(),
365 0 : MasterPageDescriptor::PageObjectComparator(pPage)));
366 0 : if (iEntry != mpImpl->maContainer.end())
367 0 : aResult = (*iEntry)->maToken;
368 : }
369 0 : return aResult;
370 : }
371 :
372 0 : OUString MasterPageContainer::GetURLForToken (
373 : MasterPageContainer::Token aToken)
374 : {
375 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
376 :
377 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
378 0 : if (pDescriptor.get() != NULL)
379 0 : return pDescriptor->msURL;
380 : else
381 0 : return OUString();
382 : }
383 :
384 0 : OUString MasterPageContainer::GetPageNameForToken (
385 : MasterPageContainer::Token aToken)
386 : {
387 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
388 :
389 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
390 0 : if (pDescriptor.get() != NULL)
391 0 : return pDescriptor->msPageName;
392 : else
393 0 : return OUString();
394 : }
395 :
396 0 : OUString MasterPageContainer::GetStyleNameForToken (
397 : MasterPageContainer::Token aToken)
398 : {
399 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
400 :
401 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
402 0 : if (pDescriptor.get() != NULL)
403 0 : return pDescriptor->msStyleName;
404 : else
405 0 : return OUString();
406 : }
407 :
408 0 : SdPage* MasterPageContainer::GetPageObjectForToken (
409 : MasterPageContainer::Token aToken,
410 : bool bLoad)
411 : {
412 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
413 :
414 0 : SdPage* pPageObject = NULL;
415 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
416 0 : if (pDescriptor.get() != NULL)
417 : {
418 0 : pPageObject = pDescriptor->mpMasterPage;
419 0 : if (pPageObject == NULL)
420 : {
421 : // The page object is not (yet) present. Call
422 : // UpdateDescriptor() to trigger the PageObjectProvider() to
423 : // provide it.
424 0 : if (bLoad)
425 0 : mpImpl->GetModel();
426 0 : if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
427 0 : pPageObject = pDescriptor->mpMasterPage;
428 : }
429 : }
430 0 : return pPageObject;
431 : }
432 :
433 0 : MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (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->meOrigin;
440 : else
441 0 : return UNKNOWN;
442 : }
443 :
444 0 : sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
445 : {
446 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
447 :
448 0 : SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
449 0 : if (pDescriptor.get() != NULL)
450 0 : return pDescriptor->mnTemplateIndex;
451 : else
452 0 : return -1;
453 : }
454 :
455 0 : SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
456 : MasterPageContainer::Token aToken)
457 : {
458 0 : const ::osl::MutexGuard aGuard (mpImpl->maMutex);
459 :
460 0 : return mpImpl->GetDescriptor(aToken);
461 : }
462 :
463 0 : void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
464 : {
465 0 : mpImpl->InvalidatePreview(aToken);
466 0 : }
467 :
468 0 : Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
469 : {
470 0 : return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
471 : }
472 :
473 0 : MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
474 : {
475 0 : return mpImpl->GetPreviewState(aToken);
476 : }
477 :
478 0 : bool MasterPageContainer::RequestPreview (Token aToken)
479 : {
480 0 : return mpImpl->RequestPreview(aToken);
481 : }
482 :
483 : //==== Implementation ================================================
484 :
485 0 : MasterPageContainer::Implementation::Implementation (void)
486 : : maMutex(),
487 : maContainer(),
488 : meInitializationState(NOT_INITIALIZED),
489 : mpRequestQueue(NULL),
490 : mxModel(NULL),
491 : mpDocument(NULL),
492 : maPreviewRenderer(),
493 : mbFirstPageObjectSeen(false),
494 : maLargePreviewBeingCreated(),
495 : maSmallPreviewBeingCreated(),
496 : maLargePreviewNotAvailable(),
497 : maSmallPreviewNotAvailable(),
498 : maChangeListeners(),
499 : maSmallPreviewSizePixel(),
500 : maLargePreviewSizePixel(),
501 0 : mbContainerCleaningPending(true)
502 :
503 : {
504 0 : UpdatePreviewSizePixel();
505 0 : }
506 :
507 0 : MasterPageContainer::Implementation::~Implementation (void)
508 : {
509 : // When the initializer or filler tasks are still running then we have
510 : // to stop them now in order to prevent them from calling us back.
511 0 : tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
512 :
513 0 : mpRequestQueue.reset();
514 :
515 0 : uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
516 0 : if (xCloseable.is())
517 : {
518 : try
519 : {
520 0 : xCloseable->close(true);
521 : }
522 0 : catch (const ::com::sun::star::util::CloseVetoException&)
523 : {
524 : }
525 : }
526 0 : mxModel = NULL;
527 0 : }
528 :
529 0 : void MasterPageContainer::Implementation::LateInit (void)
530 : {
531 0 : const ::osl::MutexGuard aGuard (maMutex);
532 :
533 0 : if (meInitializationState == NOT_INITIALIZED)
534 : {
535 0 : meInitializationState = INITIALIZING;
536 :
537 : OSL_ASSERT(Instance().get()==this);
538 : mpRequestQueue.reset(MasterPageContainerQueue::Create(
539 0 : ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
540 :
541 0 : mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
542 0 : ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
543 : 5,
544 0 : 50);
545 :
546 0 : meInitializationState = INITIALIZED;
547 0 : }
548 0 : }
549 :
550 0 : void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink)
551 : {
552 0 : const ::osl::MutexGuard aGuard (maMutex);
553 :
554 : ::std::vector<Link>::iterator iListener (
555 0 : ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
556 0 : if (iListener == maChangeListeners.end())
557 0 : maChangeListeners.push_back(rLink);
558 :
559 0 : }
560 :
561 0 : void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink)
562 : {
563 0 : const ::osl::MutexGuard aGuard (maMutex);
564 :
565 : ::std::vector<Link>::iterator iListener (
566 0 : ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
567 0 : if (iListener != maChangeListeners.end())
568 0 : maChangeListeners.erase(iListener);
569 0 : }
570 :
571 0 : void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void)
572 : {
573 0 : const ::osl::MutexGuard aGuard (maMutex);
574 :
575 : // The default aspect ratio is 4:3
576 0 : int nWidth (4);
577 0 : int nHeight (3);
578 :
579 : // Search for the first entry with an existing master page.
580 0 : MasterPageContainerType::const_iterator iDescriptor;
581 0 : MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
582 0 : for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
583 0 : if (*iDescriptor!=0 && (*iDescriptor)->mpMasterPage != NULL)
584 : {
585 0 : Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
586 : OSL_ASSERT(aPageSize.Width() > 0 && aPageSize.Height() > 0);
587 0 : if (aPageSize.Width() > 0)
588 0 : nWidth = aPageSize.Width();
589 0 : if (aPageSize.Height() > 0)
590 0 : nHeight = aPageSize.Height();
591 0 : mbFirstPageObjectSeen = true;
592 0 : break;
593 : }
594 :
595 0 : maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH;
596 0 : maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH;
597 :
598 0 : int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
599 0 : int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
600 :
601 0 : if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
602 0 : || nNewLargeHeight!=maLargePreviewSizePixel.Height())
603 : {
604 0 : maSmallPreviewSizePixel.Height() = nNewSmallHeight;
605 0 : maLargePreviewSizePixel.Height() = nNewLargeHeight;
606 : FireContainerChange(
607 : MasterPageContainerChangeEvent::SIZE_CHANGED,
608 0 : NIL_TOKEN);
609 0 : }
610 0 : }
611 :
612 0 : Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
613 : {
614 0 : if (eSize == SMALL)
615 0 : return maSmallPreviewSizePixel;
616 : else
617 0 : return maLargePreviewSizePixel;
618 : }
619 :
620 0 : IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData)
621 : {
622 0 : const ::osl::MutexGuard aGuard (maMutex);
623 :
624 0 : if (pData != NULL)
625 : {
626 0 : FireContainerChange(pData->first, pData->second, false);
627 0 : delete pData;
628 : }
629 :
630 0 : return 0;
631 : }
632 :
633 0 : MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
634 : const SharedMasterPageDescriptor& rpDescriptor)
635 : {
636 0 : const ::osl::MutexGuard aGuard (maMutex);
637 :
638 0 : Token aResult (NIL_TOKEN);
639 :
640 : // Get page object and preview when that is inexpensive.
641 0 : UpdateDescriptor(rpDescriptor,false,false, false);
642 :
643 : // Look up the new MasterPageDescriptor and either insert it or update
644 : // an already existing one.
645 : MasterPageContainerType::iterator aEntry (
646 : ::std::find_if (
647 : maContainer.begin(),
648 : maContainer.end(),
649 0 : MasterPageDescriptor::AllComparator(rpDescriptor)));
650 0 : if (aEntry == maContainer.end())
651 : {
652 : // Insert a new MasterPageDescriptor.
653 0 : bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL
654 0 : && rpDescriptor->msURL.isEmpty());
655 :
656 0 : if ( ! bIgnore)
657 : {
658 0 : if (mbContainerCleaningPending)
659 0 : CleanContainer();
660 :
661 0 : aResult = maContainer.size();
662 0 : rpDescriptor->SetToken(aResult);
663 :
664 : // Templates are precious, i.e. we lock them so that they will
665 : // not be destroyed when (temporarily) no one references them.
666 : // They will only be deleted when the container is destroyed.
667 0 : switch (rpDescriptor->meOrigin)
668 : {
669 : case TEMPLATE:
670 : case DEFAULT:
671 0 : ++rpDescriptor->mnUseCount;
672 0 : break;
673 :
674 : default:
675 0 : break;
676 : }
677 :
678 0 : maContainer.push_back(rpDescriptor);
679 0 : aEntry = maContainer.end()-1;
680 :
681 0 : FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult);
682 : }
683 : }
684 : else
685 : {
686 : // Update an existing MasterPageDescriptor.
687 0 : aResult = (*aEntry)->maToken;
688 : std::unique_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
689 0 : (*aEntry)->Update(*rpDescriptor));
690 0 : if (pEventTypes.get()!=NULL && pEventTypes->size()>0)
691 : {
692 : // One or more aspects of the descriptor have changed. Send
693 : // appropriate events to the listeners.
694 0 : UpdateDescriptor(*aEntry,false,false, true);
695 :
696 0 : std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
697 0 : for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
698 : {
699 : FireContainerChange(
700 0 : *iEventType,
701 0 : (*aEntry)->maToken,
702 0 : false);
703 : }
704 0 : }
705 : }
706 :
707 0 : return aResult;
708 : }
709 :
710 0 : bool MasterPageContainer::Implementation::HasToken (Token aToken) const
711 : {
712 : return aToken>=0
713 0 : && (unsigned)aToken<maContainer.size()
714 0 : && maContainer[aToken].get()!=NULL;
715 : }
716 :
717 0 : const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
718 : Token aToken) const
719 : {
720 0 : if (aToken>=0 && (unsigned)aToken<maContainer.size())
721 0 : return maContainer[aToken];
722 : else
723 0 : return SharedMasterPageDescriptor();
724 : }
725 :
726 0 : SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
727 : {
728 0 : if (aToken>=0 && (unsigned)aToken<maContainer.size())
729 0 : return maContainer[aToken];
730 : else
731 0 : return SharedMasterPageDescriptor();
732 : }
733 :
734 0 : void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
735 : {
736 0 : const ::osl::MutexGuard aGuard (maMutex);
737 :
738 0 : SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
739 0 : if (pDescriptor.get() != NULL)
740 : {
741 0 : pDescriptor->maSmallPreview = Image();
742 0 : pDescriptor->maLargePreview = Image();
743 0 : RequestPreview(aToken);
744 0 : }
745 0 : }
746 :
747 0 : Image MasterPageContainer::Implementation::GetPreviewForToken (
748 : MasterPageContainer::Token aToken,
749 : PreviewSize ePreviewSize)
750 : {
751 0 : const ::osl::MutexGuard aGuard (maMutex);
752 :
753 0 : Image aPreview;
754 0 : PreviewState ePreviewState (GetPreviewState(aToken));
755 :
756 0 : SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
757 :
758 : // When the preview is missing but inexpensively creatable then do that
759 : // now.
760 0 : if (pDescriptor.get()!=NULL)
761 : {
762 0 : if (ePreviewState == PS_CREATABLE)
763 0 : if (UpdateDescriptor(pDescriptor, false,false, true))
764 0 : if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
765 0 : ePreviewState = PS_AVAILABLE;
766 :
767 0 : switch (ePreviewState)
768 : {
769 : case PS_AVAILABLE:
770 0 : aPreview = pDescriptor->GetPreview(ePreviewSize);
771 0 : break;
772 :
773 : case PS_PREPARING:
774 0 : aPreview = GetPreviewSubstitution(
775 : STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
776 0 : ePreviewSize);
777 0 : break;
778 :
779 : case PS_CREATABLE:
780 0 : aPreview = GetPreviewSubstitution(
781 : STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
782 0 : ePreviewSize);
783 0 : break;
784 :
785 : case PS_NOT_AVAILABLE:
786 0 : aPreview = GetPreviewSubstitution(
787 : STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
788 0 : ePreviewSize);
789 0 : if (ePreviewSize == SMALL)
790 0 : pDescriptor->maSmallPreview = aPreview;
791 : else
792 0 : pDescriptor->maLargePreview = aPreview;
793 0 : break;
794 : }
795 : }
796 :
797 0 : return aPreview;
798 : }
799 :
800 0 : MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
801 : Token aToken) const
802 : {
803 0 : const ::osl::MutexGuard aGuard (maMutex);
804 :
805 0 : PreviewState eState (PS_NOT_AVAILABLE);
806 :
807 0 : SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
808 0 : if (pDescriptor.get() != NULL)
809 : {
810 0 : if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
811 0 : eState = PS_AVAILABLE;
812 0 : else if (pDescriptor->mpPreviewProvider.get() != NULL)
813 : {
814 : // The preview does not exist but can be created. When that is
815 : // not expensive then do it at once.
816 0 : if (mpRequestQueue->HasRequest(aToken))
817 0 : eState = PS_PREPARING;
818 : else
819 0 : eState = PS_CREATABLE;
820 : }
821 : else
822 0 : eState = PS_NOT_AVAILABLE;
823 : }
824 :
825 0 : return eState;
826 : }
827 :
828 0 : bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
829 : {
830 0 : SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
831 0 : if (pDescriptor.get() != NULL)
832 0 : return mpRequestQueue->RequestPreview(pDescriptor);
833 : else
834 0 : return false;
835 : }
836 :
837 0 : Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void)
838 : {
839 0 : const ::osl::MutexGuard aGuard (maMutex);
840 :
841 0 : if ( ! mxModel.is())
842 : {
843 : // Get the desktop a s service factory.
844 : uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(
845 0 : ::comphelper::getProcessComponentContext() );
846 :
847 : // Create a new model.
848 0 : OUString sModelServiceName ( "com.sun.star.presentation.PresentationDocument");
849 0 : mxModel = uno::Reference<frame::XModel>(
850 0 : ::comphelper::getProcessServiceFactory()->createInstance(
851 0 : sModelServiceName),
852 0 : uno::UNO_QUERY);
853 :
854 : // Initialize the model.
855 0 : uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
856 0 : if (xLoadable.is())
857 0 : xLoadable->initNew();
858 :
859 : // Use its tunnel to get a pointer to its core implementation.
860 0 : uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
861 0 : if (xUnoTunnel.is())
862 : {
863 : mpDocument = reinterpret_cast<SdXImpressDocument*>(
864 0 : xUnoTunnel->getSomething(
865 0 : SdXImpressDocument::getUnoTunnelId()))->GetDoc();
866 : }
867 :
868 : // Create a default page.
869 0 : uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
870 0 : if (xSlideSupplier.is())
871 : {
872 : uno::Reference<drawing::XDrawPages> xSlides (
873 0 : xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
874 0 : if (xSlides.is())
875 : {
876 0 : sal_Int32 nIndex (0);
877 0 : uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex));
878 0 : uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
879 0 : if (xProperties.is())
880 0 : xProperties->setPropertyValue(
881 : "Layout",
882 0 : makeAny((sal_Int16)AUTOLAYOUT_TITLE));
883 0 : }
884 0 : }
885 : }
886 0 : return mxModel;
887 : }
888 :
889 0 : SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void)
890 : {
891 0 : GetModel();
892 0 : return mpDocument;
893 : }
894 :
895 0 : Image MasterPageContainer::Implementation::GetPreviewSubstitution (
896 : sal_uInt16 nId,
897 : PreviewSize ePreviewSize)
898 : {
899 0 : const ::osl::MutexGuard aGuard (maMutex);
900 :
901 0 : Image aPreview;
902 :
903 0 : switch (nId)
904 : {
905 : case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION:
906 : {
907 : Image& rPreview (ePreviewSize==SMALL
908 : ? maSmallPreviewBeingCreated
909 0 : : maLargePreviewBeingCreated);
910 0 : if (rPreview.GetSizePixel().Width() == 0)
911 : {
912 0 : rPreview = maPreviewRenderer.RenderSubstitution(
913 : ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
914 0 : SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
915 : }
916 0 : aPreview = rPreview;
917 : }
918 0 : break;
919 :
920 : case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION:
921 : {
922 : Image& rPreview (ePreviewSize==SMALL
923 : ? maSmallPreviewNotAvailable
924 0 : : maLargePreviewNotAvailable);
925 0 : if (rPreview.GetSizePixel().Width() == 0)
926 : {
927 0 : rPreview = maPreviewRenderer.RenderSubstitution(
928 : ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
929 0 : SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
930 : }
931 0 : aPreview = rPreview;
932 : }
933 0 : break;
934 : }
935 :
936 0 : return aPreview;
937 : }
938 :
939 0 : void MasterPageContainer::Implementation::CleanContainer (void)
940 : {
941 : // Remove the empty elements at the end of the container. The empty
942 : // elements in the middle can not be removed because that would
943 : // invalidate the references still held by others.
944 0 : int nIndex (maContainer.size()-1);
945 0 : while (nIndex>=0 && maContainer[nIndex].get()==NULL)
946 0 : --nIndex;
947 0 : maContainer.resize(++nIndex);
948 0 : }
949 :
950 0 : void MasterPageContainer::Implementation::FireContainerChange (
951 : MasterPageContainerChangeEvent::EventType eType,
952 : Token aToken,
953 : bool bNotifyAsynchronously)
954 : {
955 0 : if (bNotifyAsynchronously)
956 : {
957 : Application::PostUserEvent(
958 : LINK(this,Implementation,AsynchronousNotifyCallback),
959 0 : new EventData(eType,aToken));
960 : }
961 : else
962 : {
963 0 : ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end());
964 0 : ::std::vector<Link>::iterator iListener;
965 : MasterPageContainerChangeEvent aEvent;
966 0 : aEvent.meEventType = eType;
967 0 : aEvent.maChildToken = aToken;
968 0 : for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
969 0 : iListener->Call(&aEvent);
970 : }
971 0 : }
972 :
973 0 : bool MasterPageContainer::Implementation::UpdateDescriptor (
974 : const SharedMasterPageDescriptor& rpDescriptor,
975 : bool bForcePageObject,
976 : bool bForcePreview,
977 : bool bSendEvents)
978 : {
979 0 : const ::osl::MutexGuard aGuard (maMutex);
980 :
981 : // We have to create the page object when the preview provider needs it
982 : // and the caller needs the preview.
983 : bForcePageObject |= (bForcePreview
984 0 : && rpDescriptor->mpPreviewProvider->NeedsPageObject()
985 0 : && rpDescriptor->mpMasterPage==NULL);
986 :
987 : // Define a cost threshold so that an update or page object or preview
988 : // that is at least this cost are made at once. Updates with higher cost
989 : // are scheduled for later.
990 0 : sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
991 :
992 : // Update the page object (which may be used for the preview update).
993 0 : if (bForcePageObject)
994 0 : GetDocument();
995 : int nPageObjectModified (rpDescriptor->UpdatePageObject(
996 : (bForcePageObject ? -1 : nCostThreshold),
997 0 : mpDocument));
998 0 : if (nPageObjectModified == 1 && bSendEvents)
999 : FireContainerChange(
1000 : MasterPageContainerChangeEvent::DATA_CHANGED,
1001 0 : rpDescriptor->maToken);
1002 0 : if (nPageObjectModified == -1 && bSendEvents)
1003 : FireContainerChange(
1004 : MasterPageContainerChangeEvent::CHILD_REMOVED,
1005 0 : rpDescriptor->maToken);
1006 0 : if (nPageObjectModified && ! mbFirstPageObjectSeen)
1007 0 : UpdatePreviewSizePixel();
1008 :
1009 : // Update the preview.
1010 : bool bPreviewModified (rpDescriptor->UpdatePreview(
1011 : (bForcePreview ? -1 : nCostThreshold),
1012 : maSmallPreviewSizePixel,
1013 : maLargePreviewSizePixel,
1014 0 : maPreviewRenderer));
1015 :
1016 0 : if (bPreviewModified && bSendEvents)
1017 : FireContainerChange(
1018 : MasterPageContainerChangeEvent::PREVIEW_CHANGED,
1019 0 : rpDescriptor->maToken);
1020 :
1021 0 : return nPageObjectModified || bPreviewModified;
1022 : }
1023 :
1024 0 : void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
1025 : {
1026 0 : if (aToken>=0 && (unsigned)aToken<maContainer.size())
1027 : {
1028 0 : maContainer[aToken].reset();
1029 0 : mbContainerCleaningPending = true;
1030 : }
1031 0 : }
1032 :
1033 0 : void MasterPageContainer::Implementation::FillingDone (void)
1034 : {
1035 0 : mpRequestQueue->ProcessAllRequests();
1036 0 : }
1037 :
1038 114 : } } // end of namespace sd::sidebar
1039 :
1040 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|