merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / slidesorter / cache / SlsPageCacheManager.cxx
blob6140723666a9e152b88d4000a31b7087025305f1
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: SlsPageCacheManager.cxx,v $
10 * $Revision: 1.11 $
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 "cache/SlsPageCacheManager.hxx"
36 #include "SlsBitmapCache.hxx"
37 #include "view/SlideSorterView.hxx"
38 #include "model/SlideSorterModel.hxx"
40 #include <deque>
41 #include <map>
42 #include <boost/weak_ptr.hpp>
44 namespace {
46 /** Collection of data that is stored for all active preview caches.
48 class CacheDescriptor
50 public:
51 ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
52 Size maPreviewSize;
54 CacheDescriptor(
55 ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
56 const Size& rPreviewSize)
57 :mpDocument(pDocument),maPreviewSize(rPreviewSize)
59 /// Test for equality with respect to all members.
60 class Equal {public: bool operator() (
61 const CacheDescriptor& rDescriptor1, const CacheDescriptor& rDescriptor2) const {
62 return rDescriptor1.mpDocument==rDescriptor2.mpDocument
63 && rDescriptor1.maPreviewSize==rDescriptor2.maPreviewSize;
64 } };
65 /// Hash function that takes all members into account.
66 class Hash {public: size_t operator() (const CacheDescriptor& rDescriptor) const {
67 return (size_t)rDescriptor.mpDocument.get() + rDescriptor.maPreviewSize.Width();
68 } };
74 /** Collection of data that is stored for the inactive, recently used
75 caches.
77 class RecentlyUsedCacheDescriptor
79 public:
80 ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
81 Size maPreviewSize;
82 ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache> mpCache;
84 RecentlyUsedCacheDescriptor(
85 ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
86 const Size& rPreviewSize,
87 const ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache>& rpCache)
88 :mpDocument(pDocument),maPreviewSize(rPreviewSize),mpCache(rpCache)
95 /** The list of recently used caches is organized as queue. When elements
96 are added the list is shortened to the maximally allowed number of
97 elements by removing the least recently used elements.
99 typedef ::std::deque<RecentlyUsedCacheDescriptor> RecentlyUsedQueue;
104 /** Compare the caches by preview size. Those that match the given size
105 come first, then, regardless of the given size, the largest ones before
106 the smaller ones.
108 class BestFittingCacheComparer
110 public:
111 BestFittingCacheComparer (const Size& rPreferredSize)
112 : maPreferredSize(rPreferredSize)
114 bool operator()(const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement1,
115 const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement2)
117 if (rElement1.first == maPreferredSize)
118 return true;
119 else if (rElement2.first == maPreferredSize)
120 return false;
121 else
122 return (rElement1.first.Width()*rElement1.first.Height()
123 > rElement2.first.Width()*rElement2.first.Height());
126 private:
127 Size maPreferredSize;
130 } // end of anonymous namespace
133 namespace sd { namespace slidesorter { namespace cache {
135 /** Container for the active caches.
137 class PageCacheManager::PageCacheContainer
138 : public ::std::hash_map<CacheDescriptor,
139 ::boost::shared_ptr<PageCacheManager::Cache>,
140 CacheDescriptor::Hash,
141 CacheDescriptor::Equal>
143 public:
144 PageCacheContainer (void) {}
146 /** Compare entries in the cache container with respect to the cache
147 address only.
149 class CompareWithCache { public:
150 CompareWithCache(const ::boost::shared_ptr<PageCacheManager::Cache>& rpCache)
151 : mpCache(rpCache) {}
152 bool operator () (const PageCacheContainer::value_type& rValue)
153 { return rValue.second == mpCache; }
154 private:
155 ::boost::shared_ptr<PageCacheManager::Cache> mpCache;
160 /** The recently used caches are stored in one queue for each document.
162 class PageCacheManager::RecentlyUsedPageCaches
163 : public ::std::map<DocumentKey,RecentlyUsedQueue>
165 public:
166 RecentlyUsedPageCaches (void) {};
172 class PageCacheManager::Deleter
174 public:
175 void operator() (PageCacheManager* pObject) { delete pObject; }
180 //===== PageCacheManager ====================================================
182 ::boost::weak_ptr<PageCacheManager> PageCacheManager::mpInstance;
184 ::boost::shared_ptr<PageCacheManager> PageCacheManager::Instance (void)
186 ::boost::shared_ptr<PageCacheManager> pInstance;
188 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
190 pInstance = mpInstance.lock();
191 if (pInstance.get() == NULL)
193 pInstance = ::boost::shared_ptr<PageCacheManager>(
194 new PageCacheManager(),
195 PageCacheManager::Deleter());
196 mpInstance = pInstance;
199 return pInstance;
205 PageCacheManager::PageCacheManager (void)
206 : mpPageCaches(new PageCacheContainer()),
207 mpRecentlyUsedPageCaches(new RecentlyUsedPageCaches()),
208 mnMaximalRecentlyCacheCount(2)
215 PageCacheManager::~PageCacheManager (void)
222 ::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetCache (
223 DocumentKey pDocument,
224 const Size& rPreviewSize)
226 ::boost::shared_ptr<Cache> pResult;
228 // Look for the cache in the list of active caches.
229 CacheDescriptor aKey (pDocument, rPreviewSize);
230 PageCacheContainer::iterator iCache (mpPageCaches->find(aKey));
231 if (iCache != mpPageCaches->end())
232 pResult = iCache->second;
234 // Look for the cache in the list of recently used caches.
235 if (pResult.get() == NULL)
236 pResult = GetRecentlyUsedCache(pDocument, rPreviewSize);
238 // Create the cache when no suitable one does exist.
239 if (pResult.get() == NULL)
240 pResult.reset(new Cache());
242 // The cache may be newly created and thus empty or is old and may
243 // contain previews that are not up-to-date. Recycle previews from
244 // other caches to fill in the holes.
245 Recycle(pResult, pDocument,rPreviewSize);
247 // Put the new (or old) cache into the container.
248 if (pResult.get() != NULL)
249 mpPageCaches->insert(PageCacheContainer::value_type(aKey, pResult));
251 return pResult;
257 void PageCacheManager::Recycle (
258 const ::boost::shared_ptr<Cache>& rpCache,
259 DocumentKey pDocument,
260 const Size& rPreviewSize)
262 BestFittingPageCaches aCaches;
264 // Add bitmap caches from active caches.
265 PageCacheContainer::iterator iActiveCache;
266 for (iActiveCache=mpPageCaches->begin(); iActiveCache!=mpPageCaches->end(); ++iActiveCache)
268 if (iActiveCache->first.mpDocument == pDocument)
269 aCaches.push_back(BestFittingPageCaches::value_type(
270 iActiveCache->first.maPreviewSize, iActiveCache->second));
273 // Add bitmap caches from recently used caches.
274 RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
275 if (iQueue != mpRecentlyUsedPageCaches->end())
277 RecentlyUsedQueue::const_iterator iRecentCache;
278 for (iRecentCache=iQueue->second.begin();iRecentCache!=iQueue->second.end();++iRecentCache)
279 aCaches.push_back(BestFittingPageCaches::value_type(
280 iRecentCache->maPreviewSize, iRecentCache->mpCache));
283 ::std::sort(aCaches.begin(), aCaches.end(), BestFittingCacheComparer(rPreviewSize));
285 BestFittingPageCaches::const_iterator iBestCache;
286 for (iBestCache=aCaches.begin(); iBestCache!=aCaches.end(); ++iBestCache)
288 rpCache->Recycle(*iBestCache->second);
295 void PageCacheManager::ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache)
297 PageCacheContainer::iterator iCache (::std::find_if(
298 mpPageCaches->begin(),
299 mpPageCaches->end(),
300 PageCacheContainer::CompareWithCache(rpCache)));
302 if (iCache != mpPageCaches->end())
304 OSL_ASSERT(iCache->second == rpCache);
306 PutRecentlyUsedCache(iCache->first.mpDocument,iCache->first.maPreviewSize,rpCache);
308 mpPageCaches->erase(iCache);
315 ::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::ChangeSize (
316 const ::boost::shared_ptr<Cache>& rpCache,
317 const Size& rOldPreviewSize,
318 const Size& rNewPreviewSize)
320 (void)rOldPreviewSize;
322 ::boost::shared_ptr<Cache> pResult;
324 if (rpCache.get() != NULL)
326 // Look up the given cache in the list of active caches.
327 PageCacheContainer::iterator iCacheToChange (::std::find_if(
328 mpPageCaches->begin(),
329 mpPageCaches->end(),
330 PageCacheContainer::CompareWithCache(rpCache)));
331 OSL_ASSERT(iCacheToChange != mpPageCaches->end());
332 if (iCacheToChange != mpPageCaches->end())
334 OSL_ASSERT(iCacheToChange->second == rpCache);
336 // Now, we can change the preview size of the existing one by
337 // removing the cache from the list and re-insert it with the
338 // updated size.
339 const ::sd::slidesorter::cache::PageCacheManager::DocumentKey aKey (
340 iCacheToChange->first.mpDocument);
341 mpPageCaches->erase(iCacheToChange);
342 mpPageCaches->insert(PageCacheContainer::value_type(
343 CacheDescriptor(aKey,rNewPreviewSize),
344 rpCache));
346 pResult = rpCache;
350 return pResult;
356 void PageCacheManager::InvalidatePreviewBitmap (
357 DocumentKey pDocument,
358 const SdrPage* pKey)
360 if (pDocument!=NULL)
362 // Iterate over all caches that are currently in use and invalidate
363 // the previews in those that belong to the document.
364 PageCacheContainer::iterator iCache;
365 for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
366 if (iCache->first.mpDocument == pDocument)
367 iCache->second->InvalidateBitmap(pKey);
369 // Invalidate the previews in the recently used caches belonging to
370 // the given document.
371 RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
372 if (iQueue != mpRecentlyUsedPageCaches->end())
374 RecentlyUsedQueue::const_iterator iCache2;
375 for (iCache2=iQueue->second.begin(); iCache2!=iQueue->second.end(); ++iCache2)
376 iCache2->mpCache->InvalidateBitmap(pKey);
384 void PageCacheManager::InvalidateAllCaches (void)
386 // Iterate over all caches that are currently in use and invalidate
387 // them.
388 PageCacheContainer::iterator iCache;
389 for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
390 iCache->second->InvalidateCache();
392 // Remove all recently used caches, there is not much sense in storing
393 // invalidated and unused caches.
394 mpRecentlyUsedPageCaches->clear();
400 ::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetRecentlyUsedCache (
401 DocumentKey pDocument,
402 const Size& rPreviewSize)
404 ::boost::shared_ptr<Cache> pCache;
406 // Look for the cache in the list of recently used caches.
407 RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
408 if (iQueue != mpRecentlyUsedPageCaches->end())
410 RecentlyUsedQueue::iterator iCache;
411 for (iCache=iQueue->second.begin(); iCache!= iQueue->second.end(); ++iCache)
412 if (iCache->maPreviewSize == rPreviewSize)
414 pCache = iCache->mpCache;
415 iQueue->second.erase(iCache);
416 break;
420 return pCache;
426 void PageCacheManager::PutRecentlyUsedCache(
427 DocumentKey pDocument,
428 const Size& rPreviewSize,
429 const ::boost::shared_ptr<Cache>& rpCache)
431 // Look up the list of recently used caches for the given document.
432 RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
433 if (iQueue == mpRecentlyUsedPageCaches->end())
434 iQueue = mpRecentlyUsedPageCaches->insert(
435 RecentlyUsedPageCaches::value_type(pDocument, RecentlyUsedQueue())
436 ).first;
438 if (iQueue != mpRecentlyUsedPageCaches->end())
440 iQueue->second.push_front(RecentlyUsedCacheDescriptor(pDocument,rPreviewSize,rpCache));
441 // Shorten the list of recently used caches to the allowed maximal length.
442 while (iQueue->second.size() > mnMaximalRecentlyCacheCount)
443 iQueue->second.pop_back();
449 } } } // end of namespace ::sd::slidesorter::cache