merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / toolpanel / controls / MasterPageContainer.cxx
blob72ce4d505bd73d4d570b119ce81cc9d9727c9889
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MasterPageContainer.cxx,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "MasterPageContainer.hxx"
36 #include "MasterPageDescriptor.hxx"
37 #include "MasterPageContainerFiller.hxx"
38 #include "MasterPageContainerQueue.hxx"
39 #include "TemplateScanner.hxx"
40 #include "tools/AsynchronousTask.hxx"
41 #include "strings.hrc"
42 #include <algorithm>
43 #include <list>
44 #include <set>
46 #include "unomodel.hxx"
47 #include <com/sun/star/frame/XComponentLoader.hpp>
48 #include <com/sun/star/io/XStream.hpp>
49 #include <com/sun/star/io/XInputStream.hpp>
50 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/uno/Reference.hxx>
53 #include <com/sun/star/uno/Any.hxx>
54 #include <com/sun/star/uno/Sequence.hxx>
55 #include <com/sun/star/util/XCloseable.hpp>
56 #include <comphelper/processfactory.hxx>
57 #include <tools/urlobj.hxx>
58 #include <sfx2/app.hxx>
59 #include <svx/svdpage.hxx>
60 #include "DrawDocShell.hxx"
61 #include "drawdoc.hxx"
62 #include "sdpage.hxx"
63 #include <svtools/itemset.hxx>
64 #include <svtools/eitem.hxx>
65 #include "sdresid.hxx"
66 #include "tools/TimerBasedTaskExecution.hxx"
67 #include "pres.hxx"
68 #include <osl/mutex.hxx>
69 #include <boost/weak_ptr.hpp>
71 using namespace ::com::sun::star;
72 using namespace ::com::sun::star::uno;
73 using namespace ::sd::toolpanel::controls;
75 namespace {
77 typedef ::std::vector<SharedMasterPageDescriptor> MasterPageContainerType;
80 class PreviewCreationRequest
82 public:
83 PreviewCreationRequest (MasterPageContainer::Token aToken, int nPriority);
84 MasterPageContainer::Token maToken;
85 int mnPriority;
86 class Compare {public:
87 bool operator() (const PreviewCreationRequest& r1,const PreviewCreationRequest& r2);
89 class CompareToken {public:
90 MasterPageContainer::Token maToken;
91 CompareToken(MasterPageContainer::Token aToken);
92 bool operator() (const PreviewCreationRequest& rRequest);
97 } // end of anonymous namespace
100 namespace sd { namespace toolpanel { namespace controls {
103 /** Inner implementation class of the MasterPageContainer.
105 class MasterPageContainer::Implementation
106 : public SdGlobalResource,
107 public MasterPageContainerFiller::ContainerAdapter,
108 public MasterPageContainerQueue::ContainerAdapter
110 public:
111 mutable ::osl::Mutex maMutex;
113 static ::boost::weak_ptr<Implementation> mpInstance;
114 MasterPageContainerType maContainer;
116 static ::boost::shared_ptr<Implementation> Instance (void);
118 void LateInit (void);
119 void AddChangeListener (const Link& rLink);
120 void RemoveChangeListener (const Link& rLink);
121 void UpdatePreviewSizePixel (void);
122 Size GetPreviewSizePixel (PreviewSize eSize) const;
124 bool HasToken (Token aToken) const;
125 const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const;
126 SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken);
127 virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor);
128 void InvalidatePreview (Token aToken);
129 Image GetPreviewForToken (
130 Token aToken,
131 PreviewSize ePreviewSize);
132 PreviewState GetPreviewState (Token aToken) const;
133 bool RequestPreview (Token aToken);
135 Reference<frame::XModel> GetModel (void);
136 SdDrawDocument* GetDocument (void);
138 void FireContainerChange (
139 MasterPageContainerChangeEvent::EventType eType,
140 Token aToken,
141 bool bNotifyAsynchronously = false);
143 virtual bool UpdateDescriptor (
144 const SharedMasterPageDescriptor& rpDescriptor,
145 bool bForcePageObject,
146 bool bForcePreview,
147 bool bSendEvents);
149 void ReleaseDescriptor (Token aToken);
151 /** Called by the MasterPageContainerFiller to notify that all master
152 pages from template documents have been added.
154 virtual void FillingDone (void);
156 private:
157 Implementation (void);
158 virtual ~Implementation (void);
160 class Deleter { public:
161 void operator() (Implementation* pObject) { delete pObject; }
163 friend class Deleter;
165 enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState;
167 ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue;
168 ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> mxModel;
169 SdDrawDocument* mpDocument;
170 PreviewRenderer maPreviewRenderer;
171 /** Remember whether the first page object has already been used to
172 determine the correct size ratio.
174 bool mbFirstPageObjectSeen;
176 // The widths for the previews contain two pixels for the border that is
177 // painted arround the preview.
178 static const int SMALL_PREVIEW_WIDTH = 72 + 2;
179 static const int LARGE_PREVIEW_WIDTH = 2*72 + 2;
181 /** This substition of page preview shows "Preparing preview" and is
182 shown as long as the actual previews are not being present.
184 Image maLargePreviewBeingCreated;
185 Image maSmallPreviewBeingCreated;
187 /** This substition of page preview is shown when a preview can not be
188 created and thus is not available.
190 Image maLargePreviewNotAvailable;
191 Image maSmallPreviewNotAvailable;
193 ::std::vector<Link> maChangeListeners;
195 // We have to remember the tasks for initialization and filling in case
196 // a MasterPageContainer object is destroyed before these tasks have
197 // been completed.
198 ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask;
200 Size maSmallPreviewSizePixel;
201 Size maLargePreviewSizePixel;
202 bool mbPageRatioKnown;
204 bool mbContainerCleaningPending;
206 typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData;
207 DECL_LINK(AsynchronousNotifyCallback, EventData*);
208 ::sd::DrawDocShell* LoadDocument (
209 const String& sFileName,
210 SfxObjectShellLock& rxDocumentShell);
212 Image GetPreviewSubstitution (USHORT nId, PreviewSize ePreviewSize);
214 void CleanContainer (void);
220 //===== MasterPageContainer ===================================================
222 ::boost::weak_ptr<MasterPageContainer::Implementation>
223 MasterPageContainer::Implementation::mpInstance;
224 static const MasterPageContainer::Token NIL_TOKEN (-1);
229 ::boost::shared_ptr<MasterPageContainer::Implementation>
230 MasterPageContainer::Implementation::Instance (void)
232 ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance;
234 if (Implementation::mpInstance.expired())
236 ::osl::GetGlobalMutex aMutexFunctor;
237 ::osl::MutexGuard aGuard (aMutexFunctor());
238 if (Implementation::mpInstance.expired())
240 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
241 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
242 new MasterPageContainer::Implementation(),
243 MasterPageContainer::Implementation::Deleter());
244 SdGlobalResourceContainer::Instance().AddResource(pInstance);
245 Implementation::mpInstance = pInstance;
247 else
248 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
249 Implementation::mpInstance);
251 else
253 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
254 pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>(
255 Implementation::mpInstance);
258 DBG_ASSERT (pInstance.get()!=NULL,
259 "MasterPageContainer::Implementation::Instance(): instance is NULL");
260 return pInstance;
266 MasterPageContainer::MasterPageContainer (void)
267 : mpImpl(Implementation::Instance()),
268 mePreviewSize(SMALL)
270 mpImpl->LateInit();
276 MasterPageContainer::~MasterPageContainer (void)
283 void MasterPageContainer::AddChangeListener (const Link& rLink)
285 mpImpl->AddChangeListener(rLink);
291 void MasterPageContainer::RemoveChangeListener (const Link& rLink)
293 mpImpl->RemoveChangeListener(rLink);
299 void MasterPageContainer::SetPreviewSize (PreviewSize eSize)
301 mePreviewSize = eSize;
302 mpImpl->FireContainerChange(
303 MasterPageContainerChangeEvent::SIZE_CHANGED,
304 NIL_TOKEN);
310 MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const
312 return mePreviewSize;
318 Size MasterPageContainer::GetPreviewSizePixel (void) const
320 return mpImpl->GetPreviewSizePixel(mePreviewSize);
326 MasterPageContainer::Token MasterPageContainer::PutMasterPage (
327 const SharedMasterPageDescriptor& rDescriptor)
329 return mpImpl->PutMasterPage(rDescriptor);
335 void MasterPageContainer::AcquireToken (Token aToken)
337 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
338 if (pDescriptor.get() != NULL)
340 ++pDescriptor->mnUseCount;
347 void MasterPageContainer::ReleaseToken (Token aToken)
349 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
350 if (pDescriptor.get() != NULL)
352 OSL_ASSERT(pDescriptor->mnUseCount>0);
353 --pDescriptor->mnUseCount;
354 if (pDescriptor->mnUseCount <= 0)
356 switch (pDescriptor->meOrigin)
358 case DEFAULT:
359 case TEMPLATE:
360 default:
361 break;
363 case MASTERPAGE:
364 mpImpl->ReleaseDescriptor(aToken);
365 break;
374 int MasterPageContainer::GetTokenCount (void) const
376 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
378 return mpImpl->maContainer.size();
384 bool MasterPageContainer::HasToken (Token aToken) const
386 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
388 return mpImpl->HasToken(aToken);
394 MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex)
396 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
398 Token aResult (NIL_TOKEN);
399 if (HasToken(nIndex))
400 aResult = mpImpl->maContainer[nIndex]->maToken;
401 return aResult;
407 MasterPageContainer::Token MasterPageContainer::GetTokenForURL (
408 const String& sURL)
410 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
412 Token aResult (NIL_TOKEN);
413 if (sURL.Len() > 0)
415 MasterPageContainerType::iterator iEntry (
416 ::std::find_if (
417 mpImpl->maContainer.begin(),
418 mpImpl->maContainer.end(),
419 MasterPageDescriptor::URLComparator(sURL)));
420 if (iEntry != mpImpl->maContainer.end())
421 aResult = (*iEntry)->maToken;
423 return aResult;
429 MasterPageContainer::Token MasterPageContainer::GetTokenForPageName (
430 const String& sPageName)
432 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
434 Token aResult (NIL_TOKEN);
435 if (sPageName.Len() > 0)
437 MasterPageContainerType::iterator iEntry (
438 ::std::find_if (
439 mpImpl->maContainer.begin(),
440 mpImpl->maContainer.end(),
441 MasterPageDescriptor::PageNameComparator(sPageName)));
442 if (iEntry != mpImpl->maContainer.end())
443 aResult = (*iEntry)->maToken;
445 return aResult;
451 MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName)
453 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
455 Token aResult (NIL_TOKEN);
456 if (sStyleName.Len() > 0)
458 MasterPageContainerType::iterator iEntry (
459 ::std::find_if (
460 mpImpl->maContainer.begin(),
461 mpImpl->maContainer.end(),
462 MasterPageDescriptor::StyleNameComparator(sStyleName)));
463 if (iEntry != mpImpl->maContainer.end())
464 aResult = (*iEntry)->maToken;
466 return aResult;
472 MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject (
473 const SdPage* pPage)
475 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
477 Token aResult (NIL_TOKEN);
478 if (pPage != NULL)
480 MasterPageContainerType::iterator iEntry (
481 ::std::find_if (
482 mpImpl->maContainer.begin(),
483 mpImpl->maContainer.end(),
484 MasterPageDescriptor::PageObjectComparator(pPage)));
485 if (iEntry != mpImpl->maContainer.end())
486 aResult = (*iEntry)->maToken;
488 return aResult;
494 String MasterPageContainer::GetURLForToken (
495 MasterPageContainer::Token aToken)
497 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
499 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
500 if (pDescriptor.get() != NULL)
501 return pDescriptor->msURL;
502 else
503 return String();
509 String MasterPageContainer::GetPageNameForToken (
510 MasterPageContainer::Token aToken)
512 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
514 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
515 if (pDescriptor.get() != NULL)
516 return pDescriptor->msPageName;
517 else
518 return String();
524 String MasterPageContainer::GetStyleNameForToken (
525 MasterPageContainer::Token aToken)
527 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
529 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
530 if (pDescriptor.get() != NULL)
531 return pDescriptor->msStyleName;
532 else
533 return String();
539 SdPage* MasterPageContainer::GetPageObjectForToken (
540 MasterPageContainer::Token aToken,
541 bool bLoad)
543 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
545 SdPage* pPageObject = NULL;
546 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
547 if (pDescriptor.get() != NULL)
549 pPageObject = pDescriptor->mpMasterPage;
550 if (pPageObject == NULL)
552 // The page object is not (yet) present. Call
553 // UpdateDescriptor() to trigger the PageObjectProvider() to
554 // provide it.
555 if (bLoad)
556 mpImpl->GetModel();
557 if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true))
558 pPageObject = pDescriptor->mpMasterPage;
561 return pPageObject;
567 MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken)
569 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
571 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
572 if (pDescriptor.get() != NULL)
573 return pDescriptor->meOrigin;
574 else
575 return UNKNOWN;
581 sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken)
583 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
585 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
586 if (pDescriptor.get() != NULL)
587 return pDescriptor->mnTemplateIndex;
588 else
589 return -1;
595 void MasterPageContainer::SetPreviewProviderForToken (
596 Token aToken,
597 const ::boost::shared_ptr<PreviewProvider>& rpPreviewProvider)
599 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
601 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
602 if (pDescriptor.get()!=NULL)
604 pDescriptor->mpPreviewProvider = rpPreviewProvider;
605 mpImpl->InvalidatePreview(aToken);
612 SdPage* MasterPageContainer::GetSlideForToken (
613 MasterPageContainer::Token aToken,
614 bool bLoad)
616 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
618 SdPage* pSlide = NULL;
619 SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken);
620 if (pDescriptor.get() != NULL)
622 pSlide = pDescriptor->mpSlide;
623 if (pSlide==NULL && bLoad)
625 GetPageObjectForToken(aToken, bLoad);
626 pSlide = pDescriptor->mpSlide;
629 return pSlide;
635 SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken (
636 MasterPageContainer::Token aToken)
638 const ::osl::MutexGuard aGuard (mpImpl->maMutex);
640 return mpImpl->GetDescriptor(aToken);
646 bool MasterPageContainer::UpdateDescriptor (
647 const SharedMasterPageDescriptor& rpDescriptor,
648 bool bForcePageObject,
649 bool bForcePreview,
650 bool bSendEvents)
652 return mpImpl->UpdateDescriptor(rpDescriptor, bForcePageObject, bForcePreview, bSendEvents);
658 void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken)
660 mpImpl->InvalidatePreview(aToken);
666 Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken)
668 return mpImpl->GetPreviewForToken(aToken,mePreviewSize);
674 MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken)
676 return mpImpl->GetPreviewState(aToken);
682 bool MasterPageContainer::RequestPreview (Token aToken)
684 return mpImpl->RequestPreview(aToken);
690 //==== Implementation ================================================
692 MasterPageContainer::Implementation::Implementation (void)
693 : maMutex(),
694 maContainer(),
695 meInitializationState(NOT_INITIALIZED),
696 mpRequestQueue(NULL),
697 mxModel(NULL),
698 mpDocument(NULL),
699 maPreviewRenderer(),
700 mbFirstPageObjectSeen(false),
701 maLargePreviewBeingCreated(),
702 maSmallPreviewBeingCreated(),
703 maLargePreviewNotAvailable(),
704 maSmallPreviewNotAvailable(),
705 maChangeListeners(),
706 maSmallPreviewSizePixel(),
707 maLargePreviewSizePixel(),
708 mbPageRatioKnown(false),
709 mbContainerCleaningPending(true)
712 UpdatePreviewSizePixel();
718 MasterPageContainer::Implementation::~Implementation (void)
720 // When the initializer or filler tasks are still running then we have
721 // to stop them now in order to prevent them from calling us back.
722 tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask);
724 mpRequestQueue.reset();
726 uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY);
727 if (xCloseable.is())
731 xCloseable->close(true);
733 catch (::com::sun::star::util::CloseVetoException aException)
737 mxModel = NULL;
743 void MasterPageContainer::Implementation::LateInit (void)
745 const ::osl::MutexGuard aGuard (maMutex);
747 if (meInitializationState == NOT_INITIALIZED)
749 meInitializationState = INITIALIZING;
751 OSL_ASSERT(Instance().get()==this);
752 mpRequestQueue.reset(MasterPageContainerQueue::Create(
753 ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance())));
755 mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create(
756 ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)),
758 50);
760 meInitializationState = INITIALIZED;
767 void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink)
769 const ::osl::MutexGuard aGuard (maMutex);
771 ::std::vector<Link>::iterator iListener (
772 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
773 if (iListener == maChangeListeners.end())
774 maChangeListeners.push_back(rLink);
781 void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink)
783 const ::osl::MutexGuard aGuard (maMutex);
785 ::std::vector<Link>::iterator iListener (
786 ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink));
787 if (iListener != maChangeListeners.end())
788 maChangeListeners.erase(iListener);
794 void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void)
796 const ::osl::MutexGuard aGuard (maMutex);
798 // The default aspect ratio is 4:3
799 int nWidth (4);
800 int nHeight (3);
802 // Search for the first entry with an existing master page.
803 MasterPageContainerType::const_iterator iDescriptor;
804 MasterPageContainerType::const_iterator iContainerEnd(maContainer.end());
805 for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor)
806 if (*iDescriptor!=NULL && (*iDescriptor)->mpMasterPage != NULL)
808 Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize());
809 nWidth = aPageSize.Width();
810 nHeight = aPageSize.Height();
811 mbFirstPageObjectSeen = true;
812 break;
815 maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH;
816 maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH;
818 int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
819 int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2);
821 if (nNewSmallHeight!=maSmallPreviewSizePixel.Height()
822 || nNewLargeHeight!=maLargePreviewSizePixel.Height())
824 maSmallPreviewSizePixel.Height() = nNewSmallHeight;
825 maLargePreviewSizePixel.Height() = nNewLargeHeight;
826 FireContainerChange(
827 MasterPageContainerChangeEvent::SIZE_CHANGED,
828 NIL_TOKEN);
835 Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const
837 if (eSize == SMALL)
838 return maSmallPreviewSizePixel;
839 else
840 return maLargePreviewSizePixel;
846 IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData)
848 const ::osl::MutexGuard aGuard (maMutex);
850 if (pData != NULL)
852 FireContainerChange(pData->first, pData->second, false);
853 delete pData;
856 return 0;
862 MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage (
863 const SharedMasterPageDescriptor& rpDescriptor)
865 const ::osl::MutexGuard aGuard (maMutex);
867 Token aResult (NIL_TOKEN);
869 // Get page object and preview when that is inexpensive.
870 UpdateDescriptor(rpDescriptor,false,false, false);
872 // Look up the new MasterPageDescriptor and either insert it or update
873 // an already existing one.
874 MasterPageContainerType::iterator aEntry (
875 ::std::find_if (
876 maContainer.begin(),
877 maContainer.end(),
878 MasterPageDescriptor::AllComparator(rpDescriptor)));
879 if (aEntry == maContainer.end())
881 // Insert a new MasterPageDescriptor.
882 bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL
883 && rpDescriptor->msURL.getLength()==0);
885 if ( ! bIgnore)
887 if (mbContainerCleaningPending)
888 CleanContainer();
890 aResult = maContainer.size();
891 rpDescriptor->SetToken(aResult);
893 // Templates are precious, i.e. we lock them so that they will
894 // not be destroyed when (temporarily) no one references them.
895 // They will only be deleted when the container is destroyed.
896 switch (rpDescriptor->meOrigin)
898 case TEMPLATE:
899 case DEFAULT:
900 ++rpDescriptor->mnUseCount;
901 break;
903 default:
904 break;
907 maContainer.push_back(rpDescriptor);
908 aEntry = maContainer.end()-1;
910 FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult);
913 else
915 // Update an existing MasterPageDescriptor.
916 aResult = (*aEntry)->maToken;
917 ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes(
918 (*aEntry)->Update(*rpDescriptor));
919 if (pEventTypes.get()!=NULL && pEventTypes->size()>0)
921 // One or more aspects of the descriptor have changed. Send
922 // appropriate events to the listeners.
923 UpdateDescriptor(*aEntry,false,false, true);
925 std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType;
926 for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType)
928 FireContainerChange(
929 *iEventType,
930 (*aEntry)->maToken,
931 false);
936 return aResult;
942 bool MasterPageContainer::Implementation::HasToken (Token aToken) const
944 return aToken>=0
945 && (unsigned)aToken<maContainer.size()
946 && maContainer[aToken].get()!=NULL;
952 const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (
953 Token aToken) const
955 if (aToken>=0 && (unsigned)aToken<maContainer.size())
956 return maContainer[aToken];
957 else
958 return SharedMasterPageDescriptor();
964 SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken)
966 if (aToken>=0 && (unsigned)aToken<maContainer.size())
967 return maContainer[aToken];
968 else
969 return SharedMasterPageDescriptor();
975 void MasterPageContainer::Implementation::InvalidatePreview (Token aToken)
977 const ::osl::MutexGuard aGuard (maMutex);
979 SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken));
980 if (pDescriptor.get() != NULL)
982 pDescriptor->maSmallPreview = Image();
983 pDescriptor->maLargePreview = Image();
984 RequestPreview(aToken);
991 Image MasterPageContainer::Implementation::GetPreviewForToken (
992 MasterPageContainer::Token aToken,
993 PreviewSize ePreviewSize)
995 const ::osl::MutexGuard aGuard (maMutex);
997 Image aPreview;
998 PreviewState ePreviewState (GetPreviewState(aToken));
1000 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
1002 // When the preview is missing but inexpensively creatable then do that
1003 // now.
1004 if (pDescriptor.get()!=NULL)
1006 if (ePreviewState == PS_CREATABLE)
1007 if (UpdateDescriptor(pDescriptor, false,false, true))
1008 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
1009 ePreviewState = PS_AVAILABLE;
1011 switch (ePreviewState)
1013 case PS_AVAILABLE:
1014 aPreview = pDescriptor->GetPreview(ePreviewSize);
1015 break;
1017 case PS_PREPARING:
1018 aPreview = GetPreviewSubstitution(
1019 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
1020 ePreviewSize);
1021 break;
1023 case PS_CREATABLE:
1024 aPreview = GetPreviewSubstitution(
1025 STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION,
1026 ePreviewSize);
1027 break;
1029 case PS_NOT_AVAILABLE:
1030 aPreview = GetPreviewSubstitution(
1031 STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION,
1032 ePreviewSize);
1033 if (ePreviewSize == SMALL)
1034 pDescriptor->maSmallPreview = aPreview;
1035 else
1036 pDescriptor->maLargePreview = aPreview;
1037 break;
1041 return aPreview;
1047 MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState (
1048 Token aToken) const
1050 const ::osl::MutexGuard aGuard (maMutex);
1052 PreviewState eState (PS_NOT_AVAILABLE);
1054 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
1055 if (pDescriptor.get() != NULL)
1057 if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0)
1058 eState = PS_AVAILABLE;
1059 else if (pDescriptor->mpPreviewProvider.get() != NULL)
1061 // The preview does not exist but can be created. When that is
1062 // not expensive then do it at once.
1063 if (mpRequestQueue->HasRequest(aToken))
1064 eState = PS_PREPARING;
1065 else
1066 eState = PS_CREATABLE;
1068 else
1069 eState = PS_NOT_AVAILABLE;
1072 return eState;
1078 bool MasterPageContainer::Implementation::RequestPreview (Token aToken)
1080 SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken);
1081 if (pDescriptor.get() != NULL)
1082 return mpRequestQueue->RequestPreview(pDescriptor);
1083 else
1084 return false;
1090 Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void)
1092 const ::osl::MutexGuard aGuard (maMutex);
1094 if ( ! mxModel.is())
1096 // Get the desktop a s service factory.
1097 ::rtl::OUString sDesktopServiceName (
1098 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"));
1099 uno::Reference<frame::XComponentLoader> xDesktop (
1100 ::comphelper::getProcessServiceFactory()->createInstance(
1101 sDesktopServiceName),
1102 uno::UNO_QUERY);
1104 // Create a new model.
1105 ::rtl::OUString sModelServiceName (
1106 RTL_CONSTASCII_USTRINGPARAM(
1107 "com.sun.star.presentation.PresentationDocument"));
1108 mxModel = uno::Reference<frame::XModel>(
1109 ::comphelper::getProcessServiceFactory()->createInstance(
1110 sModelServiceName),
1111 uno::UNO_QUERY);
1113 // Initialize the model.
1114 uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY);
1115 if (xLoadable.is())
1116 xLoadable->initNew();
1118 // Use its tunnel to get a pointer to its core implementation.
1119 uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY);
1120 if (xUnoTunnel.is())
1122 mpDocument = reinterpret_cast<SdXImpressDocument*>(
1123 xUnoTunnel->getSomething(
1124 SdXImpressDocument::getUnoTunnelId()))->GetDoc();
1127 // Create a default page.
1128 uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY);
1129 if (xSlideSupplier.is())
1131 uno::Reference<drawing::XDrawPages> xSlides (
1132 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
1133 if (xSlides.is())
1135 sal_Int32 nIndex (0);
1136 uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex));
1137 uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY);
1138 if (xProperties.is())
1139 xProperties->setPropertyValue(
1140 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")),
1141 makeAny((sal_Int16)AUTOLAYOUT_TITLE));
1145 return mxModel;
1151 SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void)
1153 GetModel();
1154 return mpDocument;
1160 Image MasterPageContainer::Implementation::GetPreviewSubstitution (
1161 USHORT nId,
1162 PreviewSize ePreviewSize)
1164 const ::osl::MutexGuard aGuard (maMutex);
1166 Image aPreview;
1168 switch (nId)
1170 case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION:
1172 Image& rPreview (ePreviewSize==SMALL
1173 ? maSmallPreviewBeingCreated
1174 : maLargePreviewBeingCreated);
1175 if (rPreview.GetSizePixel().Width() == 0)
1177 rPreview = maPreviewRenderer.RenderSubstitution(
1178 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
1179 SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION));
1181 aPreview = rPreview;
1183 break;
1185 case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION:
1187 Image& rPreview (ePreviewSize==SMALL
1188 ? maSmallPreviewNotAvailable
1189 : maLargePreviewNotAvailable);
1190 if (rPreview.GetSizePixel().Width() == 0)
1192 rPreview = maPreviewRenderer.RenderSubstitution(
1193 ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel,
1194 SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION));
1196 aPreview = rPreview;
1198 break;
1201 return aPreview;
1207 void MasterPageContainer::Implementation::CleanContainer (void)
1209 // Remove the empty elements at the end of the container. The empty
1210 // elements in the middle can not be removed because that would
1211 // invalidate the references still held by others.
1212 int nIndex (maContainer.size()-1);
1213 while (nIndex>=0 && maContainer[nIndex].get()==NULL)
1214 --nIndex;
1215 maContainer.resize(++nIndex);
1221 void MasterPageContainer::Implementation::FireContainerChange (
1222 MasterPageContainerChangeEvent::EventType eType,
1223 Token aToken,
1224 bool bNotifyAsynchronously)
1226 if (bNotifyAsynchronously)
1228 Application::PostUserEvent(
1229 LINK(this,Implementation,AsynchronousNotifyCallback),
1230 new EventData(eType,aToken));
1232 else
1234 ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end());
1235 ::std::vector<Link>::iterator iListener;
1236 MasterPageContainerChangeEvent aEvent;
1237 aEvent.meEventType = eType;
1238 aEvent.maChildToken = aToken;
1239 for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener)
1240 iListener->Call(&aEvent);
1247 bool MasterPageContainer::Implementation::UpdateDescriptor (
1248 const SharedMasterPageDescriptor& rpDescriptor,
1249 bool bForcePageObject,
1250 bool bForcePreview,
1251 bool bSendEvents)
1253 const ::osl::MutexGuard aGuard (maMutex);
1255 // We have to create the page object when the preview provider needs it
1256 // and the caller needs the preview.
1257 bForcePageObject |= (bForcePreview
1258 && rpDescriptor->mpPreviewProvider->NeedsPageObject()
1259 && rpDescriptor->mpMasterPage==NULL);
1261 // Define a cost threshold so that an update or page object or preview
1262 // that is at least this cost are made at once. Updates with higher cost
1263 // are scheduled for later.
1264 sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0);
1266 // Update the page object (which may be used for the preview update).
1267 if (bForcePageObject)
1268 GetDocument();
1269 bool bPageObjectModified (rpDescriptor->UpdatePageObject(
1270 (bForcePageObject ? -1 : nCostThreshold),
1271 mpDocument));
1272 if (bPageObjectModified && bSendEvents)
1273 FireContainerChange(
1274 MasterPageContainerChangeEvent::DATA_CHANGED,
1275 rpDescriptor->maToken);
1276 if (bPageObjectModified && ! mbFirstPageObjectSeen)
1277 UpdatePreviewSizePixel();
1279 // Update the preview.
1280 bool bPreviewModified (rpDescriptor->UpdatePreview(
1281 (bForcePreview ? -1 : nCostThreshold),
1282 maSmallPreviewSizePixel,
1283 maLargePreviewSizePixel,
1284 maPreviewRenderer));
1286 if (bPreviewModified && bSendEvents)
1287 FireContainerChange(
1288 MasterPageContainerChangeEvent::PREVIEW_CHANGED,
1289 rpDescriptor->maToken);
1291 return bPageObjectModified || bPreviewModified;
1297 void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken)
1299 if (aToken>=0 && (unsigned)aToken<maContainer.size())
1301 maContainer[aToken].reset();
1302 mbContainerCleaningPending = true;
1309 void MasterPageContainer::Implementation::FillingDone (void)
1311 mpRequestQueue->ProcessAllRequests();
1316 } } } // end of namespace ::sd::toolpanel::controls
1321 namespace {
1323 //===== PreviewCreationRequest ================================================
1325 PreviewCreationRequest::PreviewCreationRequest (
1326 MasterPageContainer::Token aToken,
1327 int nPriority)
1328 : maToken(aToken),
1329 mnPriority(nPriority)
1336 bool PreviewCreationRequest::Compare::operator() (
1337 const PreviewCreationRequest& aRequest1,
1338 const PreviewCreationRequest& aRequest2)
1340 if (aRequest1.mnPriority != aRequest2.mnPriority)
1342 // Prefer requests with higher priority.
1343 return aRequest1.mnPriority > aRequest2.mnPriority;
1345 else
1347 // Prefer tokens that have been earlier created (those with lower
1348 // value).
1349 return aRequest1.maToken < aRequest2.maToken;
1356 PreviewCreationRequest::CompareToken::CompareToken (MasterPageContainer::Token aToken)
1357 : maToken(aToken)
1364 bool PreviewCreationRequest::CompareToken::operator() (const PreviewCreationRequest& aRequest)
1366 return maToken==aRequest.maToken;
1371 } // end of anonymous namespace