summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter')
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx634
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx214
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx276
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx163
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx83
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx68
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx239
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx103
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx178
-rw-r--r--sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx77
-rw-r--r--sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx312
-rw-r--r--sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx149
-rw-r--r--sd/source/ui/slidesorter/cache/SlsPageCache.cxx127
-rw-r--r--sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx449
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx257
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx141
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx368
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx80
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx51
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx58
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx293
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx136
-rwxr-xr-xsd/source/ui/slidesorter/cache/makefile.mk64
-rw-r--r--sd/source/ui/slidesorter/controller/SlideSorterController.cxx999
-rw-r--r--sd/source/ui/slidesorter/controller/SlsAnimator.cxx235
-rw-r--r--sd/source/ui/slidesorter/controller/SlsClipboard.cxx780
-rw-r--r--sd/source/ui/slidesorter/controller/SlsCommand.hxx48
-rw-r--r--sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx259
-rw-r--r--sd/source/ui/slidesorter/controller/SlsFocusManager.cxx364
-rw-r--r--sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx172
-rw-r--r--sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx75
-rw-r--r--sd/source/ui/slidesorter/controller/SlsListener.cxx602
-rw-r--r--sd/source/ui/slidesorter/controller/SlsListener.hxx186
-rw-r--r--sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx103
-rw-r--r--sd/source/ui/slidesorter/controller/SlsPageSelector.cxx327
-rw-r--r--sd/source/ui/slidesorter/controller/SlsProperties.cxx236
-rw-r--r--sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx634
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx88
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx98
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx1320
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx665
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx83
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSlotManager.cxx1136
-rw-r--r--sd/source/ui/slidesorter/controller/SlsTransferable.cxx95
-rw-r--r--sd/source/ui/slidesorter/controller/SlsTransferable.hxx73
-rw-r--r--sd/source/ui/slidesorter/controller/makefile.mk71
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx108
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx151
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx180
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx340
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx99
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx218
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx108
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx238
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsPageObjectFactory.hxx99
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx184
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx130
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx252
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx206
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx214
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSlideFunction.hxx76
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx104
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx204
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx56
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx218
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx130
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx63
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx44
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx310
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsFontProvider.hxx97
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx385
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObject.hxx68
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObjectViewContact.hxx92
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObjectViewObjectContact.hxx228
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx276
-rw-r--r--sd/source/ui/slidesorter/makefile.mk58
-rw-r--r--sd/source/ui/slidesorter/model/SlideSorterModel.cxx445
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx284
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx286
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx113
-rw-r--r--sd/source/ui/slidesorter/model/makefile.mk56
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorter.cxx654
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterChildWindow.cxx69
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterChildWindow.src52
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterService.cxx650
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterService.hxx219
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx787
-rw-r--r--sd/source/ui/slidesorter/shell/makefile.mk55
-rw-r--r--sd/source/ui/slidesorter/view/SlideSorterView.cxx824
-rw-r--r--sd/source/ui/slidesorter/view/SlsFontProvider.cxx135
-rw-r--r--sd/source/ui/slidesorter/view/SlsLayouter.cxx761
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObject.cxx83
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObjectViewContact.cxx128
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx1406
-rw-r--r--sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx170
-rw-r--r--sd/source/ui/slidesorter/view/SlsViewCacheContext.hxx73
-rw-r--r--sd/source/ui/slidesorter/view/SlsViewOverlay.cxx609
-rw-r--r--sd/source/ui/slidesorter/view/makefile.mk61
98 files changed, 26025 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
new file mode 100644
index 000000000000..fdf1aaf101d3
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
@@ -0,0 +1,634 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsBitmapCache.hxx"
+#include "SlsCacheCompactor.hxx"
+#include "SlsBitmapCompressor.hxx"
+#include "SlsCacheConfiguration.hxx"
+
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include "sdpage.hxx"
+#include "drawdoc.hxx"
+
+// Uncomment the following define for some more OSL_TRACE messages.
+#ifdef DEBUG
+//#define VERBOSE
+#endif
+
+// Define the default value for the maximal cache size that is used for
+// previews that are currently not visible. The visible previews are all
+// held in memory at all times. This default is used only when the
+// configuration does not have a value.
+static const sal_Int32 MAXIMAL_CACHE_SIZE = 4L*1024L*1024L;
+
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache::CacheEntry
+{
+public:
+ CacheEntry(const ::boost::shared_ptr<BitmapEx>& rpBitmap,
+ sal_Int32 nLastAccessTime, bool bIsPrecious);
+ CacheEntry(sal_Int32 nLastAccessTime, bool bIsPrecious);
+ ~CacheEntry (void) {};
+ inline void Recycle (const CacheEntry& rEntry);
+ inline sal_Int32 GetMemorySize (void) const;
+ void Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
+ inline void Decompress (void);
+
+ bool IsUpToDate (void) const { return mbIsUpToDate; }
+ void SetUpToDate (bool bIsUpToDate) { mbIsUpToDate = bIsUpToDate; }
+ sal_Int32 GetAccessTime (void) const { return mnLastAccessTime; }
+ void SetAccessTime (sal_Int32 nAccessTime) { mnLastAccessTime = nAccessTime; }
+ ::boost::shared_ptr<BitmapEx> GetPreview (void) const { return mpPreview; }
+ inline void SetPreview (const ::boost::shared_ptr<BitmapEx>& rpPreview);
+ bool HasPreview (void) const;
+ bool HasReplacement (void) const { return (mpReplacement.get() != NULL); }
+ inline bool HasLosslessReplacement (void) const;
+ void Clear (void) { mpPreview.reset(); mpReplacement.reset(); mpCompressor.reset(); }
+ void Invalidate (void) { mpReplacement.reset(); mpCompressor.reset(); mbIsUpToDate = false; }
+ bool IsPrecious (void) const { return mbIsPrecious; }
+ void SetPrecious (bool bIsPrecious) { mbIsPrecious = bIsPrecious; }
+
+private:
+ ::boost::shared_ptr<BitmapEx> mpPreview;
+ ::boost::shared_ptr<BitmapReplacement> mpReplacement;
+ ::boost::shared_ptr<BitmapCompressor> mpCompressor;
+ Size maBitmapSize;
+ bool mbIsUpToDate;
+ sal_Int32 mnLastAccessTime;
+ // When this flag is set then the bitmap is not modified by a cache
+ // compactor.
+ bool mbIsPrecious;
+};
+class CacheEntry;
+
+class CacheHash {
+public:
+ size_t operator()(const BitmapCache::CacheKey& p) const
+ { return (size_t)p; }
+};
+
+class BitmapCache::CacheBitmapContainer
+ : public ::std::hash_map<CacheKey, CacheEntry, CacheHash>
+{
+public:
+ CacheBitmapContainer (void) {}
+};
+
+namespace {
+
+typedef ::std::vector<
+ ::std::pair< ::sd::slidesorter::cache::BitmapCache::CacheKey,
+ ::sd::slidesorter::cache::BitmapCache::CacheEntry>
+ > SortableBitmapContainer;
+
+ /** Compare elements of the bitmap cache according to their last access
+ time.
+ */
+ class AccessTimeComparator
+ {
+ public:
+ bool operator () (
+ const SortableBitmapContainer::value_type& e1,
+ const SortableBitmapContainer::value_type& e2)
+ {
+ return e1.second.GetAccessTime() < e2.second.GetAccessTime();
+ }
+ };
+
+
+} // end of anonymous namespace
+
+
+//===== BitmapCache =========================================================
+
+BitmapCache::BitmapCache (const sal_Int32 nMaximalNormalCacheSize)
+ : maMutex(),
+ mpBitmapContainer(new CacheBitmapContainer()),
+ mnNormalCacheSize(0),
+ mnPreciousCacheSize(0),
+ mnCurrentAccessTime(0),
+ mnMaximalNormalCacheSize(MAXIMAL_CACHE_SIZE),
+ mpCacheCompactor(),
+ mbIsFull(false)
+{
+ if (nMaximalNormalCacheSize > 0)
+ mnMaximalNormalCacheSize = nMaximalNormalCacheSize;
+ else
+ {
+ Any aCacheSize (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CacheSize"))));
+ if (aCacheSize.has<sal_Int32>())
+ aCacheSize >>= mnMaximalNormalCacheSize;
+ }
+
+ mpCacheCompactor = CacheCompactor::Create(*this,mnMaximalNormalCacheSize);
+}
+
+
+
+
+BitmapCache::~BitmapCache (void)
+{
+ Clear();
+}
+
+
+
+
+void BitmapCache::Clear (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mpBitmapContainer->clear();
+ mnNormalCacheSize = 0;
+ mnPreciousCacheSize = 0;
+ mnCurrentAccessTime = 0;
+}
+
+
+
+
+bool BitmapCache::IsFull (void) const
+{
+ return mbIsFull;
+}
+
+
+
+
+sal_Int32 BitmapCache::GetSize (void)
+{
+ return mnNormalCacheSize;
+}
+
+
+
+
+bool BitmapCache::HasBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ return (iEntry != mpBitmapContainer->end()
+ && (iEntry->second.HasPreview() || iEntry->second.HasReplacement()));
+}
+
+
+
+
+bool BitmapCache::BitmapIsUpToDate (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ bool bIsUpToDate = false;
+ CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
+ if (aIterator != mpBitmapContainer->end())
+ bIsUpToDate = aIterator->second.IsUpToDate();
+
+ return bIsUpToDate;
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> BitmapCache::GetBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry == mpBitmapContainer->end())
+ {
+ // Create an empty bitmap for the given key that acts as placeholder
+ // until we are given the real one. Mark it as not being up to date.
+ SetBitmap (rKey, ::boost::shared_ptr<BitmapEx>(new BitmapEx()), false);
+ iEntry = mpBitmapContainer->find(rKey);
+ iEntry->second.SetUpToDate(false);
+ SSCD_SET_UPTODATE(iEntry->first,false);
+ }
+ else
+ {
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+
+ // Maybe we have to decompress the preview.
+ if ( ! iEntry->second.HasPreview() && iEntry->second.HasReplacement())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.Decompress();
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ }
+ return iEntry->second.GetPreview();
+}
+
+
+
+
+void BitmapCache::InvalidateBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ iEntry->second.SetUpToDate(false);
+ SSCD_SET_UPTODATE(iEntry->first,false);
+
+ // When there is a preview then we release the replacement. The
+ // preview itself is kept until a new one is created.
+ if (iEntry->second.HasPreview())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.Invalidate();
+ SSCD_SET_UPTODATE(iEntry->first,false);
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ }
+}
+
+
+
+
+void BitmapCache::InvalidateCache (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry;
+ for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
+ {
+ iEntry->second.Invalidate();
+ SSCD_SET_UPTODATE(iEntry->first,false);
+ }
+ ReCalculateTotalCacheSize();
+}
+
+
+
+
+void BitmapCache::SetBitmap (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapEx>& rpPreview,
+ bool bIsPrecious)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetPreview(rpPreview);
+ iEntry->second.SetUpToDate(true);
+ SSCD_SET_UPTODATE(iEntry->first,true);
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+ }
+ else
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ rKey,
+ CacheEntry (rpPreview, mnCurrentAccessTime++, bIsPrecious))
+ ).first;
+ }
+
+ if (iEntry != mpBitmapContainer->end())
+ UpdateCacheSize(iEntry->second, ADD);
+}
+
+
+
+
+void BitmapCache::SetPrecious (const CacheKey& rKey, bool bIsPrecious)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ if (iEntry->second.IsPrecious() != bIsPrecious)
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetPrecious(bIsPrecious);
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ }
+ else if (bIsPrecious)
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ rKey,
+ CacheEntry (
+ ::boost::shared_ptr<BitmapEx>(),
+ mnCurrentAccessTime++, bIsPrecious))
+ ).first;
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+}
+
+
+
+
+void BitmapCache::ReCalculateTotalCacheSize (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mnNormalCacheSize = 0;
+ mnPreciousCacheSize = 0;
+ CacheBitmapContainer::iterator iEntry;
+ for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
+ {
+ if (iEntry->second.IsPrecious())
+ mnPreciousCacheSize += iEntry->second.GetMemorySize();
+ else
+ mnNormalCacheSize += iEntry->second.GetMemorySize();
+ }
+ mbIsFull = (mnNormalCacheSize >= mnMaximalNormalCacheSize);
+
+#ifdef VERBOSE
+ OSL_TRACE("cache size is %d/%d", mnNormalCacheSize, mnPreciousCacheSize);
+#endif
+}
+
+
+
+
+void BitmapCache::Recycle (const BitmapCache& rCache)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::const_iterator iOtherEntry;
+ for (iOtherEntry=rCache.mpBitmapContainer->begin();
+ iOtherEntry!=rCache.mpBitmapContainer->end();
+ ++iOtherEntry)
+ {
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(iOtherEntry->first));
+ if (iEntry == mpBitmapContainer->end())
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ iOtherEntry->first,
+ CacheEntry(mnCurrentAccessTime++, true))
+ ).first;
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ if (iEntry != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.Recycle(iOtherEntry->second);
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ }
+}
+
+
+
+
+::std::auto_ptr<BitmapCache::CacheIndex> BitmapCache::GetCacheIndex (
+ bool bIncludePrecious,
+ bool bIncludeNoPreview) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Create a copy of the bitmap container.
+ SortableBitmapContainer aSortedContainer;
+ aSortedContainer.reserve(mpBitmapContainer->size());
+
+ // Copy the relevant entries.
+ CacheBitmapContainer::iterator iEntry;
+ for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
+ {
+ if ( ! bIncludePrecious && iEntry->second.IsPrecious())
+ continue;
+
+ if ( ! bIncludeNoPreview && ! iEntry->second.HasPreview())
+ continue;
+
+ aSortedContainer.push_back(SortableBitmapContainer::value_type(
+ iEntry->first,iEntry->second));
+ }
+
+ // Sort the remaining entries.
+ ::std::sort(aSortedContainer.begin(), aSortedContainer.end(), AccessTimeComparator());
+
+ // Return a list with the keys of the sorted entries.
+ ::std::auto_ptr<CacheIndex> pIndex(new CacheIndex());
+ SortableBitmapContainer::iterator iIndexEntry;
+ pIndex->reserve(aSortedContainer.size());
+ for (iIndexEntry=aSortedContainer.begin(); iIndexEntry!=aSortedContainer.end(); ++iIndexEntry)
+ pIndex->push_back(iIndexEntry->first);
+ return pIndex;
+}
+
+
+
+
+void BitmapCache::Compress (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end() && iEntry->second.HasPreview())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.Compress(rpCompressor);
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+}
+
+
+
+
+void BitmapCache::UpdateCacheSize (const CacheEntry& rEntry, CacheOperation eOperation)
+{
+ sal_Int32 nEntrySize (rEntry.GetMemorySize());
+ sal_Int32& rCacheSize (rEntry.IsPrecious() ? mnPreciousCacheSize : mnNormalCacheSize);
+ switch (eOperation)
+ {
+ case ADD:
+ rCacheSize += nEntrySize;
+ if ( ! rEntry.IsPrecious() && mnNormalCacheSize>mnMaximalNormalCacheSize)
+ {
+ mbIsFull = true;
+#ifdef VERBOSE
+ OSL_TRACE("cache size is %d > %d", mnNormalCacheSize,mnMaximalNormalCacheSize);
+#endif
+ mpCacheCompactor->RequestCompaction();
+ }
+ break;
+
+ case REMOVE:
+ rCacheSize -= nEntrySize;
+ if (mnNormalCacheSize < mnMaximalNormalCacheSize)
+ mbIsFull = false;
+ break;
+
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+}
+
+
+
+
+//===== CacheEntry ============================================================
+
+BitmapCache::CacheEntry::CacheEntry(
+ sal_Int32 nLastAccessTime,
+ bool bIsPrecious)
+ : mpPreview(),
+ mbIsUpToDate(true),
+ mnLastAccessTime(nLastAccessTime),
+ mbIsPrecious(bIsPrecious)
+{
+}
+
+
+
+
+BitmapCache::CacheEntry::CacheEntry(
+ const ::boost::shared_ptr<BitmapEx>& rpPreview,
+ sal_Int32 nLastAccessTime,
+ bool bIsPrecious)
+ : mpPreview(rpPreview),
+ mbIsUpToDate(true),
+ mnLastAccessTime(nLastAccessTime),
+ mbIsPrecious(bIsPrecious)
+{
+}
+
+
+
+
+inline void BitmapCache::CacheEntry::Recycle (const CacheEntry& rEntry)
+{
+ if ((rEntry.HasPreview() || rEntry.HasLosslessReplacement())
+ && ! (HasPreview() || HasLosslessReplacement()))
+ {
+ mpPreview = rEntry.mpPreview;
+ mpReplacement = rEntry.mpReplacement;
+ mpCompressor = rEntry.mpCompressor;
+ mnLastAccessTime = rEntry.mnLastAccessTime;
+ mbIsUpToDate = rEntry.mbIsUpToDate;
+ }
+}
+
+
+
+
+inline sal_Int32 BitmapCache::CacheEntry::GetMemorySize (void) const
+{
+ sal_Int32 nSize (0);
+ if (mpPreview.get() != NULL)
+ nSize += mpPreview->GetSizeBytes();
+ if (mpReplacement.get() != NULL)
+ nSize += mpReplacement->GetMemorySize();
+ return nSize;
+}
+
+
+
+
+void BitmapCache::CacheEntry::Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
+{
+ if (mpPreview.get() != NULL)
+ {
+ if (mpReplacement.get() == NULL)
+ {
+ mpReplacement = rpCompressor->Compress(mpPreview);
+
+#ifdef VERBOSE
+ sal_uInt32 nOldSize (mpPreview->GetSizeBytes());
+ sal_uInt32 nNewSize (mpReplacement.get()!=NULL ? mpReplacement->GetMemorySize() : 0);
+ if (nOldSize == 0)
+ nOldSize = 1;
+ sal_Int32 nRatio (100L * nNewSize / nOldSize);
+ OSL_TRACE("compressing bitmap for %x from %d to %d bytes (%d%%)",
+ this,
+ nOldSize,
+ nNewSize,
+ nRatio);
+#endif
+
+ mpCompressor = rpCompressor;
+ }
+
+ mpPreview.reset();
+ }
+}
+
+
+
+
+inline void BitmapCache::CacheEntry::Decompress (void)
+{
+ if (mpReplacement.get()!=NULL && mpCompressor.get()!=NULL && mpPreview.get()==NULL)
+ {
+ mpPreview = mpCompressor->Decompress(*mpReplacement);
+ if ( ! mpCompressor->IsLossless())
+ mbIsUpToDate = false;
+ }
+}
+
+
+
+inline void BitmapCache::CacheEntry::SetPreview (const ::boost::shared_ptr<BitmapEx>& rpPreview)
+{
+ mpPreview = rpPreview;
+ mpReplacement.reset();
+ mpCompressor.reset();
+}
+
+
+
+
+bool BitmapCache::CacheEntry::HasPreview (void) const
+{
+ if (mpPreview.get() != NULL)
+ return mpPreview->GetSizePixel().Width()>0 && mpPreview->GetSizePixel().Height()>0;
+ else
+ return false;
+}
+
+
+
+
+inline bool BitmapCache::CacheEntry::HasLosslessReplacement (void) const
+{
+ return mpReplacement.get()!=NULL
+ && mpCompressor.get()!=NULL
+ && mpCompressor->IsLossless();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx
new file mode 100644
index 000000000000..bedf563c7b91
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_BITMAP_CACHE_HXX
+#define SD_SLIDESORTER_BITMAP_CACHE_HXX
+
+class SdrPage;
+
+#include <vcl/bitmapex.hxx>
+#include <osl/mutex.hxx>
+#include <memory>
+#include <boost/shared_ptr.hpp>
+#include <hash_map>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapReplacement;
+class CacheCompactor;
+class BitmapCompressor;
+
+/** This low level cache is the actual bitmap container. It supports a
+ precious flag for every preview bitmap and keeps track of total sizes
+ for all previews with as well as those without the flag. The precious
+ flag is used by compaction algorithms to determine which previews may be
+ compressed or even discarded and which have to remain in their original
+ form. The precious flag is usually set for the visible previews.
+*/
+class BitmapCache
+{
+public:
+ /** The key for looking up preview bitmaps is a pointer to an SdrPage
+ object. The prior use of PageObjectViewObjectContact objects (which
+ ultimatly use them) turned out to be less suitable because their
+ life time is shorter then that of the page objects. Frequent
+ destruction and re-creation of the preview bitmaps was the result.
+ */
+ typedef const SdrPage* CacheKey;
+ class CacheEntry;
+ class CacheBitmapContainer;
+ typedef ::std::vector<CacheKey> CacheIndex;
+
+ /** Create a new cache for bitmap objects.
+ @param nMaximalNormalCacheSize
+ When a size larger then zero is given then that size is used.
+ Otherwise the default value from the configuration is used.
+ When that does not exist either then a internal default value is
+ used.
+ */
+ BitmapCache (const sal_Int32 nMaximalNormalCacheSize = 0);
+
+ /** The destructor clears the cache and relases all bitmaps still in it.
+ */
+ ~BitmapCache (void);
+
+ /** Remove all preview bitmaps from the cache. After this call the
+ cache is empty.
+ */
+ void Clear (void);
+
+ /** Return <TRUE/> when the cache is full, i.e. the cache compactor had
+ to be run.
+ */
+ bool IsFull (void) const;
+
+ /** Return the memory size that is occupied by all non-precious bitmaps
+ in the cache.
+ */
+ sal_Int32 GetSize (void);
+
+ /** Return <TRUE/> when a preview bitmap exists for the given key.
+ */
+ bool HasBitmap (const CacheKey& rKey);
+
+ /** Return <TRUE/> when a preview bitmap exists for the given key and
+ when it is up-to-date.
+ */
+ bool BitmapIsUpToDate (const CacheKey& rKey);
+
+ /** Return the preview bitmap for the given contact object.
+ */
+ ::boost::shared_ptr<BitmapEx> GetBitmap (const CacheKey& rKey);
+
+ /** Mark the specified preview bitmap as not being up-to-date anymore.
+ */
+ void InvalidateBitmap (const CacheKey& rKey);
+
+ /** Mark all preview bitmaps as not being up-to-date anymore.
+ */
+ void InvalidateCache (void);
+
+ /** Add or replace a bitmap for the given key.
+ */
+ void SetBitmap (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapEx>& rpPreview,
+ bool bIsPrecious);
+
+ /** Mark the specified preview bitmap as precious, i.e. that it must not
+ be compressed or otherwise removed from the cache.
+ */
+ void SetPrecious (const CacheKey& rKey, bool bIsPrecious);
+
+ /** Calculate the cache size. This should rarely be necessary because
+ the cache size is tracked with each modification of preview
+ bitmaps.
+ */
+ void ReCalculateTotalCacheSize (void);
+
+ /** Use the previews in the given cache to initialize missing previews.
+ */
+ void Recycle (const BitmapCache& rCache);
+
+ /** Return a list of sorted cache keys that represent an index into (a
+ part of) the cache. The entries of the index are sorted according
+ to last access times with the least recently access time first.
+ @param bIncludePrecious
+ When this flag is <TRUE/> entries with the precious flag set are
+ included in the index. When the flag is <FALSE/> these entries
+ are ommited.
+ @param bIncludeNoPreview
+ When this flag is <TRUE/> entries with that have no preview
+ bitmaps are included in the index. When the flag is <FALSE/> these entries
+ are ommited.
+ */
+ ::std::auto_ptr<CacheIndex> GetCacheIndex (
+ bool bIncludePrecious,
+ bool bIncludeNoPreview) const;
+
+ /** Compress the specified preview bitmap with the given bitmap
+ compressor. A reference to the compressor is stored for later
+ decompression.
+ */
+ void Compress (
+ const CacheKey& rKey,
+ const ::boost::shared_ptr<BitmapCompressor>& rpCompressor);
+
+private:
+ mutable ::osl::Mutex maMutex;
+
+ ::std::auto_ptr<CacheBitmapContainer> mpBitmapContainer;
+
+ /** Total size of bytes that are occupied by bitmaps in the cache for
+ whom the slides are currently not inside the visible area.
+ */
+ sal_Int32 mnNormalCacheSize;
+
+ /** Total size of bytes that are occupied by bitmaps in the cache for
+ whom the slides are currently visible.
+ */
+ sal_Int32 mnPreciousCacheSize;
+
+ /** At the moment the access time is not an actual time or date value
+ but a counter that is increased with every access. It thus defines
+ the same ordering as a true time.
+ */
+ sal_Int32 mnCurrentAccessTime;
+
+ /** The maximal cache size for the off-screen preview bitmaps. When
+ mnNormalCacheSize grows larger than this value then the
+ mpCacheCompactor member is used to reduce the cache size.
+ */
+ sal_Int32 mnMaximalNormalCacheSize;
+
+ /** The cache compactor is used to reduce the number of bytes used by
+ off-screen preview bitmaps.
+ */
+ ::std::auto_ptr<CacheCompactor> mpCacheCompactor;
+
+ /** This flag stores if the cache is or recently was full, i.e. the
+ cache compactor has or had to be run in order to reduce the cache
+ size to the allowed value.
+ */
+ bool mbIsFull;
+
+ /** Update mnNormalCacheSize or mnPreciousCacheSize according to the
+ precious flag of the specified preview bitmap and the specified
+ operation.
+ */
+ enum CacheOperation { ADD, REMOVE };
+ void UpdateCacheSize (const CacheEntry& rKey, CacheOperation eOperation);
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
new file mode 100644
index 000000000000..1ee3d50b1512
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsBitmapCompressor.hxx"
+
+#include <tools/stream.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/pngread.hxx>
+#include <vcl/pngwrite.hxx>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== NoBitmapCompression ===================================================
+
+/** This dummy replacement simply stores a shared pointer to the original
+ preview bitmap.
+*/
+class NoBitmapCompression::DummyReplacement
+ : public BitmapReplacement
+{
+public:
+ ::boost::shared_ptr<BitmapEx> mpPreview;
+ Size maOriginalSize;
+
+ DummyReplacement (const ::boost::shared_ptr<BitmapEx>& rpPreview) : mpPreview(rpPreview)
+ {
+ }
+
+ virtual ~DummyReplacement();
+
+ virtual sal_Int32 GetMemorySize (void) const;
+};
+
+NoBitmapCompression::DummyReplacement::~DummyReplacement()
+{
+}
+
+sal_Int32 NoBitmapCompression::DummyReplacement::GetMemorySize (void) const
+{
+ return mpPreview->GetSizeBytes();
+}
+
+::boost::shared_ptr<BitmapReplacement> NoBitmapCompression::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>(new DummyReplacement(rpBitmap));
+}
+
+::boost::shared_ptr<BitmapEx> NoBitmapCompression::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ return dynamic_cast<const DummyReplacement&>(rBitmapData).mpPreview;
+}
+
+
+
+
+bool NoBitmapCompression::IsLossless (void) const
+{
+ return true;
+}
+
+
+
+
+//===== CompressionByDeletion =================================================
+
+::boost::shared_ptr<BitmapReplacement> CompressionByDeletion::Compress (
+ const ::boost::shared_ptr<BitmapEx>& ) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>();
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> CompressionByDeletion::Decompress (
+ const BitmapReplacement& ) const
+{
+ // Return a NULL pointer. This will eventually lead to a request for
+ // the creation of a new one.
+ return ::boost::shared_ptr<BitmapEx>();
+}
+
+
+
+
+bool CompressionByDeletion::IsLossless (void) const
+{
+ return false;
+}
+
+
+
+
+//===== ResolutionReduction ===================================================
+
+/** Store a scaled down bitmap together with the original size.
+*/
+class ResolutionReduction::ResolutionReducedReplacement : public BitmapReplacement
+{
+public:
+ ::boost::shared_ptr<BitmapEx> mpPreview;
+ Size maOriginalSize;
+
+ virtual ~ResolutionReducedReplacement();
+
+ virtual sal_Int32 GetMemorySize (void) const;
+};
+
+ResolutionReduction::ResolutionReducedReplacement::~ResolutionReducedReplacement()
+{
+}
+
+sal_Int32 ResolutionReduction::ResolutionReducedReplacement::GetMemorySize (void) const
+{
+ if (mpPreview.get() != NULL)
+ return mpPreview->GetSizeBytes();
+ else
+ return 0;
+}
+
+::boost::shared_ptr<BitmapReplacement> ResolutionReduction::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ ResolutionReducedReplacement* pResult = new ResolutionReducedReplacement();
+ pResult->mpPreview.reset(new BitmapEx(*rpBitmap));
+ Size aSize (rpBitmap->GetSizePixel());
+ pResult->maOriginalSize = aSize;
+ if (aSize.Width()>0 && aSize.Width()<mnWidth)
+ {
+ int nHeight = aSize.Height() * mnWidth / aSize.Width() ;
+ pResult->mpPreview->Scale(Size(mnWidth,nHeight));
+ }
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> ResolutionReduction::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ ::boost::shared_ptr<BitmapEx> pResult;
+
+ const ResolutionReducedReplacement* pData (
+ dynamic_cast<const ResolutionReducedReplacement*>(&rBitmapData));
+
+ if (pData->mpPreview.get() != NULL)
+ {
+ pResult.reset(new BitmapEx(*pData->mpPreview));
+ if (pData->maOriginalSize.Width() > mnWidth)
+ pResult->Scale(pData->maOriginalSize);
+ }
+
+ return pResult;
+}
+
+
+
+
+bool ResolutionReduction::IsLossless (void) const
+{
+ return false;
+}
+
+
+
+
+//===== PNGCompression ========================================================
+
+
+class PngCompression::PngReplacement : public BitmapReplacement
+{
+public:
+ void* mpData;
+ sal_Int32 mnDataSize;
+ Size maImageSize;
+ PngReplacement (void)
+ : mpData(NULL),
+ mnDataSize(0),
+ maImageSize(0,0)
+ {}
+ virtual ~PngReplacement (void)
+ {
+ delete [] (char*)mpData;
+ }
+ virtual sal_Int32 GetMemorySize (void) const
+ {
+ return mnDataSize;
+ }
+};
+
+
+
+
+::boost::shared_ptr<BitmapReplacement> PngCompression::Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const
+{
+ ::vcl::PNGWriter aWriter (*rpBitmap);
+ SvMemoryStream aStream (32768, 32768);
+ aWriter.Write(aStream);
+
+ PngReplacement* pResult = new PngReplacement();
+ pResult->maImageSize = rpBitmap->GetSizePixel();
+ pResult->mnDataSize = aStream.Tell();
+ pResult->mpData = new char[pResult->mnDataSize];
+ memcpy(pResult->mpData, aStream.GetData(), pResult->mnDataSize);
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> PngCompression::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ BitmapEx* pResult = NULL;
+ const PngReplacement* pData (dynamic_cast<const PngReplacement*>(&rBitmapData));
+ if (pData != NULL)
+ {
+ SvMemoryStream aStream (pData->mpData, pData->mnDataSize, STREAM_READ);
+ ::vcl::PNGReader aReader (aStream);
+ pResult = new BitmapEx(aReader.Read());
+ }
+
+// sal_Int32 nRatio ((100L * (ULONG)pResult->GetSizeBytes()) / (ULONG)pData->mnDataSize);
+
+ return ::boost::shared_ptr<BitmapEx>(pResult);
+}
+
+
+
+
+bool PngCompression::IsLossless (void) const
+{
+ return true;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx
new file mode 100644
index 000000000000..af1b0a223d82
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_BITMAP_COMPRESSOR_HXX
+#define SD_SLIDESORTER_BITMAP_COMPRESSOR_HXX
+
+#include <sal/types.h>
+#include <tools/gen.hxx>
+#include <boost/shared_ptr.hpp>
+
+class BitmapEx;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapReplacement;
+
+
+/** This interface class provides the minimal method set for classes that
+ implement the compression and decompression of preview bitmaps.
+*/
+class BitmapCompressor
+{
+public:
+ /** Compress the given bitmap into a replacement format that is specific
+ to the compressor class.
+ */
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const = 0;
+
+ /** Decompress the given replacement data into a preview bitmap.
+ Depending on the compression technique the returned bitmap may
+ differ from the original bitmap given to the Compress() method. It
+ may even of the wrong size or empty or the NULL pointer. It is the
+ task of the caller to create a new preview bitmap if the returned
+ one is not as desired.
+ */
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData)const=0;
+
+ /** Return whether the compression and decompression is lossless. This
+ value is used by the caller of Decompress() to decide whether to use
+ the returned bitmap as is or if a new preview has to be created.
+ */
+ virtual bool IsLossless (void) const = 0;
+};
+
+
+
+/** Interface for preview bitmap replacements. Each bitmap
+ compressor/decompressor has to provide an implementation that is
+ suitable to store the compressed bitmaps.
+*/
+class BitmapReplacement
+{
+public:
+ virtual sal_Int32 GetMemorySize (void) const { return 0; }
+};
+
+
+
+
+/** This is one trivial bitmap compressor. It stores bitmaps unmodified
+ instead of compressing them.
+ This compressor is lossless.
+*/
+class NoBitmapCompression
+ : public BitmapCompressor
+{
+ class DummyReplacement;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** This is another trivial bitmap compressor. Instead of compressing a
+ bitmap, it throws the bitmap away. Its Decompress() method returns a
+ NULL pointer. The caller has to create a new preview bitmap instead.
+ This compressor clearly is not lossless.
+*/
+class CompressionByDeletion
+ : public BitmapCompressor
+{
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** Compress a preview bitmap by reducing its resolution. While the aspect
+ ratio is maintained the horizontal resolution is scaled down to 100
+ pixels.
+ This compressor is not lossless.
+*/
+class ResolutionReduction
+ : public BitmapCompressor
+{
+ class ResolutionReducedReplacement;
+ static const sal_Int32 mnWidth = 100;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ /** Scale the replacement bitmap up to the original size.
+ */
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+
+
+/** Compress preview bitmaps using the PNG format.
+ This compressor is lossless.
+*/
+class PngCompression
+ : public BitmapCompressor
+{
+ class PngReplacement;
+public:
+ virtual ::boost::shared_ptr<BitmapReplacement> Compress (
+ const ::boost::shared_ptr<BitmapEx>& rpBitmap) const;
+ virtual ::boost::shared_ptr<BitmapEx> Decompress (const BitmapReplacement& rBitmapData) const;
+ virtual bool IsLossless (void) const;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx
new file mode 100644
index 000000000000..912a4ea102fc
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsBitmapFactory.hxx"
+
+#include "PreviewRenderer.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include <svx/svdtypes.hxx>
+#include <svx/svdpage.hxx>
+#include <vcl/bitmapex.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+class PageObjectViewObjectContact;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+BitmapFactory::BitmapFactory (void)
+ : maRenderer(NULL,false)
+{
+}
+
+
+
+
+BitmapFactory::~BitmapFactory (void)
+{
+}
+
+
+
+
+::boost::shared_ptr<BitmapEx> BitmapFactory::CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize)
+{
+ Image aPreview (maRenderer.RenderPage (
+ &rPage,
+ rPixelSize,
+ String()));
+
+ return ::boost::shared_ptr<BitmapEx>(new BitmapEx(aPreview.GetBitmapEx()));
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx
new file mode 100644
index 000000000000..5073774155e2
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PREVIEW_BITMAP_FACTORY_HXX
+#define SD_SLIDESORTER_PREVIEW_BITMAP_FACTORY_HXX
+
+#include "PreviewRenderer.hxx"
+#include <boost/shared_ptr.hpp>
+
+class BitmapEx;
+class SdPage;
+class Size;
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** This factory class creates preview bitmaps for page objects. It is
+ merely an adapter for the PreviewRenderer.
+*/
+class BitmapFactory
+{
+public:
+ BitmapFactory (void);
+ ~BitmapFactory (void);
+
+ ::boost::shared_ptr<BitmapEx> CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize);
+
+private:
+ PreviewRenderer maRenderer;
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx
new file mode 100644
index 000000000000..2eb3d5495aa7
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.cxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsCacheCompactor.hxx"
+
+#include "SlsBitmapCompressor.hxx"
+#include "SlsBitmapCache.hxx"
+#include "SlsCacheCompactor.hxx"
+#include "SlsCacheConfiguration.hxx"
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <set>
+
+using namespace ::com::sun::star::uno;
+
+// Uncomment the definition of VERBOSE to get some more OSL_TRACE messages.
+#ifdef DEBUG
+//#define VERBOSE
+#endif
+
+namespace {
+
+/** This is a trivial implementation of the CacheCompactor interface class.
+ It ignores calls to RequestCompaction() and thus will never decrease the
+ total size of off-screen preview bitmaps.
+*/
+class NoCacheCompaction
+ : public ::sd::slidesorter::cache::CacheCompactor
+{
+public:
+ NoCacheCompaction (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+ : CacheCompactor(rCache, nMaximalCacheSize)
+ {}
+
+ virtual void RequestCompaction (void) { /* Ignored */ };
+
+protected:
+ virtual void Run (void) { /* Do nothing */ };
+};
+
+
+
+
+/** This implementation of the CacheCompactor interface class uses one of
+ several bitmap compression algorithms to reduce the number of the bytes
+ of the off-screen previews in the bitmap cache. See the documentation
+ of CacheCompactor::Create() for more details on configuration properties
+ that control the choice of compression algorithm.
+*/
+class CacheCompactionByCompression
+ : public ::sd::slidesorter::cache::CacheCompactor
+{
+public:
+ CacheCompactionByCompression (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor>& rpCompressor);
+
+protected:
+ virtual void Run (void);
+
+private:
+ ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor> mpCompressor;
+};
+
+
+} // end of anonymous namespace
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+::std::auto_ptr<CacheCompactor> CacheCompactor::Create (
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+{
+ static const ::rtl::OUString sNone (RTL_CONSTASCII_USTRINGPARAM("None"));
+ static const ::rtl::OUString sCompress (RTL_CONSTASCII_USTRINGPARAM("Compress"));
+ static const ::rtl::OUString sErase (RTL_CONSTASCII_USTRINGPARAM("Erase"));
+ static const ::rtl::OUString sResolution (RTL_CONSTASCII_USTRINGPARAM("ResolutionReduction"));
+ static const ::rtl::OUString sPNGCompression (RTL_CONSTASCII_USTRINGPARAM("PNGCompression"));
+
+ ::boost::shared_ptr<BitmapCompressor> pCompressor;
+ ::rtl::OUString sCompressionPolicy(sPNGCompression);
+ Any aCompressionPolicy (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CompressionPolicy"))));
+ if (aCompressionPolicy.has<rtl::OUString>())
+ aCompressionPolicy >>= sCompressionPolicy;
+ if (sCompressionPolicy == sNone)
+ pCompressor.reset(new NoBitmapCompression());
+ else if (sCompressionPolicy == sErase)
+ pCompressor.reset(new CompressionByDeletion());
+ else if (sCompressionPolicy == sResolution)
+ pCompressor.reset(new ResolutionReduction());
+ else
+ pCompressor.reset(new PngCompression());
+
+ ::std::auto_ptr<CacheCompactor> pCompactor (NULL);
+ ::rtl::OUString sCompactionPolicy(sCompress);
+ Any aCompactionPolicy (CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CompactionPolicy"))));
+ if (aCompactionPolicy.has<rtl::OUString>())
+ aCompactionPolicy >>= sCompactionPolicy;
+ if (sCompactionPolicy == sNone)
+ pCompactor.reset(new NoCacheCompaction(rCache,nMaximalCacheSize));
+ else
+ pCompactor.reset(new CacheCompactionByCompression(rCache,nMaximalCacheSize,pCompressor));
+
+ return pCompactor;
+}
+
+
+
+
+void CacheCompactor::RequestCompaction (void)
+{
+ if ( ! mbIsCompactionRunning && ! maCompactionTimer.IsActive())
+ maCompactionTimer.Start();
+}
+
+
+
+
+CacheCompactor::CacheCompactor(
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize)
+ : mrCache(rCache),
+ mnMaximalCacheSize(nMaximalCacheSize),
+ mbIsCompactionRunning(false)
+{
+ maCompactionTimer.SetTimeout(100 /*ms*/);
+ maCompactionTimer.SetTimeoutHdl(LINK(this,CacheCompactor,CompactionCallback));
+
+}
+
+
+
+
+IMPL_LINK(CacheCompactor, CompactionCallback, Timer*, EMPTYARG)
+{
+ mbIsCompactionRunning = true;
+
+ try
+ {
+ Run();
+ }
+ catch(::com::sun::star::uno::RuntimeException e) { }
+ catch(::com::sun::star::uno::Exception e) { }
+
+ mbIsCompactionRunning = false;
+ return 1;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+
+namespace {
+
+//===== CacheCompactionByCompression ==========================================
+
+CacheCompactionByCompression::CacheCompactionByCompression (
+ ::sd::slidesorter::cache::BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::BitmapCompressor>& rpCompressor)
+ : CacheCompactor(rCache,nMaximalCacheSize),
+ mpCompressor(rpCompressor)
+{
+}
+
+
+
+
+void CacheCompactionByCompression::Run (void)
+{
+ if (mrCache.GetSize() > mnMaximalCacheSize)
+ {
+#ifdef VERBOSE
+ OSL_TRACE ("bitmap cache uses to much space: %d > %d",
+ mrCache.GetSize(), mnMaximalCacheSize);
+#endif
+
+ ::std::auto_ptr< ::sd::slidesorter::cache::BitmapCache::CacheIndex> pIndex (
+ mrCache.GetCacheIndex(false,false));
+ ::sd::slidesorter::cache::BitmapCache::CacheIndex::iterator iIndex;
+ for (iIndex=pIndex->begin(); iIndex!=pIndex->end(); ++iIndex)
+ {
+ if (*iIndex == NULL)
+ continue;
+
+ mrCache.Compress(*iIndex, mpCompressor);
+ if (mrCache.GetSize() < mnMaximalCacheSize)
+ break;
+ }
+ mrCache.ReCalculateTotalCacheSize();
+#ifdef VERBOSE
+ OSL_TRACE (" there are now %d bytes occupied", mrCache.GetSize());
+#endif
+ }
+}
+
+
+} // end of anonymous namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx
new file mode 100644
index 000000000000..cd8067056005
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheCompactor.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_COMPACTOR_HXX
+#define SD_SLIDESORTER_CACHE_COMPACTOR_HXX
+
+#include <sal/types.h>
+#include <vcl/timer.hxx>
+#include <memory>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class BitmapCompressor;
+
+/** This is an interface class whose implementations are created via the
+ Create() factory method.
+*/
+class CacheCompactor
+{
+public:
+ virtual ~CacheCompactor (void) {};
+
+ /** Create a new instance of the CacheCompactor interface class. The
+ type of compaction algorithm used depends on values from the
+ configuration: the SlideSorter/PreviewCache/CompactionPolicy
+ property of the Impress.xcs file currently supports the values
+ "None" and "Compress". With the later the CompressionPolicy
+ property is evaluated which implementation of the BitmapCompress
+ interface class to use as bitmap compressor.
+ @param rCache
+ The bitmap cache on which to operate.
+ @param nMaximalCacheSize
+ The total number of bytes the off-screen bitmaps in the cache
+ may have. When the Run() method is (indirectly) called the
+ compactor tries to reduce that summed size of off-screen bitmaps
+ under this number. However, it is not guaranteed that this
+ works in all cases.
+ */
+ static ::std::auto_ptr<CacheCompactor> Create (
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize);
+
+ /** Request a compaction of the off-screen previews in the bitmap
+ cache. This calls via a timer the Run() method.
+ */
+ virtual void RequestCompaction (void);
+
+protected:
+ BitmapCache& mrCache;
+ sal_Int32 mnMaximalCacheSize;
+
+ CacheCompactor(
+ BitmapCache& rCache,
+ sal_Int32 nMaximalCacheSize);
+
+ /** This method actually tries to reduce the total number of bytes used
+ by the off-screen preview bitmaps.
+ */
+ virtual void Run (void) = 0;
+
+private:
+ /** This timer is used to collect calles to RequestCompaction() and
+ eventually call Run().
+ */
+ Timer maCompactionTimer;
+ bool mbIsCompactionRunning;
+ DECL_LINK(CompactionCallback, Timer*);
+};
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx
new file mode 100644
index 000000000000..f1159b2811e3
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsCacheConfiguration.hxx"
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+::boost::shared_ptr<CacheConfiguration> CacheConfiguration::mpInstance;
+::boost::weak_ptr<CacheConfiguration> CacheConfiguration::mpWeakInstance;
+Timer CacheConfiguration::maReleaseTimer;
+
+
+
+::boost::shared_ptr<CacheConfiguration> CacheConfiguration::Instance (void)
+{
+ SolarMutexGuard aSolarGuard;
+ if (mpInstance.get() == NULL)
+ {
+ // Maybe somebody else kept a previously created instance alive.
+ if ( ! mpWeakInstance.expired())
+ mpInstance = ::boost::shared_ptr<CacheConfiguration>(mpWeakInstance);
+ if (mpInstance.get() == NULL)
+ {
+ // We have to create a new instance.
+ mpInstance.reset(new CacheConfiguration());
+ mpWeakInstance = mpInstance;
+ // Prepare to release this instance in the near future.
+ maReleaseTimer.SetTimeoutHdl(
+ LINK(mpInstance.get(),CacheConfiguration,TimerCallback));
+ maReleaseTimer.SetTimeout(5000 /* 5s */);
+ maReleaseTimer.Start();
+ }
+ }
+ return mpInstance;
+}
+
+
+
+
+CacheConfiguration::CacheConfiguration (void)
+{
+ // Get the cache size from configuration.
+ const ::rtl::OUString sConfigurationProviderServiceName(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationProvider"));
+ const ::rtl::OUString sPathToImpressConfigurationRoot(
+ RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/"));
+ const ::rtl::OUString sPathToNode(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "MultiPaneGUI/SlideSorter/PreviewCache"));
+
+ try
+ {
+ // Obtain access to the configuration.
+ Reference<lang::XMultiServiceFactory> xProvider (
+ ::comphelper::getProcessServiceFactory()->createInstance(
+ sConfigurationProviderServiceName),
+ UNO_QUERY);
+ if ( ! xProvider.is())
+ return;
+
+ // Obtain access to Impress configuration.
+ Sequence<Any> aCreationArguments(3);
+ aCreationArguments[0] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("nodepath")),
+ 0,
+ makeAny(sPathToImpressConfigurationRoot),
+ beans::PropertyState_DIRECT_VALUE));
+ aCreationArguments[1] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("depth")),
+ 0,
+ makeAny((sal_Int32)-1),
+ beans::PropertyState_DIRECT_VALUE));
+ aCreationArguments[2] = makeAny(beans::PropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("lazywrite")),
+ 0,
+ makeAny(true),
+ beans::PropertyState_DIRECT_VALUE));
+ ::rtl::OUString sAccessService (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.configuration.ConfigurationAccess")));
+ Reference<XInterface> xRoot (xProvider->createInstanceWithArguments(
+ sAccessService, aCreationArguments));
+ if ( ! xRoot.is())
+ return;
+ Reference<container::XHierarchicalNameAccess> xHierarchy (xRoot, UNO_QUERY);
+ if ( ! xHierarchy.is())
+ return;
+
+ // Get the node for the slide sorter preview cache.
+ mxCacheNode = Reference<container::XNameAccess>(
+ xHierarchy->getByHierarchicalName(sPathToNode),
+ UNO_QUERY);
+ }
+ catch (RuntimeException aException)
+ {
+ (void)aException;
+ }
+ catch (Exception aException)
+ {
+ (void)aException;
+ }
+}
+
+
+
+
+Any CacheConfiguration::GetValue (const ::rtl::OUString& rName)
+{
+ Any aResult;
+
+ if (mxCacheNode != NULL)
+ {
+ try
+ {
+ aResult = mxCacheNode->getByName(rName);
+ }
+ catch (Exception aException)
+ {
+ (void)aException;
+ }
+ }
+
+ return aResult;
+}
+
+
+
+
+IMPL_LINK(CacheConfiguration,TimerCallback, Timer*,EMPTYARG)
+{
+ // Release out reference to the instance.
+ mpInstance.reset();
+ return 0;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx
new file mode 100644
index 000000000000..27d788867378
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsCacheConfiguration.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_CONFIGURATION_HXX
+#define SD_SLIDESORTER_CACHE_CONFIGURATION_HXX
+
+#include <com/sun/star/uno/Any.hxx>
+#include <vcl/timer.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** A very simple and easy-to-use access to configuration entries regarding
+ the slide sorter cache.
+*/
+class CacheConfiguration
+{
+public:
+ /** Return an instance to this class. The reference is released after 5
+ seconds. Subsequent calls to this function will create a new
+ instance.
+ */
+ static ::boost::shared_ptr<CacheConfiguration> Instance (void);
+
+ /** Look up the specified value in
+ MultiPaneGUI/SlideSorter/PreviewCache. When the specified value
+ does not exist then an empty Any is returned.
+ */
+ ::com::sun::star::uno::Any GetValue (const ::rtl::OUString& rName);
+
+private:
+ static ::boost::shared_ptr<CacheConfiguration> mpInstance;
+ /** When a caller holds a reference after we have released ours we use
+ this weak pointer to avoid creating a new instance.
+ */
+ static ::boost::weak_ptr<CacheConfiguration> mpWeakInstance;
+ static Timer maReleaseTimer;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::container::XNameAccess> mxCacheNode;
+
+ CacheConfiguration (void);
+
+ DECL_LINK(TimerCallback, Timer*);
+};
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx
new file mode 100644
index 000000000000..ede73b79025b
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsGenericPageCache.hxx"
+
+#include "SlsQueueProcessor.hxx"
+#include "SlsRequestPriorityClass.hxx"
+#include "SlsRequestFactory.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "controller/SlideSorterController.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+GenericPageCache::GenericPageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : mpBitmapCache(),
+ maRequestQueue(rpCacheContext),
+ mpQueueProcessor(),
+ mpCacheContext(rpCacheContext),
+ maPreviewSize(rPreviewSize)
+{
+}
+
+
+
+
+GenericPageCache::~GenericPageCache (void)
+{
+ OSL_TRACE("terminating queue processor %p", mpQueueProcessor.get());
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Stop();
+ maRequestQueue.Clear();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Terminate();
+ mpQueueProcessor.reset();
+ OSL_TRACE("queue processor stopped and terminated");
+
+ if (mpBitmapCache.get() != NULL)
+ PageCacheManager::Instance()->ReleaseCache(mpBitmapCache);
+ mpBitmapCache.reset();
+}
+
+
+
+
+void GenericPageCache::ProvideCacheAndProcessor (void)
+{
+ if (mpBitmapCache.get() == NULL)
+ mpBitmapCache = PageCacheManager::Instance()->GetCache(
+ mpCacheContext->GetModel(),
+ maPreviewSize);
+
+ if (mpQueueProcessor.get() == NULL)
+ mpQueueProcessor.reset(new QueueProcessor(
+ maRequestQueue,
+ mpBitmapCache,
+ maPreviewSize,
+ mpCacheContext));
+}
+
+
+
+
+void GenericPageCache::ChangePreviewSize (const Size& rPreviewSize)
+{
+ if (rPreviewSize != maPreviewSize)
+ {
+ if (mpBitmapCache.get() != NULL)
+ {
+ mpBitmapCache = PageCacheManager::Instance()->ChangeSize(
+ mpBitmapCache, maPreviewSize, rPreviewSize);
+ if (mpQueueProcessor.get() != NULL)
+ {
+ mpQueueProcessor->SetPreviewSize(rPreviewSize);
+ mpQueueProcessor->SetBitmapCache(mpBitmapCache);
+ }
+ }
+ maPreviewSize = rPreviewSize;
+ }
+}
+
+
+
+
+BitmapEx GenericPageCache::GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ BitmapEx aPreview;
+ bool bMayBeUpToDate = true;
+ ProvideCacheAndProcessor();
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+ if (mpBitmapCache->HasBitmap(pPage))
+ {
+ ::boost::shared_ptr<BitmapEx> pPreview(mpBitmapCache->GetBitmap(pPage));
+ OSL_ASSERT(pPreview.get() != NULL);
+ aPreview = *pPreview;
+ Size aBitmapSize (aPreview.GetSizePixel());
+ if (aBitmapSize != rSize)
+ {
+ // The bitmap has the wrong size.
+ DBG_ASSERT (rSize.Width() < 1000,
+ "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. "
+ "This may indicate an error.");
+
+ // Scale the bitmap to the desired size when that is possible,
+ // i.e. the bitmap is not empty.
+ if (aBitmapSize.Width()>0 && aBitmapSize.Height()>0)
+ aPreview.Scale (rSize, BMP_SCALE_FAST);
+ }
+ bMayBeUpToDate = true;
+ }
+ else
+ bMayBeUpToDate = false;
+
+ // Request the creation of a correctly sized preview bitmap. We do this
+ // even when the size of the bitmap in the cache is correct because its
+ // content may be not up-to-date anymore.
+ RequestPreviewBitmap(aKey, rSize, bMayBeUpToDate);
+
+ return aPreview;
+}
+
+
+
+
+void GenericPageCache::RequestPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize,
+ bool bMayBeUpToDate)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+
+ ProvideCacheAndProcessor();
+
+ // Determine if the available bitmap is up to date.
+ bool bIsUpToDate = false;
+ if (bMayBeUpToDate)
+ bIsUpToDate = mpBitmapCache->BitmapIsUpToDate (pPage);
+ if (bIsUpToDate)
+ {
+ ::boost::shared_ptr<BitmapEx> pPreview (mpBitmapCache->GetBitmap(pPage));
+ if (pPreview.get()==NULL || pPreview->GetSizePixel()!=rSize)
+ bIsUpToDate = false;
+ }
+
+ if ( ! bIsUpToDate)
+ {
+ // No, the bitmap is not up-to-date. Request a new one.
+ RequestPriorityClass ePriorityClass (NOT_VISIBLE);
+ if (mpCacheContext->IsVisible(aKey))
+ {
+ if (mpBitmapCache->HasBitmap(pPage))
+ ePriorityClass = VISIBLE_OUTDATED_PREVIEW;
+ else
+ ePriorityClass = VISIBLE_NO_PREVIEW;
+ }
+ maRequestQueue.AddRequest(aKey, ePriorityClass);
+ mpQueueProcessor->Start(ePriorityClass);
+ }
+}
+
+
+
+
+void GenericPageCache::ReleasePreviewBitmap (CacheKey aKey)
+{
+ if (mpBitmapCache.get() != NULL)
+ {
+ // Suspend the queue processing temporarily to avoid the reinsertion
+ // of the request that is to be deleted.
+ mpQueueProcessor->Stop();
+
+ maRequestQueue.RemoveRequest(aKey);
+ mpQueueProcessor->RemoveRequest(aKey);
+
+ // Resume the queue processing.
+ if ( ! maRequestQueue.IsEmpty())
+ {
+ try
+ {
+ mpQueueProcessor->Start(maRequestQueue.GetFrontPriorityClass());
+ }
+ catch (::com::sun::star::uno::RuntimeException)
+ {
+ }
+ }
+ }
+
+ // We do not relase the preview bitmap that is associated with the page
+ // of the given request data because this method is called when the
+ // request data, typically a view-object-contact object, is destroyed.
+ // The page object usually lives longer than that and thus the preview
+ // bitmap may be used later on.
+}
+
+
+
+
+void GenericPageCache::InvalidateCache (bool bUpdateCache)
+{
+ if (mpBitmapCache.get() != NULL)
+ {
+ // When the cache is being invalidated then it makes no sense to
+ // continue creating preview bitmaps. However, this may be
+ // re-started below.
+ mpQueueProcessor->Stop();
+ maRequestQueue.Clear();
+
+ // Mark the previews in the cache as not being up-to-date anymore.
+ // Depending on the given bUpdateCache flag we start to create new
+ // preview bitmaps.
+ mpBitmapCache->InvalidateCache();
+ if (bUpdateCache)
+ RequestFactory()(maRequestQueue, mpCacheContext);
+ }
+}
+
+
+
+
+void GenericPageCache::SetPreciousFlag (CacheKey aKey, bool bIsPrecious)
+{
+ ProvideCacheAndProcessor();
+
+ // Change the request priority class according to the new precious flag.
+ if (bIsPrecious)
+ {
+ if (mpBitmapCache->HasBitmap(mpCacheContext->GetPage(aKey)))
+ maRequestQueue.ChangeClass(aKey,VISIBLE_OUTDATED_PREVIEW);
+ else
+ maRequestQueue.ChangeClass(aKey,VISIBLE_NO_PREVIEW);
+ }
+ else
+ {
+ if (mpBitmapCache->IsFull())
+ {
+ // When the bitmap cache is full then requests for slides that
+ // are not visible are removed.
+ maRequestQueue.RemoveRequest(aKey);
+ }
+ else
+ maRequestQueue.ChangeClass(aKey,NOT_VISIBLE);
+ }
+
+ mpBitmapCache->SetPrecious(mpCacheContext->GetPage(aKey), bIsPrecious);
+}
+
+
+
+
+void GenericPageCache::Pause (void)
+{
+ ProvideCacheAndProcessor();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Pause();
+}
+
+
+
+
+void GenericPageCache::Resume (void)
+{
+ ProvideCacheAndProcessor();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Resume();
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx
new file mode 100644
index 000000000000..17074a0db6b0
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_GENERIC_PAGE_CACHE_HXX
+#define SD_SLIDESORTER_GENERIC_PAGE_CACHE_HXX
+
+#include "SlideSorter.hxx"
+#include "SlsRequestQueue.hxx"
+#include "SlsQueueProcessor.hxx"
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class QueueProcessor;
+
+/** This basically is the implementation class for the PageCache class.
+*/
+class GenericPageCache
+{
+public:
+ /** The page chache is created with references both to the SlideSorter.
+ This allows access to both view and model and the cache can so fill
+ itself with requests for all or just the visible pages.
+ */
+ GenericPageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext);
+
+ ~GenericPageCache (void);
+
+ /** Change the size of the preview bitmaps. This may be caused by a
+ resize of the slide sorter window or a change of the number of
+ columns.
+ */
+ void ChangePreviewSize (const Size& rPreviewSize);
+
+ /** Request a preview bitmap for the specified page object in the
+ specified size. The returned bitmap may be preview of the preview,
+ i.e. either a scaled (up or down) version of a previous preview (of
+ the wrong size) or an empty bitmap. In this case a request for the
+ generation of a new preview is created and inserted into the request
+ queue. When the preview is available the page shape will be told to
+ paint itself again. When it then calls this method again if
+ receives the correctly sized preview bitmap.
+ @param rRequestData
+ This data is used to determine the preview.
+ @param rSize
+ The size of the requested preview bitmap.
+ @return
+ Returns a bitmap that is either empty, contains a scaled (up or
+ down) version or is the requested bitmap.
+ */
+ BitmapEx GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize);
+
+ /** When the requested preview bitmap does not yet exist or is not
+ up-to-date then the rendering of one is scheduled. Otherwise this
+ method does nothing.
+ @param rRequestData
+ This data is used to determine the preview.
+ @param rSize
+ The size of the requested preview bitmap in pixel coordinates.
+ @param bMayBeUpToDate
+ This flag helps the method to determine whether an existing
+ preview that matches the request is up to date. If the caller
+ know that it is not then by passing <FALSE/> he tells us that we
+ do not have to check the up-to-date flag a second time. If
+ unsure pass <TRUE/>.
+ */
+ void RequestPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize,
+ bool bMayBeUpToDate = true);
+
+ /** Call this method when a view-object-contact object is being deleted
+ and does not need (a) its current bitmap in the cache and (b) a
+ requested a new bitmap.
+ */
+ void ReleasePreviewBitmap (CacheKey aKey);
+
+ /** Call this method when all preview bitmaps have to be generated anew.
+ This is the case when the size of the page objects on the screen has
+ changed or when the model has changed.
+ */
+ void InvalidateCache (bool bUpdateCache);
+
+ /** With the precious flag you can control whether a bitmap can be
+ removed from the cache or reduced in size to make room for other
+ bitmaps or is so precious that it will not be touched. A typical
+ use is to set the precious flag for the visible pages.
+ */
+ void SetPreciousFlag (CacheKey aKey, bool bIsPrecious);
+
+ void Pause (void);
+ void Resume (void);
+
+private:
+ ::boost::shared_ptr<BitmapCache> mpBitmapCache;
+
+ RequestQueue maRequestQueue;
+
+ ::boost::scoped_ptr<QueueProcessor> mpQueueProcessor;
+
+ SharedCacheContext mpCacheContext;
+
+ /** The current size of preview bitmaps.
+ */
+ Size maPreviewSize;
+
+ /** Both bitmap cache and queue processor are created on demand by this
+ method.
+ */
+ void ProvideCacheAndProcessor (void);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsPageCache.cxx b/sd/source/ui/slidesorter/cache/SlsPageCache.cxx
new file mode 100644
index 000000000000..9558267ab7d0
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCache.cxx
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsGenericPageCache.hxx"
+#include "SlsRequestFactory.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "model/SlideSorterModel.hxx"
+#include <boost/bind.hpp>
+#include <boost/bind/protect.hpp>
+
+using namespace ::com::sun::star;
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== PageCache =============================================================
+
+PageCache::PageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : mpImplementation(
+ new GenericPageCache(
+ rPreviewSize,
+ rpCacheContext))
+{
+}
+
+
+
+
+PageCache::~PageCache (void)
+{
+}
+
+
+
+
+void PageCache::ChangeSize(const Size& rPreviewSize)
+{
+ mpImplementation->ChangePreviewSize(rPreviewSize);
+}
+
+
+
+
+BitmapEx PageCache::GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize)
+{
+ return mpImplementation->GetPreviewBitmap(aKey, rSize);
+}
+
+
+
+
+void PageCache::ReleasePreviewBitmap (
+ CacheKey aKey)
+{
+ mpImplementation->ReleasePreviewBitmap(aKey);
+}
+
+
+
+
+void PageCache::InvalidateCache (bool bUpdateCache)
+{
+ mpImplementation->InvalidateCache(bUpdateCache);
+}
+
+
+
+
+void PageCache::SetPreciousFlag (
+ CacheKey aKey,
+ bool bIsPrecious)
+{
+ mpImplementation->SetPreciousFlag(aKey, bIsPrecious);
+}
+
+
+
+
+void PageCache::Pause (void)
+{
+ mpImplementation->Pause();
+}
+
+
+
+
+void PageCache::Resume (void)
+{
+ mpImplementation->Resume();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx b/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx
new file mode 100644
index 000000000000..2fdf0bc7b117
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx
@@ -0,0 +1,449 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "cache/SlsPageCacheManager.hxx"
+
+#include "SlsBitmapCache.hxx"
+#include "view/SlideSorterView.hxx"
+#include "model/SlideSorterModel.hxx"
+
+#include <deque>
+#include <map>
+#include <boost/weak_ptr.hpp>
+
+namespace {
+
+/** Collection of data that is stored for all active preview caches.
+*/
+class CacheDescriptor
+{
+public:
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
+ Size maPreviewSize;
+
+ CacheDescriptor(
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
+ const Size& rPreviewSize)
+ :mpDocument(pDocument),maPreviewSize(rPreviewSize)
+ {}
+ /// Test for equality with respect to all members.
+ class Equal {public: bool operator() (
+ const CacheDescriptor& rDescriptor1, const CacheDescriptor& rDescriptor2) const {
+ return rDescriptor1.mpDocument==rDescriptor2.mpDocument
+ && rDescriptor1.maPreviewSize==rDescriptor2.maPreviewSize;
+ } };
+ /// Hash function that takes all members into account.
+ class Hash {public: size_t operator() (const CacheDescriptor& rDescriptor) const {
+ return (size_t)rDescriptor.mpDocument.get() + rDescriptor.maPreviewSize.Width();
+ } };
+};
+
+
+
+
+/** Collection of data that is stored for the inactive, recently used
+ caches.
+*/
+class RecentlyUsedCacheDescriptor
+{
+public:
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey mpDocument;
+ Size maPreviewSize;
+ ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache> mpCache;
+
+ RecentlyUsedCacheDescriptor(
+ ::sd::slidesorter::cache::PageCacheManager::DocumentKey pDocument,
+ const Size& rPreviewSize,
+ const ::boost::shared_ptr< ::sd::slidesorter::cache::PageCacheManager::Cache>& rpCache)
+ :mpDocument(pDocument),maPreviewSize(rPreviewSize),mpCache(rpCache)
+ {}
+};
+
+
+
+
+/** The list of recently used caches is organized as queue. When elements
+ are added the list is shortened to the maximally allowed number of
+ elements by removing the least recently used elements.
+*/
+typedef ::std::deque<RecentlyUsedCacheDescriptor> RecentlyUsedQueue;
+
+
+
+
+/** Compare the caches by preview size. Those that match the given size
+ come first, then, regardless of the given size, the largest ones before
+ the smaller ones.
+*/
+class BestFittingCacheComparer
+{
+public:
+ BestFittingCacheComparer (const Size& rPreferredSize)
+ : maPreferredSize(rPreferredSize)
+ {}
+ bool operator()(const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement1,
+ const ::sd::slidesorter::cache::PageCacheManager::BestFittingPageCaches::value_type& rElement2)
+ {
+ if (rElement1.first == maPreferredSize)
+ return true;
+ else if (rElement2.first == maPreferredSize)
+ return false;
+ else
+ return (rElement1.first.Width()*rElement1.first.Height()
+ > rElement2.first.Width()*rElement2.first.Height());
+ }
+
+private:
+ Size maPreferredSize;
+};
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** Container for the active caches.
+*/
+class PageCacheManager::PageCacheContainer
+ : public ::std::hash_map<CacheDescriptor,
+ ::boost::shared_ptr<PageCacheManager::Cache>,
+ CacheDescriptor::Hash,
+ CacheDescriptor::Equal>
+{
+public:
+ PageCacheContainer (void) {}
+
+ /** Compare entries in the cache container with respect to the cache
+ address only.
+ */
+ class CompareWithCache { public:
+ CompareWithCache(const ::boost::shared_ptr<PageCacheManager::Cache>& rpCache)
+ : mpCache(rpCache) {}
+ bool operator () (const PageCacheContainer::value_type& rValue)
+ { return rValue.second == mpCache; }
+ private:
+ ::boost::shared_ptr<PageCacheManager::Cache> mpCache;
+ };
+};
+
+
+/** The recently used caches are stored in one queue for each document.
+*/
+class PageCacheManager::RecentlyUsedPageCaches
+ : public ::std::map<DocumentKey,RecentlyUsedQueue>
+{
+public:
+ RecentlyUsedPageCaches (void) {};
+};
+
+
+
+
+class PageCacheManager::Deleter
+{
+public:
+ void operator() (PageCacheManager* pObject) { delete pObject; }
+};
+
+
+
+//===== PageCacheManager ====================================================
+
+::boost::weak_ptr<PageCacheManager> PageCacheManager::mpInstance;
+
+::boost::shared_ptr<PageCacheManager> PageCacheManager::Instance (void)
+{
+ ::boost::shared_ptr<PageCacheManager> pInstance;
+
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ pInstance = mpInstance.lock();
+ if (pInstance.get() == NULL)
+ {
+ pInstance = ::boost::shared_ptr<PageCacheManager>(
+ new PageCacheManager(),
+ PageCacheManager::Deleter());
+ mpInstance = pInstance;
+ }
+
+ return pInstance;
+}
+
+
+
+
+PageCacheManager::PageCacheManager (void)
+ : mpPageCaches(new PageCacheContainer()),
+ mpRecentlyUsedPageCaches(new RecentlyUsedPageCaches()),
+ mnMaximalRecentlyCacheCount(2)
+{
+}
+
+
+
+
+PageCacheManager::~PageCacheManager (void)
+{
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetCache (
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ ::boost::shared_ptr<Cache> pResult;
+
+ // Look for the cache in the list of active caches.
+ CacheDescriptor aKey (pDocument, rPreviewSize);
+ PageCacheContainer::iterator iCache (mpPageCaches->find(aKey));
+ if (iCache != mpPageCaches->end())
+ pResult = iCache->second;
+
+ // Look for the cache in the list of recently used caches.
+ if (pResult.get() == NULL)
+ pResult = GetRecentlyUsedCache(pDocument, rPreviewSize);
+
+ // Create the cache when no suitable one does exist.
+ if (pResult.get() == NULL)
+ pResult.reset(new Cache());
+
+ // The cache may be newly created and thus empty or is old and may
+ // contain previews that are not up-to-date. Recycle previews from
+ // other caches to fill in the holes.
+ Recycle(pResult, pDocument,rPreviewSize);
+
+ // Put the new (or old) cache into the container.
+ if (pResult.get() != NULL)
+ mpPageCaches->insert(PageCacheContainer::value_type(aKey, pResult));
+
+ return pResult;
+}
+
+
+
+
+void PageCacheManager::Recycle (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ BestFittingPageCaches aCaches;
+
+ // Add bitmap caches from active caches.
+ PageCacheContainer::iterator iActiveCache;
+ for (iActiveCache=mpPageCaches->begin(); iActiveCache!=mpPageCaches->end(); ++iActiveCache)
+ {
+ if (iActiveCache->first.mpDocument == pDocument)
+ aCaches.push_back(BestFittingPageCaches::value_type(
+ iActiveCache->first.maPreviewSize, iActiveCache->second));
+ }
+
+ // Add bitmap caches from recently used caches.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::const_iterator iRecentCache;
+ for (iRecentCache=iQueue->second.begin();iRecentCache!=iQueue->second.end();++iRecentCache)
+ aCaches.push_back(BestFittingPageCaches::value_type(
+ iRecentCache->maPreviewSize, iRecentCache->mpCache));
+ }
+
+ ::std::sort(aCaches.begin(), aCaches.end(), BestFittingCacheComparer(rPreviewSize));
+
+ BestFittingPageCaches::const_iterator iBestCache;
+ for (iBestCache=aCaches.begin(); iBestCache!=aCaches.end(); ++iBestCache)
+ {
+ rpCache->Recycle(*iBestCache->second);
+ }
+}
+
+
+
+
+void PageCacheManager::ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache)
+{
+ PageCacheContainer::iterator iCache (::std::find_if(
+ mpPageCaches->begin(),
+ mpPageCaches->end(),
+ PageCacheContainer::CompareWithCache(rpCache)));
+
+ if (iCache != mpPageCaches->end())
+ {
+ OSL_ASSERT(iCache->second == rpCache);
+
+ PutRecentlyUsedCache(iCache->first.mpDocument,iCache->first.maPreviewSize,rpCache);
+
+ mpPageCaches->erase(iCache);
+ }
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::ChangeSize (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ const Size& rOldPreviewSize,
+ const Size& rNewPreviewSize)
+{
+ (void)rOldPreviewSize;
+
+ ::boost::shared_ptr<Cache> pResult;
+
+ if (rpCache.get() != NULL)
+ {
+ // Look up the given cache in the list of active caches.
+ PageCacheContainer::iterator iCacheToChange (::std::find_if(
+ mpPageCaches->begin(),
+ mpPageCaches->end(),
+ PageCacheContainer::CompareWithCache(rpCache)));
+ OSL_ASSERT(iCacheToChange != mpPageCaches->end());
+ if (iCacheToChange != mpPageCaches->end())
+ {
+ OSL_ASSERT(iCacheToChange->second == rpCache);
+
+ // Now, we can change the preview size of the existing one by
+ // removing the cache from the list and re-insert it with the
+ // updated size.
+ const ::sd::slidesorter::cache::PageCacheManager::DocumentKey aKey (
+ iCacheToChange->first.mpDocument);
+ mpPageCaches->erase(iCacheToChange);
+ mpPageCaches->insert(PageCacheContainer::value_type(
+ CacheDescriptor(aKey,rNewPreviewSize),
+ rpCache));
+
+ pResult = rpCache;
+ }
+ }
+
+ return pResult;
+}
+
+
+
+
+void PageCacheManager::InvalidatePreviewBitmap (
+ DocumentKey pDocument,
+ const SdrPage* pKey)
+{
+ if (pDocument!=NULL)
+ {
+ // Iterate over all caches that are currently in use and invalidate
+ // the previews in those that belong to the document.
+ PageCacheContainer::iterator iCache;
+ for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
+ if (iCache->first.mpDocument == pDocument)
+ iCache->second->InvalidateBitmap(pKey);
+
+ // Invalidate the previews in the recently used caches belonging to
+ // the given document.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::const_iterator iCache2;
+ for (iCache2=iQueue->second.begin(); iCache2!=iQueue->second.end(); ++iCache2)
+ iCache2->mpCache->InvalidateBitmap(pKey);
+ }
+ }
+}
+
+
+
+
+void PageCacheManager::InvalidateAllCaches (void)
+{
+ // Iterate over all caches that are currently in use and invalidate
+ // them.
+ PageCacheContainer::iterator iCache;
+ for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
+ iCache->second->InvalidateCache();
+
+ // Remove all recently used caches, there is not much sense in storing
+ // invalidated and unused caches.
+ mpRecentlyUsedPageCaches->clear();
+}
+
+
+
+
+::boost::shared_ptr<PageCacheManager::Cache> PageCacheManager::GetRecentlyUsedCache (
+ DocumentKey pDocument,
+ const Size& rPreviewSize)
+{
+ ::boost::shared_ptr<Cache> pCache;
+
+ // Look for the cache in the list of recently used caches.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ RecentlyUsedQueue::iterator iCache;
+ for (iCache=iQueue->second.begin(); iCache!= iQueue->second.end(); ++iCache)
+ if (iCache->maPreviewSize == rPreviewSize)
+ {
+ pCache = iCache->mpCache;
+ iQueue->second.erase(iCache);
+ break;
+ }
+ }
+
+ return pCache;
+}
+
+
+
+
+void PageCacheManager::PutRecentlyUsedCache(
+ DocumentKey pDocument,
+ const Size& rPreviewSize,
+ const ::boost::shared_ptr<Cache>& rpCache)
+{
+ // Look up the list of recently used caches for the given document.
+ RecentlyUsedPageCaches::iterator iQueue (mpRecentlyUsedPageCaches->find(pDocument));
+ if (iQueue == mpRecentlyUsedPageCaches->end())
+ iQueue = mpRecentlyUsedPageCaches->insert(
+ RecentlyUsedPageCaches::value_type(pDocument, RecentlyUsedQueue())
+ ).first;
+
+ if (iQueue != mpRecentlyUsedPageCaches->end())
+ {
+ iQueue->second.push_front(RecentlyUsedCacheDescriptor(pDocument,rPreviewSize,rpCache));
+ // Shorten the list of recently used caches to the allowed maximal length.
+ while (iQueue->second.size() > mnMaximalRecentlyCacheCount)
+ iQueue->second.pop_back();
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx
new file mode 100644
index 000000000000..925da9d14ce0
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsQueueProcessor.hxx"
+#include "SlsCacheConfiguration.hxx"
+#include "SlsRequestQueue.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+//===== QueueProcessor ======================================================
+
+QueueProcessor::QueueProcessor (
+ RequestQueue& rQueue,
+ const ::boost::shared_ptr<BitmapCache>& rpCache,
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext)
+ : maMutex(),
+ maTimer(),
+ mnTimeBetweenHighPriorityRequests (10/*ms*/),
+ mnTimeBetweenLowPriorityRequests (100/*ms*/),
+ mnTimeBetweenRequestsWhenNotIdle (1000/*ms*/),
+ maPreviewSize(rPreviewSize),
+ mpCacheContext(rpCacheContext),
+ mrQueue(rQueue),
+ mpCache(rpCache),
+ maBitmapFactory(),
+ mbIsPaused(false)
+{
+ // Look into the configuration if there for overriding values.
+ ::com::sun::star::uno::Any aTimeBetweenReqeusts;
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenHighPriorityRequests")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenHighPriorityRequests;
+
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenLowPriorityRequests")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenLowPriorityRequests;
+
+ aTimeBetweenReqeusts = CacheConfiguration::Instance()->GetValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TimeBetweenRequestsDuringShow")));
+ if (aTimeBetweenReqeusts.has<sal_Int32>())
+ aTimeBetweenReqeusts >>= mnTimeBetweenRequestsWhenNotIdle;
+
+ maTimer.SetTimeoutHdl (LINK(this,QueueProcessor,ProcessRequestHdl));
+ maTimer.SetTimeout (mnTimeBetweenHighPriorityRequests);
+}
+
+
+
+
+
+QueueProcessor::~QueueProcessor (void)
+{
+}
+
+
+
+
+void QueueProcessor::Start (int nPriorityClass)
+{
+ if (mbIsPaused)
+ return;
+ if ( ! maTimer.IsActive())
+ {
+ if (nPriorityClass == 0)
+ maTimer.SetTimeout (mnTimeBetweenHighPriorityRequests);
+ else
+ maTimer.SetTimeout (mnTimeBetweenLowPriorityRequests);
+ maTimer.Start();
+ }
+}
+
+
+
+
+void QueueProcessor::Stop (void)
+{
+ if (maTimer.IsActive())
+ maTimer.Stop();
+}
+
+
+
+
+void QueueProcessor::Pause (void)
+{
+ mbIsPaused = true;
+}
+
+
+
+
+void QueueProcessor::Resume (void)
+{
+ mbIsPaused = false;
+ if ( ! mrQueue.IsEmpty())
+ Start(mrQueue.GetFrontPriorityClass());
+}
+
+
+
+
+void QueueProcessor::Terminate (void)
+{
+}
+
+
+
+
+void QueueProcessor::SetPreviewSize (const Size& rPreviewSize)
+{
+ maPreviewSize = rPreviewSize;
+}
+
+
+
+
+IMPL_LINK(QueueProcessor, ProcessRequestHdl, Timer*, EMPTYARG)
+{
+ ProcessRequests();
+ return 1;
+}
+
+
+
+
+void QueueProcessor::ProcessRequests (void)
+{
+ OSL_ASSERT(mpCacheContext.get()!=NULL);
+
+ // Never process more than one request at a time in order to prevent the
+ // lock up of the edit view.
+ if ( ! mrQueue.IsEmpty()
+ && ! mbIsPaused
+ && mpCacheContext->IsIdle())
+ {
+ CacheKey aKey = NULL;
+ RequestPriorityClass ePriorityClass (NOT_VISIBLE);
+ {
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+
+ if ( ! mrQueue.IsEmpty())
+ {
+ // Get the request with the highest priority from the queue.
+ ePriorityClass = mrQueue.GetFrontPriorityClass();
+ aKey = mrQueue.GetFront();
+ mrQueue.PopFront();
+ }
+ }
+
+ if (aKey != NULL)
+ ProcessOneRequest(aKey, ePriorityClass);
+ }
+
+ // Schedule the processing of the next element(s).
+ {
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+ if ( ! mrQueue.IsEmpty())
+ Start(mrQueue.GetFrontPriorityClass());
+ }
+}
+
+
+
+
+void QueueProcessor::ProcessOneRequest (
+ CacheKey aKey,
+ const RequestPriorityClass ePriorityClass)
+{
+ try
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Create a new preview bitmap and store it in the cache.
+ if (mpCache.get() != NULL
+ && mpCacheContext.get() != NULL)
+ {
+ const SdPage* pSdPage = dynamic_cast<const SdPage*>(mpCacheContext->GetPage(aKey));
+ if (pSdPage != NULL)
+ {
+ const ::boost::shared_ptr<BitmapEx> pPreview (
+ maBitmapFactory.CreateBitmap(*pSdPage, maPreviewSize));
+ mpCache->SetBitmap (
+ pSdPage,
+ pPreview,
+ ePriorityClass!=NOT_VISIBLE);
+
+ // Initiate a repaint of the new preview.
+ mpCacheContext->NotifyPreviewCreation(aKey, pPreview);
+ }
+ }
+ }
+ catch (::com::sun::star::uno::RuntimeException aException)
+ {
+ (void) aException;
+ OSL_ASSERT("RuntimeException caught in QueueProcessor");
+ }
+ catch (::com::sun::star::uno::Exception aException)
+ {
+ (void) aException;
+ OSL_ASSERT("Exception caught in QueueProcessor");
+ }
+}
+
+
+
+
+void QueueProcessor::RemoveRequest (CacheKey aKey)
+{
+ (void)aKey;
+ // See the method declaration above for an explanation why this makes sense.
+ ::osl::MutexGuard aGuard (maMutex);
+}
+
+
+
+
+void QueueProcessor::SetBitmapCache (
+ const ::boost::shared_ptr<BitmapCache>& rpCache)
+{
+ mpCache = rpCache;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx
new file mode 100644
index 000000000000..ba25b8b3a14b
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_QUEUE_PROCESSOR_HXX
+#define SD_SLIDESORTER_QUEUE_PROCESSOR_HXX
+
+#include "cache/SlsPageCache.hxx"
+#include "SlsRequestPriorityClass.hxx"
+#include "SlsBitmapFactory.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "tools/IdleDetection.hxx"
+#include "SlsBitmapCache.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+
+#include <svx/svdpagv.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/timer.hxx>
+#include <boost/function.hpp>
+
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class BitmapCache;
+class RequestQueue;
+
+
+
+/** This queue processor is timer based, i.e. when an entry is added to the
+ queue and the processor is started with Start() in the base class a
+ timer is started that eventually calls ProcessRequest(). This is
+ repeated until the queue is empty or Stop() is called.
+*/
+class QueueProcessor
+{
+public:
+ typedef ::boost::function<bool()> IdleDetectionCallback;
+ QueueProcessor (
+ RequestQueue& rQueue,
+ const ::boost::shared_ptr<BitmapCache>& rpCache,
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext);
+ virtual ~QueueProcessor();
+
+ /** Start the processor. This implementation is timer based and waits
+ an defined amount of time that depends on the given argument before
+ the next entry in the queue is processed.
+ @param nPriorityClass
+ A priority class of 0 tells the processor that a high priority
+ request is waiting in the queue. The time to wait is thus
+ shorter then that for a low priority request (denoted by a value
+ of 1.) When the timer is already running it is not modified.
+ */
+ void Start (int nPriorityClass = 0);
+ void Stop (void);
+ void Pause (void);
+ void Resume (void);
+
+ void Terminate (void);
+
+ void SetPreviewSize (const Size& rSize);
+
+ /** As we can not really terminate the rendering of a preview bitmap for
+ a request in midair this method acts more like a semaphor. It
+ returns only when it is save for the caller to delete the request.
+ For this to work it is important to remove the request from the
+ queue before calling this method.
+ */
+ void RemoveRequest (CacheKey aKey);
+
+ /** Use this method when the page cache is (maybe) using a different
+ BitmapCache. This is usually necessary after calling
+ PageCacheManager::ChangeSize().
+ */
+ void SetBitmapCache (const ::boost::shared_ptr<BitmapCache>& rpCache);
+
+private:
+ /** This mutex is used to guard the queue processor. Be carefull not to
+ mix its use with that of the solar mutex.
+ */
+ ::osl::Mutex maMutex;
+
+ Timer maTimer;
+ DECL_LINK(ProcessRequestHdl, Timer*);
+ sal_uInt32 mnTimeBetweenHighPriorityRequests;
+ sal_uInt32 mnTimeBetweenLowPriorityRequests;
+ sal_uInt32 mnTimeBetweenRequestsWhenNotIdle;
+ Size maPreviewSize;
+ SharedCacheContext mpCacheContext;
+ RequestQueue& mrQueue;
+ ::boost::shared_ptr<BitmapCache> mpCache;
+ BitmapFactory maBitmapFactory;
+ bool mbIsPaused;
+
+ void ProcessRequests (void);
+ void ProcessOneRequest (
+ CacheKey aKey,
+ const RequestPriorityClass ePriorityClass);
+};
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx b/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx
new file mode 100644
index 000000000000..b42a34102128
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
+#define SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
+
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include <vcl/svapp.hxx>
+#include <osl/thread.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+class QueueProcessorThread
+ : public ::osl::Thread
+{
+public:
+ QueueProcessorThread (
+ view::SlideSorterView& rView,
+ Queue& rQueue,
+ BitmapCache& rCache);
+ ~QueueProcessorThread (void);
+
+ /** Start the execution of a suspended thread. A thread is suspended
+ after Stop() is called or when the queue on which it operates is
+ empty. Calling Start() on a running thread is OK.
+ */
+ void Start (void);
+
+ /** Stop the thread by suspending it. To re-start its execution call
+ Start().
+ */
+ void Stop (void);
+
+ /** As we can not really terminate the rendering of a preview bitmap for
+ a request in midair this method acts more like a semaphor. It
+ returns only when it is save for the caller to delete the request.
+ For this to work it is important to remove the request from the
+ queue before calling this method.
+ */
+ void RemoveRequest (RequestData& rRequest);
+
+ /** Terminate the execution of the thread. When the thread is detached
+ it deletes itself. Otherwise the caller of this method may call
+ delete after this method returnes.
+ */
+ void SAL_CALL Terminate (void);
+
+protected:
+ /** This virutal method is called (among others?) from the
+ inherited create method and acts as the main function of this
+ thread.
+ */
+ virtual void SAL_CALL run (void);
+
+ /** Called after the thread is terminated via the terminate
+ method. Used to kill the thread by calling delete on this.
+ */
+ virtual void SAL_CALL onTerminated (void);
+
+private:
+ /** Flag that indicates wether the onTerminated method has been already
+ called. If so then a subsequent call to detach deletes the thread.
+ */
+ volatile bool mbIsTerminated;
+
+ volatile bool mbCanBeJoined;
+
+ /** This mutex is used to guard the queue processor. Be carefull not to
+ mix its use with that of the solar mutex.
+ */
+ ::osl::Mutex maMutex;
+
+ view::SlideSorterView& mrView;
+ Queue& mrQueue;
+ BitmapCache& mrCache;
+
+ void ProcessQueueEntry (void);
+};
+
+
+
+
+//===== QueueProcessorThread ================================================
+
+template <class Queue, class Request, class Cache, class Factory>
+ QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::QueueProcessorThread (
+ view::SlideSorterView& rView,
+ Queue& rQueue,
+ Cache& rCache)
+ : mbIsTerminated (false),
+ mbCanBeJoined (false),
+ mrView (rView),
+ mrQueue (rQueue),
+ mrCache (rCache)
+{
+ OSL_TRACE("QueueProcessorThread::constructor %p", this);
+ create();
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+ QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::~QueueProcessorThread (void)
+{
+ OSL_TRACE("QueueProcessorThread::destructor %p", this);
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+void SAL_CALL QueueProcessorThread<Queue, Request, Cache, Factory>::run (void)
+{
+ OSL_TRACE("QueueProcessorThread::run(): running thread %p", this);
+ while ( ! mbIsTerminated)
+ {
+ OSL_TRACE("QueueProcessorThread::run(): still running thread %p: %d", this, mbIsTerminated?1:0);
+ if (mrQueue.IsEmpty())
+ {
+ // Sleep while the queue is empty.
+ OSL_TRACE("QueueProcessorThread::run(): suspending thread %p", this);
+ suspend();
+ OSL_TRACE("QueueProcessorThread::run(): running again thread %p", this);
+ }
+
+ else if (GetpApp()->AnyInput())
+ {
+ yield();
+ // When there is input waiting to be processed we wait a short
+ // time and try again.
+ TimeValue aTimeToWait;
+ aTimeToWait.Seconds = 0;
+ aTimeToWait.Nanosec = 50*1000*1000;
+ OSL_TRACE("QueueProcessorThread::run(): input pending: waiting %d nanoseconds",
+ aTimeToWait.Nanosec);
+ wait (aTimeToWait);
+ }
+
+ else
+ {
+ OSL_TRACE ("QueueProcessorThread::run(): Processing Query");
+ ProcessQueueEntry();
+ yield ();
+ }
+ }
+ OSL_TRACE("QueueProcessorThread::run(): exiting run %p", this);
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+void QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::ProcessQueueEntry (void)
+{
+ Request* pRequest = NULL;
+ int nPriorityClass;
+ bool bRequestIsValid = false;
+
+ do
+ {
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): testing for mbIsTerminated %p", this);
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+ if (mrQueue.IsEmpty())
+ break;
+ }
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():acquiring mutex for bitmap creation %p", this);
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+
+ if (mrQueue.IsEmpty())
+ break;
+
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): have mutexes %p", this);
+
+ // Get the requeuest with the highest priority from the queue.
+ nPriorityClass = mrQueue.GetFrontPriorityClass();
+ pRequest = &mrQueue.GetFront();
+ mrQueue.PopFront();
+ bRequestIsValid = true;
+
+
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():using request %p for creating bitmap", pRequest);
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry():processing request for page %d with priority class ",
+ pRequest->GetPage()->GetPageNum(), nPriorityClass);
+ try
+ {
+ // Create a new preview bitmap and store it in the cache.
+ if (mbIsTerminated)
+ break;
+ BitmapEx aBitmap (Factory::CreateBitmap (*pRequest, mrView));
+ if (mbIsTerminated)
+ break;
+ mrCache.SetBitmap (
+ pRequest->GetPage(),
+ aBitmap,
+ nPriorityClass==0);
+ }
+ catch (...)
+ {
+ OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): caught exception; %p", this);
+ // We are rendering a preview and can do without if need
+ // be. So keep going if something happens that should
+ // not happen.
+ }
+ }
+ while (false);
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Start (void)
+{
+ OSL_TRACE ("QueueProcessorThread::Start %p", this);
+ resume ();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Stop (void)
+{
+ OSL_TRACE ("QueueProcessorThread::Stop %p", this);
+ suspend();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::RemoveRequest (RequestData& rRequest)
+{
+ OSL_TRACE ("QueueProcessorThread::RemoveRequest %p", this);
+ // Do nothing else then wait for the mutex to be released.
+ ::osl::MutexGuard aGuard (mrQueue.GetMutex());
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Terminate (void)
+{
+ // SolarMutexGuard aSolarGuard;
+ OSL_TRACE("QueueProcessorThread::Terminate(): terminating thread %p", this);
+ ::osl::Thread::terminate ();
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ OSL_TRACE("QueueProcessorThread::Terminate(): starting to join %p, %d", this, mbIsTerminated?1:0);
+ mbIsTerminated = true;
+ }
+ Start();
+}
+
+
+
+
+/** This callback method is called when the run() method terminates.
+*/
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void SAL_CALL QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::onTerminated (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ mbCanBeJoined = true;
+ /*
+ OSL_TRACE("QueueProcessorThread::Terminate():join %p, %d", this, mbIsTerminated?1:0);
+ while (true)
+ {
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbCanBeJoined)
+ break;
+ }
+ Start();
+ TimeValue aTimeToWait;
+ aTimeToWait.Seconds = 0;
+ aTimeToWait.Nanosec = 50*1000*1000;
+ OSL_TRACE("QueueProcessorThread::Terminate(): waiting for join");
+ wait (aTimeToWait);
+ }
+ if (mbCanBeJoined)
+ join();
+ else
+ OSL_TRACE("Can not join");
+ OSL_TRACE("QueueProcessorThread::Terminate():terminated thread %p :%d",
+ this, mbIsTerminated?1:0);
+ */
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx b/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx
new file mode 100644
index 000000000000..75963ea38cb9
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsRequestFactory.hxx"
+
+#include "SlsGenericPageCache.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include <svx/svdpagv.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+void RequestFactory::operator()(
+ RequestQueue& rRequestQueue,
+ const SharedCacheContext& rpCacheContext)
+{
+ ::boost::shared_ptr<std::vector<CacheKey> > aKeys;
+
+ // Add the requests for the visible pages.
+ aKeys = rpCacheContext->GetEntryList(true);
+ if (aKeys.get() != NULL)
+ {
+ std::vector<CacheKey>::const_iterator iKey;
+ std::vector<CacheKey>::const_iterator iEnd (aKeys->end());
+ for (iKey=aKeys->begin(); iKey!=iEnd; ++iKey)
+ rRequestQueue.AddRequest(*iKey, VISIBLE_NO_PREVIEW);
+ }
+
+ // Add the requests for the non-visible pages.
+ aKeys = rpCacheContext->GetEntryList(false);
+ if (aKeys.get() != NULL)
+ {
+ std::vector<CacheKey>::const_iterator iKey;
+ std::vector<CacheKey>::const_iterator iEnd (aKeys->end());
+ for (iKey=aKeys->begin(); iKey!=iEnd; ++iKey)
+ rRequestQueue.AddRequest(*iKey, NOT_VISIBLE);
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx b/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx
new file mode 100644
index 000000000000..f908598de2ee
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestFactory.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_REQUEST_FACTORY_HXX
+#define SD_SLIDESORTER_REQUEST_FACTORY_HXX
+
+#include "cache/SlsCacheContext.hxx"
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class RequestQueue;
+
+class RequestFactory
+{
+public:
+ void operator() (
+ RequestQueue& rRequestQueue,
+ const SharedCacheContext& rpCacheContext);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx b/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx
new file mode 100644
index 000000000000..077940a82cfb
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestPriorityClass.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_REQUEST_PRIORITY_CLASS_HXX
+#define SD_SLIDESORTER_CACHE_REQUEST_PRIORITY_CLASS_HXX
+
+namespace sd { namespace slidesorter { namespace cache {
+
+
+/** Each request for a preview creation has a priority. This enum defines
+ the available priorities. The special values MIN__CLASS and MAX__CLASS
+ are/can be used for validation and have to be kept up-to-date.
+*/
+enum RequestPriorityClass
+{
+ MIN__CLASS = 0,
+
+ // The slide is visible. A preview does not yet exist.
+ VISIBLE_NO_PREVIEW = MIN__CLASS,
+ // The slide is visible. A preview exists but is not up-to-date anymore.
+ VISIBLE_OUTDATED_PREVIEW,
+ // The slide is not visible.
+ NOT_VISIBLE,
+
+ MAX__CLASS = NOT_VISIBLE
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx b/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
new file mode 100644
index 000000000000..3004dddf7a85
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsRequestQueue.hxx"
+
+#include <set>
+
+
+#undef VERBOSE
+//#define VERBOSE
+
+namespace sd { namespace slidesorter { namespace cache {
+
+/** This class extends the actual request data with additional information
+ that is used by the priority queues.
+*/
+class Request
+{
+public:
+ Request (
+ CacheKey aKey, sal_Int32 nPriority, RequestPriorityClass eClass)
+ : maKey(aKey), mnPriorityInClass(nPriority), meClass(eClass)
+ {}
+ /** Sort requests according to priority classes and then to priorities.
+ */
+ class Comparator { public:
+ bool operator() (const Request& rRequest1, const Request& rRequest2)
+ {
+ if (rRequest1.meClass == rRequest2.meClass)
+ return (rRequest1.mnPriorityInClass > rRequest2.mnPriorityInClass);
+ else
+ return (rRequest1.meClass < rRequest2.meClass);
+ }
+ };
+ /** Request data is compared arbitrarily by their addresses in memory.
+ This just establishes an order so that the STL containers are happy.
+ The order is not semantically interpreted.
+ */
+ class DataComparator { public:
+ DataComparator (const Request&rRequest):maKey(rRequest.maKey){}
+ DataComparator (const CacheKey aKey):maKey(aKey){}
+ bool operator() (const Request& rRequest) { return maKey == rRequest.maKey; }
+ private: const CacheKey maKey;
+ };
+
+ CacheKey maKey;
+ sal_Int32 mnPriorityInClass;
+ RequestPriorityClass meClass;
+};
+
+
+class RequestQueue::Container
+ : public ::std::set<
+ Request,
+ Request::Comparator>
+{
+};
+
+
+
+
+//===== GenericRequestQueue =================================================
+
+
+RequestQueue::RequestQueue (const SharedCacheContext& rpCacheContext)
+ : maMutex(),
+ mpRequestQueue(new Container()),
+ mpCacheContext(rpCacheContext),
+ mnMinimumPriority(0),
+ mnMaximumPriority(1)
+{
+}
+
+
+
+
+RequestQueue::~RequestQueue (void)
+{
+}
+
+
+
+
+void RequestQueue::AddRequest (
+ CacheKey aKey,
+ RequestPriorityClass eRequestClass,
+ bool /*bInsertWithHighestPriority*/)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ OSL_ASSERT(eRequestClass>=MIN__CLASS && eRequestClass<=MAX__CLASS);
+
+ // If the request is already a member of the queue then remove it so
+ // that the following insertion will use the new prioritization.
+#ifdef VERBOSE
+ bool bRemoved =
+#endif
+ RemoveRequest(aKey);
+
+ // The priority of the request inside its priority class is defined by
+ // the page number. This ensures a strict top-to-bottom, left-to-right
+ // order.
+ sal_Int32 nPriority (mpCacheContext->GetPriority(aKey));
+ Request aRequest (aKey, nPriority, eRequestClass);
+ mpRequestQueue->insert(aRequest);
+
+ SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eRequestClass);
+
+#ifdef VERBOSE
+ OSL_TRACE("%s request for page %d with priority class %d",
+ bRemoved?"replaced":"added",
+ (rRequestData.GetPage()->GetPageNum()-1)/2,
+ eRequestClass);
+#endif
+}
+
+
+
+
+bool RequestQueue::RemoveRequest (
+ CacheKey aKey)
+{
+ bool bRequestWasRemoved (false);
+ ::osl::MutexGuard aGuard (maMutex);
+
+ while(true)
+ {
+ Container::const_iterator aRequestIterator = ::std::find_if (
+ mpRequestQueue->begin(),
+ mpRequestQueue->end(),
+ Request::DataComparator(aKey));
+ if (aRequestIterator != mpRequestQueue->end())
+ {
+ if (aRequestIterator->mnPriorityInClass == mnMinimumPriority+1)
+ mnMinimumPriority++;
+ else if (aRequestIterator->mnPriorityInClass == mnMaximumPriority-1)
+ mnMaximumPriority--;
+ mpRequestQueue->erase(aRequestIterator);
+ bRequestWasRemoved = true;
+
+ if (bRequestWasRemoved)
+ {
+ SSCD_SET_STATUS(rRequest.GetPage(),NONE);
+ }
+ }
+ else
+ break;
+ }
+
+ return bRequestWasRemoved;
+}
+
+
+
+
+void RequestQueue::ChangeClass (
+ CacheKey aKey,
+ RequestPriorityClass eNewRequestClass)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ OSL_ASSERT(eNewRequestClass>=MIN__CLASS && eNewRequestClass<=MAX__CLASS);
+
+ Container::const_iterator iRequest (
+ ::std::find_if (
+ mpRequestQueue->begin(),
+ mpRequestQueue->end(),
+ Request::DataComparator(aKey)));
+ if (iRequest!=mpRequestQueue->end() && iRequest->meClass!=eNewRequestClass)
+ {
+ AddRequest(aKey, eNewRequestClass, true);
+ SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eNewRequestClass);
+ }
+}
+
+
+
+
+CacheKey RequestQueue::GetFront (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mpRequestQueue->empty())
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "RequestQueue::GetFront(): queue is empty")),
+ NULL);
+
+ return mpRequestQueue->begin()->maKey;
+}
+
+
+
+
+RequestPriorityClass RequestQueue::GetFrontPriorityClass (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mpRequestQueue->empty())
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "RequestQueue::GetFrontPriorityClass(): queue is empty")),
+ NULL);
+
+ return mpRequestQueue->begin()->meClass;
+}
+
+
+
+
+void RequestQueue::PopFront (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if ( ! mpRequestQueue->empty())
+ {
+ SSCD_SET_STATUS(maRequestQueue.begin()->mpData->GetPage(),NONE);
+
+ mpRequestQueue->erase(mpRequestQueue->begin());
+
+ // Reset the priority counter if possible.
+ if (mpRequestQueue->empty())
+ {
+ mnMinimumPriority = 0;
+ mnMaximumPriority = 1;
+ }
+ }
+}
+
+
+
+
+bool RequestQueue::IsEmpty (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ return mpRequestQueue->empty();
+}
+
+
+
+
+void RequestQueue::Clear (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mpRequestQueue->clear();
+ mnMinimumPriority = 0;
+ mnMaximumPriority = 1;
+}
+
+
+
+
+::osl::Mutex& RequestQueue::GetMutex (void)
+{
+ return maMutex;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx b/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx
new file mode 100644
index 000000000000..5b9c0cdb27fb
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestQueue.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_REQUEST_QUEUE_HXX
+#define SD_SLIDESORTER_REQUEST_QUEUE_HXX
+
+#include "SlsRequestPriorityClass.hxx"
+#include "cache/SlsCacheContext.hxx"
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include <drawdoc.hxx>
+#include "osl/mutex.hxx"
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class RequestData;
+
+/** The request queue stores requests that are described by the RequestData
+ sorted according to priority class and then priority.
+*/
+class RequestQueue
+{
+public:
+ RequestQueue (const SharedCacheContext& rpCacheContext);
+ ~RequestQueue (void);
+
+ /** Insert a request with highest or lowest priority in its priority
+ class. When the request is already present then it is first
+ removed. This effect is then a re-prioritization.
+ @param rRequestData
+ The request.
+ @param eRequestClass
+ The priority class in which to insert the request with highest
+ or lowest priority.
+ @param bInsertWithHighestPriority
+ When this flag is <TRUE/> the request is inserted with highes
+ priority in its class. When <FALSE/> the request is inserted
+ with lowest priority.
+ */
+ void AddRequest (
+ CacheKey aKey,
+ RequestPriorityClass eRequestClass,
+ bool bInsertWithHighestPriority = false);
+
+ /** Remove the specified request from the queue.
+ @param rRequestData
+ It is OK when the specified request is not a member of the
+ queue.
+ @return
+ Returns <TRUE/> when the request has been successfully been
+ removed from the queue. Otherwise, e.g. because the request was
+ not a member of the queue, <FALSE/> is returned.
+ */
+ bool RemoveRequest (CacheKey aKey);
+
+ /** Change the priority class of the specified request.
+ */
+ void ChangeClass (
+ CacheKey aKey,
+ RequestPriorityClass eNewRequestClass);
+
+ /** Get the request with the highest priority int the highest priority class.
+ */
+ CacheKey GetFront (void);
+
+ // For debugging.
+ RequestPriorityClass GetFrontPriorityClass (void);
+
+ /** Really a synonym for RemoveRequest(GetFront());
+ */
+ void PopFront (void);
+
+ /** Returns <TRUE/> when there is no element in the queue.
+ */
+ bool IsEmpty (void);
+
+ /** Remove all requests from the queue. This resets the minimum and
+ maximum priorities to their default values.
+ */
+ void Clear (void);
+
+ /** Return the mutex that guards the access to the priority queue.
+ */
+ ::osl::Mutex& GetMutex (void);
+
+private:
+ ::osl::Mutex maMutex;
+ class Container;
+ ::boost::scoped_ptr<Container> mpRequestQueue;
+ SharedCacheContext mpCacheContext;
+
+ /** A lower bound of the lowest priority of all elements in the queues.
+ The start value is 0. It is assigned and then decreased every time
+ when an element is inserted or marked as the request with lowest
+ priority.
+ */
+ int mnMinimumPriority;
+ /** An upper bound of the highest priority of all elements in the queues.
+ The start value is 1. It is assigned and then increased every time
+ when an element is inserted or marked as the request with highest
+ priority.
+ */
+ int mnMaximumPriority;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/cache/makefile.mk b/sd/source/ui/slidesorter/cache/makefile.mk
new file mode 100755
index 000000000000..58862a28645a
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/makefile.mk
@@ -0,0 +1,64 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slscache
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlsBitmapCache.obj \
+ $(SLO)$/SlsBitmapCompressor.obj \
+ $(SLO)$/SlsBitmapFactory.obj \
+ $(SLO)$/SlsCacheCompactor.obj \
+ $(SLO)$/SlsCacheConfiguration.obj \
+ $(SLO)$/SlsGenericPageCache.obj \
+ $(SLO)$/SlsPageCache.obj \
+ $(SLO)$/SlsPageCacheManager.obj \
+ $(SLO)$/SlsQueueProcessor.obj \
+ $(SLO)$/SlsRequestFactory.obj \
+ $(SLO)$/SlsRequestQueue.obj
+
+
+EXCEPTIONSFILES=
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
new file mode 100644
index 000000000000..4dc825808c06
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
@@ -0,0 +1,999 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlideSorterController.hxx"
+
+#include "SlideSorter.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "SlsListener.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "SlsSelectionCommand.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "controller/SlsClipboard.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "view/SlsFontProvider.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+
+#include "drawdoc.hxx"
+#include "DrawViewShell.hxx"
+#include "TextLogger.hxx"
+#include "ViewShellBase.hxx"
+#include "Window.hxx"
+#include "FrameView.hxx"
+#include "DrawDocShell.hxx"
+#include "sdpage.hxx"
+#include "res_bmp.hrc"
+#include "sdresid.hxx"
+#include "strings.hrc"
+#include "app.hrc"
+#include "glob.hrc"
+#include "sdmod.hxx"
+#include "sdxfer.hxx"
+#include "FrameView.hxx"
+#include "ViewShellHint.hxx"
+#include "AccessibleSlideSorterView.hxx"
+#include "AccessibleSlideSorterObject.hxx"
+
+#include <vcl/window.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/svxids.hrc>
+#include <svx/ruler.hxx>
+#include <svx/zoomitem.hxx>
+#include <svtools/tabbar.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <tools/link.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::sd::slidesorter::model;
+using namespace ::sd::slidesorter::view;
+using namespace ::sd::slidesorter::controller;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mrModel(mrSlideSorter.GetModel()),
+ mrView(mrSlideSorter.GetView()),
+ mpPageSelector(),
+ mpFocusManager(),
+ mpSlotManager(),
+ mpClipboard(),
+ mpScrollBarManager(),
+ mpCurrentSlideManager(),
+ mpSelectionManager(),
+ mpAnimator(new Animator(rSlideSorter)),
+ mpListener(),
+ mnModelChangeLockCount(0),
+ mbPreModelChangeDone(false),
+ mbPostModelChangePending(false),
+ maSelectionBeforeSwitch(),
+ mnCurrentPageBeforeSwitch(0),
+ mpEditModeChangeMasterPage(NULL),
+ maTotalWindowArea(),
+ mnPaintEntranceCount(0),
+ mbIsContextMenuOpen(false),
+ mpProperties(new Properties())
+{
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ OSL_ASSERT(pWindow!=NULL);
+ if (pWindow != NULL)
+ {
+ // The whole background is painted by the view and controls.
+ ::Window* pParentWindow = pWindow->GetParent();
+ OSL_ASSERT(pParentWindow!=NULL);
+ pParentWindow->SetBackground (Wallpaper());
+
+ // Connect the view with the window that has been created by our base
+ // class.
+ pWindow->SetBackground (Wallpaper());
+ mrView.AddWindowToPaintView(pWindow);
+ mrView.SetActualWin(pWindow);
+ pWindow->SetCenterAllowed (false);
+ pWindow->SetViewSize (mrView.GetModelArea().GetSize());
+ pWindow->EnableRTL(FALSE);
+
+ // Reinitialize colors in Properties with window specific values.
+ mpProperties->SetBackgroundColor(
+ pWindow->GetSettings().GetStyleSettings().GetWindowColor());
+ mpProperties->SetTextColor(
+ pWindow->GetSettings().GetStyleSettings().GetWindowTextColor());
+ mpProperties->SetSelectionColor(
+ pWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor());
+ mpProperties->SetHighlightColor(
+ pWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor());
+ }
+}
+
+
+
+
+void SlideSorterController::Init (void)
+{
+ mrView.HandleModelChange();
+
+ mpCurrentSlideManager.reset(new CurrentSlideManager(mrSlideSorter));
+ mpPageSelector.reset(new PageSelector(mrSlideSorter));
+ mpFocusManager.reset(new FocusManager(mrSlideSorter));
+ mpSlotManager.reset(new SlotManager(mrSlideSorter));
+ mpClipboard.reset(new Clipboard(mrSlideSorter));
+ mpScrollBarManager.reset(new ScrollBarManager(mrSlideSorter));
+ mpSelectionManager.reset(new SelectionManager(mrSlideSorter));
+
+ mpScrollBarManager->LateInitialization();
+
+ // Create the selection function.
+ SfxRequest aRequest (
+ SID_OBJECT_SELECT,
+ 0,
+ mrModel.GetDocument()->GetItemPool());
+ mrSlideSorter.SetCurrentFunction(CreateSelectionFunction(aRequest));
+
+ mpListener = new Listener(mrSlideSorter);
+
+ mpPageSelector->UpdateAllPages();
+ GetSelectionManager()->SelectionHasChanged();
+}
+
+
+
+
+SlideSorterController::~SlideSorterController (void)
+{
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent (
+ static_cast<XWeak*>(mpListener.get()), uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+ catch( uno::Exception& e )
+ {
+ (void)e;
+ DBG_ERROR( "sd::SlideSorterController::~SlideSorterController(), exception caught!" );
+ }
+
+ // dispose should have been called by now so that nothing is to be done
+ // to shut down cleanly.
+}
+
+
+
+
+model::SharedPageDescriptor SlideSorterController::GetPageAt (
+ const Point& aPixelPosition)
+{
+ sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aPixelPosition));
+ model::SharedPageDescriptor pDescriptorAtPoint;
+ if (nHitPageIndex >= 0)
+ pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex);
+
+ return pDescriptorAtPoint;
+}
+
+PageSelector& SlideSorterController::GetPageSelector (void)
+{
+ OSL_ASSERT(mpPageSelector.get()!=NULL);
+ return *mpPageSelector.get();
+}
+
+
+
+
+FocusManager& SlideSorterController::GetFocusManager (void)
+{
+ OSL_ASSERT(mpFocusManager.get()!=NULL);
+ return *mpFocusManager.get();
+}
+
+
+
+
+Clipboard& SlideSorterController::GetClipboard (void)
+{
+ OSL_ASSERT(mpClipboard.get()!=NULL);
+ return *mpClipboard.get();
+}
+
+
+
+
+ScrollBarManager& SlideSorterController::GetScrollBarManager (void)
+{
+ OSL_ASSERT(mpScrollBarManager.get()!=NULL);
+ return *mpScrollBarManager.get();
+}
+
+
+
+
+::boost::shared_ptr<CurrentSlideManager> SlideSorterController::GetCurrentSlideManager (void) const
+{
+ OSL_ASSERT(mpCurrentSlideManager.get()!=NULL);
+ return mpCurrentSlideManager;
+}
+
+
+
+
+::boost::shared_ptr<SlotManager> SlideSorterController::GetSlotManager (void) const
+{
+ OSL_ASSERT(mpSlotManager.get()!=NULL);
+ return mpSlotManager;
+}
+
+
+
+
+::boost::shared_ptr<SelectionManager> SlideSorterController::GetSelectionManager (void) const
+{
+ OSL_ASSERT(mpSelectionManager.get()!=NULL);
+ return mpSelectionManager;
+}
+
+
+
+
+void SlideSorterController::PrePaint()
+{
+ // forward VCLs PrePaint window event to DrawingLayer
+ mrView.PrePaint();
+}
+
+
+
+
+void SlideSorterController::Paint (
+ const Rectangle& rBBox,
+ ::Window* pWindow)
+{
+ // if (mnPaintEntranceCount == 0)
+ {
+ ++mnPaintEntranceCount;
+
+ try
+ {
+ if (GetSelectionManager()->IsMakeSelectionVisiblePending())
+ GetSelectionManager()->MakeSelectionVisible();
+
+ mrView.SetApplicationDocumentColor(GetProperties()->GetBackgroundColor());
+ mrView.CompleteRedraw(pWindow, Region(rBBox), 0);
+ }
+ catch (const Exception&)
+ {
+ // Ignore all exceptions.
+ }
+
+ --mnPaintEntranceCount;
+ }
+}
+
+
+
+
+void SlideSorterController::FuTemporary (SfxRequest& rRequest)
+{
+ mpSlotManager->FuTemporary (rRequest);
+}
+
+
+
+
+void SlideSorterController::FuPermanent (SfxRequest &rRequest)
+{
+ mpSlotManager->FuPermanent (rRequest);
+}
+
+
+
+
+void SlideSorterController::FuSupport (SfxRequest &rRequest)
+{
+ mpSlotManager->FuSupport (rRequest);
+}
+
+
+
+
+bool SlideSorterController::Command (
+ const CommandEvent& rEvent,
+ ::sd::Window* pWindow)
+{
+ bool bEventHasBeenHandled = false;
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+
+ switch (rEvent.GetCommand())
+ {
+ case COMMAND_CONTEXTMENU:
+ {
+ SdPage* pPage = NULL;
+ USHORT nPopupId;
+
+ model::PageEnumeration aSelectedPages (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
+ if (aSelectedPages.HasMoreElements())
+ pPage = aSelectedPages.GetNextElement()->GetPage();
+
+ // Choose the popup menu depending on a) the type of the main
+ // view shell, b) the edit mode, and c) on whether the selection
+ // is empty or not.
+ ViewShell::ShellType eMainViewShellType (ViewShell::ST_NONE);
+ ::boost::shared_ptr<ViewShell> pMainViewShell (
+ pViewShell->GetViewShellBase().GetMainViewShell());
+ if (pMainViewShell.get() != NULL)
+ eMainViewShellType = pMainViewShell->GetShellType();
+ switch (eMainViewShellType)
+ {
+ case ViewShell::ST_DRAW:
+ if (pPage != NULL)
+ nPopupId = RID_SLIDE_SORTER_DRAW_SEL_POPUP;
+ else
+ nPopupId = RID_SLIDE_SORTER_DRAW_NOSEL_POPUP;
+ break;
+
+ default:
+ if (mrModel.GetEditMode() == EM_PAGE)
+ if (pPage != NULL)
+ nPopupId = RID_SLIDE_SORTER_IMPRESS_SEL_POPUP;
+ else
+ nPopupId = RID_SLIDE_SORTER_IMPRESS_NOSEL_POPUP;
+ else
+ if (pPage != NULL)
+ nPopupId = RID_SLIDE_SORTER_MASTER_SEL_POPUP;
+ else
+ nPopupId = RID_SLIDE_SORTER_MASTER_NOSEL_POPUP;
+ }
+
+ if (pPage == NULL)
+ {
+ // When there is no selection, then we show the insertion
+ // indicator so that the user knows where a page insertion
+ // would take place.
+ mrView.GetOverlay().GetInsertionIndicatorOverlay().SetPosition(
+ pWindow->PixelToLogic(rEvent.GetMousePosPixel()));
+ mrView.GetOverlay().GetInsertionIndicatorOverlay().setVisible(true);
+ }
+
+ pWindow->ReleaseMouse();
+ if (rEvent.IsMouseEvent())
+ {
+ mbIsContextMenuOpen = true;
+ if (pViewShell != NULL)
+ {
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher != NULL)
+ pDispatcher->ExecutePopup(SdResId(nPopupId));
+ }
+ }
+ else
+ {
+ // The event is not a mouse event. Use the center of the
+ // focused page as top left position of the context menu.
+ if (pPage != NULL)
+ {
+ model::SharedPageDescriptor pDescriptor (
+ GetFocusManager().GetFocusedPageDescriptor());
+ if (pDescriptor.get() != NULL)
+ {
+ Rectangle aBBox (mrView.GetPageBoundingBox (
+ pDescriptor,
+ view::SlideSorterView::CS_SCREEN,
+ view::SlideSorterView::BBT_SHAPE));
+ Point aPosition (aBBox.Center());
+ mbIsContextMenuOpen = true;
+ if (pViewShell != NULL)
+ pViewShell->GetViewFrame()->GetDispatcher()->ExecutePopup(
+ SdResId(nPopupId),
+ pWindow,
+ &aPosition);
+ }
+ }
+ }
+ mbIsContextMenuOpen = false;
+ if (pPage == NULL)
+ {
+ // Remember the position of the insertion indicator before
+ // it is hidden, so that a pending slide insertion slot call
+ // finds the right place to insert a new slide.
+ GetSelectionManager()->SetInsertionPosition(
+ mrView.GetOverlay().GetInsertionIndicatorOverlay().GetInsertionPageIndex());
+ mrView.GetOverlay().GetInsertionIndicatorOverlay().setVisible(false);
+ }
+ bEventHasBeenHandled = true;
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ // We ignore zooming with control+mouse wheel.
+ const CommandWheelData* pData = rEvent.GetWheelData();
+ if (pData!=NULL && pData->IsMod1())
+ bEventHasBeenHandled = true;
+ }
+ break;
+ }
+
+ return bEventHasBeenHandled;
+}
+
+
+
+
+void SlideSorterController::LockModelChange (void)
+{
+ mnModelChangeLockCount += 1;
+}
+
+
+
+
+void SlideSorterController::UnlockModelChange (void)
+{
+ mnModelChangeLockCount -= 1;
+ if (mnModelChangeLockCount==0 && mbPostModelChangePending)
+ PostModelChange();
+}
+
+
+
+
+void SlideSorterController::PreModelChange (void)
+{
+ // Prevent PreModelChange to execute more than once per model lock.
+ if (mbPostModelChangePending)
+ return;
+ mbPreModelChangeDone = true;
+
+ if (mrSlideSorter.GetViewShell() != NULL)
+ mrSlideSorter.GetViewShell()->Broadcast(
+ ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START));
+
+ mpPageSelector->PrepareModelChange();
+ GetCurrentSlideManager()->PrepareModelChange();
+
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow != NULL)
+ mrView.PreModelChange();
+
+ mbPostModelChangePending = true;
+}
+
+
+
+
+void SlideSorterController::PostModelChange (void)
+{
+ mbPostModelChangePending = false;
+ mrModel.Resync();
+
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow != NULL)
+ {
+ GetCurrentSlideManager()->HandleModelChange();
+
+ mrView.PostModelChange ();
+
+ pWindow->SetViewOrigin (Point (0,0));
+ pWindow->SetViewSize (mrView.GetModelArea().GetSize());
+
+ // The visibility of the scroll bars may have to be changed. Then
+ // the size of the view has to change, too. Let Rearrange() handle
+ // that.
+ Rearrange();
+ }
+
+ mpPageSelector->HandleModelChange ();
+
+ if (mrSlideSorter.GetViewShell() != NULL)
+ mrSlideSorter.GetViewShell()->Broadcast(
+ ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END));
+}
+
+
+
+
+void SlideSorterController::HandleModelChange (void)
+{
+ // Ignore this call when the document is not in a valid state, i.e. has
+ // not the same number of regular and notes pages.
+ bool bIsDocumentValid = (mrModel.GetDocument()->GetPageCount() % 2 == 1);
+
+ if (bIsDocumentValid)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+ }
+}
+
+
+
+
+IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent*, pEvent)
+{
+ if (pEvent != NULL)
+ {
+ ::Window* pWindow = pEvent->GetWindow();
+ ::sd::Window* pActiveWindow = mrSlideSorter.GetActiveWindow();
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_ACTIVATE:
+ case VCLEVENT_WINDOW_SHOW:
+ if (pActiveWindow != NULL && pWindow == pActiveWindow->GetParent())
+ mrView.RequestRepaint();
+ break;
+
+ case VCLEVENT_WINDOW_GETFOCUS:
+ if (pActiveWindow != NULL && pWindow == pActiveWindow)
+ GetFocusManager().ShowFocus(false);
+ break;
+
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ if (pActiveWindow != NULL && pWindow == pActiveWindow)
+ GetFocusManager().HideFocus();
+ break;
+
+ case VCLEVENT_APPLICATION_DATACHANGED:
+ {
+ // Invalidate the preview cache.
+ cache::PageCacheManager::Instance()->InvalidateAllCaches();
+
+ // Update the draw mode.
+ ULONG nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
+ ? ViewShell::OUTPUT_DRAWMODE_CONTRAST
+ : ViewShell::OUTPUT_DRAWMODE_COLOR);
+ if (mrSlideSorter.GetViewShell() != NULL)
+ mrSlideSorter.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode);
+ if (pActiveWindow != NULL)
+ pActiveWindow->SetDrawMode(nDrawMode);
+ mrView.HandleDrawModeChange();
+
+ // When the system font has changed a layout has to be done.
+ mrView.Resize();
+ FontProvider::Instance().Invalidate();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+void SlideSorterController::GetCtrlState (SfxItemSet& rSet)
+{
+ if (rSet.GetItemState(SID_RELOAD) != SFX_ITEM_UNKNOWN)
+ {
+ // "Letzte Version" vom SFx en/disablen lassen
+ SfxViewFrame* pSlideViewFrame = SfxViewFrame::Current();
+ DBG_ASSERT(pSlideViewFrame!=NULL,
+ "SlideSorterController::GetCtrlState: ViewFrame not found");
+ if (pSlideViewFrame)
+ {
+ pSlideViewFrame->GetSlotState (SID_RELOAD, NULL, &rSet);
+ }
+ else // MI sagt: kein MDIFrame --> disablen
+ {
+ rSet.DisableItem(SID_RELOAD);
+ }
+ }
+
+ // Output quality.
+ if (rSet.GetItemState(SID_OUTPUT_QUALITY_COLOR)==SFX_ITEM_AVAILABLE
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE)==SFX_ITEM_AVAILABLE
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE)==SFX_ITEM_AVAILABLE
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_CONTRAST)==SFX_ITEM_AVAILABLE)
+ {
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow != NULL)
+ {
+ ULONG nMode = pWindow->GetDrawMode();
+ UINT16 nQuality = 0;
+
+ switch (nMode)
+ {
+ case ViewShell::OUTPUT_DRAWMODE_COLOR:
+ nQuality = 0;
+ break;
+ case ViewShell::OUTPUT_DRAWMODE_GRAYSCALE:
+ nQuality = 1;
+ break;
+ case ViewShell::OUTPUT_DRAWMODE_BLACKWHITE:
+ nQuality = 2;
+ break;
+ case ViewShell::OUTPUT_DRAWMODE_CONTRAST:
+ nQuality = 3;
+ break;
+ }
+
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR,
+ (BOOL)(nQuality==0)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE,
+ (BOOL)(nQuality==1)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE,
+ (BOOL)(nQuality==2)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST,
+ (BOOL)(nQuality==3)));
+ }
+ }
+
+ if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SFX_ITEM_AVAILABLE)
+ {
+ rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, TRUE));
+ }
+}
+
+
+
+
+void SlideSorterController::GetStatusBarState (SfxItemSet& rSet)
+{
+ mpSlotManager->GetStatusBarState (rSet);
+}
+
+
+
+
+void SlideSorterController::ExecCtrl (SfxRequest& rRequest)
+{
+ mpSlotManager->ExecCtrl (rRequest);
+}
+
+
+
+
+void SlideSorterController::GetAttrState (SfxItemSet& rSet)
+{
+ mpSlotManager->GetAttrState (rSet);
+}
+
+
+
+
+void SlideSorterController::ExecStatusBar (SfxRequest& )
+{
+}
+
+
+
+
+void SlideSorterController::UpdateAllPages (void)
+{
+ // Do a redraw.
+ mrView.InvalidateAllWin();
+}
+
+
+
+
+Rectangle SlideSorterController::Resize (const Rectangle& rAvailableSpace)
+{
+ Rectangle aContentArea (rAvailableSpace);
+
+ if (maTotalWindowArea != rAvailableSpace)
+ {
+ maTotalWindowArea = rAvailableSpace;
+ aContentArea = Rearrange(true);
+ }
+
+ return aContentArea;
+}
+
+
+
+
+Rectangle SlideSorterController::Rearrange (bool bForce)
+{
+ Rectangle aNewContentArea (maTotalWindowArea);
+
+ ::boost::shared_ptr<sd::Window> pWindow = mrSlideSorter.GetContentWindow();
+ if (pWindow.get() != NULL)
+ {
+ // Place the scroll bars.
+ aNewContentArea = GetScrollBarManager().PlaceScrollBars(maTotalWindowArea);
+
+ bool bSizeHasChanged (false);
+ // Only when bForce is not true we have to test for a size change in
+ // order to determine whether the window and the view have to be resized.
+ if ( ! bForce)
+ {
+ Rectangle aCurrentContentArea (
+ pWindow->GetPosPixel(),
+ pWindow->GetOutputSizePixel());
+ bSizeHasChanged = (aNewContentArea != aCurrentContentArea);
+ }
+ if (bForce || bSizeHasChanged)
+ {
+ // The browser window gets the remaining space.
+ pWindow->SetPosSizePixel (aNewContentArea.TopLeft(), aNewContentArea.GetSize());
+ mrView.Resize();
+ }
+
+ // Adapt the scroll bars to the new zoom factor of the browser
+ // window and the arrangement of the page objects.
+ GetScrollBarManager().UpdateScrollBars(false, !bForce);
+ }
+
+ return aNewContentArea;
+}
+
+
+
+
+FunctionReference SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest)
+{
+ FunctionReference xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) );
+ return xFunc;
+}
+
+
+
+
+void SlideSorterController::PrepareEditModeChange (void)
+{
+ // Before we throw away the page descriptors we prepare for selecting
+ // descriptors in the other mode and for restoring the current
+ // selection when switching back to the current mode.
+ if (mrModel.GetEditMode() == EM_PAGE)
+ {
+ maSelectionBeforeSwitch.clear();
+
+ // Search for the first selected page and determine the master page
+ // used by its page object. It will be selected after the switch.
+ // In the same loop the current selection is stored.
+ PageEnumeration aSelectedPages (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
+ while (aSelectedPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ SdPage* pPage = pDescriptor->GetPage();
+ // Remember the master page of the first selected descriptor.
+ if (pPage!=NULL && mpEditModeChangeMasterPage==NULL)
+ mpEditModeChangeMasterPage = &static_cast<SdPage&>(
+ pPage->TRG_GetMasterPage());
+
+ maSelectionBeforeSwitch.push_back(pPage);
+ }
+
+ // Remember the current page.
+ if (mrSlideSorter.GetViewShell() != NULL)
+ mnCurrentPageBeforeSwitch = (mrSlideSorter.GetViewShell()->GetViewShellBase()
+ .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
+ }
+}
+
+
+
+
+bool SlideSorterController::ChangeEditMode (EditMode eEditMode)
+{
+ bool bResult (false);
+ if (mrModel.GetEditMode() != eEditMode)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+ // Do the actual edit mode switching.
+ bResult = mrModel.SetEditMode(eEditMode);
+ if (bResult)
+ HandleModelChange();
+ }
+ return bResult;
+}
+
+
+
+
+void SlideSorterController::FinishEditModeChange (void)
+{
+ if (mrModel.GetEditMode() == EM_MASTERPAGE)
+ {
+ // Search for the master page that was determined in
+ // PrepareEditModeChange() and make it the current page.
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->GetPage() == mpEditModeChangeMasterPage)
+ {
+ GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+ break;
+ }
+ }
+ }
+ else
+ {
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnCurrentPageBeforeSwitch));
+ GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+
+ // Restore the selection.
+ ::std::vector<SdPage*>::iterator iPage;
+ for (iPage=maSelectionBeforeSwitch.begin();
+ iPage!=maSelectionBeforeSwitch.end();
+ ++iPage)
+ {
+ mpPageSelector->SelectPage(*iPage);
+ }
+ maSelectionBeforeSwitch.clear( );
+ }
+ mpEditModeChangeMasterPage = NULL;
+}
+
+
+
+
+void SlideSorterController::PageNameHasChanged (int nPageIndex, const String& rsOldName)
+{
+ // Request a repaint for the page object whose name has changed.
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ mrView.RequestRepaint(pDescriptor);
+
+ // Get a pointer to the corresponding accessible object and notify
+ // that of the name change.
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow == NULL)
+ return;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
+ xAccessible (pWindow->GetAccessible(FALSE));
+ if ( ! xAccessible.is())
+ return;
+
+ // Now comes a small hack. We assume that the accessible object is
+ // an instantiation of AccessibleSlideSorterView and cast it to that
+ // class. The cleaner alternative to this cast would be a new member
+ // in which we would store the last AccessibleSlideSorterView object
+ // created by SlideSorterViewShell::CreateAccessibleDocumentView().
+ // But then there is no guaranty that the accessible object obtained
+ // from the window really is that instance last created by
+ // CreateAccessibleDocumentView().
+ // However, the dynamic cast together with the check of the result
+ // being NULL should be safe enough.
+ ::accessibility::AccessibleSlideSorterView* pAccessibleView
+ = dynamic_cast< ::accessibility::AccessibleSlideSorterView*>(xAccessible.get());
+ if (pAccessibleView == NULL)
+ return;
+
+ ::accessibility::AccessibleSlideSorterObject* pChild
+ = pAccessibleView->GetAccessibleChildImplementation(nPageIndex);
+ if (pChild == NULL || pChild->GetPage() == NULL)
+ return;
+
+ ::rtl::OUString sOldName (rsOldName);
+ ::rtl::OUString sNewName (pChild->GetPage()->GetName());
+ pChild->FireAccessibleEvent(
+ ::com::sun::star::accessibility::AccessibleEventId::NAME_CHANGED,
+ makeAny(sOldName),
+ makeAny(sNewName));
+}
+
+
+
+
+bool SlideSorterController::IsContextMenuOpen (void) const
+{
+ return mbIsContextMenuOpen;
+}
+
+
+
+
+::boost::shared_ptr<Properties> SlideSorterController::GetProperties (void) const
+{
+ return mpProperties;
+}
+
+
+
+
+void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
+{
+ if (mrModel.GetDocumentSlides() != rxSlides)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+
+ mrModel.SetDocumentSlides(rxSlides);
+ mrView.Layout();
+ }
+}
+
+
+
+
+::boost::shared_ptr<Animator> SlideSorterController::GetAnimator (void) const
+{
+ return mpAnimator;
+}
+
+
+
+
+//===== SlideSorterController::ModelChangeLock ================================
+
+SlideSorterController::ModelChangeLock::ModelChangeLock (
+ SlideSorterController& rController)
+ : mpController(&rController)
+{
+ mpController->LockModelChange();
+}
+
+
+
+
+SlideSorterController::ModelChangeLock::~ModelChangeLock (void)
+{
+ Release();
+}
+
+
+
+
+void SlideSorterController::ModelChangeLock::Release (void)
+{
+ if (mpController != NULL)
+ {
+ mpController->UnlockModelChange();
+ mpController = NULL;
+ }
+}
+
+} } } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
new file mode 100644
index 000000000000..67a06164c3b7
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
@@ -0,0 +1,235 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "view/SlideSorterView.hxx"
+#include "View.hxx"
+
+namespace sd { namespace slidesorter { namespace controller {
+
+namespace {
+ static const sal_Int32 gnResolution = 25;
+}
+/** Handle one animation function by using a timer for frequent calls to
+ the animations operator().
+*/
+class Animator::Animation
+{
+public:
+ Animation (
+ const Animator::AnimationFunction& rAnimation,
+ const double nDelta);
+ ~Animation (void);
+ bool Run (void);
+ bool IsExpired (void);
+ Animator::AnimationFunction maAnimation;
+ double mnValue;
+ double mnDelta;
+};
+
+
+
+
+class Animator::DrawLock
+{
+public:
+ DrawLock (View& rView);
+ ~DrawLock (void);
+
+private:
+ View& mrView;
+};
+
+
+
+
+Animator::Animator (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maTimer(),
+ maAnimations(),
+ mpDrawLock()
+{
+ maTimer.SetTimeout(gnResolution);
+ maTimer.SetTimeoutHdl(LINK(this,Animator,TimeoutHandler));
+}
+
+
+
+
+Animator::~Animator (void)
+{
+ maTimer.Stop();
+ mpDrawLock.reset();
+}
+
+
+
+
+void Animator::AddAnimation (
+ const AnimationFunction& rAnimation,
+ const sal_Int32 nDuration)
+{
+ const double nDelta = double(gnResolution) / double(nDuration);
+ maAnimations.push_back(boost::shared_ptr<Animation>(new Animation(rAnimation, nDelta)));
+
+ // Prevent redraws except for the ones in TimeoutHandler.
+ // While the Animator is active it will schedule repaints regularly.
+ // Repaints in between would only lead to visual artifacts.
+ mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView()));
+ maTimer.Start();
+}
+
+
+
+
+bool Animator::ServeAnimations (void)
+{
+ bool bExpired (false);
+
+ AnimationList aCopy (maAnimations);
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
+ {
+ bExpired |= (*iAnimation)->Run();
+ }
+
+ return bExpired;
+}
+
+
+
+
+void Animator::CleanUpAnimationList (void)
+{
+ AnimationList aActiveAnimations;
+
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=maAnimations.begin(); iAnimation!=maAnimations.end(); ++iAnimation)
+ {
+ if ( ! (*iAnimation)->IsExpired())
+ aActiveAnimations.push_back(*iAnimation);
+ }
+
+ maAnimations.swap(aActiveAnimations);
+}
+
+
+
+
+IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG)
+{
+ if (ServeAnimations())
+ CleanUpAnimationList();
+
+ // Unlock the draw lock. This should lead to a repaint.
+ mpDrawLock.reset();
+
+ if (maAnimations.size() > 0)
+ {
+ mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView()));
+ maTimer.Start();
+ }
+
+ return 0;
+}
+
+
+
+
+//===== Animator::Animation ===================================================
+
+Animator::Animation::Animation (
+ const Animator::AnimationFunction& rAnimation,
+ const double nDelta)
+ : maAnimation(rAnimation),
+ mnValue(0),
+ mnDelta(nDelta)
+{
+
+ maAnimation(mnValue);
+ mnValue = mnDelta;
+
+}
+
+
+
+
+Animator::Animation::~Animation (void)
+{
+}
+
+
+
+
+bool Animator::Animation::Run (void)
+{
+ if (mnValue < 1.0)
+ {
+ maAnimation(mnValue);
+ mnValue += mnDelta;
+ return false;
+ }
+ else
+ {
+ maAnimation(1.0);
+ return true;
+ }
+}
+
+
+
+
+bool Animator::Animation::IsExpired (void)
+{
+ return mnValue >= 1.0;
+}
+
+
+
+
+//===== Animator::DrawLock ====================================================
+
+Animator::DrawLock::DrawLock (View& rView)
+ : mrView(rView)
+{
+ mrView.LockRedraw(TRUE);
+}
+
+
+
+
+Animator::DrawLock::~DrawLock (void)
+{
+ mrView.LockRedraw(FALSE);
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
new file mode 100644
index 000000000000..a15d10f67ecd
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
@@ -0,0 +1,780 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsClipboard.hxx"
+
+#include "SlideSorterViewShell.hxx"
+#include "SlideSorter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "view/SlsPageObject.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "SlsTransferable.hxx"
+
+#include "ViewShellBase.hxx"
+#include "DrawViewShell.hxx"
+#include "Window.hxx"
+#include "fupoor.hxx"
+#include "fuslhide.hxx"
+#include "fuzoom.hxx"
+#include "fucushow.hxx"
+#include "fusldlg.hxx"
+#include "fuexpand.hxx"
+#include "fusumry.hxx"
+#include "app.hrc"
+#include "glob.hrc"
+#include "strings.hrc"
+#include "sdresid.hxx"
+#include "sdxfer.hxx"
+#include "sdmod.hxx"
+#include "sddll.hxx"
+#include "ins_paste.hxx"
+#include "drawdoc.hxx"
+#include "DrawDocShell.hxx"
+#include "sdpage.hxx"
+
+#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+#include <svx/svxids.hrc>
+#include <vcl/msgbox.hxx>
+#include <tools/urlobj.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+Clipboard::Clipboard (SlideSorter& rSlideSorter)
+ : ViewClipboard(rSlideSorter.GetView()),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ maPagesToRemove(),
+ maPagesToSelect(),
+ mbUpdateSelectionPending(false)
+{
+}
+
+
+
+
+Clipboard::~Clipboard (void)
+{
+}
+
+
+
+
+/** With the current implementation the forwarded calls to the current
+ function will come back eventually to call the local Do(Cut|Copy|Paste)
+ methods. A shortcut is possible but would be an unclean hack.
+*/
+void Clipboard::HandleSlotCall (SfxRequest& rRequest)
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ FunctionReference xFunc;
+ if (pViewShell != NULL)
+ xFunc = pViewShell->GetCurrentFunction();
+ switch (rRequest.GetSlot())
+ {
+ case SID_CUT:
+ if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
+ {
+ if(xFunc.is())
+ xFunc->DoCut();
+ else
+ DoCut();
+ }
+ rRequest.Done();
+ break;
+
+ case SID_COPY:
+ if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
+ {
+ if(xFunc.is())
+ xFunc->DoCopy();
+ else
+ DoCopy();
+ }
+ rRequest.Done();
+ break;
+
+ case SID_PASTE:
+ // Prevent redraws while inserting pages from the clipboard
+ // because the intermediate inconsistent state might lead to
+ // a crash.
+ if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
+ {
+ mrSlideSorter.GetView().LockRedraw (TRUE);
+ if(xFunc.is())
+ xFunc->DoPaste();
+ else
+ DoPaste();
+ mrController.GetSelectionManager()->MakeSelectionVisible();
+ mrSlideSorter.GetView().LockRedraw(FALSE);
+ }
+ rRequest.Done();
+ break;
+
+ case SID_DELETE:
+ DoDelete();
+ rRequest.Done();
+ break;
+ }
+}
+
+
+
+
+void Clipboard::DoCut (::Window* pWindow)
+{
+ if (mrSlideSorter.GetModel().GetPageCount() > 1)
+ {
+ DoCopy(pWindow);
+ DoDelete(pWindow);
+ }
+}
+
+
+
+
+void Clipboard::DoDelete (::Window* )
+{
+ if (mrSlideSorter.GetModel().GetPageCount() > 1)
+ {
+ mrController.GetSelectionManager()->DeleteSelectedPages();
+ }
+}
+
+
+
+
+void Clipboard::DoCopy (::Window* pWindow )
+{
+ CreateSlideTransferable( pWindow, FALSE );
+}
+
+
+
+
+void Clipboard::DoPaste (::Window* pWindow)
+{
+ SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
+
+ if (pClipTransferable!=NULL && pClipTransferable->IsPageTransferable())
+ {
+ sal_Int32 nInsertPosition = GetInsertionPosition(pWindow);
+
+ if (nInsertPosition >= 0)
+ {
+ // Paste the pages from the clipboard.
+ sal_Int32 nInsertPageCount = PasteTransferable(nInsertPosition);
+ // Select the pasted pages and make the first of them the
+ // current page.
+ mrSlideSorter.GetView().GetWindow()->GrabFocus();
+ SelectPageRange(nInsertPosition, nInsertPageCount);
+ }
+ }
+}
+
+
+
+
+sal_Int32 Clipboard::GetInsertionPosition (::Window* pWindow)
+{
+ sal_Int32 nInsertPosition = -1;
+
+ // Determine the insertion position:
+ // a) When the insertion indicator is visible, then at that position.
+ // b) When the focus indicator is visible, then before or after the
+ // focused page, depending on user input to a dialog.
+ // c) When there is a selection but no focus, then after the
+ // selection.
+ // d) After the last page when there is no selection and no focus.
+
+ view::InsertionIndicatorOverlay& rInsertionIndicatorOverlay (
+ mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay());
+ if (rInsertionIndicatorOverlay.isVisible())
+ {
+ nInsertPosition = rInsertionIndicatorOverlay.GetInsertionPageIndex();
+ }
+ else if (mrController.GetFocusManager().IsFocusShowing())
+ {
+ SdInsertPasteDlg aDialog (pWindow);
+ if (aDialog.Execute() == RET_OK)
+ {
+ nInsertPosition = mrController.GetFocusManager().GetFocusedPageIndex();
+ if ( ! aDialog.IsInsertBefore())
+ nInsertPosition ++;
+ }
+ }
+ else
+ {
+ nInsertPosition = mrController.GetSelectionManager()->GetInsertionPosition();
+ }
+
+ return nInsertPosition;
+}
+
+
+
+
+sal_Int32 Clipboard::PasteTransferable (sal_Int32 nInsertPosition)
+{
+ SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
+ bool bMergeMasterPages = !pClipTransferable->HasSourceDoc (
+ mrSlideSorter.GetModel().GetDocument());
+ USHORT nInsertIndex ((USHORT)(nInsertPosition * 2 + 1));
+ sal_Int32 nInsertPageCount (0);
+ if (pClipTransferable->HasPageBookmarks())
+ {
+ const List& rBookmarkList = pClipTransferable->GetPageBookmarks();
+ const SolarMutexGuard aGuard;
+
+ nInsertPageCount = (USHORT) rBookmarkList.Count();
+ mrSlideSorter.GetModel().GetDocument()->InsertBookmarkAsPage(
+ const_cast<List*>(&rBookmarkList),
+ NULL,
+ FALSE,
+ FALSE,
+ nInsertIndex,
+ FALSE,
+ pClipTransferable->GetPageDocShell(),
+ TRUE,
+ bMergeMasterPages,
+ FALSE);
+ }
+ else
+ {
+ SfxObjectShell* pShell = pClipTransferable->GetDocShell();
+ DrawDocShell* pDataDocSh = (DrawDocShell*)pShell;
+ SdDrawDocument* pDataDoc = pDataDocSh->GetDoc();
+
+ if (pDataDoc!=NULL
+ && pDataDoc->GetSdPageCount(PK_STANDARD))
+ {
+ const SolarMutexGuard aGuard;
+
+ bMergeMasterPages = (pDataDoc != mrSlideSorter.GetModel().GetDocument());
+ nInsertPageCount = pDataDoc->GetSdPageCount( PK_STANDARD );
+ mrSlideSorter.GetModel().GetDocument()->InsertBookmarkAsPage(
+ NULL,
+ NULL,
+ FALSE,
+ FALSE,
+ nInsertIndex,
+ FALSE,
+ pDataDocSh,
+ TRUE,
+ bMergeMasterPages,
+ FALSE);
+ }
+ }
+ mrController.HandleModelChange();
+ return nInsertPageCount;
+}
+
+
+
+
+void Clipboard::SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount)
+{
+ // Select the newly inserted pages. That are the nInsertPageCount pages
+ // after the nInsertIndex position.
+ PageSelector& rSelector (mrController.GetPageSelector());
+ rSelector.DeselectAllPages();
+ for (USHORT i=0; i<nPageCount; i++)
+ {
+ model::SharedPageDescriptor pDescriptor (
+ mrSlideSorter.GetModel().GetPageDescriptor(nFirstIndex + i));
+ if (pDescriptor.get() != NULL)
+ {
+ rSelector.SelectPage(pDescriptor);
+ // The first page of the new selection is made the current page.
+ if (i == 0)
+ {
+ mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+ mrController.GetFocusManager().SetFocusedPage(pDescriptor);
+ }
+ }
+ }
+}
+
+
+
+
+void Clipboard::CreateSlideTransferable (
+ ::Window* pWindow,
+ bool bDrag)
+{
+ List aBookmarkList;
+
+ // Insert all selected pages into a bookmark list and remember them in
+ // maPagesToRemove for possible later removal.
+ model::PageEnumeration aSelectedPages
+ (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ aBookmarkList.Insert (
+ new String(pDescriptor->GetPage()->GetName()),
+ LIST_APPEND);
+ maPagesToRemove.push_back (pDescriptor->GetPage());
+ }
+
+ if (aBookmarkList.Count() > 0)
+ {
+ mrSlideSorter.GetView().BrkAction();
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ SdTransferable* pTransferable = new Transferable (
+ pDocument,
+ NULL,
+ FALSE,
+ dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()));
+
+ if (bDrag)
+ SD_MOD()->pTransferDrag = pTransferable;
+ else
+ SD_MOD()->pTransferClip = pTransferable;
+
+ pDocument->CreatingDataObj (pTransferable);
+ pTransferable->SetWorkDocument( dynamic_cast<SdDrawDocument*>(pDocument->AllocModel()) );
+ pDocument->CreatingDataObj (NULL);
+ TransferableObjectDescriptor aObjDesc;
+ pTransferable->GetWorkDocument()->GetDocSh()
+ ->FillTransferableObjectDescriptor (aObjDesc);
+
+ if (pDocument->GetDocSh() != NULL)
+ aObjDesc.maDisplayName = pDocument->GetDocSh()
+ ->GetMedium()->GetURLObject().GetURLNoPass();
+
+ ::Window* pActionWindow = pWindow;
+ if (pActionWindow == NULL)
+ {
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ pActionWindow = pViewShell->GetActiveWindow();
+ }
+
+ pTransferable->SetStartPos (pActionWindow->PixelToLogic(
+ pActionWindow->GetPointerPosPixel()));
+ pTransferable->SetObjectDescriptor (aObjDesc);
+ pTransferable->SetPageBookmarks (aBookmarkList, !bDrag);
+
+ for (void* p=aBookmarkList.First(); p!=NULL; p=aBookmarkList.Next())
+ delete static_cast<String*>(p);
+
+ if (bDrag)
+ {
+ pTransferable->SetView (&mrSlideSorter.GetView());
+ sal_Int8 nDragSourceActions (DND_ACTION_COPY);
+ // The move action is available only when not all pages would be
+ // moved. Otherwise an empty document would remain. Crash.
+ sal_Int32 nRemainingPages = mrSlideSorter.GetModel().GetPageCount() - aBookmarkList.Count();
+ if (nRemainingPages > 0)
+ nDragSourceActions |= DND_ACTION_MOVE;
+ pTransferable->StartDrag (pActionWindow, nDragSourceActions);
+ }
+ else
+ pTransferable->CopyToClipboard (pActionWindow);
+ }
+}
+
+
+
+
+void Clipboard::StartDrag (
+ const Point&,
+ ::Window* pWindow)
+{
+ maPagesToRemove.clear();
+ maPagesToSelect.clear();
+ mbUpdateSelectionPending = false;
+ CreateSlideTransferable (pWindow, TRUE);
+}
+
+
+
+
+void Clipboard::DragFinished (sal_Int8 nDropAction)
+{
+ // Hide the substitution display and insertion indicator.
+ mrSlideSorter.GetView().GetOverlay().GetSubstitutionOverlay().setVisible(false);
+ mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay().setVisible(false);
+
+ SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+
+ if (pDragTransferable != NULL)
+ pDragTransferable->SetView (NULL);
+
+ PageSelector& rSelector (mrController.GetPageSelector());
+ if ((nDropAction & DND_ACTION_MOVE) != 0
+ && ! maPagesToRemove.empty())
+ {
+ // Remove the pages that have been moved to another place (possibly
+ // in the same document.)
+ rSelector.DeselectAllPages();
+ PageList::iterator aDraggedPage;
+ for (aDraggedPage=maPagesToRemove.begin();
+ aDraggedPage!=maPagesToRemove.end();
+ aDraggedPage++)
+ {
+ rSelector.SelectPage (*aDraggedPage);
+ }
+ mrController.GetSelectionManager()->DeleteSelectedPages ();
+ }
+
+ SelectPages();
+}
+
+
+
+
+void Clipboard::SelectPages (void)
+{
+ PageSelector& rSelector (mrController.GetPageSelector());
+
+ // Select the dropped pages.
+ PageList::iterator iPage;
+ rSelector.DeselectAllPages();
+ for (iPage=maPagesToSelect.begin(); iPage!=maPagesToSelect.end(); ++iPage)
+ {
+ rSelector.SelectPage(*iPage);
+ }
+}
+
+
+
+
+sal_Int8 Clipboard::AcceptDrop (
+ const AcceptDropEvent& rEvent,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer)
+{
+ sal_Int8 nResult = DND_ACTION_NONE;
+
+ switch (IsDropAccepted())
+ {
+ case DT_PAGE:
+ {
+ // Accept a drop.
+ nResult = rEvent.mnAction;
+
+ // Use the copy action when the drop action is the default, i.e. not
+ // explicitly set to move or link, and when the source and
+ // target models are not the same.
+ const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ if (pDragTransferable != NULL
+ && pDragTransferable->IsPageTransferable()
+ && ((rEvent.maDragEvent.DropAction
+ & ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_DEFAULT) != 0)
+ && (mrSlideSorter.GetModel().GetDocument()->GetDocSh()
+ != pDragTransferable->GetPageDocShell()))
+ {
+ nResult = DND_ACTION_COPY;
+ }
+
+ // Show the insertion marker and the substitution for a drop.
+ Point aPosition = pTargetWindow->PixelToLogic (rEvent.maPosPixel);
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ rOverlay.GetInsertionIndicatorOverlay().SetPosition (aPosition);
+ rOverlay.GetInsertionIndicatorOverlay().setVisible(true);
+ rOverlay.GetSubstitutionOverlay().SetPosition (aPosition);
+
+ // Scroll the window when the mouse reaches the window border.
+ mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
+ }
+ break;
+
+ case DT_SHAPE:
+ nResult = ExecuteOrAcceptShapeDrop(
+ DC_ACCEPT,
+ rEvent.maPosPixel,
+ &rEvent,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+ default:
+ break;
+ }
+
+ return nResult;
+}
+
+
+
+
+sal_Int8 Clipboard::ExecuteDrop (
+ const ExecuteDropEvent& rEvent,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer)
+{
+ sal_Int8 nResult = DND_ACTION_NONE;
+
+ switch (IsDropAccepted())
+ {
+ case DT_PAGE:
+ {
+ const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ const Point aEventModelPosition (
+ pTargetWindow->PixelToLogic (rEvent.maPosPixel));
+ long int nXOffset = labs (pDragTransferable->GetStartPos().X()
+ - aEventModelPosition.X());
+ long int nYOffset = labs (pDragTransferable->GetStartPos().Y()
+ - aEventModelPosition.Y());
+ const bool bContinue =
+ ( pDragTransferable->GetView() != &mrSlideSorter.GetView() )
+ || ( nXOffset >= 2 && nYOffset >= 2 );
+
+ // Get insertion position and then turn off the insertion indicator.
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ rOverlay.GetInsertionIndicatorOverlay().SetPosition(
+ aEventModelPosition);
+ USHORT nIndex = DetermineInsertPosition (*pDragTransferable);
+ OSL_TRACE ("Clipboard::AcceptDrop() called for index %d",
+ nIndex);
+ rOverlay.GetInsertionIndicatorOverlay().setVisible(false);
+
+ if (bContinue)
+ {
+ SlideSorterController::ModelChangeLock aModelChangeLock (mrController);
+
+ if (pDragTransferable->GetView() == &mrSlideSorter.GetView()
+ && rEvent.mnAction == DND_ACTION_MOVE)
+ {
+ // We are asked to move pages inside one view. For this we
+ // call MoveSelectedPages() which is faster than going the
+ // generic way.
+
+ // Remember to select the moved pages afterwards.
+ maPagesToRemove.swap(maPagesToSelect);
+ maPagesToRemove.clear();
+
+ USHORT nSdrModelIndex;
+ if (nIndex != SDRPAGE_NOTFOUND)
+ nSdrModelIndex = nIndex / 2 - 1;
+ else
+ nSdrModelIndex = SDRPAGE_NOTFOUND;
+ mrController.GetSelectionManager()->MoveSelectedPages(nSdrModelIndex);
+ mbUpdateSelectionPending = true;
+ nResult = DND_ACTION_NONE;
+ }
+ else
+ {
+ // Handle a general drop operation.
+ HandlePageDrop (*pDragTransferable);
+ nResult = rEvent.mnAction;
+ }
+ }
+ }
+ break;
+
+ case DT_SHAPE:
+ nResult = ExecuteOrAcceptShapeDrop(
+ DC_EXECUTE,
+ rEvent.maPosPixel,
+ &rEvent,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+ default:
+ break;
+ }
+
+ return nResult;
+}
+
+
+
+
+USHORT Clipboard::DetermineInsertPosition (const SdTransferable& )
+{
+ USHORT nInsertPosition = SDRPAGE_NOTFOUND;
+
+ // Tell the model to move the dragged pages behind the one with the
+ // index nInsertionIndex which first has to be transformed into an index
+ // understandable by the document.
+ view::InsertionIndicatorOverlay& rOverlay (
+ mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay());
+ sal_Int32 nInsertionIndex (rOverlay.GetInsertionPageIndex());
+
+ // The index returned by the overlay starts with 1 for the first slide.
+ // This is now converted that to an SdModel index that also starts with 1.
+ if (nInsertionIndex >= 0)
+ nInsertPosition = (USHORT)nInsertionIndex * 2 + 1;
+
+ return nInsertPosition;
+}
+
+
+
+
+USHORT Clipboard::InsertSlides (
+ const SdTransferable& rTransferable,
+ USHORT nInsertPosition)
+{
+ USHORT nInsertedPageCount = ViewClipboard::InsertSlides (
+ rTransferable,
+ nInsertPosition);
+
+ // Remember the inserted pages so that they can be selected when the
+ // operation is finished.
+ int nDocumentIndex = nInsertPosition / 2 - 1;
+ for (USHORT i=1; i<=nInsertedPageCount; i++)
+ {
+ model::SharedPageDescriptor pDescriptor (
+ mrSlideSorter.GetModel().GetPageDescriptor(nDocumentIndex + i));
+ if (pDescriptor.get() != NULL)
+ maPagesToSelect.push_back (pDescriptor->GetPage());
+ }
+
+ mbUpdateSelectionPending |= (nInsertedPageCount>0);
+
+ return nInsertedPageCount;
+}
+
+
+
+
+Clipboard::DropType Clipboard::IsDropAccepted (void) const
+{
+ DropType eResult (DT_NONE);
+
+ const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ if (pDragTransferable != NULL)
+ {
+ if (pDragTransferable->IsPageTransferable())
+ {
+ if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
+ eResult = DT_PAGE;
+ }
+ else
+ {
+ eResult = DT_SHAPE;
+ }
+ }
+
+ return eResult;
+}
+
+
+
+
+sal_Int8 Clipboard::ExecuteOrAcceptShapeDrop (
+ DropCommand eCommand,
+ const Point& rPosition,
+ const void* pDropEvent,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer)
+{
+ sal_Int8 nResult = 0;
+
+ // The dropping of a shape is accepted or executed only when there is
+ // DrawViewShell available to which we can forward this call. This has
+ // technical reasons: The actual code to accept or execute a shape drop
+ // is implemented in the ViewShell class and uses the page view of the
+ // main edit view. This is not possible without a DrawViewShell.
+ ::boost::shared_ptr<DrawViewShell> pDrawViewShell;
+ if (mrSlideSorter.GetViewShell() != NULL)
+ pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(
+ mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell());
+ if (pDrawViewShell.get() != NULL
+ && (pDrawViewShell->GetShellType() == ViewShell::ST_IMPRESS
+ || pDrawViewShell->GetShellType() == ViewShell::ST_DRAW))
+ {
+ // The drop is only accepted or executed when it takes place over a
+ // page object. Therefore we replace a missing page number by the
+ // number of the page under the mouse.
+ if (nPage == SDRPAGE_NOTFOUND)
+ {
+ model::SharedPageDescriptor pDescriptor (
+ mrSlideSorter.GetModel().GetPageDescriptor(
+ mrSlideSorter.GetView().GetPageIndexAtPoint(rPosition)));
+ if (pDescriptor.get() != NULL && pDescriptor->GetPage()!=NULL)
+ nPage = (pDescriptor->GetPage()->GetPageNum() - 1) / 2;
+ }
+
+ // Now comes the code that is different for the Execute and Accept:
+ // We simply forward the call to the AcceptDrop() or ExecuteDrop()
+ // methods of the DrawViewShell in the center pane.
+ if (nPage != SDRPAGE_NOTFOUND)
+ switch (eCommand)
+ {
+ case DC_ACCEPT:
+ nResult = pDrawViewShell->AcceptDrop(
+ *reinterpret_cast<const AcceptDropEvent*>(pDropEvent),
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+
+ case DC_EXECUTE:
+ nResult = pDrawViewShell->ExecuteDrop(
+ *reinterpret_cast<const ExecuteDropEvent*>(pDropEvent),
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+ }
+ }
+
+ return nResult;
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsCommand.hxx b/sd/source/ui/slidesorter/controller/SlsCommand.hxx
new file mode 100644
index 000000000000..d6dee9911742
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsCommand.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_COMMAND_HXX
+#define SD_SLIDESORTER_COMMAND_HXX
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Base class for command objects. It specifies the interface for commands
+ whose execution can be scheduled via the SlotManager.
+*/
+class Command
+{
+public:
+ virtual ~Command (void) {};
+ virtual void operator() (void) = 0;
+};
+
+} } } // end of namespace sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx
new file mode 100644
index 000000000000..546d25906a72
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx
@@ -0,0 +1,259 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "ViewShellBase.hxx"
+#include "ViewShell.hxx"
+#include "DrawViewShell.hxx"
+#include "sdpage.hxx"
+#include "FrameView.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using namespace ::sd::slidesorter::model;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+CurrentSlideManager::CurrentSlideManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mnCurrentSlideIndex(-1),
+ mpCurrentSlide()
+{
+}
+
+
+
+
+CurrentSlideManager::~CurrentSlideManager (void)
+{
+}
+
+
+
+
+void CurrentSlideManager::CurrentSlideHasChanged (const sal_Int32 nSlideIndex)
+{
+ if (mnCurrentSlideIndex != nSlideIndex)
+ {
+ ReleaseCurrentSlide();
+ AcquireCurrentSlide(nSlideIndex);
+
+ // Update the selection.
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ if (mpCurrentSlide.get() != NULL)
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(mpCurrentSlide);
+ }
+}
+
+
+
+
+void CurrentSlideManager::ReleaseCurrentSlide (void)
+{
+ if (mpCurrentSlide.get() != NULL)
+ {
+ mpCurrentSlide->SetIsCurrentPage(false);
+ mrSlideSorter.GetView().RequestRepaint(mpCurrentSlide);
+ }
+
+ mpCurrentSlide.reset();
+ mnCurrentSlideIndex = -1;
+}
+
+
+
+
+bool CurrentSlideManager::IsCurrentSlideIsValid (void)
+{
+ return mnCurrentSlideIndex >= 0 && mnCurrentSlideIndex<mrSlideSorter.GetModel().GetPageCount();
+}
+
+
+
+
+void CurrentSlideManager::AcquireCurrentSlide (const sal_Int32 nSlideIndex)
+{
+ mnCurrentSlideIndex = nSlideIndex;
+
+ if (IsCurrentSlideIsValid())
+ {
+ // Get a descriptor for the XDrawPage reference. Note that the
+ // given XDrawPage may or may not be member of the slide sorter
+ // document.
+ mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor(mnCurrentSlideIndex);
+ if (mpCurrentSlide.get() != NULL)
+ {
+ mpCurrentSlide->SetIsCurrentPage(true);
+ mrSlideSorter.GetView().RequestRepaint(mpCurrentSlide);
+ }
+ }
+}
+
+
+
+
+void CurrentSlideManager::SwitchCurrentSlide (const sal_Int32 nSlideIndex)
+{
+ SwitchCurrentSlide(mrSlideSorter.GetModel().GetPageDescriptor(nSlideIndex));
+}
+
+
+
+
+void CurrentSlideManager::SwitchCurrentSlide (const SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ mpCurrentSlide = rpDescriptor;
+ mnCurrentSlideIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL && pViewShell->IsMainViewShell())
+ {
+ FrameView* pFrameView = pViewShell->GetFrameView();
+ if (pFrameView != NULL)
+ pFrameView->SetSelectedPage(sal::static_int_cast<USHORT>(mnCurrentSlideIndex));
+ }
+ else
+ {
+ // Set current page. At the moment we have to do this in two
+ // different ways. The UNO way is the preferable one but, alas,
+ // it does not work always correctly (after some kinds of model
+ // changes). Therefore, we call DrawViewShell::SwitchPage(),
+ // too.
+ SetCurrentSlideAtViewShellBase(rpDescriptor);
+ SetCurrentSlideAtXController(rpDescriptor);
+ }
+ }
+}
+
+
+
+
+void CurrentSlideManager::SetCurrentSlideAtViewShellBase (const SharedPageDescriptor& rpDescriptor)
+{
+ OSL_ASSERT(rpDescriptor.get() != NULL);
+
+ ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
+ if (pBase != NULL)
+ {
+ DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(
+ pBase->GetMainViewShell().get());
+ if (pDrawViewShell != NULL)
+ {
+ USHORT nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+ pDrawViewShell->SwitchPage(nPageNumber);
+ pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1);
+ }
+ /*
+ else
+ {
+ presenter::PresenterViewShell* pPresenterViewShell
+ = dynamic_cast<presenter::PresenterViewShell*>(pBase->GetMainViewShell());
+ if (pPresenterViewShell != NULL)
+ {
+ pPresenterViewShell->SetCurrentSlide(
+ Reference<drawing::XDrawPage>(
+ rpDescriptor->GetPage()->getUnoPage(), UNO_QUERY));
+ }
+ }
+ */
+ }
+}
+
+
+
+
+void CurrentSlideManager::SetCurrentSlideAtXController (const SharedPageDescriptor& rpDescriptor)
+{
+ OSL_ASSERT(rpDescriptor.get() != NULL);
+
+ try
+ {
+ Reference<beans::XPropertySet> xSet (mrSlideSorter.GetXController(), UNO_QUERY);
+ if (xSet.is())
+ {
+ Any aPage;
+ aPage <<= rpDescriptor->GetPage()->getUnoPage();
+ xSet->setPropertyValue (
+ String::CreateFromAscii("CurrentPage"),
+ aPage);
+ }
+ }
+ catch (beans::UnknownPropertyException aException)
+ {
+ // We have not been able to set the current page at the main view.
+ // This is sad but still leaves us in a valid state. Therefore,
+ // this exception is silently ignored.
+ }
+}
+
+
+
+
+SharedPageDescriptor CurrentSlideManager::GetCurrentSlide (void)
+{
+ return mpCurrentSlide;
+}
+
+
+
+
+void CurrentSlideManager::PrepareModelChange (void)
+{
+ mpCurrentSlide.reset();
+}
+
+
+
+
+void CurrentSlideManager::HandleModelChange (void)
+{
+ if (mnCurrentSlideIndex >= 0)
+ {
+ mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor(
+ mnCurrentSlideIndex);
+ if (mpCurrentSlide.get() != NULL)
+ mpCurrentSlide->SetIsCurrentPage(true);
+ }
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
new file mode 100644
index 000000000000..4e6af1de67ed
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
@@ -0,0 +1,364 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+#include "controller/SlsFocusManager.hxx"
+
+#include "SlideSorter.hxx"
+#include "PaneDockingWindow.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include <vcl/toolbox.hxx>
+
+#include "Window.hxx"
+#include "sdpage.hxx"
+
+namespace sd { namespace slidesorter { namespace controller {
+
+FocusManager::FocusManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mnPageIndex(0),
+ mbPageIsFocused(false)
+{
+ if (mrSlideSorter.GetModel().GetPageCount() > 0)
+ mnPageIndex = 0;
+}
+
+
+
+
+FocusManager::~FocusManager (void)
+{
+}
+
+
+
+
+void FocusManager::MoveFocus (FocusMoveDirection eDirection)
+{
+ if (mnPageIndex >= 0 && mbPageIsFocused)
+ {
+ HideFocusIndicator (GetFocusedPageDescriptor());
+
+ int nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount());
+ switch (eDirection)
+ {
+ case FMD_NONE:
+ if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount())
+ mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1;
+ break;
+
+ case FMD_LEFT:
+ mnPageIndex -= 1;
+ if (mnPageIndex < 0)
+ {
+ mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1;
+ SetFocusToToolBox();
+ }
+ break;
+
+ case FMD_RIGHT:
+ mnPageIndex += 1;
+ if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount())
+ {
+ mnPageIndex = 0;
+ SetFocusToToolBox();
+ }
+ break;
+
+ case FMD_UP:
+ {
+ int nColumn = mnPageIndex % nColumnCount;
+ mnPageIndex -= nColumnCount;
+ if (mnPageIndex < 0)
+ {
+ // Wrap arround to the bottom row or the one above and
+ // go to the correct column.
+ int nCandidate = mrSlideSorter.GetModel().GetPageCount()-1;
+ int nCandidateColumn = nCandidate % nColumnCount;
+ if (nCandidateColumn > nColumn)
+ mnPageIndex = nCandidate - (nCandidateColumn-nColumn);
+ else if (nCandidateColumn < nColumn)
+ mnPageIndex = nCandidate
+ - nColumnCount
+ + (nColumn - nCandidateColumn);
+ else
+ mnPageIndex = nCandidate;
+ }
+ }
+ break;
+
+ case FMD_DOWN:
+ {
+ int nColumn = mnPageIndex % nColumnCount;
+ mnPageIndex += nColumnCount;
+ if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount())
+ {
+ // Wrap arround to the correct column.
+ mnPageIndex = nColumn;
+ }
+ }
+ break;
+ }
+
+ if (mbPageIsFocused)
+ ShowFocusIndicator(GetFocusedPageDescriptor(), true);
+ }
+}
+
+
+
+
+void FocusManager::ShowFocus (const bool bScrollToFocus)
+{
+ mbPageIsFocused = true;
+ ShowFocusIndicator(GetFocusedPageDescriptor(), bScrollToFocus);
+}
+
+
+
+
+void FocusManager::HideFocus (void)
+{
+ mbPageIsFocused = false;
+ HideFocusIndicator(GetFocusedPageDescriptor());
+}
+
+
+
+
+bool FocusManager::ToggleFocus (void)
+{
+ if (mnPageIndex >= 0)
+ {
+ if (mbPageIsFocused)
+ HideFocus ();
+ else
+ ShowFocus ();
+ }
+ return mbPageIsFocused;
+}
+
+
+
+
+bool FocusManager::HasFocus (void) const
+{
+ return mrSlideSorter.GetView().GetWindow()->HasFocus();
+}
+
+
+
+
+model::SharedPageDescriptor FocusManager::GetFocusedPageDescriptor (void) const
+{
+ return mrSlideSorter.GetModel().GetPageDescriptor(mnPageIndex);
+}
+
+
+
+
+sal_Int32 FocusManager::GetFocusedPageIndex (void) const
+{
+ return mnPageIndex;
+}
+
+
+
+
+void FocusManager::FocusPage (sal_Int32 nPageIndex)
+{
+ if (nPageIndex != mnPageIndex)
+ {
+ // Hide the focus while switching it to the specified page.
+ FocusHider aHider (*this);
+ mnPageIndex = nPageIndex;
+ }
+
+ if (HasFocus() && !IsFocusShowing())
+ ShowFocus();
+}
+
+
+
+
+void FocusManager::SetFocusedPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ FocusHider aFocusHider (*this);
+ mnPageIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+ }
+}
+
+
+
+
+void FocusManager::SetFocusedPage (sal_Int32 nPageIndex)
+{
+ FocusHider aFocusHider (*this);
+ mnPageIndex = nPageIndex;
+}
+
+
+
+
+bool FocusManager::IsFocusShowing (void) const
+{
+ return HasFocus() && mbPageIsFocused;
+}
+
+
+
+
+void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ rpDescriptor->RemoveFocus();
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+ }
+}
+
+
+
+
+void FocusManager::ShowFocusIndicator (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bScrollToFocus)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ rpDescriptor->SetFocus ();
+
+ if (bScrollToFocus)
+ {
+ // Scroll the focused page object into the visible area and repaint
+ // it, so that the focus indicator becomes visible.
+ view::SlideSorterView& rView (mrSlideSorter.GetView());
+ mrSlideSorter.GetController().GetSelectionManager()->MakeRectangleVisible (
+ rView.GetPageBoundingBox (
+ GetFocusedPageDescriptor(),
+ view::SlideSorterView::CS_MODEL,
+ view::SlideSorterView::BBT_INFO));
+ }
+
+ mrSlideSorter.GetView().RequestRepaint (rpDescriptor);
+ NotifyFocusChangeListeners();
+ }
+}
+
+
+
+
+void FocusManager::AddFocusChangeListener (const Link& rListener)
+{
+ if (::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener)
+ == maFocusChangeListeners.end())
+ {
+ maFocusChangeListeners.push_back (rListener);
+ }
+}
+
+
+
+
+void FocusManager::RemoveFocusChangeListener (const Link& rListener)
+{
+ maFocusChangeListeners.erase (
+ ::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener));
+}
+
+
+
+
+void FocusManager::SetFocusToToolBox (void)
+{
+ HideFocus();
+
+ if (mrSlideSorter.GetViewShell() != NULL)
+ {
+ ::Window* pParentWindow = mrSlideSorter.GetViewShell()->GetParentWindow();
+ DockingWindow* pDockingWindow = NULL;
+ while (pParentWindow!=NULL && pDockingWindow==NULL)
+ {
+ pDockingWindow = dynamic_cast<DockingWindow*>(pParentWindow);
+ pParentWindow = pParentWindow->GetParent();
+ }
+ if (pDockingWindow)
+ {
+ PaneDockingWindow* pPaneDockingWindow = dynamic_cast<PaneDockingWindow*>(pDockingWindow);
+ if (pPaneDockingWindow != NULL)
+ pPaneDockingWindow->GetToolBox().GrabFocus();
+ }
+ }
+}
+
+
+
+
+void FocusManager::NotifyFocusChangeListeners (void) const
+{
+ // Create a copy of the listener list to be safe when that is modified.
+ ::std::vector<Link> aListeners (maFocusChangeListeners);
+
+ // Tell the slection change listeners that the selection has changed.
+ ::std::vector<Link>::iterator iListener (aListeners.begin());
+ ::std::vector<Link>::iterator iEnd (aListeners.end());
+ for (; iListener!=iEnd; ++iListener)
+ {
+ iListener->Call(NULL);
+ }
+}
+
+
+
+
+FocusManager::FocusHider::FocusHider (FocusManager& rManager)
+: mbFocusVisible(rManager.IsFocusShowing())
+, mrManager(rManager)
+{
+ mrManager.HideFocus();
+}
+
+
+
+
+FocusManager::FocusHider::~FocusHider (void)
+{
+ if (mbFocusVisible)
+ mrManager.ShowFocus();
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx
new file mode 100644
index 000000000000..8f776432738f
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsHideSlideFunction.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+
+#include "app.hrc"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "ViewShell.hxx"
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <svx/svxids.hrc>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+TYPEINIT1(HideSlideFunction, SlideFunction);
+
+HideSlideFunction::HideSlideFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+ : SlideFunction( rSlideSorter, rRequest),
+ mrSlideSorter(rSlideSorter)
+{
+}
+
+
+
+
+HideSlideFunction::~HideSlideFunction (void)
+{
+}
+
+
+
+
+FunctionReference HideSlideFunction::Create (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest )
+{
+ FunctionReference xFunc( new HideSlideFunction( rSlideSorter, rRequest ) );
+ xFunc->DoExecute(rRequest);
+ return xFunc;
+}
+
+
+
+
+void HideSlideFunction::DoExecute (SfxRequest& rRequest)
+{
+ SlideFunction::DoExecute(rRequest);
+
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
+
+ ExclusionState eState (UNDEFINED);
+
+ switch (rRequest.GetSlot())
+ {
+ case SID_HIDE_SLIDE:
+ eState = EXCLUDED;
+ break;
+
+ case SID_SHOW_SLIDE:
+ eState = INCLUDED;
+ break;
+
+ default:
+ eState = UNDEFINED;
+ break;
+ }
+
+ if (eState != UNDEFINED)
+ {
+ // Set status at the selected pages.
+ aSelectedPages.Rewind ();
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ pDescriptor->GetPage()->SetExcluded (eState==EXCLUDED);
+ static_cast<view::SlideSorterView*>(mpView)->RequestRepaint(pDescriptor);
+ }
+ }
+
+ SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
+ rBindings.Invalidate (SID_PRESENTATION);
+ rBindings.Invalidate (SID_REHEARSE_TIMINGS);
+ rBindings.Invalidate (SID_HIDE_SLIDE);
+ rBindings.Invalidate (SID_SHOW_SLIDE);
+ mpDoc->SetChanged();
+}
+
+
+
+
+HideSlideFunction::ExclusionState HideSlideFunction::GetExclusionState (
+ model::PageEnumeration& rPageSet)
+{
+ ExclusionState eState (UNDEFINED);
+ BOOL bState;
+
+ // Get toggle state of the selected pages.
+ while (rPageSet.HasMoreElements() && eState!=MIXED)
+ {
+ bState = rPageSet.GetNextElement()->GetPage()->IsExcluded();
+ switch (eState)
+ {
+ case UNDEFINED:
+ // Use the first selected page to set the inital value.
+ eState = bState ? EXCLUDED : INCLUDED;
+ break;
+
+ case EXCLUDED:
+ // The pages before where all not part of the show,
+ // this one is.
+ if ( ! bState)
+ eState = MIXED;
+ break;
+
+ case INCLUDED:
+ // The pages before where all part of the show,
+ // this one is not.
+ if (bState)
+ eState = MIXED;
+ break;
+
+ case MIXED:
+ default:
+ // No need to change anything.
+ break;
+ }
+ }
+
+ return eState;
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx
new file mode 100644
index 000000000000..9fb32c2c088f
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_HIDE_SLIDE_FUNCTION_HXX
+#define SD_SLIDESORTER_HIDE_SLIDE_FUNCTION_HXX
+
+#include "controller/SlsSlideFunction.hxx"
+#include "model/SlsPageEnumeration.hxx"
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Toggle the hidden flag of the selected slides.
+ When the selected pages have not all the same state they will all set to
+ hidden. When all selected pages have the same state this state is
+ toggled for all of them
+*/
+class HideSlideFunction
+ : public SlideFunction
+{
+public:
+ TYPEINFO();
+
+ virtual ~HideSlideFunction (void);
+
+ static FunctionReference Create( SlideSorter& rSlideSorter, SfxRequest& rRequest );
+ virtual void DoExecute( SfxRequest& rReq );
+
+ // The state of a set of slides with respect to being excluded from the
+ // slide show.
+ enum ExclusionState {UNDEFINED, EXCLUDED, INCLUDED, MIXED};
+
+ /** Return for the given set of slides whether they included are
+ excluded from the slide show.
+ */
+ static ExclusionState GetExclusionState (model::PageEnumeration& rPageSet);
+
+protected:
+ HideSlideFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest);
+
+ SlideSorter& mrSlideSorter;
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsListener.cxx b/sd/source/ui/slidesorter/controller/SlsListener.cxx
new file mode 100644
index 000000000000..c3b470143303
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsListener.cxx
@@ -0,0 +1,602 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+#include "SlsListener.hxx"
+
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "ViewShellHint.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "view/SlideSorterView.hxx"
+#include "drawdoc.hxx"
+
+#include "glob.hrc"
+#include "ViewShellBase.hxx"
+#include "ViewShellManager.hxx"
+#include "FrameView.hxx"
+#include "EventMultiplexer.hxx"
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/FrameActionEvent.hpp>
+#include <com/sun/star/frame/FrameAction.hpp>
+#include <sfx2/viewfrm.hxx>
+#include <tools/diagnose_ex.h>
+
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+Listener::Listener (
+ SlideSorter& rSlideSorter)
+ : ListenerInterfaceBase(maMutex),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ mpBase(mrSlideSorter.GetViewShellBase()),
+ mbListeningToDocument (false),
+ mbListeningToUNODocument (false),
+ mbListeningToController (false),
+ mbListeningToFrame (false),
+ mbIsMainViewChangePending(false),
+ mxControllerWeak(),
+ mxFrameWeak(),
+ mpModelChangeLock()
+{
+ StartListening (*mrSlideSorter.GetModel().GetDocument());
+ mbListeningToDocument = true;
+
+ // Connect to the UNO document.
+ Reference<document::XEventBroadcaster> xBroadcaster (
+ mrSlideSorter.GetModel().GetDocument()->getUnoModel(), uno::UNO_QUERY);
+ if (xBroadcaster.is())
+ {
+ xBroadcaster->addEventListener (this);
+ mbListeningToUNODocument = true;
+ }
+
+ // Listen for disposing events from the document.
+ Reference<XComponent> xComponent (xBroadcaster, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener (
+ Reference<lang::XEventListener>(
+ static_cast<XWeak*>(this), UNO_QUERY));
+
+ // Connect to the frame to listen for controllers being exchanged.
+ bool bIsMainViewShell (false);
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ bIsMainViewShell = pViewShell->IsMainViewShell();
+ if ( ! bIsMainViewShell)
+ {
+ // Listen to changes of certain properties.
+ Reference<frame::XFrame> xFrame;
+ Reference<frame::XController> xController (mrSlideSorter.GetXController());
+ if (xController.is())
+ xFrame = xController->getFrame();
+ mxFrameWeak = xFrame;
+ if (xFrame.is())
+ {
+ xFrame->addFrameActionListener (
+ Reference<frame::XFrameActionListener>(
+ static_cast<XWeak*>(this), UNO_QUERY));
+ mbListeningToFrame = true;
+ }
+
+ // Connect to the current controller.
+ ConnectToController ();
+ }
+
+ // Listen for hints of the MainViewShell as well. If that is not yet
+ // present then the EventMultiplexer will tell us when it is available.
+ if (mpBase != NULL)
+ {
+ ViewShell* pMainViewShell = mpBase->GetMainViewShell().get();
+ if (pMainViewShell != NULL
+ && pMainViewShell!=pViewShell)
+ {
+ StartListening (*pMainViewShell);
+ }
+
+ Link aLink (LINK(this, Listener, EventMultiplexerCallback));
+ mpBase->GetEventMultiplexer()->AddEventListener(
+ aLink,
+ tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
+ | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
+ | tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
+ | tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED
+ | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
+ }
+}
+
+
+
+
+Listener::~Listener (void)
+{
+ DBG_ASSERT( !mbListeningToDocument && !mbListeningToUNODocument && !mbListeningToFrame,
+ "sd::Listener::~Listener(), disposing() was not called, ask DBO!" );
+}
+
+
+
+
+void Listener::ReleaseListeners (void)
+{
+ if (mbListeningToDocument)
+ {
+ EndListening (*mrSlideSorter.GetModel().GetDocument());
+ mbListeningToDocument = false;
+ }
+
+ if (mbListeningToUNODocument)
+ {
+ Reference<document::XEventBroadcaster> xBroadcaster (
+ mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY);
+ if (xBroadcaster.is())
+ xBroadcaster->removeEventListener (this);
+
+ // Remove the dispose listener.
+ Reference<XComponent> xComponent (xBroadcaster, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener (
+ Reference<lang::XEventListener>(
+ static_cast<XWeak*>(this), UNO_QUERY));
+
+ mbListeningToUNODocument = false;
+ }
+
+ if (mbListeningToFrame)
+ {
+ // Listen to changes of certain properties.
+ Reference<frame::XFrame> xFrame (mxFrameWeak);
+ if (xFrame.is())
+ {
+ xFrame->removeFrameActionListener (
+ Reference<frame::XFrameActionListener>(
+ static_cast<XWeak*>(this), UNO_QUERY));
+ mbListeningToFrame = false;
+ }
+ }
+
+ DisconnectFromController ();
+
+ if (mpBase != NULL)
+ {
+ Link aLink (LINK(this, Listener, EventMultiplexerCallback));
+ mpBase->GetEventMultiplexer()->RemoveEventListener(
+ aLink,
+ tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
+ | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
+ | tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
+ | tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED
+ | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
+ }
+}
+
+
+
+
+void Listener::ConnectToController (void)
+{
+ ViewShell* pShell = mrSlideSorter.GetViewShell();
+
+ // Register at the controller of the main view shell (if we are that not
+ // ourself).
+ if (pShell==NULL || ! pShell->IsMainViewShell())
+ {
+ Reference<frame::XController> xController (mrSlideSorter.GetXController());
+
+ // Listen to changes of certain properties.
+ Reference<beans::XPropertySet> xSet (xController, UNO_QUERY);
+ if (xSet.is())
+ {
+ try
+ {
+ xSet->addPropertyChangeListener(String::CreateFromAscii("CurrentPage"), this);
+ }
+ catch (beans::UnknownPropertyException aEvent)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ try
+ {
+ xSet->addPropertyChangeListener(String::CreateFromAscii("IsMasterPageMode"), this);
+ }
+ catch (beans::UnknownPropertyException aEvent)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ // Listen for disposing events.
+ Reference<XComponent> xComponent (xController, UNO_QUERY);
+ if (xComponent.is())
+ {
+ xComponent->addEventListener (
+ Reference<lang::XEventListener>(static_cast<XWeak*>(this), UNO_QUERY));
+
+ mxControllerWeak = xController;
+ mbListeningToController = true;
+ }
+ }
+}
+
+
+
+
+void Listener::DisconnectFromController (void)
+{
+ if (mbListeningToController)
+ {
+ Reference<frame::XController> xController = mxControllerWeak;
+ Reference<beans::XPropertySet> xSet (xController, UNO_QUERY);
+ try
+ {
+ // Remove the property listener.
+ if (xSet.is())
+ {
+ xSet->removePropertyChangeListener (
+ String::CreateFromAscii("CurrentPage"),
+ this);
+ xSet->removePropertyChangeListener (
+ String::CreateFromAscii("IsMasterPageMode"),
+ this);
+ }
+
+ // Remove the dispose listener.
+ Reference<XComponent> xComponent (xController, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener (
+ Reference<lang::XEventListener>(
+ static_cast<XWeak*>(this), UNO_QUERY));
+ }
+ catch (beans::UnknownPropertyException aEvent)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ mbListeningToController = false;
+ mxControllerWeak = Reference<frame::XController>();
+ }
+}
+
+
+
+
+void Listener::Notify (
+ SfxBroadcaster& rBroadcaster,
+ const SfxHint& rHint)
+{
+ if (rHint.ISA(SdrHint))
+ {
+ SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint));
+ if(rSdrHint.GetKind() == HINT_PAGEORDERCHG )
+ {
+ if (rBroadcaster.ISA(SdDrawDocument))
+ {
+ SdDrawDocument& rDocument (
+ static_cast<SdDrawDocument&>(rBroadcaster));
+ if (rDocument.GetMasterSdPageCount(PK_STANDARD)
+ == rDocument.GetMasterSdPageCount(PK_NOTES))
+ {
+ mrController.HandleModelChange();
+ }
+ }
+ }
+ }
+ else if (rHint.ISA(ViewShellHint))
+ {
+ ViewShellHint& rViewShellHint (*PTR_CAST(ViewShellHint,&rHint));
+ switch (rViewShellHint.GetHintId())
+ {
+ case ViewShellHint::HINT_PAGE_RESIZE_START:
+ // Initiate a model change but do nothing (well, not much)
+ // until we are told that all slides have been resized.
+ mpModelChangeLock.reset(new SlideSorterController::ModelChangeLock(mrController));
+ mrController.HandleModelChange();
+ break;
+
+ case ViewShellHint::HINT_PAGE_RESIZE_END:
+ // All slides have been resized. The model has to be updated.
+ mpModelChangeLock.reset();
+ break;
+
+ case ViewShellHint::HINT_CHANGE_EDIT_MODE_START:
+ mrController.PrepareEditModeChange();
+ break;
+
+ case ViewShellHint::HINT_CHANGE_EDIT_MODE_END:
+ mrController.FinishEditModeChange();
+ break;
+
+ case ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
+ mpModelChangeLock.reset(new SlideSorterController::ModelChangeLock(mrController));
+ break;
+
+ case ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
+ mpModelChangeLock.reset();
+ break;
+ }
+ }
+}
+
+
+
+
+IMPL_LINK(Listener, EventMultiplexerCallback, ::sd::tools::EventMultiplexerEvent*, pEvent)
+{
+ switch (pEvent->meEventId)
+ {
+ case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
+ {
+ if (mpBase != NULL)
+ {
+ ViewShell* pMainViewShell = mpBase->GetMainViewShell().get();
+ if (pMainViewShell != NULL)
+ EndListening(*pMainViewShell);
+ }
+ }
+ break;
+
+
+ case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
+ mbIsMainViewChangePending = true;
+ break;
+
+ case tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
+ if (mbIsMainViewChangePending && mpBase != NULL)
+ {
+ mbIsMainViewChangePending = false;
+ ViewShell* pMainViewShell = mpBase->GetMainViewShell().get();
+ if (pMainViewShell != NULL
+ && pMainViewShell!=mrSlideSorter.GetViewShell())
+ {
+ StartListening (*pMainViewShell);
+ }
+ }
+ break;
+
+ case tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED:
+ {
+ ConnectToController();
+ mrController.GetPageSelector().UpdateAllPages();
+ UpdateEditMode();
+ }
+ break;
+
+
+ case tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED:
+ DisconnectFromController();
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+
+
+//===== lang::XEventListener ================================================
+
+void SAL_CALL Listener::disposing (
+ const lang::EventObject& rEventObject)
+ throw (RuntimeException)
+{
+ if ((mbListeningToDocument || mbListeningToUNODocument)
+ && mrSlideSorter.GetModel().GetDocument()!=NULL
+ && rEventObject.Source
+ == mrSlideSorter.GetModel().GetDocument()->getUnoModel())
+ {
+ mbListeningToDocument = false;
+ mbListeningToUNODocument = false;
+ }
+ else if (mbListeningToController)
+ {
+ Reference<frame::XController> xController (mxControllerWeak);
+ if (rEventObject.Source == xController)
+ {
+ mbListeningToController = false;
+ }
+ }
+}
+
+
+
+
+//===== document::XEventListener ============================================
+
+void SAL_CALL Listener::notifyEvent (
+ const document::EventObject& )
+ throw (RuntimeException)
+{
+}
+
+
+
+
+//===== beans::XPropertySetListener =========================================
+
+void SAL_CALL Listener::propertyChange (
+ const PropertyChangeEvent& rEvent)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+
+ static const ::rtl::OUString sCurrentPagePropertyName (
+ RTL_CONSTASCII_USTRINGPARAM("CurrentPage"));
+ static const ::rtl::OUString sEditModePropertyName (
+ RTL_CONSTASCII_USTRINGPARAM("IsMasterPageMode"));
+
+ if (rEvent.PropertyName.equals (sCurrentPagePropertyName))
+ {
+ Any aCurrentPage = rEvent.NewValue;
+ Reference<beans::XPropertySet> xPageSet (aCurrentPage, UNO_QUERY);
+ if (xPageSet.is())
+ {
+ try
+ {
+ Any aPageNumber = xPageSet->getPropertyValue (
+ String(RTL_CONSTASCII_USTRINGPARAM("Number")));
+ sal_Int32 nCurrentPage = 0;
+ aPageNumber >>= nCurrentPage;
+ mrController.GetPageSelector().UpdateAllPages ();
+ // The selection is already set but we call SelectPage()
+ // nevertheless in order to make the new current page the
+ // last recently selected page of the PageSelector. This is
+ // used when making the selection visible.
+ mrController.GetPageSelector().SelectPage(nCurrentPage-1);
+ mrController.GetCurrentSlideManager()->CurrentSlideHasChanged(nCurrentPage-1);
+ }
+ catch (beans::UnknownPropertyException aEvent)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ catch (lang::DisposedException&)
+ {
+ // Something is already disposed. There is not much we can
+ // do, except not to crash.
+ }
+ }
+ }
+ else if (rEvent.PropertyName.equals (sEditModePropertyName))
+ {
+ sal_Bool bIsMasterPageMode = sal_False;
+ rEvent.NewValue >>= bIsMasterPageMode;
+ mrController.ChangeEditMode (
+ bIsMasterPageMode ? EM_MASTERPAGE : EM_PAGE);
+ }
+}
+
+
+
+
+//===== frame::XFrameActionListener ==========================================
+
+void SAL_CALL Listener::frameAction (const frame::FrameActionEvent& rEvent)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ switch (rEvent.Action)
+ {
+ case frame::FrameAction_COMPONENT_DETACHING:
+ DisconnectFromController();
+ break;
+
+ case frame::FrameAction_COMPONENT_REATTACHED:
+ {
+ ConnectToController();
+ mrController.GetPageSelector().UpdateAllPages();
+ UpdateEditMode();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+
+//===== accessibility::XAccessibleEventListener ==============================
+
+void SAL_CALL Listener::notifyEvent (
+ const AccessibleEventObject& )
+ throw (RuntimeException)
+{
+}
+
+
+
+
+void SAL_CALL Listener::disposing (void)
+{
+ ReleaseListeners();
+}
+
+
+
+
+void Listener::UpdateEditMode (void)
+{
+ // When there is a new controller then the edit mode may have changed at
+ // the same time.
+ Reference<frame::XController> xController (mxControllerWeak);
+ Reference<beans::XPropertySet> xSet (xController, UNO_QUERY);
+ bool bIsMasterPageMode = false;
+ if (xSet != NULL)
+ {
+ try
+ {
+ Any aValue (xSet->getPropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsMasterPageMode"))));
+ aValue >>= bIsMasterPageMode;
+ }
+ catch (beans::UnknownPropertyException e)
+ {
+ // When the property is not supported then the master page mode
+ // is not supported, too.
+ bIsMasterPageMode = false;
+ }
+ }
+ mrController.ChangeEditMode (
+ bIsMasterPageMode ? EM_MASTERPAGE : EM_PAGE);
+}
+
+
+
+
+void Listener::ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ throw lang::DisposedException (
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SlideSorterController object has already been disposed")),
+ static_cast<uno::XWeak*>(this));
+ }
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsListener.hxx b/sd/source/ui/slidesorter/controller/SlsListener.hxx
new file mode 100644
index 000000000000..3a9f511d05b6
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsListener.hxx
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_LISTENER_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_LISTENER_HXX
+
+#include "MutexOwner.hxx"
+#include "controller/SlideSorterController.hxx"
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#include <cppuhelper/compbase4.hxx>
+
+#include <svl/lstner.hxx>
+#include <tools/link.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace sd {
+class ViewShellBase;
+}
+
+namespace sd { namespace tools {
+class EventMultiplexerEvent;
+} }
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+typedef cppu::WeakComponentImplHelper4<
+ ::com::sun::star::document::XEventListener,
+ ::com::sun::star::beans::XPropertyChangeListener,
+ ::com::sun::star::accessibility::XAccessibleEventListener,
+ ::com::sun::star::frame::XFrameActionListener
+ > ListenerInterfaceBase;
+
+class SlideSorterController;
+
+/** Listen for events of various types and sources and react to them. This
+ class is a part of the controller.
+
+ When the view shell in the center pane is replaced by another the
+ associated controller is replaced as well. Therefore we have to
+ register at the frame and on certain FrameActionEvents to stop listening
+ to the old controller and register as listener at the new one.
+*/
+class Listener
+ : protected MutexOwner,
+ public ListenerInterfaceBase,
+ public SfxListener
+{
+public:
+ Listener (SlideSorter& rSlideSorter);
+ virtual ~Listener (void);
+
+ /** Connect to the current controller of the view shell as listener.
+ This method is called once during initialization and every time a
+ FrameActionEvent signals the current controller being exchanged.
+ When the connection is successfull then the flag
+ mbListeningToController is set to <TRUE/>.
+ */
+ void ConnectToController (void);
+
+ /** Disconnect from the current controller of the view shell as
+ listener. This method is called once during initialization and
+ every time a FrameActionEvent signals the current controller being
+ exchanged. When this method terminates then mbListeningToController
+ is <FALSE/>.
+ */
+ void DisconnectFromController (void);
+
+ virtual void Notify (
+ SfxBroadcaster& rBroadcaster,
+ const SfxHint& rHint);
+
+ //===== lang::XEventListener ============================================
+ virtual void SAL_CALL
+ disposing (const ::com::sun::star::lang::EventObject& rEventObject)
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ //===== document::XEventListener ========================================
+ virtual void SAL_CALL
+ notifyEvent (
+ const ::com::sun::star::document::EventObject& rEventObject)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== beans::XPropertySetListener =====================================
+ virtual void SAL_CALL
+ propertyChange (
+ const com::sun::star::beans::PropertyChangeEvent& rEvent)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== accessibility::XAccessibleEventListener ==========================
+ virtual void SAL_CALL
+ notifyEvent (
+ const ::com::sun::star::accessibility::AccessibleEventObject&
+ rEvent)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== frame::XFrameActionListener ======================================
+ /** For certain actions the listener connects to a new controller of the
+ frame it is listening to. This usually happens when the view shell
+ in the center pane is replaced by another view shell.
+ */
+ virtual void SAL_CALL
+ frameAction (const ::com::sun::star::frame::FrameActionEvent& rEvent)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL disposing (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+ ViewShellBase* mpBase;
+
+ /// Remember whether we are listening to the document.
+ bool mbListeningToDocument;
+ /// Remember whether we are listening to the UNO document.
+ bool mbListeningToUNODocument;
+ /// Remember whether we are listening to the UNO controller.
+ bool mbListeningToController;
+ /// Remember whether we are listening to the frame.
+ bool mbListeningToFrame;
+ bool mbIsMainViewChangePending;
+
+ ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XController> mxControllerWeak;
+ ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XFrame> mxFrameWeak;
+
+ /** This object is used to lock the model between some
+ events. It is refernce counted in order to cope with events that
+ are expected but never sent.
+ */
+ ::boost::shared_ptr<SlideSorterController::ModelChangeLock> mpModelChangeLock;
+
+ void ReleaseListeners (void);
+
+ /** Called when the edit mode has changed. Update model accordingly.
+ */
+ void UpdateEditMode (void);
+
+ /** This method throws a DisposedException when the object has already been
+ disposed.
+ */
+ void ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException);
+
+ DECL_LINK(EventMultiplexerCallback, tools::EventMultiplexerEvent*);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx b/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx
new file mode 100644
index 000000000000..7e49d884bedf
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsPageObjectFactory.hxx"
+
+#include "view/SlsPageObject.hxx"
+#include "view/SlsPageObjectViewContact.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+
+#include "sdpage.hxx"
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+PageObjectFactory::PageObjectFactory (
+ const ::boost::shared_ptr<cache::PageCache>& rpCache,
+ const ::boost::shared_ptr<controller::Properties>& rpProperties)
+ : mpPageCache(rpCache),
+ mpProperties(rpProperties)
+{
+}
+
+
+
+
+PageObjectFactory::~PageObjectFactory (void)
+{
+}
+
+
+
+
+view::PageObject* PageObjectFactory::CreatePageObject (
+ SdPage* pPage,
+ const model::SharedPageDescriptor& rpDescriptor) const
+{
+ return new view::PageObject(
+ Rectangle (Point(0,0), pPage->GetSize()),
+ pPage,
+ rpDescriptor);
+}
+
+
+
+
+::sdr::contact::ViewContact*
+ PageObjectFactory::CreateViewContact (
+ view::PageObject* pPageObject,
+ const model::SharedPageDescriptor& rpDescriptor) const
+{
+ return new view::PageObjectViewContact (
+ *pPageObject,
+ rpDescriptor);
+}
+
+
+
+
+::sdr::contact::ViewObjectContact*
+ PageObjectFactory::CreateViewObjectContact (
+ ::sdr::contact::ObjectContact& rObjectContact,
+ ::sdr::contact::ViewContact& rViewContact) const
+{
+ return new view::PageObjectViewObjectContact (
+ rObjectContact,
+ rViewContact,
+ mpPageCache,
+ mpProperties);
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx
new file mode 100644
index 000000000000..52c5b3d54de7
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsPageSelector.hxx"
+
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "view/SlideSorterView.hxx"
+
+#include "sdpage.hxx"
+#include "ViewShell.hxx"
+#include "DrawViewShell.hxx"
+#include "ViewShellBase.hxx"
+#include <com/sun/star/drawing/XDrawView.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::sd::slidesorter::model;
+using namespace ::sd::slidesorter::view;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+PageSelector::PageSelector (SlideSorter& rSlideSorter)
+ : mrModel(rSlideSorter.GetModel()),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ mnSelectedPageCount(0),
+ mnBroadcastDisableLevel(0),
+ mbSelectionChangeBroadcastPending(false),
+ mpMostRecentlySelectedPage(),
+ mpSelectionAnchor()
+{
+ CountSelectedPages ();
+}
+
+
+
+
+void PageSelector::SelectAllPages (void)
+{
+ int nPageCount = mrModel.GetPageCount();
+ for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
+ SelectPage (nPageIndex);
+}
+
+
+
+
+void PageSelector::DeselectAllPages (void)
+{
+ int nPageCount = mrModel.GetPageCount();
+ for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
+ DeselectPage (nPageIndex);
+ DBG_ASSERT (mnSelectedPageCount==0,
+ "PageSelector::DeselectAllPages: the selected pages counter is not 0");
+ mnSelectedPageCount = 0;
+ mpMostRecentlySelectedPage.reset();
+ mpSelectionAnchor.reset();
+}
+
+
+
+
+void PageSelector::UpdateAllPages (void)
+{
+ bool bSelectionHasChanged (true);
+ mnSelectedPageCount = 0;
+ model::PageEnumeration aAllPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->UpdateSelection())
+ {
+ mrSlideSorter.GetView().RequestRepaint(pDescriptor);
+ bSelectionHasChanged = true;
+ }
+
+ if (pDescriptor->IsSelected())
+ mnSelectedPageCount++;
+ }
+
+ if (bSelectionHasChanged)
+ {
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ }
+}
+
+
+
+
+void PageSelector::SelectPage (int nPageIndex)
+{
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ SelectPage(pDescriptor);
+}
+
+
+
+
+void PageSelector::SelectPage (const SdPage* pPage)
+{
+ int nPageIndex = (pPage->GetPageNum()-1) / 2;
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
+ SelectPage(pDescriptor);
+}
+
+
+
+
+void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get()!=NULL && rpDescriptor->Select())
+ {
+ mnSelectedPageCount ++;
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+
+ mpMostRecentlySelectedPage = rpDescriptor;
+ if (mpSelectionAnchor == NULL)
+ mpSelectionAnchor = rpDescriptor;
+
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ }
+}
+
+
+
+
+void PageSelector::DeselectPage (int nPageIndex)
+{
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ DeselectPage(pDescriptor);
+}
+
+
+
+
+void PageSelector::DeselectPage (const SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get()!=NULL && rpDescriptor->Deselect())
+ {
+ mnSelectedPageCount --;
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+ if (mpMostRecentlySelectedPage == rpDescriptor)
+ mpMostRecentlySelectedPage.reset();
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ }
+}
+
+
+
+
+bool PageSelector::IsPageSelected (int nPageIndex)
+{
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ return pDescriptor->IsSelected();
+ else
+ return false;
+}
+
+
+
+
+int PageSelector::GetPageCount (void) const
+{
+ return mrModel.GetPageCount();
+}
+
+
+
+
+int PageSelector::GetSelectedPageCount (void) const
+{
+ return mnSelectedPageCount;
+}
+
+
+
+
+void PageSelector::PrepareModelChange (void)
+{
+ DeselectAllPages ();
+}
+
+
+
+
+void PageSelector::HandleModelChange (void)
+{
+ UpdateAllPages();
+}
+
+
+
+
+SharedPageDescriptor PageSelector::GetMostRecentlySelectedPage (void) const
+{
+ return mpMostRecentlySelectedPage;
+}
+
+
+
+
+SharedPageDescriptor PageSelector::GetSelectionAnchor (void) const
+{
+ return mpSelectionAnchor;
+}
+
+
+
+
+void PageSelector::CountSelectedPages (void)
+{
+ mnSelectedPageCount = 0;
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
+ while (aSelectedPages.HasMoreElements())
+ {
+ mnSelectedPageCount++;
+ aSelectedPages.GetNextElement();
+ }
+}
+
+
+
+
+void PageSelector::EnableBroadcasting (bool bMakeSelectionVisible)
+{
+ if (mnBroadcastDisableLevel > 0)
+ mnBroadcastDisableLevel --;
+ if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
+ {
+ mrController.GetSelectionManager()->SelectionHasChanged(bMakeSelectionVisible);
+ mbSelectionChangeBroadcastPending = false;
+ }
+}
+
+
+
+
+void PageSelector::DisableBroadcasting (void)
+{
+ mnBroadcastDisableLevel ++;
+}
+
+
+
+
+::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const
+{
+ ::boost::shared_ptr<PageSelection> pSelection (new PageSelection());
+ pSelection->reserve(GetSelectedPageCount());
+
+ int nPageCount = GetPageCount();
+ for (int nIndex=0; nIndex<nPageCount; nIndex++)
+ {
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
+ if (pDescriptor.get()!=NULL && pDescriptor->IsSelected())
+ pSelection->push_back(pDescriptor->GetPage());
+ }
+
+ return pSelection;
+}
+
+
+
+
+void PageSelector::SetPageSelection (const ::boost::shared_ptr<PageSelection>& rpSelection)
+{
+ PageSelection::const_iterator iPage;
+ for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
+ SelectPage(*iPage);
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsProperties.cxx b/sd/source/ui/slidesorter/controller/SlsProperties.cxx
new file mode 100644
index 000000000000..1dedfe74b8d9
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsProperties.cxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsProperties.hxx"
+#include <vcl/svapp.hxx>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+Properties::Properties (void)
+ : mbIsHighlightCurrentSlide(false),
+ mbIsShowSelection(true),
+ mbIsShowFocus(true),
+ mbIsCenterSelection(false),
+ mbIsSmoothSelectionScrolling(false),
+ mbIsSuspendPreviewUpdatesDuringFullScreenPresentation(true),
+ maBackgroundColor(Application::GetSettings().GetStyleSettings().GetWindowColor()),
+ maTextColor(Application::GetSettings().GetStyleSettings().GetActiveTextColor()),
+ maSelectionColor(Application::GetSettings().GetStyleSettings().GetMenuHighlightColor()),
+ maHighlightColor(Application::GetSettings().GetStyleSettings().GetMenuHighlightColor()),
+ mbIsUIReadOnly(false)
+{
+}
+
+
+
+
+Properties::~Properties (void)
+{
+}
+
+
+
+
+bool Properties::IsHighlightCurrentSlide (void) const
+{
+ return mbIsHighlightCurrentSlide;
+}
+
+
+
+
+void Properties::SetHighlightCurrentSlide (const bool bIsHighlightCurrentSlide)
+{
+ mbIsHighlightCurrentSlide = bIsHighlightCurrentSlide;
+}
+
+
+
+
+bool Properties::IsShowSelection (void) const
+{
+ return mbIsShowSelection;
+}
+
+
+
+
+void Properties::SetShowSelection (const bool bIsShowSelection)
+{
+ mbIsShowSelection = bIsShowSelection;
+}
+
+
+
+
+bool Properties::IsShowFocus (void) const
+{
+ return mbIsShowFocus;
+}
+
+
+
+
+void Properties::SetShowFocus (const bool bIsShowFocus)
+{
+ mbIsShowFocus = bIsShowFocus;
+}
+
+
+
+
+bool Properties::IsCenterSelection (void) const
+{
+ return mbIsCenterSelection;
+}
+
+
+
+
+void Properties::SetCenterSelection (const bool bIsCenterSelection)
+{
+ mbIsCenterSelection = bIsCenterSelection;
+}
+
+
+
+
+bool Properties::IsSmoothSelectionScrolling (void) const
+{
+ return mbIsSmoothSelectionScrolling;
+}
+
+
+
+
+void Properties::SetSmoothSelectionScrolling (const bool bIsSmoothSelectionScrolling)
+{
+ mbIsSmoothSelectionScrolling = bIsSmoothSelectionScrolling;
+}
+
+
+
+
+bool Properties::IsSuspendPreviewUpdatesDuringFullScreenPresentation (void) const
+{
+ return mbIsSuspendPreviewUpdatesDuringFullScreenPresentation;
+}
+
+
+
+
+void Properties::SetSuspendPreviewUpdatesDuringFullScreenPresentation (const bool bFlag)
+{
+ mbIsSuspendPreviewUpdatesDuringFullScreenPresentation = bFlag;
+}
+
+
+
+
+Color Properties::GetBackgroundColor (void) const
+{
+ return maBackgroundColor;
+}
+
+
+
+
+void Properties::SetBackgroundColor (const Color& rColor)
+{
+ maBackgroundColor = rColor;
+}
+
+
+
+Color Properties::GetTextColor (void) const
+{
+ return maTextColor;
+}
+
+
+
+
+void Properties::SetTextColor (const Color& rColor)
+{
+ maTextColor = rColor;
+}
+
+
+
+
+Color Properties::GetSelectionColor (void) const
+{
+ return maSelectionColor;
+}
+
+
+
+
+void Properties::SetSelectionColor (const Color& rColor)
+{
+ maSelectionColor = rColor;
+}
+
+
+
+
+Color Properties::GetHighlightColor (void) const
+{
+ return maHighlightColor;
+}
+
+
+
+
+void Properties::SetHighlightColor (const Color& rColor)
+{
+ maHighlightColor = rColor;
+}
+
+
+
+
+bool Properties::IsUIReadOnly (void) const
+{
+ return mbIsUIReadOnly;
+}
+
+
+
+
+void Properties::SetUIReadOnly (const bool bIsUIReadOnly)
+{
+ mbIsUIReadOnly = bIsUIReadOnly;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx
new file mode 100644
index 000000000000..70dad4a5c8ee
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx
@@ -0,0 +1,634 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsScrollBarManager.hxx"
+
+#include "SlideSorter.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "Window.hxx"
+#include "sdpage.hxx"
+
+#include <boost/limits.hpp>
+
+#include <vcl/scrbar.hxx>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+ScrollBarManager::ScrollBarManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mpHorizontalScrollBar(mrSlideSorter.GetHorizontalScrollBar()),
+ mpVerticalScrollBar(mrSlideSorter.GetVerticalScrollBar()),
+ mnHorizontalPosition (0),
+ mnVerticalPosition (0),
+ maScrollBorder (10,10),
+ mnHorizontalScrollFactor (0.1),
+ mnVerticalScrollFactor (0.1),
+ mpScrollBarFiller(mrSlideSorter.GetScrollBarFiller()),
+ mpContentWindow(mrSlideSorter.GetContentWindow())
+{
+ // Hide the scroll bars by default to prevent display errors while
+ // switching between view shells: In the short time between initiating
+ // such a switch and the final rearrangement of UI controls the scroll
+ // bars and the filler where displayed in the upper left corner of the
+ // ViewTabBar.
+ mpHorizontalScrollBar->Hide();
+ mpVerticalScrollBar->Hide();
+ mpScrollBarFiller->Hide();
+
+ maAutoScrollTimer.SetTimeout(50);
+ maAutoScrollTimer.SetTimeoutHdl (
+ LINK(this, ScrollBarManager, AutoScrollTimeoutHandler));
+}
+
+
+
+
+ScrollBarManager::~ScrollBarManager (void)
+{
+}
+
+
+
+
+void ScrollBarManager::LateInitialization (void)
+{
+}
+
+
+
+
+void ScrollBarManager::Connect (void)
+{
+ if (mpVerticalScrollBar != NULL)
+ mpVerticalScrollBar->SetScrollHdl (
+ LINK(
+ this,
+ ScrollBarManager,
+ VerticalScrollBarHandler));
+ if (mpHorizontalScrollBar != NULL)
+ mpHorizontalScrollBar->SetScrollHdl (
+ LINK(
+ this,
+ ScrollBarManager,
+ HorizontalScrollBarHandler));
+}
+
+
+
+
+void ScrollBarManager::Disconnect (void)
+{
+ if (mpVerticalScrollBar != NULL)
+ mpVerticalScrollBar->SetScrollHdl (Link());
+ if (mpHorizontalScrollBar != NULL)
+ mpHorizontalScrollBar->SetScrollHdl (Link());
+}
+
+
+
+
+/** Placing the scroll bars is an iterative process. The visibility of one
+ scroll bar affects the remaining size and thus may lead to the other
+ scroll bar becoming visible.
+
+ First we determine the visibility of the horizontal scroll bar. After
+ that we do the same for the vertical scroll bar. To have an initial
+ value for the required size we call the layouter before that. When one
+ of the two scroll bars is made visible then the size of the browser
+ window changes and a second call to the layouter becomes necessary.
+ That call is made anyway after this method returns.
+*/
+Rectangle ScrollBarManager::PlaceScrollBars (const Rectangle& rAvailableArea)
+{
+ Rectangle aRemainingSpace (DetermineScrollBarVisibilities(rAvailableArea));
+ PlaceHorizontalScrollBar (rAvailableArea);
+ PlaceVerticalScrollBar (rAvailableArea);
+ PlaceFiller (rAvailableArea);
+
+ return aRemainingSpace;
+}
+
+
+
+
+void ScrollBarManager::PlaceHorizontalScrollBar (const Rectangle& aAvailableArea)
+{
+ if (mpHorizontalScrollBar != NULL
+ && mpHorizontalScrollBar->IsVisible())
+ {
+ // Save the current relative position.
+ mnHorizontalPosition = double(mpHorizontalScrollBar->GetThumbPos())
+ / double(mpHorizontalScrollBar->GetRange().Len());
+
+ // Place the scroll bar.
+ Size aScrollBarSize (mpHorizontalScrollBar->GetSizePixel());
+ mpHorizontalScrollBar->SetPosSizePixel (
+ Point(aAvailableArea.Left(),
+ aAvailableArea.Bottom()-aScrollBarSize.Height()+1),
+ Size (aAvailableArea.GetWidth() - GetVerticalScrollBarWidth(),
+ aScrollBarSize.Height()));
+
+ // Restore the relative position.
+ mpHorizontalScrollBar->SetThumbPos(
+ (long)(0.5 + mnHorizontalPosition * mpHorizontalScrollBar->GetRange().Len()));
+ }
+}
+
+
+
+
+void ScrollBarManager::PlaceVerticalScrollBar (const Rectangle& aArea)
+{
+ if (mpVerticalScrollBar != NULL
+ && mpVerticalScrollBar->IsVisible())
+ {
+ view::Layouter::DoublePoint aLayouterPosition
+ = mrSlideSorter.GetView().GetLayouter().ConvertModelToLayouterCoordinates (
+ Point (0, mpVerticalScrollBar->GetThumbPos()));
+
+ // Place the scroll bar.
+ Size aScrollBarSize (mpVerticalScrollBar->GetSizePixel());
+ Point aPosition (aArea.Right()-aScrollBarSize.Width()+1, aArea.Top());
+ Size aSize (aScrollBarSize.Width(), aArea.GetHeight() - GetHorizontalScrollBarHeight());
+ mpVerticalScrollBar->SetPosSizePixel(aPosition, aSize);
+
+ // Restore the position.
+ mpVerticalScrollBar->SetThumbPos(
+ mrSlideSorter.GetView().GetLayouter().ConvertLayouterToModelCoordinates(
+ aLayouterPosition).Y());
+ mnVerticalPosition = double(mpVerticalScrollBar->GetThumbPos())
+ / double(mpVerticalScrollBar->GetRange().Len());
+ }
+}
+
+
+
+
+void ScrollBarManager::PlaceFiller (const Rectangle& aArea)
+{
+ // Place the filler when both scroll bars are visible.
+ if (mpHorizontalScrollBar != NULL
+ && mpVerticalScrollBar != NULL
+ && mpHorizontalScrollBar->IsVisible()
+ && mpVerticalScrollBar->IsVisible())
+ {
+ mpScrollBarFiller->SetPosSizePixel(
+ Point(
+ aArea.Right()-mpVerticalScrollBar->GetSizePixel().Width()+1,
+ aArea.Bottom()-mpHorizontalScrollBar->GetSizePixel().Height()+1),
+ Size (
+ mpVerticalScrollBar->GetSizePixel().Width(),
+ mpHorizontalScrollBar->GetSizePixel().Height()));
+ mpScrollBarFiller->Show();
+ }
+ else
+ mpScrollBarFiller->Hide();
+}
+
+
+
+
+void ScrollBarManager::UpdateScrollBars (bool bResetThumbPosition, bool bUseScrolling)
+{
+ Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
+ ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow();
+ Size aWindowModelSize (pWindow->PixelToLogic(pWindow->GetSizePixel()));
+
+ // The horizontal scroll bar is only shown when the window is
+ // horizontally smaller than the view.
+ if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible())
+ {
+ mpHorizontalScrollBar->Show();
+ mpHorizontalScrollBar->SetRange (
+ Range(aModelArea.Left(), aModelArea.Right()));
+ if (bResetThumbPosition)
+ {
+ mpHorizontalScrollBar->SetThumbPos (0);
+ mnHorizontalPosition = 0;
+ }
+ else
+ mnHorizontalPosition =
+ double(mpHorizontalScrollBar->GetThumbPos())
+ / double(mpHorizontalScrollBar->GetRange().Len());
+
+ mpHorizontalScrollBar->SetVisibleSize (aWindowModelSize.Width());
+
+ const long nWidth (mpContentWindow->PixelToLogic(
+ mpContentWindow->GetSizePixel()).Width());
+ // Make the line size about 10% of the visible width.
+ mpHorizontalScrollBar->SetLineSize (nWidth / 10);
+ // Make the page size about 90% of the visible width.
+ mpHorizontalScrollBar->SetPageSize ((nWidth * 9) / 10);
+ }
+ else
+ {
+ mnHorizontalPosition = 0;
+ }
+
+ // The vertical scroll bar is always shown.
+ if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible())
+ {
+ mpVerticalScrollBar->SetRange (
+ Range(aModelArea.Top(), aModelArea.Bottom()));
+ if (bResetThumbPosition)
+ {
+ mpVerticalScrollBar->SetThumbPos (0);
+ mnVerticalPosition = 0;
+ }
+ else
+ mnVerticalPosition =
+ double(mpVerticalScrollBar->GetThumbPos())
+ / double(mpVerticalScrollBar->GetRange().Len());
+
+ mpVerticalScrollBar->SetVisibleSize (aWindowModelSize.Height());
+
+ const long nHeight (mpContentWindow->PixelToLogic(
+ mpContentWindow->GetSizePixel()).Height());
+ // Make the line size about 10% of the visible height.
+ mpVerticalScrollBar->SetLineSize (nHeight / 10);
+ // Make the page size about 90% of the visible height.
+ mpVerticalScrollBar->SetPageSize ((nHeight * 9) / 10);
+ }
+ else
+ {
+ mnVerticalPosition = 0;
+ }
+
+
+ double nEps (::std::numeric_limits<double>::epsilon());
+ if (fabs(mnHorizontalPosition-pWindow->GetVisibleX()) > nEps
+ || fabs(mnVerticalPosition-pWindow->GetVisibleY()) > nEps)
+ {
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ if (bUseScrolling)
+ pWindow->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
+ else
+ SetWindowOrigin(mnHorizontalPosition, mnVerticalPosition);
+ }
+}
+
+
+
+
+IMPL_LINK(ScrollBarManager, VerticalScrollBarHandler, ScrollBar*, pScrollBar)
+{
+ if (pScrollBar!=NULL
+ && pScrollBar==mpVerticalScrollBar.get()
+ && pScrollBar->IsVisible()
+ && mrSlideSorter.GetView().GetWindow()!=NULL)
+ {
+ double nRelativePosition = double(pScrollBar->GetThumbPos())
+ / double(pScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetView().GetWindow()->SetVisibleXY (
+ -1,
+ nRelativePosition);
+ }
+ return TRUE;
+}
+
+
+
+
+IMPL_LINK(ScrollBarManager, HorizontalScrollBarHandler, ScrollBar*, pScrollBar)
+{
+ if (pScrollBar!=NULL
+ && pScrollBar==mpHorizontalScrollBar.get()
+ && pScrollBar->IsVisible()
+ && mrSlideSorter.GetView().GetWindow()!=NULL)
+ {
+ double nRelativePosition = double(pScrollBar->GetThumbPos())
+ / double(pScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetView().GetWindow()->SetVisibleXY (nRelativePosition, -1);
+ }
+ return TRUE;
+}
+
+
+
+
+void ScrollBarManager::SetWindowOrigin (
+ double nHorizontalPosition,
+ double nVerticalPosition)
+{
+ mnHorizontalPosition = nHorizontalPosition;
+ mnVerticalPosition = nVerticalPosition;
+
+ ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow();
+ Size aViewSize (pWindow->GetViewSize());
+ Point aOrigin (
+ (long int) (mnHorizontalPosition * aViewSize.Width()),
+ (long int) (mnVerticalPosition * aViewSize.Height()));
+
+ pWindow->SetWinViewPos (aOrigin);
+ pWindow->UpdateMapMode ();
+ pWindow->Invalidate ();
+}
+
+
+
+
+/** Determining the visibility of the scroll bars is quite complicated. The
+ visibility of one influences that of the other because showing a scroll
+ bar makes the available space smaller and may lead to the need of
+ displaying the other.
+ To solve this we test all four combinations of showing or hiding each
+ scroll bar and use the best one. The best one is that combination that
+ a) shows the least number of scroll bars with preference of showing the
+ vertical over showing the horizontal and
+ b) when not showing a scroll bar the area used by the page objects fits
+ into the available area in the scroll bars orientation.
+*/
+Rectangle ScrollBarManager::DetermineScrollBarVisibilities (const Rectangle& rAvailableArea)
+{
+ // Test which combination of scroll bars is the best.
+ bool bShowHorizontal = false;
+ bool bShowVertical = false;
+ do
+ {
+ if (mrSlideSorter.GetModel().GetPageCount() == 0)
+ // No pages => no scroll bars.
+ break;
+
+ if (TestScrollBarVisibilities(bShowHorizontal=false, bShowVertical=false, rAvailableArea))
+ break;
+ if (TestScrollBarVisibilities(bShowHorizontal=true, bShowVertical=false, rAvailableArea))
+ break;
+ if (TestScrollBarVisibilities(bShowHorizontal=false, bShowVertical=true, rAvailableArea))
+ break;
+ if (TestScrollBarVisibilities(bShowHorizontal=true, bShowVertical=true, rAvailableArea))
+ break;
+ }
+ while (false);
+
+ // Make the visibility of the scroll bars permanent.
+ mpVerticalScrollBar->Show(bShowVertical);
+ mpHorizontalScrollBar->Show(bShowHorizontal);
+
+ // Adapt the remaining space accordingly.
+ Rectangle aRemainingSpace (rAvailableArea);
+ if (bShowVertical)
+ aRemainingSpace.Right() -= mpVerticalScrollBar->GetSizePixel().Width();
+ if (bShowHorizontal)
+ aRemainingSpace.Bottom() -= mpHorizontalScrollBar->GetSizePixel().Height();
+
+ return aRemainingSpace;
+}
+
+
+
+
+bool ScrollBarManager::TestScrollBarVisibilities (
+ bool bHorizontalScrollBarVisible,
+ bool bVerticalScrollBarVisible,
+ const Rectangle& rAvailableArea)
+{
+ bool bAreVisibilitiesOK = true;
+
+ // Adapt the available size by subtracting the sizes of the scroll bars
+ // visible in this combination.
+ Size aBrowserSize (rAvailableArea.GetSize());
+ if (bHorizontalScrollBarVisible)
+ aBrowserSize.Height() -= mpHorizontalScrollBar->GetSizePixel().Height();
+ if (bVerticalScrollBarVisible)
+ aBrowserSize.Width() -= mpVerticalScrollBar->GetSizePixel().Width();
+
+ // Tell the view to rearrange its page objects and check whether the
+ // page objects can be shown without clipping.
+ bool bRearrangeSuccess (false);
+ if (mrSlideSorter.GetView().GetOrientation() == view::SlideSorterView::HORIZONTAL)
+ {
+ bRearrangeSuccess = mrSlideSorter.GetView().GetLayouter().RearrangeHorizontal (
+ aBrowserSize,
+ mrSlideSorter.GetModel().GetPageDescriptor(0)->GetPage()->GetSize(),
+ mpContentWindow.get(),
+ mrSlideSorter.GetModel().GetPageCount());
+ }
+ else
+ {
+ bRearrangeSuccess = mrSlideSorter.GetView().GetLayouter().RearrangeVertical (
+ aBrowserSize,
+ mrSlideSorter.GetModel().GetPageDescriptor(0)->GetPage()->GetSize(),
+ mpContentWindow.get());
+ }
+
+ if (bRearrangeSuccess)
+ {
+ Size aPageSize = mrSlideSorter.GetView().GetLayouter().GetPageBox (
+ mrSlideSorter.GetModel().GetPageCount()).GetSize();
+ Size aWindowModelSize = mpContentWindow->PixelToLogic(aBrowserSize);
+
+ bool bHorizontallyClipped = (aPageSize.Width() > aWindowModelSize.Width());
+ bool bVerticallyClipped = (aPageSize.Height() > aWindowModelSize.Height());
+ bAreVisibilitiesOK = (bHorizontallyClipped == bHorizontalScrollBarVisible)
+ && (bVerticallyClipped == bVerticalScrollBarVisible);
+ }
+ else
+ bAreVisibilitiesOK = false;
+
+ return bAreVisibilitiesOK;
+}
+
+
+
+
+void ScrollBarManager::SetTop (const sal_Int32 nNewTop)
+{
+ if (mpVerticalScrollBar != NULL
+ && mpVerticalScrollBar->GetThumbPos() != nNewTop)
+ {
+ // Flush pending repaints before scrolling to avoid temporary artifacts.
+ mrSlideSorter.GetView().GetWindow()->Update();
+
+ mpVerticalScrollBar->SetThumbPos(nNewTop);
+ mnVerticalPosition = double(nNewTop) / double(mpVerticalScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().GetWindow()->SetVisibleXY (
+ mnHorizontalPosition, mnVerticalPosition);
+ }
+}
+
+
+
+
+void ScrollBarManager::SetLeft (const sal_Int32 nNewLeft)
+{
+ if (mpHorizontalScrollBar != NULL
+ && mpHorizontalScrollBar->GetThumbPos() != nNewLeft)
+ {
+ // Flush pending repaints before scrolling to avoid temporary artifacts.
+ mrSlideSorter.GetView().GetWindow()->Update();
+
+ mpHorizontalScrollBar->SetThumbPos(nNewLeft);
+ mnHorizontalPosition = double(nNewLeft) / double(mpHorizontalScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().GetWindow()->SetVisibleXY (
+ mnHorizontalPosition, mnVerticalPosition);
+ }
+}
+
+
+
+
+int ScrollBarManager::GetVerticalScrollBarWidth (void) const
+{
+ if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible())
+ return mpVerticalScrollBar->GetSizePixel().Width();
+ else
+ return 0;
+}
+
+
+
+
+int ScrollBarManager::GetHorizontalScrollBarHeight (void) const
+{
+ if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible())
+ return mpHorizontalScrollBar->GetSizePixel().Height();
+ else
+ return 0;
+}
+
+
+
+
+void ScrollBarManager::CalcAutoScrollOffset (const Point& rMouseWindowPosition)
+{
+ ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow();
+
+ int nDx = 0;
+ int nDy = 0;
+
+ Size aWindowSize = pWindow->GetOutputSizePixel();
+ Rectangle aWindowArea (pWindow->GetPosPixel(), aWindowSize);
+ Rectangle aViewPixelArea (
+ pWindow->LogicToPixel(mrSlideSorter.GetView().GetModelArea()));
+
+ if (aWindowSize.Width() > maScrollBorder.Width() * 3
+ && mpHorizontalScrollBar != NULL
+ && mpHorizontalScrollBar->IsVisible())
+ {
+ if (rMouseWindowPosition.X() < maScrollBorder.Width()
+ && aWindowArea.Left() > aViewPixelArea.Left())
+ {
+ nDx = -1 + (int)(mnHorizontalScrollFactor
+ * (rMouseWindowPosition.X() - maScrollBorder.Width()));
+ }
+
+ if (rMouseWindowPosition.X() >= (aWindowSize.Width() - maScrollBorder.Width())
+ && aWindowArea.Right() < aViewPixelArea.Right())
+ {
+ nDx = 1 + (int)(mnHorizontalScrollFactor
+ * (rMouseWindowPosition.X() - aWindowSize.Width()
+ + maScrollBorder.Width()));
+ }
+ }
+
+ if (aWindowSize.Height() > maScrollBorder.Height() * 3
+ && aWindowSize.Height() < aViewPixelArea.GetHeight())
+ {
+ if (rMouseWindowPosition.Y() < maScrollBorder.Height()
+ && aWindowArea.Top() > aViewPixelArea.Top())
+ {
+ nDy = -1 + (int)(mnVerticalScrollFactor
+ * (rMouseWindowPosition.Y() - maScrollBorder.Height()));
+ }
+
+ if (rMouseWindowPosition.Y() >= (aWindowSize.Height() - maScrollBorder.Height())
+ && aWindowArea.Bottom() < aViewPixelArea.Bottom())
+ {
+ nDy = 1 + (int)(mnVerticalScrollFactor
+ * (rMouseWindowPosition.Y() - aWindowSize.Height()
+ + maScrollBorder.Height()));
+ }
+ }
+
+ maAutoScrollOffset = Size(nDx,nDy);
+}
+
+
+
+
+bool ScrollBarManager::AutoScroll (const Point& rMouseWindowPosition)
+{
+ CalcAutoScrollOffset (rMouseWindowPosition);
+ bool bResult = RepeatAutoScroll();
+ if (bResult)
+ {
+ maAutoScrollTimer.Start();
+ }
+ return bResult;
+}
+
+
+
+
+void ScrollBarManager::StopAutoScroll (void)
+{
+ maAutoScrollTimer.Stop();
+}
+
+
+
+
+bool ScrollBarManager::RepeatAutoScroll (void)
+{
+ if (maAutoScrollOffset != Size(0,0))
+ {
+ if (mrSlideSorter.GetViewShell() != NULL)
+ {
+ mrSlideSorter.GetViewShell()->ScrollLines(
+ maAutoScrollOffset.Width(),
+ maAutoScrollOffset.Height());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+
+IMPL_LINK(ScrollBarManager, AutoScrollTimeoutHandler, Timer *, EMPTYARG)
+{
+ RepeatAutoScroll();
+
+ return 0;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx
new file mode 100644
index 000000000000..a6228a75df21
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlsSelectionCommand.hxx"
+
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+
+#include "sdpage.hxx"
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+
+SelectionCommand::SelectionCommand (
+ PageSelector& rSelector,
+ const ::boost::shared_ptr<CurrentSlideManager>& rpCurrentSlideManager,
+ const model::SlideSorterModel& rModel)
+ : mrPageSelector(rSelector),
+ mpCurrentSlideManager(rpCurrentSlideManager),
+ mrModel(rModel),
+ maPagesToSelect(),
+ mnCurrentPageIndex(-1)
+{
+}
+
+
+
+
+void SelectionCommand::AddSlide (USHORT nPageIndex)
+{
+ maPagesToSelect.push_back(nPageIndex);
+}
+
+
+
+
+void SelectionCommand::operator() (void)
+{
+ OSL_ASSERT(mpCurrentSlideManager.get()!=NULL);
+
+ mrPageSelector.DeselectAllPages();
+
+ if (mnCurrentPageIndex >= 0)
+ mpCurrentSlideManager->SwitchCurrentSlide(mnCurrentPageIndex);
+
+ PageList::iterator iPage = maPagesToSelect.begin();
+ PageList::iterator iEnd = maPagesToSelect.end();
+ for (; iPage!=iEnd; ++iPage)
+ {
+ sal_Int32 nIndex (*iPage);
+ if (nIndex >= 0)
+ mrPageSelector.SelectPage(mrModel.GetPageDescriptor(nIndex));
+ }
+}
+
+
+} } } // end of namespace sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx
new file mode 100644
index 000000000000..e42138a4f813
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SELECTION_COMMAND_HXX
+#define SD_SLIDESORTER_SELECTION_COMMAND_HXX
+
+#include "controller/SlsPageSelector.hxx"
+#include "SlsCommand.hxx"
+#include <tools/solar.h>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class CurrentSlideManager;
+class PageSelector;
+
+/** The SelectionCommand stores a list of pages that it will select on its
+ execution. Furthermore it will make a page the current page. Note that
+ internally pages are stored with pointers because this command is designed
+ to be executed after model changes where page indices may change but
+ page object identities remain.
+*/
+class SelectionCommand
+ : public Command
+{
+public:
+ /** Create a new command object that will on its exection use the given
+ PageSelector to select a set of pages.
+ */
+ SelectionCommand (
+ PageSelector& rSelector,
+ const ::boost::shared_ptr<controller::CurrentSlideManager>& rpCurrentSlideManager,
+ const model::SlideSorterModel& rModel);
+
+ /** Remember the specified page to be selected when this command is
+ executed.
+ */
+ void AddSlide (USHORT nPageIndex);
+
+ /** Execute the command and select the pages added by previous calls to
+ AddPages() and AddPage().
+ */
+ virtual void operator() (void);
+
+private:
+ /// The page selector is used to select pages and set the current page.
+ PageSelector& mrPageSelector;
+ /// Used for setting the current slide.
+ ::boost::shared_ptr<controller::CurrentSlideManager> mpCurrentSlideManager;
+ /// The model is used to translate page indices into page pointers.
+ const model::SlideSorterModel& mrModel;
+ /// The list of pages to be selected when the command is executed.
+ typedef ::std::vector<sal_Int32> PageList;
+ PageList maPagesToSelect;
+ /** The page that will be made the current page when the command is
+ executed.
+ */
+ sal_Int32 mnCurrentPageIndex;
+};
+
+} } } // end of namespace sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
new file mode 100644
index 000000000000..1a4f14be656c
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
@@ -0,0 +1,1320 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsSelectionFunction.hxx"
+
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsClipboard.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsProperties.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "ViewShellBase.hxx"
+#include "DrawController.hxx"
+#include <vcl/sound.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svdpagv.hxx>
+#include <vcl/msgbox.hxx>
+#include "Window.hxx"
+#include "sdpage.hxx"
+#include "drawdoc.hxx"
+#include "ViewShell.hxx"
+#include "ViewShellBase.hxx"
+#include "FrameView.hxx"
+#include "app.hrc"
+#include "sdresid.hxx"
+#include "strings.hrc"
+
+namespace {
+static const sal_uInt32 SINGLE_CLICK (0x00000001);
+static const sal_uInt32 DOUBLE_CLICK (0x00000002);
+static const sal_uInt32 LEFT_BUTTON (0x00000010);
+static const sal_uInt32 RIGHT_BUTTON (0x00000020);
+static const sal_uInt32 MIDDLE_BUTTON (0x00000040);
+static const sal_uInt32 BUTTON_DOWN (0x00000100);
+static const sal_uInt32 BUTTON_UP (0x00000200);
+static const sal_uInt32 MOUSE_MOTION (0x00000400);
+// The rest leaves the lower 16 bit untouched so that it can be used with
+// key codes.
+static const sal_uInt32 OVER_SELECTED_PAGE (0x00010000);
+static const sal_uInt32 OVER_UNSELECTED_PAGE (0x00020000);
+static const sal_uInt32 OVER_FADE_INDICATOR (0x00040000);
+static const sal_uInt32 SHIFT_MODIFIER (0x00100000);
+static const sal_uInt32 CONTROL_MODIFIER (0x00200000);
+static const sal_uInt32 SUBSTITUTION_VISIBLE (0x01000000);
+static const sal_uInt32 RECTANGLE_VISIBLE (0x02000000);
+
+static const sal_uInt32 KEY_EVENT (0x10000000);
+
+// Some absent events are defined so they can be expressed explicitly.
+static const sal_uInt32 NO_MODIFIER (0x00000000);
+static const sal_uInt32 SUBSTITUTION_NOT_VISIBLE (0x00000000);
+static const sal_uInt32 NOT_OVER_PAGE (0x00000000);
+
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SelectionFunction::SubstitutionHandler
+{
+public:
+ SubstitutionHandler (SlideSorter& rSlideSorter);
+ ~SubstitutionHandler (void);
+
+ /** Create a substitution display of the currently selected pages and
+ use the given position as the anchor point.
+ */
+ void Start (const Point& rMouseModelPosition);
+
+ /** Move the substitution display by the distance the mouse has
+ travelled since the last call to this method or to
+ CreateSubstitution(). The given point becomes the new anchor.
+ */
+ void UpdatePosition (const Point& rMouseModelPosition);
+
+ /** Move the substitution display of the currently selected pages.
+ */
+ void Process (void);
+
+ void End (void);
+
+ bool HasBeenMoved (void) const;
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ bool mbHasBeenMoved;
+
+ /** Determine whether there is a) a substitution and b) its insertion at
+ the current position of the insertion marker would alter the
+ document. This would be the case when the substitution has been
+ moved or is not consecutive.
+ */
+ bool IsSubstitutionInsertionNonTrivial (void) const;
+};
+
+
+class SelectionFunction::EventDescriptor
+{
+public:
+
+ Point maMousePosition;
+ Point maMouseModelPosition;
+ ::boost::weak_ptr<model::PageDescriptor> mpHitDescriptor;
+ SdrPage* mpHitPage;
+ sal_uInt32 mnEventCode;
+
+ EventDescriptor (
+ sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter);
+ EventDescriptor (
+ const KeyEvent& rEvent,
+ SlideSorter& rSlideSorter);
+};
+
+
+TYPEINIT1(SelectionFunction, FuPoor);
+
+
+SelectionFunction::SelectionFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+ : SlideFunction (rSlideSorter, rRequest),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ mbDragSelection(false),
+ maInsertionMarkerBox(),
+ mbProcessingMouseButtonDown(false),
+ mpSubstitutionHandler(new SubstitutionHandler(mrSlideSorter))
+{
+ //af aDelayToScrollTimer.SetTimeout(50);
+ aDragTimer.SetTimeoutHdl( LINK( this, SelectionFunction, DragSlideHdl ) );
+}
+
+SelectionFunction::~SelectionFunction (void)
+{
+ aDragTimer.Stop();
+}
+
+
+
+
+FunctionReference SelectionFunction::Create(
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+{
+ FunctionReference xFunc( new SelectionFunction( rSlideSorter, rRequest ) );
+ return xFunc;
+}
+
+
+
+
+BOOL SelectionFunction::MouseButtonDown (const MouseEvent& rEvent)
+{
+ // #95491# remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+ mbProcessingMouseButtonDown = true;
+
+ mpWindow->CaptureMouse();
+
+ ProcessMouseEvent(BUTTON_DOWN, rEvent);
+
+ return TRUE;
+}
+
+
+
+
+BOOL SelectionFunction::MouseMove (const MouseEvent& rEvent)
+{
+ Point aMousePosition (rEvent.GetPosPixel());
+
+ // Determine page under mouse and show the mouse over effect.
+ model::SharedPageDescriptor pHitDescriptor (mrController.GetPageAt(aMousePosition));
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ rOverlay.GetMouseOverIndicatorOverlay().SetSlideUnderMouse(
+ rEvent.IsLeaveWindow() ? model::SharedPageDescriptor() : pHitDescriptor);
+ if (pHitDescriptor.get() != NULL)
+ rOverlay.GetMouseOverIndicatorOverlay().setVisible(true);
+ else
+ rOverlay.GetMouseOverIndicatorOverlay().setVisible(false);
+
+ // Allow one mouse move before the drag timer is disabled.
+ if (aDragTimer.IsActive())
+ {
+ if (bFirstMouseMove)
+ bFirstMouseMove = FALSE;
+ else
+ aDragTimer.Stop();
+ }
+
+ Rectangle aRectangle (Point(0,0),mpWindow->GetOutputSizePixel());
+ if ( ! aRectangle.IsInside(aMousePosition)
+ && rOverlay.GetSubstitutionOverlay().isVisible())
+ {
+ // Mouse left the window with pressed left button. Make it a drag.
+ StartDrag();
+ }
+ else
+ {
+ // Call ProcessMouseEvent() only when one of the buttons is
+ // pressed. This prevents calling the method on every motion.
+ if (rEvent.GetButtons() != 0
+ && mbProcessingMouseButtonDown)
+ {
+ ProcessMouseEvent(MOUSE_MOTION, rEvent);
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+BOOL SelectionFunction::MouseButtonUp (const MouseEvent& rEvent)
+{
+ mrController.GetScrollBarManager().StopAutoScroll ();
+
+ // #95491# remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+
+ if (aDragTimer.IsActive())
+ aDragTimer.Stop();
+
+ ProcessMouseEvent(BUTTON_UP, rEvent);
+
+ mbProcessingMouseButtonDown = false;
+ mpWindow->ReleaseMouse();
+
+ return TRUE;
+}
+
+
+
+
+BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
+{
+ FocusManager& rFocusManager (mrController.GetFocusManager());
+ BOOL bResult = FALSE;
+
+ switch (rEvent.GetKeyCode().GetCode())
+ {
+ case KEY_RETURN:
+ if (rFocusManager.HasFocus())
+ {
+ model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
+ if (pDescriptor.get() != NULL)
+ {
+ SetCurrentPage(pDescriptor);
+ SwitchView(pDescriptor);
+ }
+ bResult = TRUE;
+ }
+ break;
+
+ case KEY_TAB:
+ if ( ! rFocusManager.IsFocusShowing())
+ rFocusManager.ShowFocus();
+ else
+ if (rEvent.GetKeyCode().IsShift())
+ rFocusManager.MoveFocus (FocusManager::FMD_LEFT);
+ else
+ rFocusManager.MoveFocus (FocusManager::FMD_RIGHT);
+ bResult = TRUE;
+ break;
+
+ case KEY_ESCAPE:
+ rFocusManager.SetFocusToToolBox();
+ bResult = TRUE;
+ break;
+
+ case KEY_SPACE:
+ {
+ // Toggle the selection state.
+ model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
+ if (pDescriptor.get() != NULL)
+ {
+ // Doing a multi selection by default. Can we ask the event
+ // for the state of the shift key?
+ if (pDescriptor->IsSelected())
+ mrController.GetPageSelector().DeselectPage(pDescriptor);
+ else
+ mrController.GetPageSelector().SelectPage(pDescriptor);
+ }
+ bResult = TRUE;
+ }
+ break;
+
+
+ // Move the focus indicator left.
+ case KEY_LEFT:
+ rFocusManager.MoveFocus (FocusManager::FMD_LEFT);
+ bResult = TRUE;
+ break;
+
+ // Move the focus indicator right.
+ case KEY_RIGHT:
+ rFocusManager.MoveFocus (FocusManager::FMD_RIGHT);
+ bResult = TRUE;
+ break;
+
+ // Move the focus indicator up.
+ case KEY_UP:
+ rFocusManager.MoveFocus (FocusManager::FMD_UP);
+ bResult = TRUE;
+ break;
+
+ // Move the focus indicator down.
+ case KEY_DOWN:
+ rFocusManager.MoveFocus (FocusManager::FMD_DOWN);
+ bResult = TRUE;
+ break;
+
+ // Go to previous page. No wrap around.
+ case KEY_PAGEUP:
+ GotoNextPage(-1);
+ bResult = TRUE;
+ break;
+
+ // Go to next page. No wrap around..
+ case KEY_PAGEDOWN:
+ GotoNextPage(+1);
+ bResult = TRUE;
+ break;
+
+ case KEY_DELETE:
+ case KEY_BACKSPACE:
+ {
+ if (mrController.GetProperties()->IsUIReadOnly())
+ break;
+
+ int nSelectedPagesCount = 0;
+
+ // Count the selected pages and look if there any objects on any
+ // of the selected pages so that we can warn the user and
+ // prevent an accidental deletion.
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ nSelectedPagesCount++;
+ aSelectedPages.GetNextElement();
+ }
+
+ if (nSelectedPagesCount > 0)
+ mrController.GetSelectionManager()->DeleteSelectedPages();
+
+ bResult = TRUE;
+ }
+ break;
+
+ case KEY_F10:
+ if (rEvent.GetKeyCode().IsShift())
+ ProcessKeyEvent(rEvent);
+ break;
+
+ default:
+ break;
+ }
+
+ if ( ! bResult)
+ bResult = SlideFunction::KeyInput (rEvent);
+
+ return bResult;
+}
+
+
+
+
+void SelectionFunction::Activate()
+{
+ FuPoor::Activate();
+}
+
+
+
+
+void SelectionFunction::Deactivate()
+{
+ FuPoor::Deactivate();
+}
+
+
+
+void SelectionFunction::ScrollStart (void)
+{
+}
+
+
+
+
+void SelectionFunction::ScrollEnd (void)
+{
+}
+
+
+
+
+void SelectionFunction::DoCut (void)
+{
+ if ( ! mrController.GetProperties()->IsUIReadOnly())
+ {
+ mrController.GetClipboard().DoCut();
+ }
+}
+
+
+
+
+void SelectionFunction::DoCopy (void)
+{
+ mrController.GetClipboard().DoCopy();
+}
+
+
+
+
+void SelectionFunction::DoPaste (void)
+{
+ if ( ! mrController.GetProperties()->IsUIReadOnly())
+ {
+ mrController.GetClipboard().DoPaste();
+ }
+}
+
+
+
+
+void SelectionFunction::Paint (const Rectangle&, ::sd::Window* )
+{
+}
+
+
+
+
+IMPL_LINK( SelectionFunction, DragSlideHdl, Timer*, EMPTYARG )
+{
+ StartDrag();
+ return 0;
+}
+
+
+
+
+void SelectionFunction::StartDrag (void)
+{
+ if (mbPageHit
+ && ! mrController.GetProperties()->IsUIReadOnly())
+ {
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ mpSubstitutionHandler->Start(rOverlay.GetSubstitutionOverlay().GetPosition());
+ mbPageHit = false;
+ mpWindow->ReleaseMouse();
+
+ if (mrSlideSorter.GetViewShell() != NULL)
+ {
+ SlideSorterViewShell* pSlideSorterViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ pSlideSorterViewShell->StartDrag (
+ rOverlay.GetSubstitutionOverlay().GetPosition(),
+ mpWindow);
+ }
+ }
+}
+
+
+
+
+bool SelectionFunction::cancel (void)
+{
+ mrController.GetFocusManager().ToggleFocus();
+ return true;
+}
+
+
+
+
+void SelectionFunction::SelectHitPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ mrController.GetPageSelector().SelectPage(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::DeselectHitPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ mrController.GetPageSelector().DeselectPage(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::DeselectAllPages (void)
+{
+ mrController.GetPageSelector().DeselectAllPages();
+}
+
+
+
+
+void SelectionFunction::StartRectangleSelection (const Point& rMouseModelPosition)
+{
+ if (mrController.GetProperties()->IsShowSelection())
+ {
+ mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Start(
+ rMouseModelPosition);
+ }
+}
+
+
+
+
+void SelectionFunction::UpdateRectangleSelection (const Point& rMouseModelPosition)
+{
+ if (mrController.GetProperties()->IsShowSelection())
+ {
+ mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Update(
+ rMouseModelPosition);
+ }
+}
+
+
+
+
+void SelectionFunction::ProcessRectangleSelection (bool bToggleSelection)
+{
+ if ( ! mrController.GetProperties()->IsShowSelection())
+ return;
+
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ if (rOverlay.GetSelectionRectangleOverlay().isVisible())
+ {
+ PageSelector& rSelector (mrController.GetPageSelector());
+
+ rOverlay.GetSelectionRectangleOverlay().setVisible(false);
+
+ // Select all pages whose page object lies completly inside the drag
+ // rectangle.
+ const Rectangle& rSelectionRectangle (
+ rOverlay.GetSelectionRectangleOverlay().GetSelectionRectangle());
+ model::PageEnumeration aPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ Rectangle aPageBox (mrSlideSorter.GetView().GetPageBoundingBox(
+ pDescriptor,
+ view::SlideSorterView::CS_MODEL,
+ view::SlideSorterView::BBT_SHAPE));
+ if (rSelectionRectangle.IsOver(aPageBox))
+ {
+ // When we are extending the selection (shift key is
+ // pressed) then toggle the selection state of the page.
+ // Otherwise select it: this results in the previously
+ // selected pages becoming deslected.
+ if (bToggleSelection && pDescriptor->IsSelected())
+ rSelector.DeselectPage(pDescriptor);
+ else
+ rSelector.SelectPage(pDescriptor);
+ }
+ }
+ }
+}
+
+
+
+
+void SelectionFunction::PrepareMouseMotion (const Point& )
+{
+ if ( ! mrController.GetProperties()->IsUIReadOnly())
+ {
+ bFirstMouseMove = TRUE;
+ aDragTimer.Start();
+ }
+}
+
+
+
+
+void SelectionFunction::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
+{
+ PageSelector& rSelector (mrController.GetPageSelector());
+
+ model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor());
+ DeselectAllPages();
+
+ if (pAnchor.get() != NULL)
+ {
+ // Select all pages between the anchor and the given one, including
+ // the two.
+ USHORT nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2);
+ USHORT nOtherIndex ((rpDescriptor->GetPage()->GetPageNum()-1) / 2);
+
+ // Iterate over all pages in the range. Start with the anchor
+ // page. This way the PageSelector will recognize it again as
+ // anchor (the first selected page after a DeselectAllPages()
+ // becomes the anchor.)
+ USHORT nStep = (nAnchorIndex < nOtherIndex) ? +1 : -1;
+ USHORT nIndex = nAnchorIndex;
+ while (true)
+ {
+ rSelector.SelectPage(nIndex);
+ if (nIndex == nOtherIndex)
+ break;
+ nIndex = nIndex + nStep;
+ }
+ }
+}
+
+
+
+
+void SelectionFunction::GotoNextPage (int nOffset)
+{
+ model::SharedPageDescriptor pDescriptor
+ = mrController.GetCurrentSlideManager()->GetCurrentSlide();
+ if (pDescriptor.get() != NULL)
+ {
+ SdPage* pPage = pDescriptor->GetPage();
+ OSL_ASSERT(pPage!=NULL);
+ sal_Int32 nIndex = (pPage->GetPageNum()-1) / 2;
+ nIndex += nOffset;
+ USHORT nPageCount = (USHORT)mrSlideSorter.GetModel().GetPageCount();
+
+ if (nIndex >= nPageCount)
+ nIndex = nPageCount - 1;
+ if (nIndex < 0)
+ nIndex = 0;
+
+ mrController.GetFocusManager().SetFocusedPage(nIndex);
+ model::SharedPageDescriptor pNextPageDescriptor (
+ mrSlideSorter.GetModel().GetPageDescriptor (nIndex));
+ if (pNextPageDescriptor.get() != NULL)
+ SetCurrentPage(pNextPageDescriptor);
+ else
+ {
+ OSL_ASSERT(pNextPageDescriptor.get() != NULL);
+ }
+ }
+}
+
+
+
+
+void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
+{
+ // #95491# remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+
+ // 1. Compute some frequently used values relating to the event.
+ ::std::auto_ptr<EventDescriptor> pEventDescriptor (
+ new EventDescriptor(nEventType, rEvent, mrSlideSorter));
+
+ // 2. Compute a numerical code that describes the event and that is used
+ // for fast look-up of the associated reaction.
+ pEventDescriptor->mnEventCode = EncodeMouseEvent(*pEventDescriptor, rEvent);
+
+ // 3. Process the event.
+ EventPreprocessing(*pEventDescriptor);
+ if ( ! EventProcessing(*pEventDescriptor))
+ {
+ OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode);
+ }
+ EventPostprocessing(*pEventDescriptor);
+
+ if (nEventType == BUTTON_UP)
+ mbPageHit = false;
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EncodeMouseEvent (
+ const EventDescriptor& rDescriptor,
+ const MouseEvent& rEvent) const
+{
+ // Initialize with the type of mouse event.
+ sal_uInt32 nEventCode (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION));
+
+ // Detect the affected button.
+ switch (rEvent.GetButtons())
+ {
+ case MOUSE_LEFT: nEventCode |= LEFT_BUTTON; break;
+ case MOUSE_RIGHT: nEventCode |= RIGHT_BUTTON; break;
+ case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break;
+ }
+
+ // Detect the number of clicks.
+ switch (rEvent.GetClicks())
+ {
+ case 1: nEventCode |= SINGLE_CLICK; break;
+ case 2: nEventCode |= DOUBLE_CLICK; break;
+ }
+
+ // Detect whether the event has happened over a page object.
+ if (rDescriptor.mpHitPage != NULL && ! rDescriptor.mpHitDescriptor.expired())
+ {
+ model::SharedPageDescriptor pHitDescriptor (rDescriptor.mpHitDescriptor);
+ if (pHitDescriptor->IsSelected())
+ nEventCode |= OVER_SELECTED_PAGE;
+ else
+ nEventCode |= OVER_UNSELECTED_PAGE;
+ }
+
+ // Detect pressed modifier keys.
+ if (rEvent.IsShift())
+ nEventCode |= SHIFT_MODIFIER;
+ if (rEvent.IsMod1())
+ nEventCode |= CONTROL_MODIFIER;
+
+ // Detect whether we are dragging pages or dragging a selection rectangle.
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ if (rOverlay.GetSubstitutionOverlay().isVisible())
+ nEventCode |= SUBSTITUTION_VISIBLE;
+ if (rOverlay.GetSelectionRectangleOverlay().isVisible())
+ nEventCode |= RECTANGLE_VISIBLE;
+
+ return nEventCode;
+}
+
+
+
+
+void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent)
+{
+ // 1. Compute some frequently used values relating to the event.
+ ::std::auto_ptr<EventDescriptor> pEventDescriptor (
+ new EventDescriptor(rEvent, mrSlideSorter));
+
+ // 2. Encode the event.
+ pEventDescriptor->mnEventCode = EncodeKeyEvent(*pEventDescriptor, rEvent);
+
+ // 3. Process the event.
+ EventPreprocessing(*pEventDescriptor);
+ if ( ! EventProcessing(*pEventDescriptor))
+ OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode);
+ EventPostprocessing(*pEventDescriptor);
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EncodeKeyEvent (
+ const EventDescriptor& rDescriptor,
+ const KeyEvent& rEvent) const
+{
+ // Initialize as key event.
+ sal_uInt32 nEventCode (KEY_EVENT);
+
+ // Add the actual key code in the lower 16 bit.
+ nEventCode |= rEvent.GetKeyCode().GetCode();
+
+ // Detect pressed modifier keys.
+ if (rEvent.GetKeyCode().IsShift())
+ nEventCode |= SHIFT_MODIFIER;
+ if (rEvent.GetKeyCode().IsMod1())
+ nEventCode |= CONTROL_MODIFIER;
+
+ // Detect whether the event has happened over a page object.
+ if (rDescriptor.mpHitPage != NULL && ! rDescriptor.mpHitDescriptor.expired())
+ {
+ model::SharedPageDescriptor pHitDescriptor (rDescriptor.mpHitDescriptor);
+ if (pHitDescriptor->IsSelected())
+ nEventCode |= OVER_SELECTED_PAGE;
+ else
+ nEventCode |= OVER_UNSELECTED_PAGE;
+ }
+
+ // Detect whether we are dragging pages or dragging a selection rectangle.
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ if (rOverlay.GetSubstitutionOverlay().isVisible())
+ nEventCode |= SUBSTITUTION_VISIBLE;
+ if (rOverlay.GetSelectionRectangleOverlay().isVisible())
+ nEventCode |= RECTANGLE_VISIBLE;
+
+ return nEventCode;
+}
+
+
+
+void SelectionFunction::EventPreprocessing (const EventDescriptor& rDescriptor)
+{
+ // Some general processing that is not specific to the exact event code.
+ if (rDescriptor.mnEventCode & BUTTON_DOWN)
+ mbPageHit = (rDescriptor.mpHitPage!=NULL);
+
+ // Set the focus to the slide under the mouse.
+ if (rDescriptor.mpHitPage != NULL)
+ mrController.GetFocusManager().FocusPage((rDescriptor.mpHitPage->GetPageNum()-1)/2);
+}
+
+
+
+
+bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor)
+{
+ // Define some macros to make the following switch statement more readable.
+#define ANY_MODIFIER(code) \
+ code|NO_MODIFIER: \
+ case code|SHIFT_MODIFIER: \
+ case code|CONTROL_MODIFIER
+#define ANY_PAGE(code) \
+ code|NOT_OVER_PAGE: \
+ case code|OVER_UNSELECTED_PAGE: \
+ case code|OVER_SELECTED_PAGE
+#define ANY_PAGE_AND_MODIFIER(code) \
+ ANY_PAGE(code|NO_MODIFIER): \
+ case ANY_PAGE(code|SHIFT_MODIFIER): \
+ case ANY_PAGE(code|CONTROL_MODIFIER)
+
+
+ bool bResult (true);
+ bool bMakeSelectionVisible (true);
+
+ mrController.GetPageSelector().DisableBroadcasting();
+
+ // 2b. With the event code determine the type of operation with which to
+ // react to the event.
+
+ // Acquire a shared_ptr to the hit page descriptor.
+ model::SharedPageDescriptor pHitDescriptor;
+ if ( ! rDescriptor.mpHitDescriptor.expired())
+ pHitDescriptor = model::SharedPageDescriptor(rDescriptor.mpHitDescriptor);
+
+ switch (rDescriptor.mnEventCode)
+ {
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
+ SetCurrentPage(pHitDescriptor);
+ PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition));
+ mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition);
+ break;
+
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ SetCurrentPage(pHitDescriptor);
+ mpSubstitutionHandler->End();
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition));
+ mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition);
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE:
+ case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE:
+ // A double click allways shows the selected slide in the center
+ // pane in an edit view.
+ SetCurrentPage(pHitDescriptor);
+ SwitchView(pHitDescriptor);
+ break;
+
+ // Multi selection with the control modifier.
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER:
+ DeselectHitPage(pHitDescriptor);
+ PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition));
+ break;
+
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER:
+ SelectHitPage(pHitDescriptor);
+ PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition));
+
+ break;
+
+ // Range selection with the shift modifier.
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER:
+ RangeSelect(pHitDescriptor);
+ break;
+
+ // Was: Preview of the page transition effect.
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_FADE_INDICATOR:
+ // No action.
+ break;
+
+ // Right button for context menu.
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
+ case KEY_EVENT | KEY_F10 | SHIFT_MODIFIER | OVER_UNSELECTED_PAGE:
+ // Single right click and shift+F10 select as preparation to
+ // show the context menu. Change the selection only when the
+ // page under the mouse is not selected. In this case the
+ // selection is set to this single page. Otherwise the
+ // selection is not modified.
+ DeselectAllPages();
+ SelectHitPage(pHitDescriptor);
+ SetCurrentPage(pHitDescriptor);
+ bMakeSelectionVisible = false;
+ break;
+
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ case KEY_EVENT | KEY_F10 | OVER_SELECTED_PAGE | SHIFT_MODIFIER:
+ // Do not change the selection. Just adjust the insertion indicator.
+ bMakeSelectionVisible = false;
+ break;
+
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
+ // The Shift+F10 key event is here just for completeness. It should
+ // not be possible to really receive this (not being over a page.)
+ case KEY_EVENT | KEY_F10 | SHIFT_MODIFIER | NOT_OVER_PAGE:
+ DeselectAllPages();
+ bMakeSelectionVisible = false;
+ break;
+
+ // A mouse motion without visible substitution starts that.
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE):
+ mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition);
+ mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition);
+ break;
+
+ // Move substitution.
+ case ANY_PAGE_AND_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | SUBSTITUTION_VISIBLE):
+ if ((rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0)
+ StartDrag();
+ mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition);
+ mpSubstitutionHandler->UpdatePosition(rDescriptor.maMouseModelPosition);
+ break;
+
+ // Place substitution.
+ case ANY_PAGE_AND_MODIFIER(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | SUBSTITUTION_VISIBLE):
+ // When the substitution has not been moved the button up event
+ // is taken to be part of a single click. The selected pages
+ // are therefore not moved (which technically would be necessary
+ // for unconsecutive multi selections). Instead the page under
+ // the mouse becomes the only selected page.
+ if (mpSubstitutionHandler->HasBeenMoved())
+ {
+ // The following Process() call may lead to the desctruction
+ // of pHitDescriptor so release our reference to it.
+ pHitDescriptor.reset();
+ mpSubstitutionHandler->Process();
+ }
+ else
+ if (pHitDescriptor != NULL)
+ SetCurrentPage(pHitDescriptor);
+ mpSubstitutionHandler->End();
+ break;
+
+ // Rectangle selection.
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | NO_MODIFIER:
+ DeselectAllPages();
+ StartRectangleSelection(rDescriptor.maMouseModelPosition);
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | SHIFT_MODIFIER:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | CONTROL_MODIFIER:
+ StartRectangleSelection(rDescriptor.maMouseModelPosition);
+ break;
+
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE):
+ case ANY_PAGE_AND_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE):
+ mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition);
+ UpdateRectangleSelection(rDescriptor.maMouseModelPosition);
+ break;
+
+ case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | NO_MODIFIER):
+ ProcessRectangleSelection(false);
+ break;
+
+ case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | SHIFT_MODIFIER):
+ case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | CONTROL_MODIFIER):
+ ProcessRectangleSelection(true);
+ break;
+
+ default:
+ bResult = false;
+ break;
+ }
+ mrController.GetPageSelector().EnableBroadcasting(bMakeSelectionVisible);
+
+ return bResult;
+}
+
+
+
+
+void SelectionFunction::EventPostprocessing (const EventDescriptor& rDescriptor)
+{
+ if (rDescriptor.mnEventCode & BUTTON_UP)
+ {
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+
+ mpWindow->ReleaseMouse();
+
+ // The overlays should not be visible anymore. Warn when one of
+ // them still is. An exception is th insertion indicator in the
+ // case that the context menu is visible.
+ DBG_ASSERT(
+ mrController.IsContextMenuOpen()
+ || !rOverlay.GetInsertionIndicatorOverlay().isVisible(),
+ "slidesorter::SelectionFunction: insertion indicator still visible");
+ DBG_ASSERT(
+ !rOverlay.GetSubstitutionOverlay().isVisible(),
+ "slidesorter::SelectionFunction: substitution still visible");
+ DBG_ASSERT(
+ !rOverlay.GetSelectionRectangleOverlay().isVisible(),
+ "slidesorter::SelectionFunction: selection rectangle still visible");
+
+ // Now turn them off.
+ if ( ! mrController.IsContextMenuOpen())
+ rOverlay.GetInsertionIndicatorOverlay().setVisible(false);
+ rOverlay.GetSubstitutionOverlay().setVisible(false);
+ rOverlay.GetSelectionRectangleOverlay().setVisible(false);
+ }
+}
+
+
+
+
+void SelectionFunction::SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ PageSelector& rSelector (mrController.GetPageSelector());
+ rSelector.DeselectAllPages ();
+ rSelector.SelectPage(rpDescriptor);
+
+ mrController.GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::SwitchView (const model::SharedPageDescriptor& rpDescriptor)
+{
+ // Switch to the draw view. This is done only when the current
+ // view is the main view.
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell!=NULL && pViewShell->IsMainViewShell())
+ {
+ if (rpDescriptor.get()!=NULL && rpDescriptor->GetPage()!=NULL)
+ {
+ mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), TRUE);
+ mpViewShell->GetFrameView()->SetSelectedPage(
+ (rpDescriptor->GetPage()->GetPageNum()-1)/2);
+ }
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView(
+ framework::FrameworkHelper::msImpressViewURL,
+ framework::FrameworkHelper::msCenterPaneURL);
+ }
+}
+
+
+
+
+//===== EventDescriptor =======================================================
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(nEventType)
+{
+ ::Window* pWindow = rSlideSorter.GetActiveWindow();
+
+ maMousePosition = rEvent.GetPosPixel();
+ maMouseModelPosition = pWindow->PixelToLogic(maMousePosition);
+ model::SharedPageDescriptor pHitDescriptor (
+ rSlideSorter.GetController().GetPageAt(maMousePosition));
+ if (pHitDescriptor.get() != NULL)
+ {
+ mpHitDescriptor = pHitDescriptor;
+ mpHitPage = pHitDescriptor->GetPage();
+ }
+}
+
+
+
+
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const KeyEvent&,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(0)
+{
+ mpHitDescriptor = rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor();
+ model::SharedPageDescriptor pHitDescriptor (
+ rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
+ if (pHitDescriptor.get() != NULL)
+ {
+ mpHitPage = pHitDescriptor->GetPage();
+ mpHitDescriptor = pHitDescriptor;
+ }
+}
+
+
+
+
+
+//===== SubstitutionHandler ===================================================
+
+SelectionFunction::SubstitutionHandler::SubstitutionHandler (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mbHasBeenMoved(false)
+{
+}
+
+
+
+
+SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void)
+{
+ if (mrSlideSorter.IsValid())
+ {
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ rOverlay.GetSubstitutionOverlay().setVisible(false);
+ rOverlay.GetSubstitutionOverlay().Clear();
+ }
+}
+
+
+
+
+void SelectionFunction::SubstitutionHandler::Start (const Point& rMouseModelPosition)
+{
+ // No Drag-and-Drop for master pages.
+ if (mrSlideSorter.GetModel().GetEditMode() != EM_PAGE)
+ return;
+
+ if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
+ return;
+
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+
+ if ( ! rOverlay.GetSubstitutionOverlay().isVisible())
+ {
+ // Show a new substitution for the selected page objects.
+ model::PageEnumeration aSelectedPages(
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ rOverlay.GetSubstitutionOverlay().Create(aSelectedPages, rMouseModelPosition);
+ rOverlay.GetSubstitutionOverlay().setVisible(true);
+ mbHasBeenMoved = false;
+ }
+ else
+ UpdatePosition(rMouseModelPosition);
+}
+
+
+
+
+void SelectionFunction::SubstitutionHandler::UpdatePosition (const Point& rMouseModelPosition)
+{
+ if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
+ return;
+
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+
+ // Move the existing substitution to the new position.
+ rOverlay.GetSubstitutionOverlay().SetPosition(rMouseModelPosition);
+
+ rOverlay.GetInsertionIndicatorOverlay().SetPosition(rMouseModelPosition);
+ rOverlay.GetInsertionIndicatorOverlay().setVisible(true);
+
+ mbHasBeenMoved = true;
+}
+
+
+
+
+void SelectionFunction::SubstitutionHandler::Process (void)
+{
+ if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
+ return;
+
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+
+ if (IsSubstitutionInsertionNonTrivial())
+ {
+ // Tell the model to move the selected pages behind the one with the
+ // index mnInsertionIndex which first has to transformed into an index
+ // understandable by the document.
+ sal_Int32 nInsertionIndex = rOverlay.GetInsertionIndicatorOverlay().GetInsertionPageIndex();
+ if (nInsertionIndex >= 0)
+ {
+ USHORT nDocumentIndex = (USHORT)nInsertionIndex-1;
+ mrSlideSorter.GetController().GetSelectionManager()->MoveSelectedPages(nDocumentIndex);
+ }
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_STATUS_PAGE);
+ }
+}
+
+
+
+
+void SelectionFunction::SubstitutionHandler::End (void)
+{
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ rOverlay.GetSubstitutionOverlay().setVisible(false);
+ rOverlay.GetSubstitutionOverlay().Clear();
+ rOverlay.GetInsertionIndicatorOverlay().setVisible(false);
+}
+
+
+
+
+bool SelectionFunction::SubstitutionHandler::HasBeenMoved (void) const
+{
+ return mbHasBeenMoved;
+}
+
+
+
+
+bool SelectionFunction::SubstitutionHandler::IsSubstitutionInsertionNonTrivial (void) const
+{
+ bool bIsNonTrivial = false;
+
+ do
+ {
+ view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+
+ // Make sure that the substitution and the insertion indicator are visible.
+ if ( ! rOverlay.GetSubstitutionOverlay().isVisible())
+ break;
+ if ( ! rOverlay.GetInsertionIndicatorOverlay().isVisible())
+ break;
+
+ // Iterate over all selected pages and check whether there are
+ // holes. While we do this we remember the indices of the first and
+ // last selected page as preparation for the next step.
+ sal_Int32 nCurrentIndex = -1;
+ sal_Int32 nFirstIndex = -1;
+ sal_Int32 nLastIndex = -1;
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements() && ! bIsNonTrivial)
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ SdPage* pPage = pDescriptor->GetPage();
+ if (pPage != NULL)
+ {
+ // Get the page number and compare it to the last one.
+ sal_Int32 nPageNumber = (pPage->GetPageNum()-1)/2;
+ if (nCurrentIndex>=0 && nPageNumber>(nCurrentIndex+1))
+ bIsNonTrivial = true;
+ else
+ nCurrentIndex = nPageNumber;
+
+ // Remember indices of the first and last page of the selection.
+ if (nFirstIndex == -1)
+ nFirstIndex = nPageNumber;
+ nLastIndex = nPageNumber;
+ }
+ }
+ if (bIsNonTrivial)
+ break;
+
+ // When we come here then the selection is consecutive. We still
+ // have to check that the insertion position is not directly in
+ // front or directly behind the selection and thus moving the
+ // selection there would not change the model.
+ sal_Int32 nInsertionIndex = rOverlay.GetInsertionIndicatorOverlay().GetInsertionPageIndex();
+ if (nInsertionIndex<nFirstIndex || nInsertionIndex>(nLastIndex+1))
+ bIsNonTrivial = true;
+ }
+ while (false);
+
+ return bIsNonTrivial;
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx
new file mode 100644
index 000000000000..77e39f48156b
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx
@@ -0,0 +1,665 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsSelectionManager.hxx"
+
+#include "SlideSorter.hxx"
+#include "SlsSelectionCommand.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "drawdoc.hxx"
+#include "Window.hxx"
+#include <svx/svxids.hrc>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+
+#include "res_bmp.hrc"
+#include "sdresid.hxx"
+#include "strings.hrc"
+#include "app.hrc"
+#include "glob.hrc"
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::uno;
+using namespace ::sd::slidesorter::model;
+using namespace ::sd::slidesorter::view;
+using namespace ::sd::slidesorter::controller;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+namespace {
+ class VerticalVisibleAreaScroller
+ {
+ public:
+ VerticalVisibleAreaScroller (SlideSorter& rSlideSorter,
+ const double nStart, const double nEnd);
+ void operator() (const double nValue);
+ private:
+ SlideSorter& mrSlideSorter;
+ double mnStart;
+ double mnEnd;
+ };
+ class HorizontalVisibleAreaScroller
+ {
+ public:
+ HorizontalVisibleAreaScroller (SlideSorter& rSlideSorter,
+ const double nStart, const double nEnd);
+ void operator() (const double nValue);
+ private:
+ SlideSorter& mrSlideSorter;
+ double mnStart;
+ double mnEnd;
+ };
+}
+
+
+
+
+SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mrController(rSlideSorter.GetController()),
+ maSelectionBeforeSwitch(),
+ mbIsMakeSelectionVisiblePending(true)
+{
+}
+
+
+
+
+SelectionManager::~SelectionManager (void)
+{
+}
+
+
+
+
+void SelectionManager::DeleteSelectedPages (void)
+{
+ SlideSorterController::ModelChangeLock aLock (mrController);
+
+ // Hide focus.
+ bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing();
+ if (bIsFocusShowing)
+ mrController.GetFocusManager().ToggleFocus();
+
+ // Store pointers to all selected page descriptors. This is necessary
+ // because the pages get deselected when the first one is deleted.
+ model::PageEnumeration aPageEnumeration (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
+ ::std::vector<SdPage*> aSelectedPages;
+ while (aPageEnumeration.HasMoreElements())
+ aSelectedPages.push_back (aPageEnumeration.GetNextElement()->GetPage());
+
+ // The actual deletion of the selected pages is done in one of two
+ // helper functions. They are specialized for normal respectively for
+ // master pages.
+ mrSlideSorter.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES));
+ if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
+ DeleteSelectedNormalPages(aSelectedPages);
+ else
+ DeleteSelectedMasterPages(aSelectedPages);
+ mrSlideSorter.GetView().EndUndo ();
+
+ mrController.HandleModelChange();
+ aLock.Release();
+
+ // Show focus and move it to next valid location.
+ if (bIsFocusShowing)
+ mrController.GetFocusManager().ToggleFocus ();
+ mrController.GetFocusManager().MoveFocus (FocusManager::FMD_NONE);
+}
+
+
+
+
+void SelectionManager::DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedPages)
+{
+ // Prepare the deletion via the UNO API.
+ OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_PAGE);
+
+ try
+ {
+ Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
+ Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
+
+ // Iterate over all pages that where seleted when this method was called
+ // and delete the draw page the notes page. The iteration is done in
+ // reverse order so that when one slide is not deleted (to avoid an
+ // empty document) the remaining slide is the first one.
+ ::std::vector<SdPage*>::const_reverse_iterator aI;
+ for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
+ {
+ // Do not delete the last slide in the document.
+ if (xPages->getCount() <= 1)
+ break;
+
+ USHORT nPage = ((*aI)->GetPageNum()-1) / 2;
+
+ Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
+ xPages->remove(xPage);
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERROR("SelectionManager::DeleteSelectedNormalPages(), exception caught!");
+ }
+}
+
+
+
+
+void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages)
+{
+ // Prepare the deletion via the UNO API.
+ OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE);
+
+ try
+ {
+ Reference<drawing::XMasterPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
+ Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_QUERY_THROW );
+
+ // Iterate over all pages that where seleted when this method was called
+ // and delete the draw page the notes page. The iteration is done in
+ // reverse order so that when one slide is not deleted (to avoid an
+ // empty document) the remaining slide is the first one.
+ ::std::vector<SdPage*>::const_reverse_iterator aI;
+ for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
+ {
+ // Do not delete the last slide in the document.
+ if (xPages->getCount() <= 1)
+ break;
+
+ USHORT nPage = ((*aI)->GetPageNum()-1) / 2;
+
+ Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
+ xPages->remove(xPage);
+ }
+ }
+ catch( Exception& )
+ {
+ DBG_ERROR("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
+ }
+}
+
+
+
+
+bool SelectionManager::MoveSelectedPages (const sal_Int32 nTargetPageIndex)
+{
+ bool bMoved (false);
+ PageSelector& rSelector (mrController.GetPageSelector());
+
+ mrSlideSorter.GetView().LockRedraw (TRUE);
+ SlideSorterController::ModelChangeLock aLock (mrController);
+
+ // Transfer selection of the slide sorter to the document.
+ mrSlideSorter.GetModel().SynchronizeDocumentSelection ();
+
+ // Detect how many pages lie between document start and insertion
+ // position.
+ sal_Int32 nPageCountBeforeTarget (0);
+ ::boost::shared_ptr<PageSelector::PageSelection> pSelection (rSelector.GetPageSelection());
+ PageSelector::PageSelection::const_iterator iSelectedPage (pSelection->begin());
+ PageSelector::PageSelection::const_iterator iSelectionEnd (pSelection->end());
+ for ( ; iSelectedPage!=iSelectionEnd; ++iSelectedPage)
+ {
+ if (*iSelectedPage==NULL)
+ continue;
+ if (((*iSelectedPage)->GetPageNum()-1)/2 <= nTargetPageIndex)
+ ++nPageCountBeforeTarget;
+ else
+ break;
+ }
+
+ // Prepare to select the moved pages.
+ SelectionCommand* pCommand = new SelectionCommand(
+ rSelector,mrController.GetCurrentSlideManager(),mrSlideSorter.GetModel());
+ sal_Int32 nSelectedPageCount (rSelector.GetSelectedPageCount());
+ for (sal_Int32 nOffset=0; nOffset<nSelectedPageCount; ++nOffset)
+ pCommand->AddSlide(sal::static_int_cast<USHORT>(
+ nTargetPageIndex + nOffset - nPageCountBeforeTarget + 1));
+
+ // At the moment we can not move master pages.
+ if (nTargetPageIndex>=0)
+ {
+ if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
+ bMoved = mrSlideSorter.GetModel().GetDocument()->MovePages(
+ sal::static_int_cast<sal_uInt16>(nTargetPageIndex));
+ }
+ if (bMoved)
+ mrController.GetSlotManager()->ExecuteCommandAsynchronously(
+ ::std::auto_ptr<controller::Command>(pCommand));
+
+ mrSlideSorter.GetView().LockRedraw (FALSE);
+
+ return bMoved;
+}
+
+
+
+
+void SelectionManager::SelectionHasChanged (const bool bMakeSelectionVisible)
+{
+ if (bMakeSelectionVisible)
+ mbIsMakeSelectionVisiblePending = true;
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ {
+ pViewShell->Invalidate (SID_EXPAND_PAGE);
+ pViewShell->Invalidate (SID_SUMMARY_PAGE);
+ pViewShell->Invalidate(SID_SHOW_SLIDE);
+ pViewShell->Invalidate(SID_HIDE_SLIDE);
+ pViewShell->Invalidate(SID_DELETE_PAGE);
+ pViewShell->Invalidate(SID_DELETE_MASTER_PAGE);
+ pViewShell->Invalidate(SID_ASSIGN_LAYOUT);
+
+ // StatusBar
+ pViewShell->Invalidate (SID_STATUS_PAGE);
+ pViewShell->Invalidate (SID_STATUS_LAYOUT);
+
+ OSL_ASSERT(mrController.GetCurrentSlideManager());
+ SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide());
+ if (pDescriptor.get() != NULL)
+ pViewShell->UpdatePreview(pDescriptor->GetPage());
+
+ // Tell the slection change listeners that the selection has changed.
+ ::std::vector<Link>::iterator iListener (maSelectionChangeListeners.begin());
+ ::std::vector<Link>::iterator iEnd (maSelectionChangeListeners.end());
+ for (; iListener!=iEnd; ++iListener)
+ {
+ iListener->Call(NULL);
+ }
+
+ // Reset the insertion position: until set again it is calculated from
+ // the current selection.
+ mnInsertionPosition = -1;
+ }
+}
+
+
+
+
+bool SelectionManager::IsMakeSelectionVisiblePending (void) const
+{
+ return mbIsMakeSelectionVisiblePending;
+}
+
+
+
+
+/** We have to distinguish three cases: 1) the selection is empty, 2) the
+ selection fits completely into the visible area, 3) it does not.
+ 1) The visible area is not modified.
+ 2) When the selection fits completely into the visible area we have to
+ decide how to align it. It is done by scrolling it there and thus when
+ we scoll up the (towards the end of the document) the bottom of the
+ selection is aligned with the bottom of the window. When we scroll
+ down (towards the beginning of the document) the top of the selection is
+ aligned with the top of the window.
+ 3) We have to decide what part of the selection to make visible. Here
+ we use the eSelectionHint and concentrate on either the first, the last,
+ or the most recently selected page. We then again apply the algorithm
+ of a).
+
+*/
+Size SelectionManager::MakeSelectionVisible (const SelectionHint eSelectionHint)
+{
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow == NULL)
+ return Size(0,0);
+
+ mbIsMakeSelectionVisiblePending = false;
+
+ // Determine the descriptors of the first and last selected page and the
+ // bounding box that encloses their page objects.
+ model::SharedPageDescriptor pFirst;
+ model::SharedPageDescriptor pLast;
+ Rectangle aSelectionBox;
+ model::PageEnumeration aSelectedPages (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+
+ if (pFirst.get() == NULL)
+ pFirst = pDescriptor;
+ pLast = pDescriptor;
+
+ aSelectionBox.Union (mrSlideSorter.GetView().GetPageBoundingBox (
+ pDescriptor,
+ view::SlideSorterView::CS_MODEL,
+ view::SlideSorterView::BBT_INFO));
+ }
+
+ if (pFirst != NULL)
+ {
+ // Determine scroll direction and the position in model coordinates
+ // that will be aligned with the top/left or bottom/right window
+ // border.
+ if (DoesSelectionExceedVisibleArea(aSelectionBox))
+ {
+ // We can show only a part of the selection.
+ aSelectionBox = ResolveLargeSelection(pFirst,pLast, eSelectionHint);
+ }
+
+ return MakeRectangleVisible(aSelectionBox);
+ }
+
+ return Size(0,0);
+}
+
+
+
+
+Size SelectionManager::MakeRectangleVisible (const Rectangle& rBox)
+{
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow == NULL)
+ return Size(0,0);
+
+ Rectangle aVisibleArea (pWindow->PixelToLogic(
+ Rectangle(
+ Point(0,0),
+ pWindow->GetOutputSizePixel())));
+
+ if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL)
+ {
+ // Scroll the visible area to make aSelectionBox visible.
+ sal_Int32 nNewTop (aVisibleArea.Top());
+ if (mrSlideSorter.GetController().GetProperties()->IsCenterSelection())
+ {
+ nNewTop = rBox.Top() - (aVisibleArea.GetHeight() - rBox.GetHeight()) / 2;
+ }
+ else
+ {
+ if (rBox.Top() < aVisibleArea.Top())
+ nNewTop = rBox.Top();
+ else if (rBox.Bottom() > aVisibleArea.Bottom())
+ nNewTop = rBox.Bottom() - aVisibleArea.GetHeight();
+ // otherwise we do not modify the visible area.
+ }
+
+ // Make some corrections of the new visible area.
+ Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
+ if (nNewTop + aVisibleArea.GetHeight() > aModelArea.Bottom())
+ nNewTop = aModelArea.GetHeight() - aVisibleArea.GetHeight();
+ if (nNewTop < aModelArea.Top())
+ nNewTop = aModelArea.Top();
+
+ // Scroll.
+ if (nNewTop != aVisibleArea.Top())
+ {
+ mrController.GetAnimator()->AddAnimation(
+ VerticalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Top(), nNewTop),
+ mrSlideSorter.GetController().GetProperties()->IsSmoothSelectionScrolling() ?
+ 1000 : 0
+ );
+ }
+
+ return Size(0,aVisibleArea.Top() - nNewTop);
+ }
+ else
+ {
+ // Scroll the visible area to make aSelectionBox visible.
+ sal_Int32 nNewLeft (aVisibleArea.Left());
+ if (mrSlideSorter.GetController().GetProperties()->IsCenterSelection())
+ {
+ nNewLeft = rBox.Left() - (aVisibleArea.GetWidth() - rBox.GetWidth()) / 2;
+ }
+ else
+ {
+ if (rBox.Left() < aVisibleArea.Left())
+ nNewLeft = rBox.Left();
+ else if (rBox.Right() > aVisibleArea.Right())
+ nNewLeft = rBox.Right() - aVisibleArea.GetWidth();
+ // otherwise we do not modify the visible area.
+ }
+
+ // Make some corrections of the new visible area.
+ Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
+ if (nNewLeft + aVisibleArea.GetWidth() > aModelArea.Right())
+ nNewLeft = aModelArea.GetWidth() - aVisibleArea.GetWidth();
+ if (nNewLeft < aModelArea.Left())
+ nNewLeft = aModelArea.Left();
+
+ // Scroll.
+ if (nNewLeft != aVisibleArea.Left())
+ {
+ mrController.GetAnimator()->AddAnimation(
+ HorizontalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Left(), nNewLeft),
+ mrSlideSorter.GetController().GetProperties()->IsSmoothSelectionScrolling() ?
+ 1000 : 0
+ );
+ }
+
+ return Size(aVisibleArea.Left() - nNewLeft, 0);
+ }
+}
+
+
+
+
+void SelectionManager::AddSelectionChangeListener (const Link& rListener)
+{
+ if (::std::find (
+ maSelectionChangeListeners.begin(),
+ maSelectionChangeListeners.end(),
+ rListener) == maSelectionChangeListeners.end())
+ {
+ maSelectionChangeListeners.push_back (rListener);
+ }
+}
+
+
+
+
+void SelectionManager::RemoveSelectionChangeListener(const Link&rListener)
+{
+ maSelectionChangeListeners.erase (
+ ::std::find (
+ maSelectionChangeListeners.begin(),
+ maSelectionChangeListeners.end(),
+ rListener));
+}
+
+
+
+
+bool SelectionManager::DoesSelectionExceedVisibleArea (const Rectangle& rSelectionBox) const
+{
+ ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow();
+ if (pWindow == NULL)
+ return true;
+
+ Rectangle aVisibleArea (pWindow->PixelToLogic(
+ Rectangle(
+ Point(0,0),
+ pWindow->GetOutputSizePixel())));
+ if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL)
+ return rSelectionBox.GetHeight() > aVisibleArea.GetHeight();
+ else
+ return rSelectionBox.GetWidth() > aVisibleArea.GetWidth();
+}
+
+
+
+
+Rectangle SelectionManager::ResolveLargeSelection (
+ const SharedPageDescriptor& rpFirst,
+ const SharedPageDescriptor& rpLast,
+ const SelectionHint eSelectionHint)
+{
+ OSL_ASSERT(rpFirst.get()!=NULL);
+ OSL_ASSERT(rpLast.get()!=NULL);
+
+ // The mose recently selected page is assumed to lie in the range
+ // between first and last selected page. Therefore the bounding box is
+ // not modified.
+ model::SharedPageDescriptor pRecent (
+ mrController.GetPageSelector().GetMostRecentlySelectedPage());
+
+ // Get the bounding box of the page object on which to concentrate.
+ model::SharedPageDescriptor pRepresentative;
+ switch (eSelectionHint)
+ {
+ case SH_FIRST:
+ pRepresentative = rpFirst;
+ break;
+
+ case SH_LAST:
+ pRepresentative = rpLast;
+ break;
+
+ case SH_RECENT:
+ default:
+ if (pRecent.get() == NULL)
+ pRepresentative = rpFirst;
+ else
+ pRepresentative = pRecent;
+ break;
+ }
+ OSL_ASSERT(pRepresentative.get() != NULL);
+
+ return mrSlideSorter.GetView().GetPageBoundingBox (
+ pRepresentative,
+ view::SlideSorterView::CS_MODEL,
+ view::SlideSorterView::BBT_INFO);
+}
+
+
+
+
+sal_Int32 SelectionManager::GetInsertionPosition (void) const
+{
+ sal_Int32 nInsertionPosition (mnInsertionPosition);
+ if (nInsertionPosition < 0)
+ {
+ model::PageEnumeration aSelectedPages
+ (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ // Initialize (for the case of an empty selection) with the position
+ // at the end of the document.
+ nInsertionPosition = mrSlideSorter.GetModel().GetPageCount();
+ while (aSelectedPages.HasMoreElements())
+ {
+ const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum());
+ // Convert *2+1 index to straight index (n-1)/2 after the page
+ // (+1).
+ nInsertionPosition = (nPosition-1)/2 + 1;
+ }
+
+ }
+ return nInsertionPosition;
+}
+
+
+
+
+void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition)
+{
+ if (nInsertionPosition < 0)
+ mnInsertionPosition = -1;
+ else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount())
+ {
+ // Assert but then ignore invalid values.
+ OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount());
+ return;
+ }
+ else
+ mnInsertionPosition = nInsertionPosition;
+}
+
+
+
+
+//===== VerticalVisibleAreaScroller ===========================================
+
+namespace {
+
+VerticalVisibleAreaScroller::VerticalVisibleAreaScroller (
+ SlideSorter& rSlideSorter,
+ const double nStart,
+ const double nEnd)
+ : mrSlideSorter(rSlideSorter),
+ mnStart(nStart),
+ mnEnd(nEnd)
+{
+}
+
+
+
+void VerticalVisibleAreaScroller::operator() (const double nValue)
+{
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetController().GetScrollBarManager().SetTop(
+ int(mnStart * (1.0 - nValue) + mnEnd * nValue));
+}
+
+
+
+
+HorizontalVisibleAreaScroller::HorizontalVisibleAreaScroller (
+ SlideSorter& rSlideSorter,
+ const double nStart,
+ const double nEnd)
+ : mrSlideSorter(rSlideSorter),
+ mnStart(nStart),
+ mnEnd(nEnd)
+{
+}
+
+
+
+
+void HorizontalVisibleAreaScroller::operator() (const double nValue)
+{
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetController().GetScrollBarManager().SetLeft(
+ int(mnStart * (1.0 - nValue) + mnEnd * nValue));
+}
+
+} // end of anonymous namespace
+
+} } } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx
new file mode 100644
index 000000000000..800586e3a1ef
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsSlideFunction.hxx"
+
+#include "SlideSorter.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "view/SlideSorterView.hxx"
+#include "model/SlideSorterModel.hxx"
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+TYPEINIT1(SlideFunction, FuPoor);
+
+
+SlideFunction::SlideFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+ : FuPoor (
+ rSlideSorter.GetViewShell(),
+ rSlideSorter.GetView().GetWindow(),
+ &rSlideSorter.GetView(),
+ rSlideSorter.GetModel().GetDocument(),
+ rRequest)
+{
+}
+
+void SlideFunction::ScrollStart (void)
+{
+}
+
+void SlideFunction::ScrollEnd (void)
+{
+}
+
+BOOL SlideFunction::MouseMove(const MouseEvent& )
+{
+ return FALSE;
+}
+
+BOOL SlideFunction::MouseButtonUp(const MouseEvent& )
+{
+ return FALSE;
+
+}
+
+BOOL SlideFunction::MouseButtonDown(const MouseEvent& )
+{
+ return FALSE;
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx
new file mode 100644
index 000000000000..6fb08e4e24f7
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx
@@ -0,0 +1,1136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include <com/sun/star/presentation/XPresentation2.hpp>
+
+#include "controller/SlsSlotManager.hxx"
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsClipboard.hxx"
+#include "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "SlsHideSlideFunction.hxx"
+#include "SlsCommand.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "Window.hxx"
+#include "fupoor.hxx"
+#include "fuzoom.hxx"
+#include "fucushow.hxx"
+#include "fusldlg.hxx"
+#include "fuexpand.hxx"
+#include "fusumry.hxx"
+#include "fuscale.hxx"
+#include "slideshow.hxx"
+#include "app.hrc"
+#include "strings.hrc"
+#include "sdresid.hxx"
+#include "drawdoc.hxx"
+#include "DrawDocShell.hxx"
+#include "ViewShellBase.hxx"
+#include "ViewShellImplementation.hxx"
+#include "sdattr.hxx"
+#include "FrameView.hxx"
+#include "zoomlist.hxx"
+#include "sdpage.hxx"
+#include "sdxfer.hxx"
+#include "helpids.h"
+#include "glob.hrc"
+#include "unmodpg.hxx"
+#include "DrawViewShell.hxx"
+
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svxids.hrc>
+#include <svx/zoomitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/dialogs.hrc>
+#include <vcl/msgbox.hxx>
+#include <svl/intitem.hxx>
+#include <svl/whiter.hxx>
+#include <svl/itempool.hxx>
+#include <svl/aeitem.hxx>
+#include <com/sun/star/presentation/FadeEffect.hpp>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::presentation;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+SlotManager::SlotManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maCommandQueue()
+{
+}
+
+
+
+
+SlotManager::~SlotManager (void)
+{
+}
+
+
+
+
+void SlotManager::FuTemporary (SfxRequest& rRequest)
+{
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+
+ SlideSorterViewShell* pShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pShell == NULL)
+ return;
+
+ switch (rRequest.GetSlot())
+ {
+ case SID_PRESENTATION:
+ case SID_REHEARSE_TIMINGS:
+ ShowSlideShow (rRequest);
+ pShell->Cancel();
+ rRequest.Done();
+ break;
+
+ case SID_HIDE_SLIDE:
+ case SID_SHOW_SLIDE:
+ HideSlideFunction::Create(mrSlideSorter, rRequest);
+ break;
+
+ case SID_PAGES_PER_ROW:
+ if (rRequest.GetArgs() != NULL)
+ {
+ SFX_REQUEST_ARG(rRequest, pPagesPerRow, SfxUInt16Item,
+ SID_PAGES_PER_ROW, FALSE);
+ if (pPagesPerRow != NULL)
+ {
+ sal_Int32 nColumnCount = pPagesPerRow->GetValue();
+ // Force the given number of columns by setting the
+ // minimal and maximal number of columns to the same
+ // value.
+ mrSlideSorter.GetView().GetLayouter().SetColumnCount (
+ nColumnCount, nColumnCount);
+ // Force a repaint and re-layout.
+ pShell->ArrangeGUIElements ();
+ // Rearrange the UI-elements controlled by the
+ // controller and force a rearrangement of the view.
+ mrSlideSorter.GetController().Rearrange(true);
+ }
+ }
+ rRequest.Done();
+ break;
+
+ case SID_SELECTALL:
+ mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
+ rRequest.Done();
+ break;
+
+ case SID_SLIDE_TRANSITIONS_PANEL:
+ {
+ // Make the slide transition panel visible (expand it) in the
+ // tool pane.
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())
+ ->RequestTaskPanel(sd::framework::FrameworkHelper::msSlideTransitionTaskPanelURL);
+ rRequest.Ignore ();
+ break;
+ }
+
+ case SID_PRESENTATION_DLG:
+ FuSlideShowDlg::Create (
+ pShell,
+ mrSlideSorter.GetView().GetWindow(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_CUSTOMSHOW_DLG:
+ FuCustomShowDlg::Create (
+ pShell,
+ mrSlideSorter.GetView().GetWindow(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_EXPAND_PAGE:
+ FuExpandPage::Create (
+ pShell,
+ mrSlideSorter.GetView().GetWindow(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_SUMMARY_PAGE:
+ FuSummaryPage::Create (
+ pShell,
+ mrSlideSorter.GetView().GetWindow(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_INSERTPAGE:
+ case SID_INSERT_MASTER_PAGE:
+ InsertSlide(rRequest);
+ rRequest.Done();
+ break;
+
+ case SID_DELETE_PAGE:
+ case SID_DELETE_MASTER_PAGE:
+ case SID_DELETE: // we need SID_CUT to handle the delete key
+ // (DEL -> accelerator -> SID_CUT).
+ if (mrSlideSorter.GetModel().GetPageCount() > 1)
+ {
+ mrSlideSorter.GetController().GetSelectionManager()->DeleteSelectedPages();
+ }
+
+ rRequest.Done();
+ break;
+
+ case SID_RENAMEPAGE:
+ case SID_RENAME_MASTER_PAGE:
+ RenameSlide ();
+ rRequest.Done ();
+ break;
+
+ case SID_ASSIGN_LAYOUT:
+ {
+ pShell->mpImpl->AssignLayout( rRequest, mrSlideSorter.GetModel().GetPageType() );
+ rRequest.Done ();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+
+void SlotManager::FuPermanent (SfxRequest& rRequest)
+{
+ ViewShell* pShell = mrSlideSorter.GetViewShell();
+ if (pShell == NULL)
+ return;
+
+ if(pShell->GetCurrentFunction().is())
+ {
+ FunctionReference xEmpty;
+ if (pShell->GetOldFunction() == pShell->GetCurrentFunction())
+ pShell->SetOldFunction(xEmpty);
+
+ pShell->GetCurrentFunction()->Deactivate();
+ pShell->SetCurrentFunction(xEmpty);
+ }
+
+ switch(rRequest.GetSlot())
+ {
+ case SID_OBJECT_SELECT:
+ pShell->SetCurrentFunction( SelectionFunction::Create(mrSlideSorter, rRequest) );
+ rRequest.Done();
+ break;
+
+ default:
+ break;
+ }
+
+ if(pShell->GetOldFunction().is())
+ {
+ pShell->GetOldFunction()->Deactivate();
+ FunctionReference xEmpty;
+ pShell->SetOldFunction(xEmpty);
+ }
+
+ if(pShell->GetCurrentFunction().is())
+ {
+ pShell->GetCurrentFunction()->Activate();
+ pShell->SetOldFunction(pShell->GetCurrentFunction());
+ }
+
+ //! das ist nur bis das ENUM-Slots sind
+ // Invalidate( SID_OBJECT_SELECT );
+}
+
+void SlotManager::FuSupport (SfxRequest& rRequest)
+{
+ switch (rRequest.GetSlot())
+ {
+ case SID_STYLE_FAMILY:
+ if (rRequest.GetArgs() != NULL)
+ {
+ SdDrawDocument* pDocument
+ = mrSlideSorter.GetModel().GetDocument();
+ if (pDocument != NULL)
+ {
+ const SfxPoolItem& rItem (
+ rRequest.GetArgs()->Get(SID_STYLE_FAMILY));
+ pDocument->GetDocSh()->SetStyleFamily(
+ static_cast<const SfxUInt16Item&>(rItem).GetValue());
+ }
+ }
+ break;
+
+ case SID_PASTE:
+ {
+ SdTransferable* pTransferClip = SD_MOD()->pTransferClip;
+ if( pTransferClip )
+ {
+ SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell();
+
+ DrawDocShell* pDocShell = dynamic_cast<DrawDocShell*>(pTransferDocShell);
+ if (pDocShell && pDocShell->GetDoc()->GetPageCount() > 1)
+ {
+ mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest);
+ break;
+ }
+ }
+ ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
+ if (pBase != NULL)
+ {
+ ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
+ ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
+ if (pDrawViewShell.get() != NULL)
+ pDrawViewShell->FuSupport(rRequest);
+ }
+ }
+ break;
+
+ case SID_CUT:
+ case SID_COPY:
+ case SID_DELETE:
+ mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest);
+ break;
+
+ case SID_DRAWINGMODE:
+ case SID_NOTESMODE:
+ case SID_HANDOUTMODE:
+ case SID_DIAMODE:
+ case SID_OUTLINEMODE:
+ {
+ ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
+ if (pBase != NULL)
+ {
+ framework::FrameworkHelper::Instance(*pBase)->HandleModeChangeSlot(
+ rRequest.GetSlot(), rRequest);
+ rRequest.Done();
+ }
+ break;
+ }
+
+ case SID_UNDO :
+ {
+ SlideSorterViewShell* pViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pViewShell != NULL)
+ pViewShell->ImpSidUndo (FALSE, rRequest);
+ break;
+ }
+
+ case SID_REDO :
+ {
+ SlideSorterViewShell* pViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pViewShell != NULL)
+ pViewShell->ImpSidRedo (FALSE, rRequest);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+
+
+void SlotManager::ExecCtrl (SfxRequest& rRequest)
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ USHORT nSlot = rRequest.GetSlot();
+ switch (nSlot)
+ {
+ case SID_RELOAD:
+ {
+ // Undo-Manager leeren
+ mrSlideSorter.GetModel().GetDocument()->GetDocSh()->ClearUndoBuffer();
+
+ // Normale Weiterleitung an ViewFrame zur Ausfuehrung
+ if (pViewShell != NULL)
+ pViewShell->GetViewFrame()->ExecuteSlot(rRequest);
+
+ // Muss sofort beendet werden
+ return;
+ }
+
+ case SID_OUTPUT_QUALITY_COLOR:
+ case SID_OUTPUT_QUALITY_GRAYSCALE:
+ case SID_OUTPUT_QUALITY_BLACKWHITE:
+ case SID_OUTPUT_QUALITY_CONTRAST:
+ {
+ // flush page cache
+ if (pViewShell != NULL)
+ pViewShell->ExecReq (rRequest);
+ break;
+ }
+
+ case SID_MAIL_SCROLLBODY_PAGEDOWN:
+ {
+ if (pViewShell != NULL)
+ pViewShell->ExecReq (rRequest);
+ break;
+ }
+
+ case SID_OPT_LOCALE_CHANGED:
+ {
+ mrSlideSorter.GetController().UpdateAllPages();
+ if (pViewShell != NULL)
+ pViewShell->UpdatePreview (pViewShell->GetActualPage());
+ rRequest.Done();
+ break;
+ }
+
+ case SID_SEARCH_DLG:
+ // We have to handle the SID_SEARCH_DLG slot explicitly because
+ // in some cases (when the slide sorter is displayed in the
+ // center pane) we want to disable the search dialog. Therefore
+ // we have to handle the execution of that slot as well.
+ // We try to do that by forwarding the request to the view frame
+ // of the view shell.
+ if (pViewShell != NULL)
+ pViewShell->GetViewFrame()->ExecuteSlot(rRequest);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+
+void SlotManager::GetAttrState (SfxItemSet& rSet)
+{
+ // Iteratate over all items.
+ SfxWhichIter aIter (rSet);
+ USHORT nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ USHORT nSlotId (nWhich);
+ if (SfxItemPool::IsWhich(nWhich) && mrSlideSorter.GetViewShell()!=NULL)
+ nSlotId = mrSlideSorter.GetViewShell()->GetPool().GetSlotId(nWhich);
+ switch (nSlotId)
+ {
+ case SID_PAGES_PER_ROW:
+ rSet.Put (
+ SfxUInt16Item (
+ nSlotId,
+ (USHORT)mrSlideSorter.GetView().GetLayouter().GetColumnCount()
+ )
+ );
+ break;
+ }
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SlotManager::GetMenuState ( SfxItemSet& rSet)
+{
+ EditMode eEditMode = mrSlideSorter.GetModel().GetEditMode();
+ ViewShell* pShell = mrSlideSorter.GetViewShell();
+ DrawDocShell* pDocShell = mrSlideSorter.GetModel().GetDocument()->GetDocSh();
+
+ if (pShell!=NULL && pShell->GetCurrentFunction().is())
+ {
+ USHORT nSId = pShell->GetCurrentFunction()->GetSlotID();
+
+ rSet.Put( SfxBoolItem( nSId, TRUE ) );
+ }
+ rSet.Put( SfxBoolItem( SID_DRAWINGMODE, FALSE ) );
+ rSet.Put( SfxBoolItem( SID_DIAMODE, TRUE ) );
+ rSet.Put( SfxBoolItem( SID_OUTLINEMODE, FALSE ) );
+ rSet.Put( SfxBoolItem( SID_NOTESMODE, FALSE ) );
+ rSet.Put( SfxBoolItem( SID_HANDOUTMODE, FALSE ) );
+
+ // Vorlagenkatalog darf nicht aufgerufen werden
+ rSet.DisableItem(SID_STYLE_CATALOG);
+
+ if (pShell!=NULL && pShell->IsMainViewShell())
+ {
+ rSet.DisableItem(SID_SPELL_DIALOG);
+ rSet.DisableItem(SID_SEARCH_DLG);
+ }
+
+ if (SFX_ITEM_AVAILABLE == rSet.GetItemState(SID_EXPAND_PAGE))
+ {
+ bool bDisable = true;
+ if (eEditMode == EM_PAGE)
+ {
+ // At least one of the selected pages has to contain an outline
+ // presentation objects in order to enable the expand page menu
+ // entry.
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
+ SdrObject* pObj = pPage->GetPresObj(PRESOBJ_OUTLINE);
+ if (pObj!=NULL && !pObj->IsEmptyPresObj())
+ bDisable = false;
+ }
+ }
+
+ if (bDisable)
+ rSet.DisableItem (SID_EXPAND_PAGE);
+ }
+
+ if (SFX_ITEM_AVAILABLE == rSet.GetItemState(SID_SUMMARY_PAGE))
+ {
+ bool bDisable = true;
+ if (eEditMode == EM_PAGE)
+ {
+ // At least one of the selected pages has to contain a title
+ // presentation objects in order to enable the summary page menu
+ // entry.
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
+ SdrObject* pObj = pPage->GetPresObj(PRESOBJ_TITLE);
+
+ if (pObj!=NULL && !pObj->IsEmptyPresObj())
+ bDisable = false;
+ }
+ }
+ if (bDisable)
+ rSet.DisableItem (SID_SUMMARY_PAGE);
+ }
+
+ // Starten der Praesentation moeglich?
+ if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_PRESENTATION ) ||
+ SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_REHEARSE_TIMINGS ) )
+ {
+ BOOL bDisable = TRUE;
+ model::PageEnumeration aAllPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter.GetModel()));
+ while (aAllPages.HasMoreElements())
+ {
+ SdPage* pPage = aAllPages.GetNextElement()->GetPage();
+
+ if( !pPage->IsExcluded() )
+ bDisable = FALSE;
+ }
+ if( bDisable || pDocShell->IsPreview())
+ {
+ rSet.DisableItem( SID_PRESENTATION );
+ rSet.DisableItem( SID_REHEARSE_TIMINGS );
+ }
+ }
+
+
+ // Disable the rename slots when there are no or more than one slides/master
+ // pages selected.
+ if (rSet.GetItemState(SID_RENAMEPAGE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_RENAME_MASTER_PAGE) == SFX_ITEM_AVAILABLE)
+ {
+ if (mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount() != 1)
+ {
+ rSet.DisableItem(SID_RENAMEPAGE);
+ rSet.DisableItem(SID_RENAME_MASTER_PAGE);
+ }
+ }
+
+ if (rSet.GetItemState(SID_HIDE_SLIDE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_SHOW_SLIDE) == SFX_ITEM_AVAILABLE)
+ {
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ HideSlideFunction::ExclusionState eState (
+ HideSlideFunction::GetExclusionState(aSelectedPages));
+ switch (eState)
+ {
+ case HideSlideFunction::MIXED:
+ // Show both entries.
+ break;
+
+ case HideSlideFunction::EXCLUDED:
+ rSet.DisableItem(SID_HIDE_SLIDE);
+ break;
+
+ case HideSlideFunction::INCLUDED:
+ rSet.DisableItem(SID_SHOW_SLIDE);
+ break;
+
+ case HideSlideFunction::UNDEFINED:
+ rSet.DisableItem(SID_HIDE_SLIDE);
+ rSet.DisableItem(SID_SHOW_SLIDE);
+ break;
+ }
+ }
+
+ PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
+ if( (eEditMode == EM_MASTERPAGE) && (ePageKind != PK_HANDOUT ) )
+ {
+ rSet.DisableItem(SID_ASSIGN_LAYOUT);
+ }
+
+ if( (eEditMode == EM_MASTERPAGE) || (ePageKind==PK_NOTES) )
+ {
+ rSet.DisableItem(SID_INSERTPAGE);
+ }
+}
+
+
+
+
+void SlotManager::GetClipboardState ( SfxItemSet& rSet)
+{
+ SdTransferable* pTransferClip = SD_MOD()->pTransferClip;
+
+ if (rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE)
+ {
+ // Keine eigenen Clipboard-Daten?
+ if ( !pTransferClip || !pTransferClip->GetDocShell() )
+ {
+ rSet.DisableItem(SID_PASTE);
+ rSet.DisableItem(SID_PASTE_SPECIAL);
+ }
+ else
+ {
+ SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell();
+
+ if( !pTransferDocShell || ( (DrawDocShell*) pTransferDocShell)->GetDoc()->GetPageCount() <= 1 )
+ {
+ bool bIsPastingSupported (false);
+
+ // No or just one page. Check if there is anything that can be
+ // pasted via a DrawViewShell.
+ ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
+ if (pBase != NULL)
+ {
+ ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
+ ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
+ if (pDrawViewShell.get() != NULL)
+ {
+ TransferableDataHelper aDataHelper (
+ TransferableDataHelper::CreateFromSystemClipboard(
+ pDrawViewShell->GetActiveWindow()));
+ if (aDataHelper.GetFormatCount() > 0)
+ bIsPastingSupported = true;
+ }
+ }
+
+ if ( ! bIsPastingSupported)
+ {
+ rSet.DisableItem(SID_PASTE);
+ rSet.DisableItem(SID_PASTE_SPECIAL);
+ }
+ }
+ }
+ }
+
+ // Cut, copy and paste of master pages is not yet implemented properly
+ if (rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE)
+ {
+ if (mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE)
+ {
+ if (rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_CUT);
+ if (rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_COPY);
+ if (rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_PASTE);
+ if (rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_PASTE_SPECIAL);
+ }
+ }
+
+ // Cut, copy, and delete page are disabled when there is no selection.
+ if (rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_DELETE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_DELETE_PAGE) == SFX_ITEM_AVAILABLE
+ || rSet.GetItemState(SID_DELETE_MASTER_PAGE) == SFX_ITEM_AVAILABLE)
+ {
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+
+ // For copy to work we have to have at least one selected page.
+ if ( ! aSelectedPages.HasMoreElements())
+ rSet.DisableItem(SID_COPY);
+
+ bool bDisable = false;
+ // The operations that lead to the deletion of a page are valid if
+ // a) there is at least one selected page
+ // b) deleting the selected pages leaves at least one page in the
+ // document
+ // c) selected master pages must not be used by slides.
+
+ // Test a).
+ if ( ! aSelectedPages.HasMoreElements())
+ bDisable = true;
+ // Test b): Count the number of selected pages. It has to be less
+ // than the number of all pages.
+ else if (mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount()
+ >= mrSlideSorter.GetController().GetPageSelector().GetPageCount())
+ bDisable = true;
+ // Test c): Iterate over the selected pages and look for a master
+ // page that is used by at least one page.
+ else while (aSelectedPages.HasMoreElements())
+ {
+ SdPage* pPage = aSelectedPages.GetNextElement()->GetPage();
+ int nUseCount (mrSlideSorter.GetModel().GetDocument()
+ ->GetMasterPageUserCount(pPage));
+ if (nUseCount > 0)
+ {
+ bDisable = true;
+ break;
+ }
+ }
+
+ if (bDisable)
+ {
+ rSet.DisableItem(SID_CUT);
+ rSet.DisableItem(SID_DELETE_PAGE);
+ rSet.DisableItem(SID_DELETE_MASTER_PAGE);
+ }
+ }
+}
+
+
+
+
+void SlotManager::GetStatusBarState (SfxItemSet& rSet)
+{
+ // Seitenanzeige und Layout
+ /*
+ if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_STATUS_PAGE ) ||
+ SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_STATUS_LAYOUT ) )
+ */
+ SdPage* pPage = NULL;
+ SdPage* pFirstPage = NULL;
+ USHORT nFirstPage;
+ USHORT nSelectedPages = (USHORT)mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
+ String aPageStr;
+ String aLayoutStr;
+
+ if (nSelectedPages > 0)
+ aPageStr = String(SdResId(STR_SD_PAGE));
+
+ if (nSelectedPages == 1)
+ {
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ pPage = aSelectedPages.GetNextElement()->GetPage();
+ nFirstPage = pPage->GetPageNum()/2;
+ pFirstPage = pPage;
+
+ aPageStr += sal_Unicode(' ');
+ aPageStr += String::CreateFromInt32( nFirstPage + 1 );
+ aPageStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " / " ));
+ aPageStr += String::CreateFromInt32(
+ mrSlideSorter.GetModel().GetPageCount());
+
+ aLayoutStr = pFirstPage->GetLayoutName();
+ aLayoutStr.Erase( aLayoutStr.SearchAscii( SD_LT_SEPARATOR ) );
+ }
+
+ rSet.Put( SfxStringItem( SID_STATUS_PAGE, aPageStr ) );
+ rSet.Put( SfxStringItem( SID_STATUS_LAYOUT, aLayoutStr ) );
+
+ if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_ATTR_ZOOMSLIDER ) )
+ {
+ rSet.Put( SfxVoidItem( SID_ATTR_ZOOMSLIDER ) );
+ }
+}
+
+void SlotManager::ShowSlideShow( SfxRequest& rReq)
+{
+ Reference< XPresentation2 > xPresentation( mrSlideSorter.GetModel().GetDocument()->getPresentation() );
+ if( xPresentation.is() )
+ {
+ if( ( SID_REHEARSE_TIMINGS != rReq.GetSlot() ) )
+ xPresentation->start();
+ else
+ xPresentation->rehearseTimings();
+ }
+}
+
+void SlotManager::RenameSlide (void)
+{
+ PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
+ View* pDrView = &mrSlideSorter.GetView();
+
+ if (ePageKind==PK_STANDARD || ePageKind==PK_NOTES)
+ {
+ if ( pDrView->IsTextEdit() )
+ {
+ pDrView->SdrEndTextEdit();
+ }
+
+ SdPage* pSelectedPage = NULL;
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ if (aSelectedPages.HasMoreElements())
+ pSelectedPage = aSelectedPages.GetNextElement()->GetPage();
+ if (pSelectedPage != NULL)
+ {
+ String aTitle( SdResId( STR_TITLE_RENAMESLIDE ) );
+ String aDescr( SdResId( STR_DESC_RENAMESLIDE ) );
+ String aPageName = pSelectedPage->GetName();
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ DBG_ASSERT(pFact, "Dialogdiet fail!");
+ AbstractSvxNameDialog* aNameDlg = pFact->CreateSvxNameDialog(
+ mrSlideSorter.GetActiveWindow(),
+ aPageName, aDescr);
+ DBG_ASSERT(aNameDlg, "Dialogdiet fail!");
+ aNameDlg->SetText( aTitle );
+ aNameDlg->SetCheckNameHdl( LINK( this, SlotManager, RenameSlideHdl ), true );
+ aNameDlg->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE );
+
+ if( aNameDlg->Execute() == RET_OK )
+ {
+ String aNewName;
+ aNameDlg->GetName( aNewName );
+ if( ! aNewName.Equals( aPageName ) )
+ {
+#ifdef DBG_UTIL
+ bool bResult =
+#endif
+ RenameSlideFromDrawViewShell(
+ pSelectedPage->GetPageNum()/2, aNewName );
+ DBG_ASSERT( bResult, "Couldn't rename slide" );
+ }
+ }
+ delete aNameDlg;
+
+ // Tell the slide sorter about the name change (necessary for
+ // accessibility.)
+ mrSlideSorter.GetController().PageNameHasChanged(
+ (pSelectedPage->GetPageNum()-1)/2, aPageName);
+ }
+ }
+}
+
+IMPL_LINK(SlotManager, RenameSlideHdl, AbstractSvxNameDialog*, pDialog)
+{
+ if( ! pDialog )
+ return 0;
+
+ String aNewName;
+ pDialog->GetName( aNewName );
+
+ model::SharedPageDescriptor pDescriptor (
+ mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
+ SdPage* pCurrentPage = NULL;
+ if (pDescriptor.get() != NULL)
+ pCurrentPage = pDescriptor->GetPage();
+
+ return ( (pCurrentPage!=NULL && aNewName.Equals( pCurrentPage->GetName() ))
+ || (mrSlideSorter.GetViewShell()
+ && mrSlideSorter.GetViewShell()->GetDocSh()->IsNewPageNameValid( aNewName ) ));
+}
+
+bool SlotManager::RenameSlideFromDrawViewShell( USHORT nPageId, const String & rName )
+{
+ BOOL bOutDummy;
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ if( pDocument->GetPageByName( rName, bOutDummy ) != SDRPAGE_NOTFOUND )
+ return false;
+
+ SdPage* pPageToRename = NULL;
+ PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
+
+ SfxUndoManager* pManager = pDocument->GetDocSh()->GetUndoManager();
+
+ if( mrSlideSorter.GetModel().GetEditMode() == EM_PAGE )
+ {
+ model::SharedPageDescriptor pDescriptor (
+ mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
+ if (pDescriptor.get() != NULL)
+ pPageToRename = pDescriptor->GetPage();
+
+ if (pPageToRename != NULL)
+ {
+ // Undo
+ SdPage* pUndoPage = pPageToRename;
+ SdrLayerAdmin & rLayerAdmin = pDocument->GetLayerAdmin();
+ BYTE nBackground = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRND )), FALSE );
+ BYTE nBgObj = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRNDOBJ )), FALSE );
+ SetOfByte aVisibleLayers = pPageToRename->TRG_GetMasterPageVisibleLayers();
+
+ // (#67720#)
+ ModifyPageUndoAction* pAction = new ModifyPageUndoAction(
+ pManager, pDocument, pUndoPage, rName, pUndoPage->GetAutoLayout(),
+ aVisibleLayers.IsSet( nBackground ),
+ aVisibleLayers.IsSet( nBgObj ));
+ pManager->AddUndoAction( pAction );
+
+ // rename
+ pPageToRename->SetName( rName );
+
+ if( ePageKind == PK_STANDARD )
+ {
+ // also rename notes-page
+ SdPage* pNotesPage = pDocument->GetSdPage( nPageId, PK_NOTES );
+ if (pNotesPage != NULL)
+ pNotesPage->SetName (rName);
+ }
+ }
+ }
+ else
+ {
+ // rename MasterPage -> rename LayoutTemplate
+ pPageToRename = pDocument->GetMasterSdPage( nPageId, ePageKind );
+ if (pPageToRename != NULL)
+ {
+ const String aOldLayoutName( pPageToRename->GetLayoutName() );
+ pManager->AddUndoAction( new RenameLayoutTemplateUndoAction( pDocument, aOldLayoutName, rName ) );
+ pDocument->RenameLayoutTemplate( aOldLayoutName, rName );
+ }
+ }
+
+ bool bSuccess = pPageToRename!=NULL && ( FALSE != rName.Equals( pPageToRename->GetName()));
+
+ if( bSuccess )
+ {
+ // user edited page names may be changed by the page so update control
+ // aTabControl.SetPageText( nPageId, rName );
+
+ // set document to modified state
+ pDocument->SetChanged( TRUE );
+
+ // inform navigator about change
+ SfxBoolItem aItem( SID_NAVIGATOR_INIT, TRUE );
+ if (mrSlideSorter.GetViewShell() != NULL)
+ mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
+ SID_NAVIGATOR_INIT, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, &aItem, 0L );
+ }
+
+ return bSuccess;
+}
+
+
+
+
+/** Insert a slide. The insertion position depends on a) the selection and
+ b) the mouse position when there is no selection.
+
+ When there is a selection then insertion takes place after the last
+ slide of the selection. For this to work all but the last selected
+ slide are deselected first.
+
+ Otherwise, when there is no selection but the insertion marker is visible
+ the slide is inserted at that position. The slide before that marker is
+ selected first.
+
+ When both the selection and the insertion marker are not visible--can
+ that happen?--the new slide is inserted after the last slide.
+*/
+void SlotManager::InsertSlide (SfxRequest& rRequest)
+{
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+ // The fallback insertion position is after the last slide.
+ sal_Int32 nInsertionIndex (rSelector.GetPageCount() - 1);
+ if (rSelector.GetSelectedPageCount() > 0)
+ {
+ // Deselect all but the last selected slide.
+ bool bLastSelectedSlideSeen (false);
+ for (int nIndex=rSelector.GetPageCount()-1; nIndex>=0; --nIndex)
+ {
+ if (rSelector.IsPageSelected(nIndex))
+ {
+ if (bLastSelectedSlideSeen)
+ rSelector.DeselectPage (nIndex);
+ else
+ {
+ nInsertionIndex = nIndex;
+ bLastSelectedSlideSeen = true;
+ }
+ }
+ }
+ }
+
+ // No selection. Is there an insertion indicator?
+ else if (mrSlideSorter.GetView().GetOverlay()
+ .GetInsertionIndicatorOverlay().isVisible())
+ {
+ // Select the page before the insertion indicator.
+ nInsertionIndex = mrSlideSorter.GetView().GetOverlay()
+ .GetInsertionIndicatorOverlay().GetInsertionPageIndex();
+ nInsertionIndex --;
+ rSelector.SelectPage (nInsertionIndex);
+ }
+
+ // Is there a stored insertion position?
+ else if (mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() >= 0)
+ {
+ nInsertionIndex
+ = mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() - 1;
+ rSelector.SelectPage(nInsertionIndex);
+ }
+
+ // Select the last page when there is at least one page.
+ else if (rSelector.GetPageCount() > 0)
+ {
+ nInsertionIndex = rSelector.GetPageCount() - 1;
+ rSelector.SelectPage (nInsertionIndex);
+ }
+
+ // Hope for the best that CreateOrDuplicatePage() can cope with an empty
+ // selection.
+ else
+ {
+ nInsertionIndex = -1;
+ }
+
+ USHORT nPageCount ((USHORT)mrSlideSorter.GetModel().GetPageCount());
+
+ rSelector.DisableBroadcasting();
+ // In order for SlideSorterController::GetActualPage() to select the
+ // selected page as current page we have to turn off the focus
+ // temporarily.
+ {
+ FocusManager::FocusHider aTemporaryFocusHider (
+ mrSlideSorter.GetController().GetFocusManager());
+
+ SdPage* pPreviousPage = NULL;
+ if (nInsertionIndex >= 0)
+ pPreviousPage = mrSlideSorter.GetModel()
+ .GetPageDescriptor(nInsertionIndex)->GetPage();
+
+ if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
+ {
+ SlideSorterViewShell* pShell = dynamic_cast<SlideSorterViewShell*>(
+ mrSlideSorter.GetViewShell());
+ if (pShell != NULL)
+ {
+ pShell->CreateOrDuplicatePage (
+ rRequest,
+ mrSlideSorter.GetModel().GetPageType(),
+ pPreviousPage);
+ }
+ }
+ else
+ {
+ // Use the API to create a new page.
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ Reference<drawing::XMasterPagesSupplier> xMasterPagesSupplier (
+ pDocument->getUnoModel(), UNO_QUERY);
+ if (xMasterPagesSupplier.is())
+ {
+ Reference<drawing::XDrawPages> xMasterPages (
+ xMasterPagesSupplier->getMasterPages());
+ if (xMasterPages.is())
+ {
+ xMasterPages->insertNewByIndex (nInsertionIndex+1);
+
+ // Create shapes for the default layout.
+ SdPage* pMasterPage = pDocument->GetMasterSdPage(
+ (USHORT)(nInsertionIndex+1), PK_STANDARD);
+ pMasterPage->CreateTitleAndLayout (TRUE,TRUE);
+ }
+ }
+ }
+ }
+
+ // When a new page has been inserted then select it and make it the
+ // current page.
+ mrSlideSorter.GetView().LockRedraw(TRUE);
+ if (mrSlideSorter.GetModel().GetPageCount() > nPageCount)
+ {
+ nInsertionIndex++;
+ model::SharedPageDescriptor pDescriptor = mrSlideSorter.GetModel().GetPageDescriptor(nInsertionIndex);
+ if (pDescriptor.get() != NULL)
+ mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+ }
+ rSelector.EnableBroadcasting();
+ mrSlideSorter.GetView().LockRedraw(FALSE);
+}
+
+void SlotManager::ExecuteCommandAsynchronously (::std::auto_ptr<Command> pCommand)
+{
+ // Ownership of command is (implicitely) transferred to the queue.
+ maCommandQueue.push(pCommand.get());
+ pCommand.release();
+ Application::PostUserEvent(LINK(this,SlotManager,UserEventCallback));
+}
+
+IMPL_LINK(SlotManager, UserEventCallback, void*, EMPTYARG)
+{
+ if ( ! maCommandQueue.empty())
+ {
+ Command* pCommand = maCommandQueue.front();
+ maCommandQueue.pop();
+
+ if (pCommand != NULL)
+ {
+ // The queue ownes the command that has just been removed from
+ // it. Therefore it is deleted after it has been executed.
+ (*pCommand)();
+ delete pCommand;
+ }
+ }
+
+ return 1;
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.cxx b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx
new file mode 100644
index 000000000000..a2da21e383d8
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlsTransferable.hxx"
+
+#include "SlideSorterViewShell.hxx"
+#include "View.hxx"
+
+namespace sd { namespace slidesorter { namespace controller {
+
+Transferable::Transferable (
+ SdDrawDocument* pSrcDoc,
+ ::sd::View* pWorkView,
+ BOOL bInitOnGetData,
+ SlideSorterViewShell* pViewShell)
+ : SdTransferable (pSrcDoc, pWorkView, bInitOnGetData),
+ mpViewShell(pViewShell)
+{
+ if (mpViewShell != NULL)
+ StartListening(*mpViewShell);
+}
+
+
+
+Transferable::~Transferable (void)
+{
+ if (mpViewShell != NULL)
+ EndListening(*mpViewShell);
+}
+
+
+
+
+void Transferable::DragFinished (sal_Int8 nDropAction)
+{
+ if (mpViewShell != NULL)
+ mpViewShell->DragFinished(nDropAction);
+}
+
+
+
+
+void Transferable::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
+{
+ if (rHint.ISA(SfxSimpleHint) && mpViewShell!=NULL)
+ {
+ SfxSimpleHint& rSimpleHint (*PTR_CAST(SfxSimpleHint, &rHint));
+ if (rSimpleHint.GetId() == SFX_HINT_DYING)
+ {
+ // This hint may come either from the ViewShell or from the
+ // document (registered by SdTransferable). We do not know
+ // which but both are sufficient to disconnect from the
+ // ViewShell.
+ EndListening(*mpViewShell);
+ mpViewShell = NULL;
+ }
+ }
+
+ SdTransferable::Notify(rBroadcaster, rHint);
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.hxx b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx
new file mode 100644
index 000000000000..1cf448511b9e
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_TRANSFERABLE_HXX
+#define SD_SLIDESORTER_TRANSFERABLE_HXX
+
+#include "sdxfer.hxx"
+
+class SdDrawDocument;
+namespace sd
+{
+ class pWorkView;
+ namespace slidesorter
+ {
+ class SlideSorterViewShell;
+ }
+}
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** This class exists to have DragFinished call the correct object: the
+ SlideSorterViewShell instead of the old SlideView.
+*/
+class Transferable
+ : public SdTransferable
+{
+public:
+ Transferable (
+ SdDrawDocument* pSrcDoc,
+ ::sd::View* pWorkView,
+ BOOL bInitOnGetData,
+ SlideSorterViewShell* pViewShell);
+
+ virtual ~Transferable (void);
+
+ virtual void DragFinished (sal_Int8 nDropAction);
+
+private:
+ SlideSorterViewShell* mpViewShell;
+
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/makefile.mk b/sd/source/ui/slidesorter/controller/makefile.mk
new file mode 100644
index 000000000000..8ab63ddf776c
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/makefile.mk
@@ -0,0 +1,71 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slscontroller
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlideSorterController.obj \
+ $(SLO)$/SlsAnimator.obj \
+ $(SLO)$/SlsClipboard.obj \
+ $(SLO)$/SlsCurrentSlideManager.obj \
+ $(SLO)$/SlsFocusManager.obj \
+ $(SLO)$/SlsListener.obj \
+ $(SLO)$/SlsPageObjectFactory.obj \
+ $(SLO)$/SlsPageSelector.obj \
+ $(SLO)$/SlsProperties.obj \
+ $(SLO)$/SlsScrollBarManager.obj \
+ $(SLO)$/SlsSelectionCommand.obj \
+ $(SLO)$/SlsSelectionManager.obj \
+ $(SLO)$/SlsSlotManager.obj \
+ $(SLO)$/SlsTransferable.obj \
+ \
+ $(SLO)$/SlsHideSlideFunction.obj \
+ $(SLO)$/SlsSelectionFunction.obj \
+ $(SLO)$/SlsSlideFunction.obj
+
+EXCEPTIONSFILES= \
+ $(SLO)$/SlideSorterController.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx b/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx
new file mode 100644
index 000000000000..fe70b2461658
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CACHE_CONTEXT_HXX
+#define SD_SLIDESORTER_CACHE_CONTEXT_HXX
+
+#include <sal/types.h>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+class BitmapEx;
+class SdrPage;
+
+namespace sd { namespace slidesorter { namespace cache {
+
+typedef const SdrPage* CacheKey;
+
+/** This interface allows the individualisation of different instances of
+ the PreviewCache.
+*/
+class CacheContext
+{
+public:
+ /** This method is called when the asynchronous creation of a preview
+ has been finished.
+ @param aKey
+ The key of the page for which the preview has been created.
+ @param aPreview
+ The newly created preview.
+ */
+ virtual void NotifyPreviewCreation (
+ CacheKey aKey,
+ const ::boost::shared_ptr<BitmapEx>& rPreview) = 0;
+
+ /** Called to determine whether the system is idle and a preview can be
+ created without annoying the user.
+ */
+ virtual bool IsIdle (void) = 0;
+
+ /** This method is used to determine whether a page is currently visible
+ or not. It is called when the cache becomes to large and some
+ previews have to be released or scaled down.
+ */
+ virtual bool IsVisible (CacheKey aKey) = 0;
+
+ /** Return the page associdated with the given key. Note that different
+ keys may map to a single page (this may be the case with custom
+ slide shows.)
+ */
+ virtual const SdrPage* GetPage (CacheKey aKey) = 0;
+
+ /** This method is used when the request queue is filled. It asks for
+ the list of visible entries and maybe for the list of not visible
+ entries and creates preview creation requests for them.
+ @param bVisible
+ When this is <FALSE/> then the implementation can decide whether
+ to allow rendering of previews that are not visible (ahead of
+ time). When not then return an empty pointer or an empty vector.
+ */
+ virtual ::boost::shared_ptr<std::vector<CacheKey> > GetEntryList (bool bVisible) = 0;
+
+ /** Return the priority that defines the order in which previews are
+ created for different keys/pages. Typically the visible pages come
+ first, then top-down, left-to-right.
+ */
+ virtual sal_Int32 GetPriority (CacheKey aKey) = 0;
+
+ /** Return the model to which the pages belong for which the called
+ cache manages the previews. Different caches that belong to the
+ same model but have different preview sizes may acces previews of
+ each other in order to create fast previews of the previews.
+ */
+ virtual ::com::sun::star::uno::Reference<com::sun::star::uno::XInterface> GetModel (void) = 0;
+};
+
+typedef ::boost::shared_ptr<CacheContext> SharedCacheContext;
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx b/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx
new file mode 100644
index 000000000000..95d9bf1be815
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_CACHE_HXX
+#define SD_SLIDESORTER_PAGE_CACHE_HXX
+
+#include "cache/SlsCacheContext.hxx"
+#include <sal/types.h>
+#include <vcl/bitmapex.hxx>
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace view {
+class PageObjectViewObjectContact;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+class GenericPageCache;
+class RequestData;
+
+/** The page cache is responsible for the creation and storage of preview
+ bitmaps of pages that are shown by the slide sorter.
+
+ <p>Bitmaps for previews and a cache are used to speed up the display
+ (painting) of the slide sorter. But, of course, we have to limit this
+ time-space-tradeoff by limiting the amount of space that can be use to
+ store bitmaps.</p>
+
+ <p>There are several strategies employed by this class to shorten the
+ perceived time that is used to paint the slide sorter:
+ <ul>
+ <li>Rendering pages ahead of time. Additionally to rendering the
+ visible slides we try to render part or all of the slides that are not
+ (yet) visible. This, of course, makes sense only when the computer is
+ ohterwise idle while doing that.</li>
+ <li>When the size of the slides on the screen changes we mark the
+ bitmaps as needing an update but use them while the new bitmap in the
+ correct size is not available.</li>
+ <li>Give the UI the chance to handle user events between the rendering
+ of differe slides.</li>
+ <li>Limit the amount of space that may be used for storing preview
+ bitmaps and throw.</li>
+ </p>
+
+ <p>There is another somewhat similar methods for requesting new previews:
+ GetPreviewBitmap() schedules a re-rendering (when necessary) and
+ returns the preview what is currently available, either as a preview of
+ the preview or, when nothing has changed since the last call, as the
+ final thing.
+ </p>
+*/
+class PageCache
+{
+public:
+ /** The page chache is created with a reference to the slide sorter so
+ that it has access to both the view and the model and so can fill
+ itself with requests for all or just the visible pages.
+
+ It is the task of the PageCacheManager to create new objects of this
+ class.
+ */
+ PageCache (
+ const Size& rPreviewSize,
+ const SharedCacheContext& rpCacheContext);
+
+ ~PageCache (void);
+
+ void ChangeSize(const Size& rPreviewSize);
+
+ /** Request a preview bitmap for the specified page object in the
+ specified size. The returned bitmap may be a preview of the
+ preview, i.e. either a scaled (up or down) version of a previous
+ preview (of the wrong size) or an empty bitmap. In this case a
+ request for the generation of a new preview is created and inserted
+ into the request queue. When the preview is available the page
+ shape will be told to paint itself again. When it then calls this
+ method again if receives the correctly sized preview bitmap.
+ @param rRequestData
+ This data is used to determine the preview.
+ @param rSize
+ The size of the requested preview bitmap.
+ @return
+ Returns a bitmap that is either empty, contains a scaled (up or
+ down) version or is the requested bitmap.
+ */
+ BitmapEx GetPreviewBitmap (
+ CacheKey aKey,
+ const Size& rSize);
+
+ /** Call this method when a view-object-contact object is being deleted
+ and does not need (a) its current bitmap in the cache and (b) a
+ requested new bitmap.
+ */
+ void ReleasePreviewBitmap (CacheKey aKey);
+
+ /** Call this method when all preview bitmaps have to be generated anew.
+ This is the case when the size of the page objects on the screen has
+ changed or when the model has changed.
+ @param bUpdateCache
+ When this flags is <TRUE/> then requests for updated previews
+ are created. When it is <FALSE/> the existing previews are only
+ marked as not being up-to-date anymore.
+ */
+ void InvalidateCache (bool bUpdateCache = true);
+
+ /** With the precious flag you can control whether a bitmap can be
+ removed or reduced in size to make room for other bitmaps or is so
+ precious that it will not touched. A typical use is to set the
+ precious flag for exactly the visible pages.
+ */
+ void SetPreciousFlag (CacheKey aKey, bool bIsPrecious);
+
+ void Pause (void);
+ void Resume (void);
+
+private:
+ ::boost::scoped_ptr<GenericPageCache> mpImplementation;
+};
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx b/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx
new file mode 100644
index 000000000000..2416c99295b0
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_PAGE_CACHE_MANAGER_HXX
+#define SD_PAGE_CACHE_MANAGER_HXX
+
+#include <sal/types.h>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <vector>
+
+class Size;
+class SdDrawDocument;
+class SdrPage;
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+class PageObjectViewObjectContact;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+
+namespace css = ::com::sun::star;
+
+class BitmapCache;
+
+
+/** Provide and manage the preview bitmap caches for all slide sorter
+ instances. There is one cache per active slide sorter plus a small
+ number of caches that are no longer in use. The later are kept to speed
+ up the switching between views.
+*/
+class PageCacheManager
+{
+public:
+ typedef BitmapCache Cache;
+ typedef ::std::vector< ::std::pair<Size, ::boost::shared_ptr<BitmapCache> > > BestFittingPageCaches;
+ typedef css::uno::Reference<css::uno::XInterface> DocumentKey;
+
+ /** Return the one instance of the PageCacheManager class.
+ */
+ static ::boost::shared_ptr<PageCacheManager> Instance (void);
+
+ /** Look up the cache for the given model in which the previews have the
+ specified size. If no such cache exists, then one is created. When
+ a new BitmapCache is created its Recycle() method is called with a
+ sorted list of existing caches from which the new one initialize its
+ previews.
+ @return
+ The returned cache lives as long as somebody keeps a shared
+ pointer and the ReleaseCache() method has not been called.
+ */
+ ::boost::shared_ptr<Cache> GetCache (
+ DocumentKey pDocument,
+ const Size& rPreviewSize);
+
+ /** Tell the cache manager to release its own reference to the specified
+ cache. After that the cache will live as long as the caller (and
+ maybe others) holds its reference.
+ */
+ void ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache);
+
+ /** This is an information to the cache manager that the size of preview
+ bitmaps in the specified cache has changed.
+
+ */
+ ::boost::shared_ptr<Cache> ChangeSize (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ const Size& rOldPreviewSize,
+ const Size& rNewPreviewSize);
+
+ /** Invalidate the preview bitmap for one slide that belongs to the
+ specified document. The bitmaps for this slide in all caches are
+ marked as out-of-date and will be re-created when they are requested
+ the next time.
+ */
+ void InvalidatePreviewBitmap (
+ DocumentKey pDocument,
+ const SdrPage* pPage);
+
+ /** Invalidate all the caches that are currently in use and destroy
+ those that are not. This is used for example when the high contrast
+ mode is turned on or off.
+ */
+ void InvalidateAllCaches (void);
+
+private:
+ /** Singleton instance of the cache manager. Note that this is a weak
+ pointer. The (implementation class of) ViewShellBase holds a
+ shared_ptr so that the cache manager has the same life time as the
+ ViewShellBase.
+ */
+ static ::boost::weak_ptr<PageCacheManager> mpInstance;
+
+ /// List of active caches.
+ class PageCacheContainer;
+ ::std::auto_ptr<PageCacheContainer> mpPageCaches;
+
+ /// List of inactive, recently used caches.
+ class RecentlyUsedPageCaches;
+ ::std::auto_ptr<RecentlyUsedPageCaches> mpRecentlyUsedPageCaches;
+
+ /** The maximal number of recently used caches that are kept alive after
+ they have become inactive, i.e. after they are not used anymore by a
+ slide sorter.
+ */
+ const sal_uInt32 mnMaximalRecentlyCacheCount;
+
+ PageCacheManager (void);
+ ~PageCacheManager (void);
+
+ class Deleter;
+ friend class Deleter;
+
+ ::boost::shared_ptr<Cache> GetRecentlyUsedCache(
+ DocumentKey pDocument,
+ const Size& rSize);
+
+ /** Add the given cache to the list of recently used caches for the
+ document. There is one such list per document. Each least has at
+ most mnMaximalRecentlyCacheCount members.
+ */
+ void PutRecentlyUsedCache(
+ DocumentKey pDocument,
+ const Size& rPreviewSize,
+ const ::boost::shared_ptr<Cache>& rpCache);
+
+ /** Return a sorted list of the available caches, both active caches and
+ those recently used, for the given document. The sort order is so
+ that an exact match of the preview size is at the front. Other
+ caches follow with the largest size first.
+ */
+ BestFittingPageCaches GetBestFittingCaches (
+ DocumentKey pDocument,
+ const Size& rPreviewSize);
+
+ /** This method is used internally to initialize a newly created
+ BitmapCache with already exisiting previews.
+ */
+ void Recycle (
+ const ::boost::shared_ptr<Cache>& rpCache,
+ DocumentKey pDocument,
+ const Size& rPreviewSize);
+};
+
+} } } // end of namespace ::sd::slidesorter::cache
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
new file mode 100644
index 000000000000..4c7c8ac8edf5
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_CONTROLLER_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_CONTROLLER_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "ViewShell.hxx"
+
+#include <com/sun/star/drawing/XDrawPages.hpp>
+
+#include <sfx2/shell.hxx>
+#include <sfx2/viewfac.hxx>
+#include <tools/link.hxx>
+#include <tools/gen.hxx>
+#include <memory>
+#include <comphelper/implementationreference.hxx>
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+class HighlightObject;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class Animator;
+class Clipboard;
+class CurrentSlideManager;
+class FocusManager;
+class Listener;
+class PageSelector;
+class Properties;
+class ScrollBarManager;
+class SelectionManager;
+class SlotManager;
+
+class SlideSorterController
+{
+public:
+ /** Create a new controller for the slide sorter.
+ @param pParentWindow
+ The window that contains the controls of the new
+ controller.
+ */
+ SlideSorterController (SlideSorter& rSlideSorter);
+
+ /** Late initialization. Call this method once a new new object has been
+ created.
+ */
+ virtual void Init (void);
+
+ virtual ~SlideSorterController (void);
+
+ /** Place and size the scroll bars and the browser window so that the
+ given rectangle is filled.
+ @return
+ The space occupied by the browser window is returned.
+ */
+ Rectangle Resize (const Rectangle& rAvailableSpace);
+
+ /** Determine which of the UI elements--the scroll bars, the scroll bar
+ filler, the actual slide sorter view--are visible and place them in
+ the area last passed to Resize().
+ @param bForce
+ When <TRUE/> is given (<FALSE/> is the default) then the content
+ window and with it the SlideSorterView is resized event when its
+ size does not change (the size does change when the visibility
+ of scroll bars changes.)
+ @return
+ Returns the space occupied by the browser window.
+ */
+ Rectangle Rearrange (bool bForce = false);
+
+ /** Return the descriptor of the page that is rendered under the
+ given position.
+ @return
+ Returns a pointer to a page descriptor instead of a
+ reference because when no page is found at the position
+ then NULL is returned to indicate this.
+ */
+ model::SharedPageDescriptor GetPageAt (const Point& rPixelPosition);
+
+ PageSelector& GetPageSelector (void);
+ FocusManager& GetFocusManager (void);
+ controller::Clipboard& GetClipboard (void);
+
+ /** Return the object that manages the scroll bars.
+ */
+ ScrollBarManager& GetScrollBarManager (void);
+
+ ::boost::shared_ptr<CurrentSlideManager> GetCurrentSlideManager (void) const;
+ ::boost::shared_ptr<SlotManager> GetSlotManager (void) const;
+ ::boost::shared_ptr<SelectionManager> GetSelectionManager (void) const;
+
+ // forward VCLs PrePaint window event to DrawingLayer
+ void PrePaint();
+
+ /** This method forwards the call to the SlideSorterView and executes
+ pending operations like moving selected pages into the visible area.
+ */
+ void Paint (const Rectangle& rRect, ::Window* pWin);
+
+ void FuTemporary (SfxRequest& rRequest);
+ void FuPermanent (SfxRequest& rRequest);
+ void FuSupport (SfxRequest& rRequest);
+ bool Command (
+ const CommandEvent& rEvent,
+ ::sd::Window* pWindow);
+
+ void GetCtrlState (SfxItemSet &rSet);
+ void GetStatusBarState (SfxItemSet& rSet);
+
+ void ExecCtrl (SfxRequest& rRequest);
+ void GetAttrState (SfxItemSet& rSet);
+ void ExecStatusBar (SfxRequest& rRequest);
+
+ bool IsLocked (void) const;
+
+ /** Create an object of this inner class to prevent updates due to model
+ changes.
+ */
+ class ModelChangeLock
+ {public:
+ ModelChangeLock (SlideSorterController& rController);
+ ~ModelChangeLock (void);
+ void Release (void);
+ private:
+ SlideSorterController* mpController;
+ };
+ friend class ModelChangeLock;
+
+
+ /** Handle a change of the model, that is, handle the removal and
+ insertion of whole pages or a change of the edit mode.
+
+ This method is a convenience function that simply calls
+ PreModelChange() and then PostModelChange().
+ */
+ void HandleModelChange (void);
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent*);
+
+ /** Update the display of all pages. This involves a redraw and
+ releasing previews and caches.
+ */
+ void UpdateAllPages (void);
+
+ /** This factory method creates a selection function.
+ */
+ virtual FunctionReference CreateSelectionFunction (SfxRequest& rRequest);
+
+ /** Prepare for a change of the edit mode. Depending on the current
+ edit mode we may save the selection so that it can be restored when
+ later changing back to the current edit mode.
+ */
+ void PrepareEditModeChange (void);
+
+ /** Set a new edit mode and return whether the edit mode really
+ has been changed. For proper saving and restoring of the selection
+ this method should be called between calls to
+ PrepareEditModeChange() and FinishEditModeChange().
+ @return
+ A return value of <TRUE/> indicates that the edit mode has
+ changed.
+ */
+ bool ChangeEditMode (EditMode eEditMode);
+
+ /** Finish the change of the edit mode. Here we may select a page or
+ restore a previously saved selection.
+ */
+ void FinishEditModeChange (void);
+
+ /** Call this method when the name of one of the pages has changed.
+ This is then notified to the accessibility object, when that exists.
+ @param nPageIndex
+ The index of the page whose name has been changed.
+ @param rsOldName
+ The old name of the page. The new name can be taken from the
+ page object.
+ */
+ void PageNameHasChanged (int nPageIndex, const String& rsOldName);
+
+ /** Return whether a context menu has been opened by the called
+ SlideSorterController object and is still open.
+ */
+ bool IsContextMenuOpen (void) const;
+
+ /** Return a collection of properties that are used througout the slide
+ sorter.
+ */
+ ::boost::shared_ptr<Properties> GetProperties (void) const;
+
+ /** Provide the set of pages to be displayed in the slide sorter. The
+ GetDocumentSlides() method can be found only in the SlideSorterModel.
+ */
+ void SetDocumentSlides (const css::uno::Reference<css::container::XIndexAccess>& rxSlides);
+
+ /** Return an Animator object.
+ */
+ ::boost::shared_ptr<Animator> GetAnimator (void) const;
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SlideSorterModel& mrModel;
+ view::SlideSorterView& mrView;
+ ::std::auto_ptr<PageSelector> mpPageSelector;
+ ::std::auto_ptr<FocusManager> mpFocusManager;
+ ::boost::shared_ptr<SlotManager> mpSlotManager;
+ ::std::auto_ptr<controller::Clipboard> mpClipboard;
+ ::std::auto_ptr<ScrollBarManager> mpScrollBarManager;
+ mutable ::boost::shared_ptr<CurrentSlideManager> mpCurrentSlideManager;
+ ::boost::shared_ptr<SelectionManager> mpSelectionManager;
+ ::boost::shared_ptr<Animator> mpAnimator;
+
+ // The listener listens to UNO events and thus is a UNO object.
+ // For proper life time management and at the same time free access to
+ // the implementation object we use the ImplementationReference class.
+ ::rtl::Reference<controller::Listener> mpListener;
+
+ int mnModelChangeLockCount;
+
+ bool mbPreModelChangeDone;
+ bool mbPostModelChangePending;
+
+ ::std::vector<Link> maSelectionChangeListeners;
+
+ /** This array stores the indices of the selected page descriptors at
+ the time when the edit mode is switched to EM_MASTERPAGE. With this
+ we can restore the selection when switching back to EM_PAGE mode.
+ */
+ ::std::vector<SdPage*> maSelectionBeforeSwitch;
+ /// The current page before the edit mode is switched to EM_MASTERPAGE.
+ int mnCurrentPageBeforeSwitch;
+
+ /** The master page to select after the edit mode is changed. This
+ member is used to pass the pointer from PrepareEditModeChange() to
+ FinishEditModeChange().
+ */
+ SdPage* mpEditModeChangeMasterPage;
+
+ /** This rectangle in the parent window encloses scroll bars and slide
+ sorter window. It is set when Resize() is called.
+ */
+ Rectangle maTotalWindowArea;
+
+ /** This counter is used to avoid processing of reentrant calls to
+ Paint().
+ */
+ sal_Int32 mnPaintEntranceCount;
+
+ /** Remember whether the context menu is open.
+ */
+ bool mbIsContextMenuOpen;
+
+ /** Some slide sorter wide properties that are used in different
+ classes.
+ */
+ ::boost::shared_ptr<Properties> mpProperties;
+
+ /** Delete the given list of normal pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedNormalPages
+ A list of normal pages. Supplying master pages is an error.
+ */
+ void DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedNormalPages);
+
+ /** Delete the given list of master pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedMasterPages
+ A list of master pages. Supplying normal pages is an error.
+ */
+ void DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedMasterPages);
+
+ /** Prepare for several model changes, i.e. prevent time-consuming and
+ non-critical operations like repaints until UnlockModelChange() is
+ called. Ciritcal operations like releasing references to pages that
+ do not exist anymore are executed.
+ */
+ void LockModelChange (void);
+
+ /** Further calls to HandleModelChange() will result in a full featured
+ update of model, view, and controller. When HandleModelChange() has
+ been called since the last LockModelChange() then this is done right
+ away to bring the view up-to-date.
+ */
+ void UnlockModelChange (void);
+
+ /** Prepare for a model change. This method does all the things that
+ need to be done _before_ the model changes, e.g. because they need
+ access to the model data before the change.
+ */
+ void PreModelChange (void);
+
+ /** Complete a model change. This includes the recreation of data
+ structures that depend on the model and the request for a repaint to
+ show the changes.
+ */
+ void PostModelChange (void);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx b/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx
new file mode 100644
index 000000000000..75660b90f174
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CONTROLLER_ANIMATOR_HXX
+#define SD_SLIDESORTER_CONTROLLER_ANIMATOR_HXX
+
+#include "SlideSorter.hxx"
+#include <vcl/timer.hxx>
+#include <sal/types.h>
+#include <vector>
+#include <boost/function.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Experimental class for simple eye candy animations.
+*/
+class Animator
+ : private ::boost::noncopyable
+{
+public:
+ Animator (SlideSorter& rSlideSorter);
+ ~Animator (void);
+
+ /** An animation object is called with values between 0 and 1 as single
+ argument to its operator() method.
+ */
+ typedef ::boost::function1<void, double> AnimationFunction;
+
+ /** Schedule a new animation for execution. The () operator of that
+ animation will be called with increasing values between 0 and 1 for
+ the specified duration.
+ @param rAnimation
+ The animation operation.
+ @param nDuration
+ The duration in milli seconds.
+ */
+ void AddAnimation (
+ const AnimationFunction& rAnimation,
+ const sal_Int32 nDuration);
+
+private:
+ SlideSorter& mrSlideSorter;
+ Timer maTimer;
+
+ class Animation;
+ typedef ::std::vector<boost::shared_ptr<Animation> > AnimationList;
+ AnimationList maAnimations;
+
+ class DrawLock;
+ ::boost::scoped_ptr<DrawLock> mpDrawLock;
+
+ DECL_LINK(TimeoutHandler, Timer*);
+
+ /** Execute one step of every active animation.
+ @return
+ When one or more animation has finished then <TRUE/> is
+ returned. Call CleanUpAnimationList() in this case.
+ */
+ bool ServeAnimations (void);
+
+ /** Remove animations that have expired.
+ */
+ void CleanUpAnimationList (void);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx
new file mode 100644
index 000000000000..20d0e788f31e
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SD_SLIDESORTER_CLIPBOARD
+#define SD_SLIDESORTER_CLIPBOARD
+
+#include "ViewClipboard.hxx"
+
+#include <sal/types.h>
+#include <tools/solar.h>
+#include <svx/svdpage.hxx>
+
+#include <set>
+
+class SfxRequest;
+class Window;
+
+struct AcceptDropEvent;
+class DropTargetHelper;
+struct ExecuteDropEvent;
+class Point;
+class SdPage;
+class Window;
+
+namespace sd {
+class Window;
+}
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace model {
+class PageDescriptor;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+
+class Clipboard
+ : public ViewClipboard
+{
+public:
+ Clipboard (SlideSorter& rSlideSorter);
+ ~Clipboard (void);
+
+ void HandleSlotCall (SfxRequest& rRequest);
+
+ void DoCut (::Window* pWindow = 0);
+ void DoCopy (::Window* pWindow = 0);
+ void DoPaste (::Window* pWindow = 0);
+ void DoDelete (::Window* pWindow = 0);
+
+ void StartDrag (
+ const Point& rDragPt,
+ ::Window* pWindow );
+
+ void DragFinished (
+ sal_Int8 nDropAction);
+
+ sal_Int8 AcceptDrop (
+ const AcceptDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow = NULL,
+ USHORT nPage = SDRPAGE_NOTFOUND,
+ USHORT nLayer = SDRPAGE_NOTFOUND );
+
+ sal_Int8 ExecuteDrop (
+ const ExecuteDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow = NULL,
+ USHORT nPage = SDRPAGE_NOTFOUND,
+ USHORT nLayer = SDRPAGE_NOTFOUND);
+
+protected:
+ virtual USHORT DetermineInsertPosition (
+ const SdTransferable& rTransferable);
+
+ virtual USHORT InsertSlides (
+ const SdTransferable& rTransferable,
+ USHORT nInsertPosition);
+
+private:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ typedef ::std::vector<SdPage*> PageList;
+ /** Remember the pages that are dragged to another document or to
+ another place in the same document so that they can be removed after
+ a move operation.
+ */
+ PageList maPagesToRemove;
+
+ /** Remember the pages inserted from another document or another place
+ in the same document so that they can be selected after the
+ drag-and-drop operation is completed.
+ */
+ PageList maPagesToSelect;
+
+ /** When pages are moved or copied then the selection of the slide
+ sorter has to be updated. This flag is used to remember whether the
+ selection has to be updated or can stay as it is (FALSE).
+ */
+ bool mbUpdateSelectionPending;
+
+ void CreateSlideTransferable (
+ ::Window* pWindow,
+ bool bDrag);
+
+ /** Select the pages stored in the maPagesToSelect member. The list in
+ the member is cleared afterwards.
+ */
+ void SelectPages (void);
+
+ /** Determine the position of where to insert the pages in the current
+ transferable of the sd module.
+ @param pWindow
+ This window is used as parent for dialogs that have to be shown
+ to the user.
+ @return
+ The index in the range [0,n] (both inclusive) with n the number
+ of pages is returned.
+ */
+ sal_Int32 GetInsertionPosition (::Window* pWindow);
+
+ /** Paste the pages of the transferable of the sd module at the given
+ position.
+ @param nInsertPosition
+ The position at which to insert the pages. The valid range is
+ [0,n] (both inclusive) with n the number of pages in the
+ document.
+ @return
+ The number of inserted pages is returned.
+ */
+ sal_Int32 PasteTransferable (sal_Int32 nInsertPosition);
+
+ /** Select a range of pages of the model. Typicall usage is the
+ selection of newly inserted pages.
+ @param nFirstIndex
+ The index of the first page to select.
+ @param nPageCount
+ The number of pages to select.
+ */
+ void SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount);
+
+ /** Return <TRUE/> when the current transferable in the current state of
+ the slidesorter is acceptable to be pasted. For this the
+ transferable has to
+ a) exist,
+ b) contain one or more regular draw pages, no master pages.
+ When master pages are involved, either in the transferable or in the
+ slide sorter (by it displaying master pages) the drop of the
+ transferable is not accepted. The reason is the missing
+ implementation of proper handling master pages copy-and-paste.
+ */
+ enum DropType { DT_PAGE, DT_SHAPE, DT_NONE };
+ DropType IsDropAccepted (void) const;
+
+ /** This method contains the code for AcceptDrop() and ExecuteDrop() shapes.
+ There are only minor differences for the two cases at this level.
+ @param eCommand
+ This parameter specifies whether to do a AcceptDrop() or
+ ExecuteDrop().
+ @param rPosition
+ Since the event is given as void pointer we can not take the
+ mouse position from it. The caller has to supply it in this
+ parameter.
+ @param pDropEvent
+ Event though the AcceptDropEvent and ExecuteDropEvent are very
+ similar they do not have a common base class. Because of that
+ we have to use a void* to pase these structs.
+ @param nPage
+ When the page number is given as 0xffff then it is replaced by
+ the number of the page at the mouse position. If the mouse is
+ not over a page then neither AcceptDrop() nor ExecuteDrop() are
+ executed.
+ */
+ enum DropCommand { DC_ACCEPT, DC_EXECUTE };
+ sal_Int8 ExecuteOrAcceptShapeDrop (
+ DropCommand eCommand,
+ const Point& rPosition,
+ const void* pDropEvent ,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx
new file mode 100644
index 000000000000..769cb2372cca
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CURRENT_SLIDE_MANAGER_HXX
+#define SD_SLIDESORTER_CURRENT_SLIDE_MANAGER_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <com/sun/star/drawing/XDrawPage.hpp>
+
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Manage the current slide. This includes setting the according flags at
+ the PageDescriptor objects and setting the current slide at the main
+ view shell.
+*/
+class CurrentSlideManager
+{
+public:
+ /** Create a new CurrentSlideManager object that manages the current
+ slide for the given SlideSorter.
+ */
+ CurrentSlideManager (SlideSorter& rSlideSorter);
+
+ ~CurrentSlideManager (void);
+
+ /** Call this when the current page of the main view shell has been
+ switched. Use SwitchCurrentSlide() to initiate such a switch.
+ */
+ void CurrentSlideHasChanged (const sal_Int32 nSlideIndex);
+
+ /** Call this method to switch the current page of the main view shell
+ to the given slide. Use CurrentSlideHasChanged() when the current
+ slide change has been initiated by someone else.
+ */
+ void SwitchCurrentSlide (const sal_Int32 nSlideIndex);
+ void SwitchCurrentSlide (const model::SharedPageDescriptor& rpSlide);
+
+ /** Return the page descriptor for the current slide. Note, that when
+ there is no current slide then the returned pointer is empty.
+ */
+ model::SharedPageDescriptor GetCurrentSlide (void);
+
+ /** Release all references to model data.
+ */
+ void PrepareModelChange (void);
+
+ /** Modify inner state in reaction to a change of the SlideSorterModel.
+ */
+ void HandleModelChange (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+ sal_Int32 mnCurrentSlideIndex;
+ model::SharedPageDescriptor mpCurrentSlide;
+
+ bool IsCurrentSlideIsValid (void);
+ void SetCurrentSlideAtViewShellBase (const model::SharedPageDescriptor& rpSlide);
+ void SetCurrentSlideAtXController (const model::SharedPageDescriptor& rpSlide);
+
+ /** When switching from one slide to a new current slide then this
+ method releases all ties to the old slide.
+ */
+ void ReleaseCurrentSlide (void);
+
+ /** When switching from one slide to a new current slide then this
+ method connects to the new current slide.
+ */
+ void AcquireCurrentSlide (const sal_Int32 nSlideIndex);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx
new file mode 100644
index 000000000000..f647f914e318
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_FOCUS_MANAGER_HXX
+#define SD_SLIDESORTER_FOCUS_MANAGER_HXX
+
+#include <model/SlsSharedPageDescriptor.hxx>
+
+#include <sal/types.h>
+#include <tools/link.hxx>
+#include <vector>
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** This class manages the focus of the slide sorter. There is the focus
+ page which is or is not focused. Initialized to point to the first page
+ it can be set to other pages by using the MoveFocus() method. The
+ focused state of the focus page can be toggled with the ToggleFocus()
+ method.
+*/
+class FocusManager
+{
+public:
+ /** Create a new focus manager that operates on the pages of the model
+ associated with the given controller. The focus page is set to the
+ first page. Focused state is off.
+ */
+ FocusManager (SlideSorter& rSlideSorter);
+
+ ~FocusManager (void);
+
+ enum FocusMoveDirection
+ {
+ FMD_NONE,
+ FMD_LEFT,
+ FMD_RIGHT,
+ FMD_UP,
+ FMD_DOWN
+ };
+
+ /** Move the focus from the currently focused page to one that is
+ displayed adjacent to it, either vertically or horizontally.
+ @param eDirection
+ Direction in which to move the focus. Wrap arround is done
+ differently when moving vertically or horizontally. Vertical
+ wrap arround takes place in the same column, i.e. when you are
+ in the top row and move up you come out in the bottom row in the
+ same column. Horizontal wrap arround moves to the next
+ (FMD_RIGHT) or previous (FMD_LEFT) page. Moving to the right
+ from the last page goes to the first page and vice versa.
+ When FMD_NONE is given, the current page index is checked for
+ being valid. If it is not, then it is set to the nearest valid
+ page index.
+ */
+ void MoveFocus (FocusMoveDirection eDirection);
+
+ /** Show the focus indicator of the current slide.
+ @param bScrollToFocus
+ When <TRUE/> (the default) then the view is scrolled so that the
+ focus rectangle lies inside its visible area.
+ */
+ void ShowFocus (const bool bScrollToFocus = true);
+
+ /** Hide the focus indicator.
+ */
+ void HideFocus (void);
+
+ /** Toggle the focused state of the current slide.
+ @return
+ Returns the focused state of the focus page after the call.
+ */
+ bool ToggleFocus (void);
+
+ /** Return whether the window managed by the called focus manager has
+ the input focus of the application.
+ */
+ bool HasFocus (void) const;
+
+ /** Return the descriptor of the page that currently has the focus.
+ @return
+ When there is no page that currently has the focus then NULL is
+ returned.
+ */
+ model::SharedPageDescriptor GetFocusedPageDescriptor (void) const;
+
+ /** Return the index of the page that currently has the focus as it is
+ accepted by the slide sorter model.
+ @return
+ When there is no page that currently has the focus then -1 is
+ returned.
+ */
+ sal_Int32 GetFocusedPageIndex (void) const;
+
+ /** DEPRECATED. (Use equivalent SetFocusedPage(sal_Int32) instead.
+
+ Set the focus to the page with the given index. This does not make
+ the focus visible.
+ @param nPageIndex
+ Index of a page as it is accepted by the slide sorter model.
+ The index is not checked for validity.
+ */
+ void FocusPage (sal_Int32 nPageIndex);
+
+ /** Set the focused page to the one described by the given page
+ descriptor. The visibility of the focus indicator is not modified.
+ @param rDescriptor
+ One of the page descriptors that are currently managed by the
+ SlideSorterModel.
+ */
+ void SetFocusedPage (const model::SharedPageDescriptor& rDescriptor);
+
+ /** Set the focused page to the one described by the given page
+ index. The visibility of the focus indicator is not modified.
+ @param nPageIndex
+ A valid page index that is understood by the SlideSorterModel.
+ */
+ void SetFocusedPage (sal_Int32 nPageIndex);
+
+ /** Return <TRUE/> when the focus inidcator is currently shown. A
+ prerequisite is that the window managed by this focus manager has
+ the input focus as indicated by a <TRUE/> return value of
+ HasFocus(). It is not necessary that the focus indicator is
+ visible. It may have been scrolled outside the visible area.
+ */
+ bool IsFocusShowing (void) const;
+
+ /** Add a listener that is called when the focus is shown or hidden or
+ set to another page object.
+ @param rListener
+ When this method is called multiple times for the same listener
+ the second and all following calls are ignored. Each listener
+ is added only once.
+ */
+ void AddFocusChangeListener (const Link& rListener);
+
+ /** Remove a focus change listener.
+ @param rListener
+ It is save to pass a listener that was not added are has been
+ removed previously. Such calls are ignored.
+ */
+ void RemoveFocusChangeListener (const Link& rListener);
+
+ /** Move focus to sibling outside the actual slide sorter. This is
+ typically the tool bar with the close button.
+ */
+ void SetFocusToToolBox (void);
+
+ /** Create an instance of this class to temporarily hide the focus
+ indicator. It is restored to its former visibility state when the
+ FocusHider is destroyed.
+ */
+ class FocusHider
+ {
+ public:
+ FocusHider (FocusManager&);
+ ~FocusHider (void);
+ private:
+ bool mbFocusVisible;
+ FocusManager& mrManager;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** Index of the page that may be focused. It is -1 when the model
+ contains no page.
+ */
+ sal_Int32 mnPageIndex;
+
+ /** This flag indicates whether the page pointed to by mpFocusDescriptor
+ has the focus.
+ */
+ bool mbPageIsFocused;
+
+ ::std::vector<Link> maFocusChangeListeners;
+
+ /** Reset the focus state of the given descriptor and request a repaint
+ so that the focus indicator is hidden.
+ @param pDescriptor
+ When NULL is given then the call is ignored.
+ */
+ void HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Set the focus state of the given descriptor, scroll it into the
+ visible area and request a repaint so that the focus indicator is
+ made visible.
+ @param pDescriptor
+ When NULL is given then the call is ignored.
+ @param bScrollToFocus
+ When <TRUE/> (the default) then the view is scrolled so that the
+ focus rectangle lies inside its visible area.
+ */
+ void ShowFocusIndicator (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bScrollToFocus);
+
+ /** Call all currently registered listeners that a focus change has
+ happended. The focus may be hidden or shown or moved from one page
+ object to another.
+ */
+ void NotifyFocusChangeListeners (void) const;
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsPageObjectFactory.hxx b/sd/source/ui/slidesorter/inc/controller/SlsPageObjectFactory.hxx
new file mode 100644
index 000000000000..fef75520ca22
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsPageObjectFactory.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_OBJECT_FACTORY_HEADER
+#define SD_SLIDESORTER_PAGE_OBJECT_FACTORY_HEADER
+
+#include <boost/shared_ptr.hpp>
+#include "model/SlsSharedPageDescriptor.hxx"
+
+class SdPage;
+
+namespace sdr { namespace contact {
+class ObjectContact;
+class ViewContact;
+class ViewObjectContact;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+class PageObject;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+class PageCache;
+} } }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class Properties;
+
+/** This class is a factory for the creation of objects that represent page
+ objects (shapes). This includes the contact objects of the drawing
+ layer.
+
+ <p>The factory methods are called by the model::PageDescriptor and the
+ standard implementations of the contact objects.</p>
+
+ <p>The factory forwars the preview cache and Properties object to page
+ objects and contact objects.</p>
+*/
+class PageObjectFactory
+{
+public:
+ /** Create a new PageObjectFactory object that has references to the
+ given cache and properties.
+ */
+ PageObjectFactory (
+ const ::boost::shared_ptr<cache::PageCache>& rpCache,
+ const ::boost::shared_ptr<controller::Properties>& rpProperties);
+ PageObjectFactory (const ::boost::shared_ptr<cache::PageCache>& rpCache);
+ virtual ~PageObjectFactory (void);
+
+ virtual view::PageObject* CreatePageObject (
+ SdPage* pPage,
+ const model::SharedPageDescriptor& rpDescriptor) const;
+
+ virtual ::sdr::contact::ViewContact* CreateViewContact (
+ view::PageObject* pPageObject,
+ const model::SharedPageDescriptor& rpDescriptor) const;
+
+ virtual ::sdr::contact::ViewObjectContact* CreateViewObjectContact (
+ ::sdr::contact::ObjectContact& rObjectContact,
+ ::sdr::contact::ViewContact& rViewContact) const;
+
+private:
+ ::boost::shared_ptr<cache::PageCache> mpPageCache;
+ ::boost::shared_ptr<controller::Properties> mpProperties;
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
new file mode 100644
index 000000000000..11594a03a493
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_SELECTOR_HXX
+#define SD_SLIDESORTER_PAGE_SELECTOR_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <vector>
+#include <memory>
+
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+
+
+/** A sub-controller that handles page selection of the slide browser.
+ Selecting a page does not make it the current page (of the main view)
+ automatically as this would not be desired in a multi selection. This
+ has to be done explicitly by calling the
+ CurrentSlideManager::SetCurrentSlide() method.
+
+ Indices of pages relate allways to the number of all pages in the model
+ (as returned by GetPageCount()) not just the selected pages.
+*/
+class PageSelector
+{
+public:
+ PageSelector (SlideSorter& rSlideSorter);
+
+ void SelectAllPages (void);
+ void DeselectAllPages (void);
+ /** Update the selection state of all page descriptors to be the same as
+ that of the pages of the SdDrawDocument they describe and issue
+ redraw requests where necessary.
+ */
+ void UpdateAllPages (void);
+
+ void SelectPage (int nPageIndex);
+ /** Select the descriptor that is associated with the given page.
+ */
+ void SelectPage (const SdPage* pPage);
+ void SelectPage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Return whether the specified page is selected. This convenience
+ method is a subsitute for
+ SlideSorterModel::GetPageDescriptor(i)->IsSelected() is included
+ here to make this class more self contained.
+ */
+ bool IsPageSelected (int nPageIndex);
+
+ /** Deselect the descriptor that is associated with the given page.
+ */
+ void DeselectPage (int nPageIndex);
+ void DeselectPage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** This convenience method returns the same number of pages that
+ SlideSorterModel.GetPageCount() returns. It is included here so
+ that it is self contained for iterating over all pages to select or
+ deselect them.
+ */
+ int GetPageCount (void) const;
+ int GetSelectedPageCount (void) const;
+
+ void PrepareModelChange (void);
+ void HandleModelChange (void);
+
+ /** Enable the broadcasting of selection change events. This calls the
+ SlideSorterController::SelectionHasChanged() method to do the actual
+ work. When EnableBroadcasting has been called as many times as
+ DisableBroadcasting() was called before and the selection has been
+ changed in the mean time, this change will be broadcasted.
+ */
+ void EnableBroadcasting (bool bMakeSelectionVisible = true);
+
+ /** Disable the broadcasting o selectio change events. Subsequent
+ changes of the selection will set a flag that triggers the sending
+ of events when EnableBroadcasting() is called.
+ */
+ void DisableBroadcasting (void);
+
+ /** Return the descriptor of the most recently selected page. This
+ works only when the page has not been de-selected in the mean time.
+ This method helps the view when it scrolls the selection into the
+ visible area.
+ @return
+ When the selection is empty or when the most recently selected
+ page has been deselected already (but other pages are still
+ selected) then NULL is returned, even when a selection did exist
+ but has been cleared.
+ */
+ model::SharedPageDescriptor GetMostRecentlySelectedPage (void) const;
+
+ /** Return the anchor for a range selection. This usually is the first
+ selected page after all pages have been deselected.
+ @return
+ The returned anchor may be NULL.
+ */
+ model::SharedPageDescriptor GetSelectionAnchor (void) const;
+
+
+ typedef ::std::vector<SdPage*> PageSelection;
+
+ /** Return an object that describes the current selection. The caller
+ can use that object to later restore the selection.
+ @return
+ The object returned describes the selection via indices. So
+ even if pages are exchanged a later call to SetPageSelection()
+ is valid.
+ */
+ ::boost::shared_ptr<PageSelection> GetPageSelection (void) const;
+
+ /** Restore a page selection according to the given selection object.
+ @param rSelection
+ Typically obtained by calling GetPageSelection() this object
+ is used to restore the selection. If pages were exchanged since
+ the last call to GetPageSelection() it is still valid to call
+ this method with the selection. When pages have been inserted
+ or removed the result may be unexpected.
+ */
+ void SetPageSelection (const ::boost::shared_ptr<PageSelection>& rSelection);
+
+ void UpdateCurrentPage (const model::SharedPageDescriptor& rCurrentPageDescriptor);
+
+private:
+ model::SlideSorterModel& mrModel;
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+ int mnSelectedPageCount;
+ int mnBroadcastDisableLevel;
+ bool mbSelectionChangeBroadcastPending;
+ model::SharedPageDescriptor mpMostRecentlySelectedPage;
+ /// Anchor for a range selection.
+ model::SharedPageDescriptor mpSelectionAnchor;
+ model::SharedPageDescriptor mpCurrentPage;
+
+ void CountSelectedPages (void);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
new file mode 100644
index 000000000000..905f5aeccc72
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PROPERTIES_HEADER
+#define SD_SLIDESORTER_PROPERTIES_HEADER
+
+#include <tools/color.hxx>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** An extensible set of properties used throughout the slide sorter.
+*/
+class Properties
+{
+public:
+ Properties (void);
+ ~Properties (void);
+
+ /** When this method returns <TRUE/> then the current slide is
+ highlighted in the view. The default value is <FALSE/>.
+ */
+ bool IsHighlightCurrentSlide (void) const;
+ void SetHighlightCurrentSlide (const bool bIsHighlightCurrentSlide);
+
+ /** When this method returns <TRUE/> then the selection is indicated in
+ the view (typically by drawing rectangles around the selected
+ slides.) The default value is <TRUE/>.
+ */
+ bool IsShowSelection (void) const;
+ void SetShowSelection (const bool bIsShowSelection);
+
+ /** When this method returns <TRUE/> then the focusdselection is indicated in
+ the view (typically by drawing dotted rectangles around the selected
+ slides.) The default value is <TRUE/>.
+ */
+ bool IsShowFocus (void) const;
+ void SetShowFocus (const bool bIsShowFocus);
+
+ /** When this method returns <TRUE/> then on a selection change the
+ visible area is adapted so that the selected slides are shown
+ centered in the view. This can be used to center the current slide
+ by selecting only the current slide. The default value is <FALSE/>.
+ */
+ bool IsCenterSelection (void) const;
+ void SetCenterSelection (const bool bIsCenterSelection);
+
+ /** When this mehod returns <TRUE/> then the view may try to change the
+ visible area by scrolling it smoothly on the screen. Experimental.
+ Default value is <FALSE/>.
+ */
+ bool IsSmoothSelectionScrolling (void) const;
+ void SetSmoothSelectionScrolling (const bool bIsSmoothSelectionScrolling);
+
+ /** When this method returns <TRUE/> then during a full screen
+ presentation the previews in a slide sorter are not updated.
+ Default value is <TRUE/>.
+ */
+ bool IsSuspendPreviewUpdatesDuringFullScreenPresentation (void) const;
+ void SetSuspendPreviewUpdatesDuringFullScreenPresentation (const bool bFlag);
+
+ /** Return the background color.
+ */
+ Color GetBackgroundColor (void) const;
+ void SetBackgroundColor (const Color& rColor);
+
+ /** Return the text color.
+ */
+ Color GetTextColor (void) const;
+ void SetTextColor (const Color& rColor);
+
+ /** Return the color in which selections are to be painted.
+ */
+ Color GetSelectionColor (void) const;
+ void SetSelectionColor (const Color& rColor);
+
+ /** Return the color used for highlighting e.g. the current slide.
+ */
+ Color GetHighlightColor (void) const;
+ void SetHighlightColor (const Color& rColor);
+
+ /** The UI can be set to be read only indepently from the model status.
+ Used for instance in the presenter view.
+ */
+ bool IsUIReadOnly (void) const;
+ void SetUIReadOnly (const bool bIsUIReadOnly);
+
+private:
+ bool mbIsHighlightCurrentSlide;
+ bool mbIsShowSelection;
+ bool mbIsShowFocus;
+ bool mbIsCenterSelection;
+ bool mbIsSmoothSelectionScrolling;
+ bool mbIsSuspendPreviewUpdatesDuringFullScreenPresentation;
+ Color maBackgroundColor;
+ Color maTextColor;
+ Color maSelectionColor;
+ Color maHighlightColor;
+ bool mbIsUIReadOnly;
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx
new file mode 100644
index 000000000000..d3c25c81025e
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_SCROLL_BAR_MANAGER_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_SCROLL_BAR_MANAGER_HXX
+
+#include <tools/link.hxx>
+#include <tools/gen.hxx>
+#include <vcl/timer.hxx>
+#include <boost/shared_ptr.hpp>
+
+class Point;
+class Rectangle;
+class ScrollBar;
+class ScrollBarBox;
+class Window;
+
+namespace sd {
+class Window;
+}
+
+namespace sd { namespace slidesorter {
+ class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Manage the horizontal and vertical scroll bars. Listen for events, set
+ their sizes, place them in the window, determine their visibilities.
+
+ <p>Handle auto scrolling, i.e. the scrolling of the window when the
+ mouse comes near the window border while dragging a selection.</p>
+
+ <p>In order to make the slide sorter be used in the task pane with its
+ own vertical scrollbars the vertical scrollbar of the use of the slide
+ sorter is optional. When using it the available area in a window is
+ used and the vertical scrollbar is displayed when that area is not large
+ enough. When the vertical scrollbar is not used then the available area
+ is assumed to be modifiable. In that case the PlaceScrollBars() method
+ may return an area larger than the one given.<p>
+*/
+class ScrollBarManager
+{
+public:
+ /** Create a new scroll bar manager that manages three controls: the
+ horizontal scroll bar, the vertical scroll bar, and the little
+ window that fills the gap at the bottom right corner that is left
+ between the two scroll bars. Call LateInitialization() after
+ constructing a new object.
+ */
+ ScrollBarManager (SlideSorter& rSlideSorter);
+
+ ~ScrollBarManager (void);
+
+ /** Call this method after constructing a new object of this class.
+ */
+ void LateInitialization (void);
+
+ /** Register listeners at the scroll bars. This method is called after
+ startup of a new slide sorter object or after a reactivation of a
+ slide sorter that for example is taken from a cache.
+ */
+ void Connect (void);
+
+ /** Remove listeners from the scroll bars. This method is called whent
+ the slide sorter is destroyed or when it is suspended, e.g. put
+ into a cache for later reuse.
+ */
+ void Disconnect (void);
+
+ /** Set up the scroll bar, i.e. thumb size and position. Call this
+ method when the content of the browser window changed, i.e. pages
+ were inserted or deleted, the layout or the zoom factor has
+ changed.
+ @param bResetThumbPosition
+ When <TRUE/> then set the thumb position to position 0. This is
+ done when e.g. switching between master page mode and draw mode.
+ @param bScrollToCurrentPosition
+ When <TRUE/> then scroll the window to the new offset that is
+ defined by the scroll bars. Otherwise the new offset is simply
+ set and the whole window is repainted.
+ */
+ void UpdateScrollBars (
+ bool bResetThumbPosition = false,
+ bool bScrollToCurrentPosition = true);
+
+ /** Place the scroll bars inside the given area. When the available
+ area is not large enough for the content to display the resulting
+ behaviour depends on the mbUseVerticalScrollBar flag. When it is
+ set to true then a vertical scroll bar is shown. Otherwise the
+ height of the returned area is enlarged so that the content fits
+ into it.
+ @param rAvailableArea
+ The scroll bars will be placed inside this rectangle. It is
+ expected to be given in pixel relative to its parent.
+ @return
+ Returns the space that remains after the scroll bars are
+ placed. When the mbUseVerticalScrollBar flag is false then the
+ returned rectangle may be larger than the given one.
+ */
+ Rectangle PlaceScrollBars (const Rectangle& rAvailableArea);
+
+ /** Update the vertical scroll bar so that the visible area has the
+ given top value.
+ */
+ void SetTop (const sal_Int32 nTop);
+
+ /** Update the horizontal scroll bar so that the visible area has the
+ given left value.
+ */
+ void SetLeft (const sal_Int32 nLeft);
+
+ /** Return the width of the vertical scroll bar, which--when
+ shown--should be fixed in contrast to its height.
+ @return
+ Returns 0 when the vertical scroll bar is not shown or does not
+ exist, otherwise its width in pixel is returned.
+ */
+ int GetVerticalScrollBarWidth (void) const;
+
+ /** Return the height of the horizontal scroll bar, which--when
+ shown--should be fixed in contrast to its width.
+ @return
+ Returns 0 when the vertical scroll bar is not shown or does not
+ exist, otherwise its height in pixel is returned.
+ */
+ int GetHorizontalScrollBarHeight (void) const;
+
+ /** Call this method to scroll a window while the mouse is in dragging a
+ selection. If the mouse is near the window border or is outside the
+ window then scroll the window accordingly.
+ @return
+ When the window is scrolled then this method returns <TRUE/>.
+ When the window is not changed then <FALSE/> is returned.
+ */
+ bool AutoScroll (const Point& rMouseWindowPosition);
+
+ void StopAutoScroll (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** The horizontal scroll bar. Note that is used but not owned by
+ objects of this class. It is given to the constructor.
+ */
+ ::boost::shared_ptr<ScrollBar> mpHorizontalScrollBar;
+
+ /** The vertical scroll bar. Note that is used but not owned by
+ objects of this class. It is given to the constructor.
+ */
+ ::boost::shared_ptr<ScrollBar> mpVerticalScrollBar;
+
+ /// Relative horizontal position of the visible area in the view.
+ double mnHorizontalPosition;
+ /// Relative vertical position of the visible area in the view.
+ double mnVerticalPosition;
+ /** The width and height of the border at the inside of the window which
+ when entered while in drag mode leads to a scrolling of the window.
+ */
+ Size maScrollBorder;
+ double mnHorizontalScrollFactor;
+ double mnVerticalScrollFactor;
+ /** The only task of this little window is to paint the little square at
+ the bottom right corner left by the two scroll bars (when both are
+ visible).
+ */
+ ::boost::shared_ptr<ScrollBarBox> mpScrollBarFiller;
+
+ /** The auto scroll timer is used for keep scrolling the window when the
+ mouse reaches its border while dragging a selection. When the mouse
+ is not moved the timer issues events to keep scrolling.
+ */
+ Timer maAutoScrollTimer;
+ Size maAutoScrollOffset;
+
+ /** The content window is the one whose view port is controlled by the
+ scroll bars.
+ */
+ ::boost::shared_ptr<sd::Window> mpContentWindow;
+
+ void SetWindowOrigin (
+ double nHorizontalPosition,
+ double nVerticalPosition);
+
+ /** Determine the visibility of the scroll bars so that the window
+ content is not clipped in any dimension without showing a scroll
+ bar.
+ @param rAvailableArea
+ The area in which the scroll bars, the scroll bar filler, and
+ the SlideSorterView will be placed.
+ @return
+ The area that is enclosed by the scroll bars is returned. It
+ will be filled with the SlideSorterView.
+ */
+ Rectangle DetermineScrollBarVisibilities (const Rectangle& rAvailableArea);
+
+ /** Typically called by DetermineScrollBarVisibilities() this method
+ tests a specific configuration of the two scroll bars being visible
+ or hidden.
+ @return
+ When the window content can be shown with only being clipped in
+ an orientation where the scroll bar would be shown then <TRUE/>
+ is returned.
+ */
+ bool TestScrollBarVisibilities (
+ bool bHorizontalScrollBarVisible,
+ bool bVerticalScrollBarVisible,
+ const Rectangle& rAvailableArea);
+
+ void CalcAutoScrollOffset (const Point& rMouseWindowPosition);
+ bool RepeatAutoScroll (void);
+
+ DECL_LINK(HorizontalScrollBarHandler, ScrollBar*);
+ DECL_LINK(VerticalScrollBarHandler, ScrollBar*);
+ DECL_LINK(AutoScrollTimeoutHandler, Timer*);
+
+ void PlaceHorizontalScrollBar (const Rectangle& aArea);
+ void PlaceVerticalScrollBar (const Rectangle& aArea);
+ void PlaceFiller (const Rectangle& aArea);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx
new file mode 100644
index 000000000000..f69f6e1fefa2
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SELECTION_FUNCTION_HXX
+#define SD_SLIDESORTER_SELECTION_FUNCTION_HXX
+
+#include "controller/SlsSlideFunction.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <tools/list.hxx>
+#include <memory>
+
+class SdSlideViewShell;
+class SdWindow;
+class SdSlideView;
+class SdDrawDocument;
+class Sound;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+
+class SelectionFunction
+ : public SlideFunction
+{
+public:
+ TYPEINFO();
+
+ static FunctionReference Create( SlideSorter& rSlideSorter, SfxRequest& rRequest );
+
+ // Mouse- & Key-Events
+ virtual BOOL KeyInput(const KeyEvent& rKEvt);
+ virtual BOOL MouseMove(const MouseEvent& rMEvt);
+ virtual BOOL MouseButtonUp(const MouseEvent& rMEvt);
+ virtual BOOL MouseButtonDown(const MouseEvent& rMEvt);
+ virtual void Paint(const Rectangle&, ::sd::Window* );
+
+ virtual void Activate(); // Function aktivieren
+ virtual void Deactivate(); // Function deaktivieren
+
+ virtual void ScrollStart();
+ virtual void ScrollEnd();
+
+ /// Forward to the clipboard manager.
+ virtual void DoCut (void);
+
+ /// Forward to the clipboard manager.
+ virtual void DoCopy (void);
+
+ /// Forward to the clipboard manager.
+ virtual void DoPaste (void);
+
+ /** is called when the current function should be aborted. <p>
+ This is used when a function gets a KEY_ESCAPE but can also
+ be called directly.
+
+ @returns
+ true if a active function was aborted
+ */
+ virtual bool cancel();
+
+protected:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ SelectionFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest);
+
+ virtual ~SelectionFunction();
+
+private:
+ class SubstitutionHandler;
+ class EventDescriptor;
+
+ /// Set in MouseButtonDown this flag indicates that a page has been hit.
+ bool mbPageHit;
+
+ /// The rectangle of the mouse drag selection.
+ Rectangle maDragSelectionRectangle;
+ bool mbDragSelection;
+
+ /// Box of the insert marker in model coordinates.
+ Rectangle maInsertionMarkerBox;
+
+ /** We use this flag to filter out the cases where MouseMotion() is called
+ with a pressed mouse button but without a prior MouseButtonDown()
+ call. This is an indication that the mouse button was pressed over
+ another control, e.g. the view tab bar, and that a re-layout of the
+ controls moved the slide sorter under the mouse.
+ */
+ bool mbProcessingMouseButtonDown;
+
+ ::std::auto_ptr<SubstitutionHandler> mpSubstitutionHandler;
+
+ DECL_LINK( DragSlideHdl, Timer* );
+ void StartDrag (void);
+
+ /** Set the selection to exactly the specified page and also set it as
+ the current page.
+ */
+ void SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** When the view on which this selection function is working is the
+ main view then the view is switched to the regular editing view.
+ */
+ void SwitchView (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Make the slide nOffset slides away of the current one the new
+ current slide. When the new index is outside the range of valid
+ page numbers it is clipped to that range.
+ @param nOffset
+ When nOffset is negative then go back. When nOffset if positive go
+ forward. When it is zero then ignore the call.
+ */
+ void GotoNextPage (int nOffset);
+
+ void ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent);
+ void ProcessKeyEvent (const KeyEvent& rEvent);
+
+ // What follows are a couple of helper methods that are used by
+ // ProcessMouseEvent().
+
+ /// Select the specified page and set the selection anchor.
+ void SelectHitPage (const model::SharedPageDescriptor& rpDescriptor);
+ /// Deselect the specified page.
+ void DeselectHitPage (const model::SharedPageDescriptor& rpDescriptor);
+ /// Deselect all pages.
+ void DeselectAllPages (void);
+
+ /** for a possibly following mouse motion by starting the drag timer
+ that after a short time of pressed but un-moved mouse starts a drag
+ operation.
+ */
+ void PrepareMouseMotion (const Point& aMouseModelPosition);
+
+ /** Select all pages between and including the selection anchor and the
+ specified page.
+ */
+ void RangeSelect (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Start a rectangle selection at the given position.
+ */
+ void StartRectangleSelection (const Point& aMouseModelPosition);
+
+ /** Update the rectangle selection so that the given position becomes
+ the new second point of the selection rectangle.
+ */
+ void UpdateRectangleSelection (const Point& aMouseModelPosition);
+
+ /** Select all pages that lie completly in the selection rectangle.
+ */
+ void ProcessRectangleSelection (bool bToggleSelection);
+
+ /** Compute a numerical code that describes a mouse event and that can
+ be used for fast look up of the appropriate reaction.
+ */
+ sal_uInt32 EncodeMouseEvent (
+ const EventDescriptor& rDescriptor,
+ const MouseEvent& rEvent) const;
+
+ /** Compute a numerical code that describes a key event and that can
+ be used for fast look up of the appropriate reaction.
+ */
+ sal_uInt32 EncodeKeyEvent (
+ const EventDescriptor& rDescriptor,
+ const KeyEvent& rEvent) const;
+
+ void EventPreprocessing (const EventDescriptor& rEvent);
+ bool EventProcessing (const EventDescriptor& rEvent);
+ void EventPostprocessing (const EventDescriptor& rEvent);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx
new file mode 100644
index 000000000000..70cfc409214b
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CONTROLLER_SELECTION_MANAGER_HXX
+#define SD_SLIDESORTER_CONTROLLER_SELECTION_MANAGER_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <sal/types.h>
+#include <tools/gen.hxx>
+#include <vector>
+
+class Link;
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+
+/** This class is a part of the controller and handles the selection of
+ slides.
+ <p>It has methods to modify the selected slides (delete them or
+ move them to other places in the document), change the visible area so
+ to make the selected slides visble, tell listeners when the selection
+ changes.</p>
+*/
+class SelectionManager
+{
+public:
+ /** Create a new SelectionManger for the given slide sorter.
+ */
+ SelectionManager (SlideSorter& rSlideSorter);
+
+ ~SelectionManager (void);
+
+ /** Delete the currently selected slides. When this method returns the
+ selection is empty.
+ */
+ void DeleteSelectedPages (void);
+
+ /** Move the maked pages to a position directly after the specified page.
+ */
+ bool MoveSelectedPages (const sal_Int32 nTargetPage);
+
+ /** Call this method after the selection has changed (possible several
+ calls to the PageSelector) to invalidate the relevant slots and send
+ appropriate events.
+ */
+ void SelectionHasChanged (const bool bMakeSelectionVisible = true);
+
+ /** Return <TRUE/> when the selection has changed but has not yet been
+ moved to the visible area of the slide sorter view.
+ */
+ bool IsMakeSelectionVisiblePending (void) const;
+
+ enum SelectionHint { SH_FIRST, SH_LAST, SH_RECENT };
+
+ /** Try to make all currently selected page objects visible, i.e. set
+ the origin so that the page objects lie inside the visible area.
+ When the selection is empty then the visible area is not modified.
+
+ <p>This method, and the ones is calls, look into the Properties
+ object of the SlideSorter in order to determine whether the current
+ selection is to be displayed centered.</p>
+ @param eSelectionHint
+ This is an advice on which selected page object to handle with
+ the highest priority when the whole selection does not fit into
+ the visible area.
+ @return
+ Returns the vertical translation of the visible area. It is 0
+ when no update of the visible area was done.
+ */
+ Size MakeSelectionVisible (
+ const SelectionHint eSelectionHint = SH_RECENT);
+
+ /** Modify the origin of the visible area so that the given rectangle
+ comes into view. This is done with the smallest change: no
+ scrolling takes place when the given rectangle already lies in the
+ visible area. Otherwise either the top or the bottom of the given
+ rectangle is aligned with the top or the bottom of the visible area.
+ @return
+ Returns the vertical translation of the visible area. It is 0
+ when no update of the visible area was done.
+ */
+ Size MakeRectangleVisible (const Rectangle& rBox);
+
+ /** Add a listener that is called when the selection of the slide sorter
+ changes.
+ @param rListener
+ When this method is called multiple times for the same listener
+ the second and all following calls are ignored. Each listener
+ is added only once.
+ */
+ void AddSelectionChangeListener (const Link& rListener);
+
+ /** Remove a listener that was called when the selection of the slide
+ sorter changes.
+ @param rListener
+ It is save to pass a listener that was not added are has been
+ removed previously. Such calls are ignored.
+ */
+ void RemoveSelectionChangeListener (const Link& rListener);
+
+ /** Return the position where to insert pasted slides based on the
+ current selection. When there is a selection then the insert
+ position is behind the last slide. When the selection is empty then
+ most of the time the insert position is at the end of the document.
+ There is an exception right after the display of a popup-menu. The
+ position of the associated insertion marker is stored here and reset
+ the next time the selection changes.
+ */
+ sal_Int32 GetInsertionPosition (void) const;
+
+ /** Store an insertion position temporarily. It is reset when the
+ selection changes the next time.
+ */
+ void SetInsertionPosition (const sal_Int32 nInsertionPosition);
+
+private:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ ::std::vector<Link> maSelectionChangeListeners;
+
+ /** This array stores the indices of the selected page descriptors at
+ the time when the edit mode is switched to EM_MASTERPAGE. With this
+ we can restore the selection when switching back to EM_PAGE mode.
+ */
+ ::std::vector<SdPage*> maSelectionBeforeSwitch;
+
+ /** When this flag is set then on the next call to Paint() the selection
+ is moved into the visible area.
+ */
+ bool mbIsMakeSelectionVisiblePending;
+
+ /** The insertion position is only temporarily valid. Negative values
+ indicate that the explicit insertion position is not valid. In this
+ case GetInsertionPosition() calculates it from the current selection.
+ */
+ sal_Int32 mnInsertionPosition;
+
+ /** Delete the given list of normal pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedNormalPages
+ A list of normal pages. Supplying master pages is an error.
+ */
+ void DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedNormalPages);
+
+ /** Delete the given list of master pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedMasterPages
+ A list of master pages. Supplying normal pages is an error.
+ */
+ void DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedMasterPages);
+
+ /** Return <TRUE/> when the given rectangle, that typically is the
+ bounding box of all currently selected slides, does not fit entirely
+ into the visible area of the slide sorter view.
+ */
+ bool DoesSelectionExceedVisibleArea (const Rectangle& rSelectionBox) const;
+
+ /** When not all currently selected slides fit into the visible area of
+ the slide sorter view, and thus DoesSelectionExceedVisibleArea()
+ would return <TRUE/>, then it is the task of this method to
+ determine which part of the selection to move into the visible area.
+ @param rpFirst
+ The first selected slide. Must not be an empty pointer.
+ @param rpLast
+ The last selected slide. Must not be an empty pointer.
+ @param eSelectionHint
+ This hint tells the method on which slide to concentrate,
+ i.e. which slide has to be inside the returned visible area.
+ @return
+ Returns the new visible area.
+ */
+ Rectangle ResolveLargeSelection (
+ const model::SharedPageDescriptor& rpFirst,
+ const model::SharedPageDescriptor& rpLast,
+ const SelectionHint eSelectionHint);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSlideFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSlideFunction.hxx
new file mode 100644
index 000000000000..3a1b46675673
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSlideFunction.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_FUNCTION_HXX
+#define SD_SLIDESORTER_SLIDE_FUNCTION_HXX
+
+#include "fupoor.hxx"
+
+class SdDrawDocument;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+
+
+/** Base class for functions of the slide sorter.
+*/
+class SlideFunction
+ : public FuPoor
+{
+public:
+ TYPEINFO();
+
+ virtual BOOL MouseMove (const MouseEvent& rMEvt);
+ virtual BOOL MouseButtonUp (const MouseEvent& rMEvt);
+ virtual BOOL MouseButtonDown (const MouseEvent& rMEvt);
+
+ /** Called from ForceScroll() before the actual scrolling.
+ */
+ virtual void ScrollStart (void);
+
+ /** Called from ForceScroll() after the actual scrolling.
+ */
+ virtual void ScrollEnd (void);
+
+protected:
+ SlideFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx
new file mode 100644
index 000000000000..d56fc1b44388
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SD_SLIDESORTER_SLOT_MANAGER_HXX
+#define SD_SLIDESORTER_SLOT_MANAGER_HXX
+
+#include <tools/link.hxx>
+#include <memory>
+#include <queue>
+
+class AbstractSvxNameDialog;
+class SfxItemSet;
+class SfxRequest;
+class String;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class Command;
+
+/** This manager takes over the work of handling slot calls from the
+ controller of the slide sorter.
+*/
+class SlotManager
+{
+public:
+ /** Create a new slot manager that handles slot calls for the controller
+ of a slide sorter.
+ @param rController
+ The controller for which to handle the slot calls.
+ */
+ SlotManager (SlideSorter& rSlideSorter);
+
+ ~SlotManager (void);
+
+ void FuTemporary (SfxRequest& rRequest);
+ void FuPermanent (SfxRequest& rRequest);
+ void FuSupport (SfxRequest& rRequest);
+ void GetMenuState (SfxItemSet &rSet);
+ void GetClipboardState (SfxItemSet &rSet);
+ void GetStatusBarState (SfxItemSet& rSet);
+ void ExecCtrl (SfxRequest& rRequest);
+ void GetAttrState (SfxItemSet& rSet);
+
+ void ExecuteCommandAsynchronously (::std::auto_ptr<Command> pCommand);
+
+private:
+ /// The controller for which we manage the slot calls.
+ SlideSorter& mrSlideSorter;
+
+ typedef ::std::queue<Command*> CommandQueue;
+ CommandQueue maCommandQueue;
+
+ /** Called by FuTemporary to show the slide show.
+ */
+ void ShowSlideShow (SfxRequest& rRequest);
+
+ /** The implementation is a copy of the code for SID_RENAMEPAGE in
+ drviews2.cxx.
+ */
+ void RenameSlide (void);
+ DECL_LINK(RenameSlideHdl, AbstractSvxNameDialog*);
+ bool RenameSlideFromDrawViewShell( USHORT nPageId, const String& rName);
+
+ /** Handle SID_INSERTPAGE slot calls.
+ */
+ void InsertSlide (SfxRequest& rRequest);
+
+ DECL_LINK(UserEventCallback, void*);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx
new file mode 100644
index 000000000000..9cb743ffc174
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_MODEL_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_MODEL_HXX
+
+class SdDrawDocument;
+
+#include "model/SlsPageEnumeration.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include "pres.hxx"
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <osl/mutex.hxx>
+
+#include <memory>
+#include <vector>
+#include <functional>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+class PageObjectFactory;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+
+class DocumentPageContainer;
+
+/** The model of the slide sorter gives access to the slides that are to be
+ displayed in the slide sorter view. Via the SetDocumentSlides() method
+ this set of slides can be modified (but do not call it directly, use
+ SlideSorterController::SetDocumentSlides() instead.)
+*/
+class SlideSorterModel
+{
+public:
+ SlideSorterModel (SlideSorter& rSlideSorter);
+
+ virtual ~SlideSorterModel (void);
+
+ /** This method is present to let the view create a ShowView for
+ displaying slides.
+ */
+ SdDrawDocument* GetDocument (void);
+
+ /** Set a new edit mode and return whether the edit mode really
+ has been changed. When the edit mode is changed then the
+ previous page descriptor list is replaced by a new one which
+ has to be repainted.
+ @return
+ A return value of <TRUE/> indicates that the edit mode has
+ changed and thus the page descriptor list has been set up
+ to reflect that change. A repaint is necessary.
+ */
+ bool SetEditMode (EditMode eEditMode);
+
+ EditMode GetEditMode (void) const;
+ PageKind GetPageType (void) const;
+
+ /** Return the number of slides in the document regardless of whether
+ they are visible or not or whether they are hidden or not.
+ The number of slides depends on the set of slides available through
+ the XIndexAccess given to SetDocumentSlides().
+ */
+ sal_Int32 GetPageCount (void) const;
+
+ /** Return a page descriptor for the page with the specified index.
+ Page descriptors are created on demand. The page descriptor is
+ found (or not found) in constant time.
+ @param nPageIndex
+ The index of the requested slide. The valid values
+ are 0 to GetPageCount()-1.
+ @param bCreate
+ When <TRUE/> and the requested page descriptor is missing then
+ it is created. When <FALSE/> then an empty reference is
+ returned for missing descriptors.
+ @return
+ When the given index is not valid, i.e. lower then zero or
+ larger than or equal to the number of pages then an empty
+ reference is returned. Note that the page count may change
+ between calls to GetPageCount() and GetPageDescriptor().
+ */
+ SharedPageDescriptor GetPageDescriptor (
+ const sal_Int32 nPageIndex,
+ const bool bCreate = true) const;
+
+ /** Return a page descriptor for the given XDrawPage. Page descriptors
+ are created on demand. The page descriptor is found (or not found)
+ in (at most) linear time. Note that all page descriptors in front of
+ the one associated with the given XDrawPage are created when not yet
+ present. When the XDrawPage is not found then all descriptors are
+ created.
+ @return
+ Returns the index to the requested page descriptor or -1 when
+ there is no such page descriptor.
+ */
+ sal_Int32 GetIndex (
+ const ::com::sun::star::uno::Reference<com::sun::star::drawing::XDrawPage>& rxSlide) const;
+
+ /** Call this method after the document has changed its structure. This
+ will get the model in sync with the SdDrawDocument. This method
+ tries not to throw away to much information already gathered. This
+ is especially important for previews of complex pages that take some
+ time to create.
+ */
+ void Resync (void);
+
+ /** Delete all descriptors that currently are in the container. The size
+ of the container, however, is not altered. Use the AdaptSize
+ method for that.
+ */
+ void ClearDescriptorList (void);
+
+ /** Set the selection of the document to exactly that of the called model.
+ */
+ void SynchronizeDocumentSelection (void);
+
+ /** Replace the factory for the creation of the page objects and
+ contacts with the given object. The old factory is destroyed.
+ */
+ void SetPageObjectFactory(
+ ::std::auto_ptr<controller::PageObjectFactory> pPageObjectFactory);
+
+ /** Return the page object factory. It none has been set so far or it
+ has been reset, then a new one is created.
+ */
+ const controller::PageObjectFactory& GetPageObjectFactory (void) const;
+
+ /** Return the mutex so that the caller can lock it and then safely
+ access the model.
+ */
+ ::osl::Mutex& GetMutex (void);
+
+ /** Set the XIndexAccess from which the called SlideSorterModel takes
+ its pages.
+ @param rxSlides
+ The set of slides accessible through this XIndexAccess are not
+ necessarily the same as the ones of the XModel of the
+ XController (although it typically is a subset).
+ */
+ void SetDocumentSlides (const css::uno::Reference<css::container::XIndexAccess>& rxSlides);
+
+ /** Return the set of pages that is currently displayed by the slide sorter.
+ */
+ css::uno::Reference<css::container::XIndexAccess> GetDocumentSlides (void) const;
+
+ /** This method is called when the edit mode has changed. It calls
+ SetDocumentSlides() with the set of slides or master pages obtained
+ from the model of the XController.
+ */
+ void UpdatePageList (void);
+
+private:
+ mutable ::osl::Mutex maMutex;
+ SlideSorter& mrSlideSorter;
+ ::com::sun::star::uno::Reference<com::sun::star::container::XIndexAccess> mxSlides;
+ PageKind mePageKind;
+ EditMode meEditMode;
+ typedef ::std::vector<SharedPageDescriptor> DescriptorContainer;
+ mutable DescriptorContainer maPageDescriptors;
+ mutable ::std::auto_ptr<controller::PageObjectFactory> mpPageObjectFactory;
+
+ /** Resize the descriptor container according to current values of
+ page kind and edit mode.
+ */
+ void AdaptSize (void);
+
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx b/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx
new file mode 100644
index 000000000000..ff3e45018957
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_ENUMERATION_HXX
+#define SD_SLIDESORTER_ENUMERATION_HXX
+
+#include <memory>
+
+namespace sd { namespace slidesorter { namespace model {
+
+
+/** Interface to generic enumerations. Designed to operate on shared
+ pointers. Therefore GetNextElement() returns T and not T&.
+*/
+template <class T>
+class Enumeration
+{
+public:
+ virtual bool HasMoreElements (void) const = 0;
+ /** Returns T instead of T& so that it can handle shared pointers.
+ */
+ virtual T GetNextElement (void) = 0;
+ virtual void Rewind (void) = 0;
+ virtual ::std::auto_ptr<Enumeration<T> > Clone (void) = 0;
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx
new file mode 100644
index 000000000000..892b3b8171d3
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX
+#define SD_SLIDESORTER_PAGE_DESCRIPTOR_HXX
+
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <tools/gen.hxx>
+#include <tools/link.hxx>
+#include <vcl/bitmap.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <memory>
+#include <boost/enable_shared_from_this.hpp>
+
+class SdPage;
+
+namespace sdr { namespace contact {
+class ObjectContact;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+class PageObject;
+class PageObjectViewObjectContact;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+class PageObjectFactory;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+
+class SlideRenderer;
+
+namespace css = ::com::sun::star;
+
+/** Each PageDescriptor object represents the preview of one draw page,
+ slide, or master page of a Draw or Impress document as they are displayed
+ in the slide sorter. This class gives access to some associated
+ information like prerendered preview or position on the screen.
+
+ <p>Bounding boxes of page objects come in four varieties:
+ Model and screen/pixel coordinates and the bounding boxes of the actual
+ page objects and the larger bounding boxes that include page names and
+ fade symbol.</p>
+*/
+class PageDescriptor
+ : public ::boost::enable_shared_from_this<PageDescriptor>
+{
+public:
+ /** Create a PageDescriptor for the given SdPage object.
+ @param rxPage
+ The page that is represented by the new PageDescriptor object.
+ @param pPage
+ The page pointer can in some situations not be detected from
+ rxPage, e.g. after undo of page deletion. Therefore supply it
+ seperately.
+ @param nIndex
+ This index is displayed in the view as page number. It is not
+ necessaryily the page index (not even when you add or subtract 1
+ or use (x-1)/2 magic).
+ */
+ PageDescriptor (
+ const css::uno::Reference<css::drawing::XDrawPage>& rxPage,
+ SdPage* pPage,
+ const sal_Int32 nIndex,
+ const controller::PageObjectFactory& rPageObjectFactory);
+
+ ~PageDescriptor (void);
+
+ /** Return the page that is represented by the descriptor as SdPage pointer .
+ */
+ SdPage* GetPage (void) const;
+
+ /** Return the page that is represented by the descriptor as XDrawPage reference.
+ */
+ css::uno::Reference<css::drawing::XDrawPage> GetXDrawPage (void) const;
+
+ /** Return the page shape that is used for visualizing the page.
+ */
+ view::PageObject* GetPageObject (void);
+ void ReleasePageObject (void);
+
+ /** Return <TRUE/> when the page object is fully or parially visible. */
+ bool IsVisible (void) const;
+
+ /** Set the visible state that is returned by the IsVisible() method.
+ This method is typically called by the view who renders the object
+ onto the screen.
+ */
+ void SetVisible (bool bVisible);
+
+ /** Make sure that the page is selected and return whether the
+ selection state changed.
+ */
+ bool Select (void);
+ /** Make sure that the page is not selected and return whether the
+ selection state changed.
+ */
+ bool Deselect (void);
+
+ /** Return whether the page is selected (and thus bypasses the internal
+ mbIsSelected flag.
+ */
+ bool IsSelected (void) const;
+
+ /** Set the internal mbIsSelected flag to the selection state of the
+ page. Use this method to synchronize a page descriptor with the
+ page it describes and determine whether a redraw to update the
+ selection indicator is necessary.
+ @return
+ When the two selection states were different <TRUE/> is
+ returned. When they were the same this method returns
+ <FALSE/>.
+ */
+ bool UpdateSelection (void);
+
+ bool IsFocused (void) const;
+ void SetFocus (void);
+ void RemoveFocus (void);
+
+ view::PageObjectViewObjectContact* GetViewObjectContact (void) const;
+
+ void SetViewObjectContact (
+ view::PageObjectViewObjectContact* pViewObjectContact);
+
+ /** Return the currently used page object factory.
+ */
+ const controller::PageObjectFactory& GetPageObjectFactory (void) const;
+
+ /** Replace the current page object factory by the given one.
+ */
+ void SetPageObjectFactory (const controller::PageObjectFactory& rFactory);
+
+ void SetModelBorder (const SvBorder& rBorder);
+ SvBorder GetModelBorder (void) const;
+
+ /** The size of the area in which the page number is displayed is
+ calculated by the SlideSorterView and then stored in the page
+ descriptors so that the contact objects can access them. The
+ contact objects can not calculate them on demand because the total
+ number of slides is needed to do that and this number is not known
+ to the contact objects.
+ */
+ void SetPageNumberAreaModelSize (const Size& rSize);
+ Size GetPageNumberAreaModelSize (void) const;
+
+ /** Set or revoke the state of this slide being the current slide.
+ */
+ void SetIsCurrentPage (const bool bIsCurrent);
+
+private:
+ SdPage* mpPage;
+ css::uno::Reference<css::drawing::XDrawPage> mxPage;
+ /** This index is displayed as page number in the view. It may or may
+ not be actual page index.
+ */
+ const sal_Int32 mnIndex;
+
+ /// The factory that is used to create PageObject objects.
+ const controller::PageObjectFactory* mpPageObjectFactory;
+
+ /** The page object will be destroyed by the page into which it has
+ been inserted.
+ */
+ view::PageObject* mpPageObject;
+
+ bool mbIsSelected;
+ bool mbIsVisible;
+ bool mbIsFocused;
+ bool mbIsCurrent;
+
+ view::PageObjectViewObjectContact* mpViewObjectContact;
+
+ /// The borders in model coordinates arround the page object.
+ SvBorder maModelBorder;
+
+ /// The size of the page number area in model coordinates.
+ Size maPageNumberAreaModelSize;
+
+ // Do not use the copy constructor operator. It is not implemented.
+ PageDescriptor (const PageDescriptor& rDescriptor);
+
+ // Do not use the assignment operator. It is not implemented
+ // (mrPage can not be assigned).
+ PageDescriptor& operator= (const PageDescriptor& rDescriptor);
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx
new file mode 100644
index 000000000000..abbd121c1d16
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_ENUMERATION_HXX
+#define SD_SLIDESORTER_PAGE_ENUMERATION_HXX
+
+#include "pres.hxx"
+
+
+#include "model/SlsEnumeration.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include <boost/function.hpp>
+#include <memory>
+
+namespace sd { namespace slidesorter { namespace model {
+
+class SlideSorterModel;
+
+
+/** Public class of page enumerations that delegates its calls to an
+ implementation object that can filter pages by using a given predicate.
+
+ @see PageEnumerationProvider
+ The PageEnumerationProvider has methods for creating different types
+ of page enumerations.
+*/
+class PageEnumeration
+ : public Enumeration<SharedPageDescriptor>
+{
+public:
+ /** Create a new page enumeration that enumerates a subset of the pages
+ of the given model.
+ @param rModel
+ The new page enumeration enumerates the pages of this model.
+ @param rPredicate
+ This predicate determines which pages to include in the
+ enumeration. Pages for which rPredicate returns <FALSE/> are
+ exclude.
+ */
+ typedef ::boost::function<bool(const SharedPageDescriptor&)> PagePredicate;
+ static PageEnumeration Create (
+ const SlideSorterModel& rModel,
+ const PagePredicate& rPredicate);
+
+ /** This copy constructor creates a copy of the given enumeration.
+ */
+ PageEnumeration (const PageEnumeration& rEnumeration);
+
+ virtual ~PageEnumeration();
+
+ /** Create a new enumeration object. The ownership of the
+ implementation object goes to the new object. Use this copy
+ constructor only when you know what you are doing. When in doubt,
+ use the one argument version.
+ @param bCloneImpl
+ When <TRUE/> is given this constructor behaves exactly like its
+ one argument version. When <FALSE/> is given then the
+ implementation object is not copied but moved from the given
+ enumeration to the newly created one. The given enumeration
+ thus becomes empty.
+ */
+ PageEnumeration (PageEnumeration& rEnumeration, bool bCloneImpl);
+
+ /** Create and return an exact copy of the called object.
+ */
+ virtual ::std::auto_ptr<Enumeration<SharedPageDescriptor> > Clone (void);
+
+ PageEnumeration& operator= (const PageEnumeration& rEnumeration);
+
+ /** Return <TRUE/> when the enumeration has more elements, i.e. it is
+ save to call GetNextElement() at least one more time.
+ */
+ virtual bool HasMoreElements (void) const;
+
+ /** Return the next element of the enumeration. Call the
+ HasMoreElements() before to make sure that there exists at least one
+ more element. Calling this method with HasMoreElements() returning
+ <FALSE/> is an error.
+ */
+ virtual SharedPageDescriptor GetNextElement (void);
+
+ /** Rewind the enumeration so that the next call to GetNextElement()
+ will return its first element.
+ */
+ virtual void Rewind (void);
+
+private:
+ /// Implementation object.
+ ::std::auto_ptr<Enumeration<SharedPageDescriptor> > mpImpl;
+
+ /** This constructor expects an implementation object that holds
+ the predicate that filters the pages.
+ */
+ PageEnumeration (::std::auto_ptr<Enumeration<SharedPageDescriptor> > pImpl);
+
+ // Default constructor not implemented.
+ PageEnumeration (void);
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx
new file mode 100644
index 000000000000..f587586e5b60
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_ENUMERATION_PROVIDER_HXX
+#define SD_SLIDESORTER_PAGE_ENUMERATION_PROVIDER_HXX
+
+#include "model/SlsPageEnumeration.hxx"
+
+namespace sd { namespace slidesorter { namespace model {
+
+class SlideSorterModel;
+
+/** Collection of methods that create enumeration of slides.
+*/
+class PageEnumerationProvider
+{
+public:
+ /** The returned enumeration of slides iterates over all slides of the
+ given model.
+ */
+ static PageEnumeration CreateAllPagesEnumeration (const SlideSorterModel& rModel);
+
+ /** The returned enumeration of slides iterates over the currently
+ selected slides of the given model.
+ */
+ static PageEnumeration CreateSelectedPagesEnumeration (const SlideSorterModel& rModel);
+
+ /** The returned enumeration of slides iterates over the slides
+ (partially) inside the visible area.
+ */
+ static PageEnumeration CreateVisiblePagesEnumeration (const SlideSorterModel& rModel);
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx b/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx
new file mode 100644
index 000000000000..746681530e9c
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SHARED_PAGE_DESCRIPTOR_HXX
+#define SD_SLIDESORTER_SHARED_PAGE_DESCRIPTOR_HXX
+
+#include <boost/shared_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace model {
+
+class PageDescriptor;
+
+typedef ::boost::shared_ptr<PageDescriptor> SharedPageDescriptor;
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx
new file mode 100644
index 000000000000..d9ccff6451f4
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx
@@ -0,0 +1,310 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_VIEW_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_VIEW_HXX
+
+#include "View.hxx"
+
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include <sfx2/viewfrm.hxx>
+#include "pres.hxx"
+#include <tools/gen.hxx>
+#include <memory>
+#include <boost/shared_ptr.hpp>
+
+class Point;
+
+namespace sdr { namespace contact {
+class ObjectContact;
+} }
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+class SlideSorterController;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+class PageCache;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class Layouter;
+class ViewOverlay;
+
+
+class SlideSorterView
+ : public View
+{
+public:
+ TYPEINFO();
+
+ /** Create a new view for the slide sorter.
+ @param rViewShell
+ This reference is simply passed to the base class and not used
+ by this class.
+
+ */
+ SlideSorterView (SlideSorter& rSlideSorter);
+
+ virtual ~SlideSorterView (void);
+
+ enum Orientation { HORIZONTAL, VERTICAL };
+ void SetOrientation (const Orientation eOrientation);
+ Orientation GetOrientation (void) const;
+
+ void RequestRepaint (void);
+ void RequestRepaint (const model::SharedPageDescriptor& rDescriptor);
+
+ Rectangle GetModelArea (void);
+
+ enum CoordinateSystem { CS_SCREEN, CS_MODEL };
+ enum BoundingBoxType { BBT_SHAPE, BBT_INFO };
+
+ /** Return the rectangle that bounds the page object represented by the
+ given page descriptor.
+ @param rDescriptor
+ The descriptor of the page for which to return the bounding box.
+ @param eCoordinateSystem
+ Specifies whether to return the screen or model coordinates.
+ @param eBoundingBoxType
+ Specifies whether to return the bounding box of only the page
+ object or the one that additionally includes other displayed
+ information like page name and fader symbol.
+ */
+ Rectangle GetPageBoundingBox (
+ const model::SharedPageDescriptor& rpDescriptor,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const;
+
+ /** Return the rectangle that bounds the page object represented by the
+ given page index .
+ @param nIndex
+ The index of the page for which to return the bounding box.
+ @param eCoordinateSystem
+ Specifies whether to return the screen or model coordinates.
+ @param eBoundingBoxType
+ Specifies whether to return the bounding box of only the page
+ object or the one that additionally includes other displayed
+ information like page name and fader symbol.
+ */
+ Rectangle GetPageBoundingBox (
+ sal_Int32 nIndex,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const;
+
+ /** Return the index of the page that is rendered at the given position.
+ @param rPosition
+ The position is expected to be in pixel coordinates.
+ @return
+ The returned index is -1 when there is no page object at the
+ given position.
+ */
+ sal_Int32 GetPageIndexAtPoint (const Point& rPosition) const;
+
+ view::Layouter& GetLayouter (void);
+
+ virtual void ModelHasChanged (void);
+
+ void LocalModelHasChanged(void);
+
+ /** This method is typically called before a model change takes place.
+ All references to model data are released. PostModelChange() has to
+ be called to complete the handling of the model change. When the
+ calls to Pre- and PostModelChange() are very close to each other you
+ may call HandleModelChange() instead.
+ */
+ void PreModelChange (void);
+
+ /** This method is typically called after a model change took place.
+ References to model data are re-allocated. Call this method only
+ after PreModelChange() has been called.
+ */
+ void PostModelChange (void);
+
+ /** This method is a convenience function that simply calls
+ PreModelChange() and then PostModelChange().
+ */
+ void HandleModelChange (void);
+
+ void HandleDrawModeChange (void);
+
+ virtual void Resize (void);
+ virtual void CompleteRedraw (OutputDevice* pDevice, const Region& rPaintArea, sdr::contact::ViewObjectContactRedirector* pRedirector = 0L);
+ virtual void InvalidateOneWin (
+ ::Window& rWindow);
+ virtual void InvalidateOneWin (
+ ::Window& rWindow,
+ const Rectangle& rPaintArea );
+
+ void Layout (void);
+ /** This tells the view that it has to re-determine the visibility of
+ the page objects before painting them the next time.
+ */
+ void InvalidatePageObjectVisibilities (void);
+
+ /** Return the window to which this view renders its output.
+ */
+ ::sd::Window* GetWindow (void) const;
+
+
+ ::boost::shared_ptr<cache::PageCache> GetPreviewCache (void);
+
+ view::ViewOverlay& GetOverlay (void);
+
+ /** Set the bounding box of the insertion marker in model coordinates.
+
+ It will be painted as a dark rectangle that fills the given box.
+ */
+ void SetInsertionMarker (const Rectangle& rBBox);
+
+ /** Specify whether the insertion marker will be painted or not.
+ */
+ void SetInsertionMarkerVisibility (bool bVisible);
+
+ /** Set the size and position of the selection rectangle.
+
+ It will be painted as a dashed rectangle.
+ */
+ void SetSelectionRectangle (const Rectangle& rBox);
+
+ /** Specify whether the selection rectangle will be painted or not.
+ */
+ void SetSelectionRectangleVisibility (bool bVisible);
+
+ typedef ::std::pair<sal_Int32,sal_Int32> PageRange;
+ /** Return the range of currently visible page objects including the
+ first and last one in that range.
+ @return
+ The returned pair of page object indices is empty when the
+ second index is lower than the first.
+ */
+ PageRange GetVisiblePageRange (void);
+
+ /** Add a shape to the page. Typically used from inside
+ PostModelChange().
+ */
+ void AddSdrObject (SdrObject& rObject);
+
+ /** Add a listener that is called when the set of visible slides.
+ @param rListener
+ When this method is called multiple times for the same listener
+ the second and all following calls are ignored. Each listener
+ is added only once.
+ */
+ void AddVisibilityChangeListener (const Link& rListener);
+
+ /** Remove a listener that is called when the set of visible slides changes.
+ @param rListener
+ It is save to pass a listener that was not added or has been
+ removed previously. Such calls are ignored.
+ */
+ void RemoveVisibilityChangeListener (const Link& rListener);
+
+protected:
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SlideSorterModel& mrModel;
+ /// This model is used for the maPage object and for the page visualizers
+ /// (SdrPageObj)
+ SdrModel maPageModel;
+ /** This page acts as container for the page objects that represent the
+ pages of the document that is represented by the SlideSorterModel.
+ */
+ SdrPage* mpPage;
+ ::std::auto_ptr<Layouter> mpLayouter;
+ bool mbPageObjectVisibilitiesValid;
+ ::boost::shared_ptr<cache::PageCache> mpPreviewCache;
+ ::std::auto_ptr<ViewOverlay> mpViewOverlay;
+
+ int mnFirstVisiblePageIndex;
+ int mnLastVisiblePageIndex;
+
+ SvBorder maPagePixelBorder;
+
+ bool mbModelChangedWhileModifyEnabled;
+
+ Size maPreviewSize;
+
+ bool mbPreciousFlagUpdatePending;
+
+ Size maPageNumberAreaModelSize;
+ SvBorder maModelBorder;
+
+ Orientation meOrientation;
+
+ ::std::vector<Link> maVisibilityChangeListeners;
+
+ /** Adapt the coordinates of the given bounding box according to the
+ other parameters.
+ @param rModelPageObjectBoundingBox
+ Bounding box given in model coordinates that bounds only the
+ page object.
+ @param eCoordinateSystem
+ When CS_SCREEN is given then the bounding box is converted into
+ screen coordinates.
+ @param eBoundingBoxType
+ When BBT_INFO is given then the bounding box is made larger so
+ that it encloses all relevant displayed information.
+ */
+ void AdaptBoundingBox (
+ Rectangle& rModelPageObjectBoundingBox,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const;
+
+ /** Determine the visibility of all page objects.
+ */
+ void DeterminePageObjectVisibilities (void);
+
+ /** Update the page borders used by the layouter by using those returned
+ by the first page. Call this function when the model changes,
+ especially when the number of pages changes, or when the window is
+ resized as the borders may be device dependent.
+ */
+ void UpdatePageBorders (void);
+
+ void UpdatePreciousFlags (void);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsFontProvider.hxx b/sd/source/ui/slidesorter/inc/view/SlsFontProvider.hxx
new file mode 100644
index 000000000000..bef3a05c5706
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsFontProvider.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_VIEW_FONT_PROVIDER_HXX
+#define SD_SLIDESORTER_VIEW_FONT_PROVIDER_HXX
+
+#include "tools/SdGlobalResourceContainer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <vcl/mapmod.hxx>
+
+class Font;
+class OutputDevice;
+class VclWindowEvent;
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** This simple singleton class provides fonts that are scaled so that they
+ have a fixed height on the given device regardless of its map mode.
+*/
+class FontProvider
+ : public SdGlobalResource
+{
+public:
+ typedef ::boost::shared_ptr<Font> SharedFontPointer;
+
+ /** Return the single instance of this class. Throws a RuntimeException
+ when no instance can be created.
+ */
+ static FontProvider& Instance (void);
+
+ /** Return a font that is scaled according to the current map mode of
+ the given device. Repeated calls with a device, not necessarily the
+ same device, with the same map mode will return the same font. The
+ first call with a different map mode will release the old font and
+ create a new one that is correctly scaled.
+ */
+ SharedFontPointer GetFont (const OutputDevice& rDevice);
+
+ /** Call this method to tell an object to release its currently used
+ font. The next call to GetFont() will then create a new one.
+ Typically called after a DataChange event when for instance a system
+ font has been modified.
+ */
+ void Invalidate (void);
+
+private:
+ static FontProvider* mpInstance;
+
+ /** The font that was created by a previous call to GetFont(). It is
+ replaced by another one only when GetFont() is called with a device
+ with a different map mode or by a call to Invalidate().
+ */
+ SharedFontPointer maFont;
+ /** The mape mode for which maFont was created.
+ */
+ MapMode maMapMode;
+
+ FontProvider (void);
+ virtual ~FontProvider (void);
+
+ // Copy constructor is not implemented.
+ FontProvider (const FontProvider&);
+ // Assignment operator is not implemented.
+ FontProvider& operator= (const FontProvider&);
+};
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx
new file mode 100644
index 000000000000..e5ed8f553799
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_VIEW_LAYOUTER_HXX
+#define SD_SLIDESORTER_VIEW_LAYOUTER_HXX
+
+#include <sal/types.h>
+#include <tools/fract.hxx>
+#include <vcl/mapmod.hxx>
+#include <vector>
+#include <utility>
+
+class MapMode;
+class OutputDevice;
+class Size;
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** Calculate the size and position of page objects displayed by a slide
+ sorter. The layouter takes into account various input values:
+ 1.) Size of the window in which the slide sorter is displayed.
+ 2.) Desired and minimal and maximal widths of page objects.
+ 3.) Minimal and maximal number of columns.
+ 4.) Vertical and horizontal gaps between objects in adjacent columns.
+ 5.) Borders arround every page object.
+ 6.) Vertical and horizontal borders between enclosing page and outer
+ page objects.
+ From these it calculates various output values:
+ 1.) The width of page objects.
+ 2.) The number of columns.
+ 3.) The size of the enclosing page.
+
+ <p>Sizes and lengths are all in pixel except where explicitly stated
+ otherwise.</p>
+
+ <p>The GetIndex... methods may return indices that are larger than or
+ equal to (zero based) the number of pages. This is so because the
+ number of pages is not known to the class instances. Indices are
+ calculated with reference to the general grid layout of page
+ objects.</p>
+*/
+class Layouter
+{
+public:
+ Layouter (void);
+ ~Layouter (void);
+
+ /** Set the horizontal and vertical borders in pixel coordinates between
+ the enclosing window and page objects. The borders may be painted
+ larger then the given values when the space for the insertion marker
+ is not sufficient.
+ @param nLeftBorder
+ Use a negative value to indicate that the left border size
+ shall not be modified. A value of 10 is the default.
+ @param nRightBorder
+ Use a negative value to indicate that the right border size
+ shall not be modified. A value of 10 is the default.
+ @param nTopBorder
+ Use a negative value to indicate that the top border size
+ shall not be modified. A value of 10 is the default.
+ @param nBottomBorder
+ Use a negative value to indicate that the bottom border size
+ shall not be modified. A value of 10 is the default.
+ */
+ void SetBorders (sal_Int32 nLeftBorder, sal_Int32 nRightBorder,
+ sal_Int32 nTopBorder, sal_Int32 nBottomBorder);
+
+ /** Set the borders arround every page object.
+ @param nLeftBorder
+ A negative value indicates that the left border shall not be
+ modified. A value of 0 is the default.
+ @param nRightBorder
+ A negative value indicates that the left border shall not be
+ modified. A value of 0 is the default.
+ @param nTopBorder
+ A negative value indicates that the left border shall not be
+ modified. A value of 0 is the default.
+ @param nBottomBorder
+ A negative value indicates that the left border shall not be
+ modified. A value of 0 is the default.
+ */
+ void SetPageBorders (sal_Int32 nLeftBorder, sal_Int32 nRightBorder,
+ sal_Int32 nTopBorder, sal_Int32 nBottomBorder);
+
+ /** Set the interval of valid column counts. When nMinimalColumnCount
+ <= nMaximalColumnCount is not fullfilled then the call is ignored.
+ @param nMinimalColumnCount
+ The default value is 1. The question whether higher values make
+ any sense is left to the caller.
+ @param nMaximalColumnCount
+ The default value is 5.
+ */
+ void SetColumnCount (sal_Int32 nMinimalColumnCount,
+ sal_Int32 nMaximalColumnCount);
+
+ /** Central method of this class. It takes the input values and
+ calculates the output values. Both given sizes must not be 0 in any
+ dimension or the call is ignored.
+ @param rWindowSize
+ The size of the window in pixels that the slide sorter is
+ displayed in.
+ @param rPageObjectSize
+ Size of each page in model coordinates.
+ @param pDevice
+ The map mode of this output device is adapted to the new layout
+ of the page objects.
+ @return
+ The return value indicates whether the Get... methods can be
+ used to obtain valid values (<TRUE/>).
+ */
+ bool RearrangeHorizontal (
+ const Size& rWindowSize,
+ const Size& rPageObjectSize,
+ OutputDevice* pDevice,
+ const sal_uInt32 nPageCount);
+ bool RearrangeVertical (
+ const Size& rWindowSize,
+ const Size& rPageObjectSize,
+ OutputDevice* pDevice);
+
+ /** Change the zoom factor. This does not change the general layout
+ (number of columns).
+ */
+ void SetZoom (Fraction nZoomFactor, OutputDevice* pDevice);
+
+ /** Return the number of columns.
+ */
+ sal_Int32 GetColumnCount (void) const;
+
+ /** Return the scale factor that can be set at the map mode of the
+ output window.
+ */
+ Fraction GetScaleFactor (void) const;
+
+ Size GetPageObjectSize (void) const;
+
+ /** Return the bounding box in model coordinates of the nIndex-th page
+ object.
+ */
+ Rectangle GetPageObjectBox (sal_Int32 nIndex) const;
+
+ /** Return the bounding box in model coordinates of the page that
+ contains the given amount of page objects.
+ */
+ Rectangle GetPageBox (sal_Int32 nObjectCount) const;
+
+ /** Return the rectangle that bounds the insertion marker that is
+ specified by the parameters.
+ @param nIndex
+ Index of the page object from which the position of the marker
+ will be calculated.
+ @param bVertical
+ When <TRUE/> then the insertion marker will be calculated with a
+ vertical orientation positioned to the left or right of the
+ specified page object. A horizontal orientation is indicated by
+ <FALSE/>. In this case the marker will be positioned above or
+ below the page object.
+ @param bLeftOrTop
+ This flag indicates whether the insertion marker will be
+ positioned above or to the left (<TRUE/>) the page object. When
+ <FALSE/> is given then the marker will be positioned below or to
+ the right of the page object.
+ */
+ Rectangle GetInsertionMarkerBox (
+ sal_Int32 nIndex,
+ bool bVertical,
+ bool bLeftOrTop) const;
+
+ /** Return the index of the first fully or partially visible page
+ object. This takes into account only the vertical dimension.
+ */
+ sal_Int32 GetIndexOfFirstVisiblePageObject (
+ const Rectangle& rVisibleArea) const;
+
+ /** Return the index of the last fully or partially visible page
+ object. This takes into account only the vertical dimension.
+ @return
+ The returned index may be larger than the number of existing
+ page objects.
+ */
+ sal_Int32 GetIndexOfLastVisiblePageObject (
+ const Rectangle& rVisibleArea) const;
+
+ /** Return the index of the page object that is rendered at the given
+ point.
+ @param rPosition
+ The position is expected to be in model coordinates relative to
+ the page origin.
+ @param bIncludePageBorders
+ When <TRUE/> then include the page borders into the calculation,
+ i.e. when a point lies in the border of a page object but not on
+ the actual page area the index of that page is returned;
+ otherwise -1 would be returned to indicate that no page object
+ has been hit.
+ @return
+ The returned index may be larger than the number of existing
+ page objects.
+ */
+ sal_Int32 GetIndexAtPoint (
+ const Point& rModelPosition,
+ bool bIncludePageBorders = false) const;
+
+ /** Return the page index of where to do an insert operation when the
+ user would release the the mouse button at the given position after
+ a drag operation.
+ @param rPosition
+ The position in the model coordinate system for which to
+ determine the insertion page index. The position does not have
+ to be over a page object to return a valid value.
+ @param bAllowVerticalPosition
+ When this flag is <TRUE/> then the vertical gaps between rows
+ may be taken into account for calculating the insertion index as
+ well as the horizontal gaps between columns. This will happen
+ only when there is only one column.
+ (better name, anyone?)
+ @return
+ Returns the page index, as accepted by the slide sorter model,
+ of the page after which an insertion would take place. An index
+ of 0 means that insertion will take place before the first page,
+ An index equal to or greater than the page count means to insert
+ after the last page.
+ A value of -1 indicates that no valid insertion index exists for
+ the given point.
+ */
+ sal_Int32 GetInsertionIndex (
+ const Point& rModelPosition,
+ bool bAllowVerticalPosition) const;
+
+ typedef ::std::pair<double,double> DoublePoint;
+ /** Transform a point given in model coordinates in to layouter
+ coordinates. Layouter coordinates are floating point numbers where
+ the integer part denotes a row or a column and the part after the
+ decimal point is a relative position in that row or column.
+ */
+ DoublePoint ConvertModelToLayouterCoordinates (
+ const Point& rModelPoint) const;
+
+ /** Transform a point given in layouter coordinates to model
+ coordinates. See ConvertModelToLayouterCoordinates for a
+ description of layouter coordinates.
+ */
+ Point ConvertLayouterToModelCoordinates (
+ const DoublePoint&rLayouterPoint) const;
+
+ typedef ::std::vector<Rectangle> BackgroundRectangleList;
+
+private:
+ class ScreenAndModelValue {public:
+ sal_Int32 mnScreen,mnModel;
+ explicit ScreenAndModelValue (sal_Int32 nScreen, sal_Int32 nModel = 0)
+ : mnScreen(nScreen),mnModel(nModel) {}
+ };
+ ScreenAndModelValue mnRequestedLeftBorder;
+ ScreenAndModelValue mnRequestedRightBorder;
+ ScreenAndModelValue mnRequestedTopBorder;
+ ScreenAndModelValue mnRequestedBottomBorder;
+ ScreenAndModelValue mnLeftBorder;
+ ScreenAndModelValue mnRightBorder;
+ ScreenAndModelValue mnTopBorder;
+ ScreenAndModelValue mnBottomBorder;
+ ScreenAndModelValue mnLeftPageBorder;
+ ScreenAndModelValue mnRightPageBorder;
+ ScreenAndModelValue mnTopPageBorder;
+ ScreenAndModelValue mnBottomPageBorder;
+ ScreenAndModelValue mnVerticalGap;
+ ScreenAndModelValue mnHorizontalGap;
+ ScreenAndModelValue mnInsertionMarkerThickness;
+ ScreenAndModelValue mnTotalVerticalGap;
+ ScreenAndModelValue mnTotalHorizontalGap;
+ sal_Int32 mnMinimalWidth;
+ sal_Int32 mnPreferredWidth;
+ sal_Int32 mnMaximalWidth;
+ sal_Int32 mnMinimalColumnCount;
+ sal_Int32 mnMaximalColumnCount;
+ sal_Int32 mnColumnCount;
+ Size maPageObjectModelSize;
+ Size maPageObjectPixelSize;
+
+ BackgroundRectangleList maBackgroundRectangleList;
+
+ enum GapMembership { GM_NONE, GM_PREVIOUS, GM_BOTH, GM_NEXT,
+ GM_PAGE_BORDER};
+
+ /** Calculate the row that the point with the given vertical coordinate
+ is over. The horizontal component is ignored.
+ @param nYPosition
+ Vertical position in model coordinates.
+ @param bIncludeBordersAndGaps
+ When this flag is <TRUE/> then the area of borders and gaps are
+ interpreted as belonging to one of the rows.
+ @param eGapMembership
+ Specifies to what row the gap areas belong. Here GM_NONE
+ corresponds to bIncludeBordersAndGaps being <FALSE/>. When
+ GM_BOTH is given then the upper half is associated to the row
+ above and the lower half to the row below. Values of
+ GM_PREVIOUS and GM_NEXT associate the whole gap area with the
+ row above or below respectively.
+ */
+ sal_Int32 GetRowAtPosition (
+ sal_Int32 nYPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership = GM_NONE) const;
+
+ /** Calculate the column that the point with the given horizontal
+ coordinate is over. The verical component is ignored.
+ @param nXPosition
+ Horizontal position in model coordinates.
+ @param bIncludeBordersAndGaps
+ When this flag is <TRUE/> then the area of borders and gaps are
+ interpreted as belonging to one of the columns.
+ @param eGapMembership
+ Specifies to what column the gap areas belong. Here GM_NONE
+ corresponds to bIncludeBordersAndGaps being <FALSE/>. When
+ GM_BOTH is given then the left half is associated with the
+ column at the left and the right half with the column to the
+ right. Values of GM_PREVIOUS and GM_NEXT associate the whole
+ gap area with the column to the left or right respectively.
+ */
+ sal_Int32 GetColumnAtPosition (
+ sal_Int32 nXPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership = GM_NONE) const;
+
+ /** This method is typically called from GetRowAtPosition() and
+ GetColumnAtPosition() to handle a position that lies inside the gap
+ between two adjacent rows or columns.
+ @param nDistanceIntoGap
+ Vertical distance from the bottom of the upper row down into the
+ gap or or horizontal distance from the right edge right into the
+ gap.
+ @param eGapMemberhship
+ This value decides what areas in the gap belong to which (or no)
+ row or column.
+ @param nIndex
+ The row index of the upper row or the column index of the left
+ column.
+ @param nLeftOrTopPageBorder
+ Width in model coordinates of the border the the right of or
+ below a page.
+ @param nGap
+ Width or height of the gap in model coordiantes between the
+ page borders.
+ @return
+ Returns either the index of the upper row (as given as nRow), the
+ index of the lower row (nRow+1) or -1 to indicate that the
+ position belongs to no row.
+ */
+ sal_Int32 ResolvePositionInGap (
+ sal_Int32 nDistanceIntoGap,
+ GapMembership eGapMembership,
+ sal_Int32 nIndex,
+ sal_Int32 nLeftOrTopPageBorder,
+ sal_Int32 nGap) const;
+};
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObject.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObject.hxx
new file mode 100644
index 000000000000..e58e48ca701c
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsPageObject.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_OBJECT_HXX
+#define SD_SLIDESORTER_PAGE_OBJECT_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include <svx/svdopage.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+/** This sub class of the SdrPageObject exists to create the view contact
+ and indirectly to create view-object-contact objects.
+*/
+class PageObject
+ : public SdrPageObj
+{
+public:
+ PageObject (
+ const Rectangle& rRect,
+ SdrPage* pPage,
+ const model::SharedPageDescriptor& rpDescriptor);
+
+ virtual ~PageObject (void);
+
+ model::SharedPageDescriptor GetDescriptor (void) const;
+
+private:
+ model::SharedPageDescriptor mpDescriptor;
+
+protected:
+ virtual sdr::contact::ViewContact* CreateObjectSpecificViewContact();
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewContact.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewContact.hxx
new file mode 100644
index 000000000000..59033cd101c7
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewContact.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX
+#define SD_SLIDESORTER_PAGE_OBJECT_VIEW_CONTACT_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <svx/sdtakitm.hxx>
+#include <svx/sdr/contact/viewcontactofpageobj.hxx>
+
+class SdrPageObj;
+
+namespace sdr {namespace contact {
+class ViewObjectContact;
+class ObjectContact;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** Details:
+ This class has to provide the bounding box but can not determine it
+ fully because it has no access to the output device. It therefore
+ retrieves some of the necessary data, the border, from the
+ PageDescriptor which acts here as persistent storage.
+*/
+class PageObjectViewContact
+ : public ::sdr::contact::ViewContactOfPageObj
+{
+public:
+ PageObjectViewContact (
+ SdrPageObj& rPageObj,
+ const model::SharedPageDescriptor& rpDescriptor);
+ ~PageObjectViewContact (void);
+
+ /** Create a ViewObjectContact object that buffers its output in a
+ bitmap.
+ @return
+ Ownership of the new object passes to the caller.
+ */
+ virtual ::sdr::contact::ViewObjectContact&
+ CreateObjectSpecificViewObjectContact(
+ ::sdr::contact::ObjectContact& rObjectContact);
+
+ const SdrPage* GetPage (void) const;
+
+ SdrPageObj& GetPageObject (void) const;
+
+ virtual void ActionChanged (void);
+
+protected:
+ // create graphical visualisation data
+ virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
+
+private:
+ /** This flag is set to <TRUE/> when the destructor is called to
+ indicate that further calls made to it must not call outside.
+ */
+ bool mbInDestructor;
+
+ model::SharedPageDescriptor mpDescriptor;
+};
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewObjectContact.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewObjectContact.hxx
new file mode 100644
index 000000000000..df3d69f14cc0
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectViewObjectContact.hxx
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_PAGE_OBJECT_VIEW_OBJECT_CONTACT_HXX
+#define SD_SLIDESORTER_PAGE_OBJECT_VIEW_OBJECT_CONTACT_HXX
+
+#include <svx/sdr/contact/viewobjectcontactofpageobj.hxx>
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <svx/sdr/contact/viewobjectcontact.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/image.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <memory>
+#include <boost/shared_ptr.hpp>
+
+class SdrPage;
+
+namespace sdr { namespace contact {
+class DisplayInfo;
+} }
+
+namespace sd { namespace slidesorter { namespace cache {
+class PageCache;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+class Properties;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class SlideSorterView;
+
+/** This object-view-contact of page objects maintains a preview bitmap for
+ the page to speed up redraws of the same. It does so by colaborating
+ with a cache of bitmaps (see ../cache).
+*/
+
+// needs to be derived from ViewObjectContactOfPageObj, else the calls to parent implementations
+// would use ViewObjectContact and thus not enable e.g. the correct primitive creation
+// for view-independent printer output
+// changed: ViewObjectContact -> ViewObjectContactOfPageObj
+
+class PageObjectViewObjectContact : public ::sdr::contact::ViewObjectContactOfPageObj
+{
+public:
+ /** Create a new view-object-contact object for the given contact
+ objects of both model and view.
+ @param pCache
+ The caller should provide a pointer to a preview cache, if
+ available. If given then the cache is used to control when to
+ create a preview and to store it. If NULL is given then the
+ preview is created every time when requested.
+ */
+ PageObjectViewObjectContact (
+ ::sdr::contact::ObjectContact& rObjectContact,
+ ::sdr::contact::ViewContact& rViewContact,
+ const ::boost::shared_ptr<cache::PageCache>& rpCache,
+ const ::boost::shared_ptr<controller::Properties>& rpProperties);
+ virtual ~PageObjectViewObjectContact (void);
+
+ /** This method is primarily for releasing the current preview cache (by
+ providing a NULL pointer.)
+ */
+ void SetCache (const ::boost::shared_ptr<cache::PageCache>& rpCache);
+
+ /** Return the page that is painted by this object.
+ */
+ const SdrPage* GetPage (void) const;
+
+ /** This fallback method is called when no preview cache is available.
+ It creates a preview for the page.
+ */
+ BitmapEx CreatePreview (const sdr::contact::DisplayInfo& rDisplayInfo);
+
+ /** Return the page descriptor of the slide sorter model that is
+ associated with the same page object as this contact object is.
+ */
+ model::SharedPageDescriptor GetPageDescriptor (void) const;
+
+ /** Return the border widths in the screen coordinate system of the
+ border arround the page object. The border contains frames for
+ selection, focus, the page name and number, and the indicator for
+ the page transition.
+ @param pDevice
+ The output device is used to convert pixel coordinates into
+ model coordinates. When NULL is given then the device dependent
+ part is not re-calculated but taken from an earlier calculation
+ or from the default values.
+ @param nPageCount
+ The total number of pages is used to determine the width of the
+ box that contains the page number.
+ */
+ static SvBorder CalculatePageModelBorder (
+ OutputDevice* pDevice,
+ int nPageCount);
+
+ /** Calculate the size of the page number area so that all page numbers
+ including the given number fit in. Because this is device dependent
+ we need the device as parameter. The result is returned and stored
+ in maPageNumberAreaPixelSize so that it can be used later without
+ access to the device or page count.
+ */
+ static Size CalculatePageNumberAreaModelSize (
+ OutputDevice* pDevice,
+ int nPageCount);
+
+ /** Paint a mouse over effect.
+ @param bVisible
+ When bVisible is <FALSE/> then paint the area of the mouse over
+ effect in the background color, i.e. erase it.
+ */
+ drawinglayer::primitive2d::Primitive2DSequence createMouseOverEffectPrimitive2DSequence();
+
+ enum BoundingBoxType {
+ // This is the outer bounding box that includes the preview, page
+ // number, title.
+ PageObjectBoundingBox,
+ // Bounding box of the actual preview.
+ PreviewBoundingBox,
+ // Bounding box of the mouse indicator indicator frame.
+ MouseOverIndicatorBoundingBox,
+ // Bounding box of the focus indicator frame.
+ FocusIndicatorBoundingBox,
+ // Bounding box of the selection indicator frame.
+ SelectionIndicatorBoundingBox,
+ // Bounding box of the page number.
+ PageNumberBoundingBox,
+ // Bounding box of the pane name.
+ NameBoundingBox,
+ FadeEffectIndicatorBoundingBox
+ };
+ enum CoordinateSystem { ModelCoordinateSystem, PixelCoordinateSystem };
+
+ /** Return the bounding box of the page object or one of its graphical
+ parts.
+ @param rDevice
+ This device is used to translate between model and window
+ coordinates.
+ @param eType
+ The part of the page object for which to return the bounding
+ box.
+ @param eCoodinateSystem
+ The bounding box can be returned in model and in pixel
+ (window) coordinates.
+ */
+ Rectangle GetBoundingBox (
+ OutputDevice& rDevice,
+ BoundingBoxType eType,
+ CoordinateSystem eCoordinateSystem) const;
+
+ // create the graphical visualisation data
+ virtual drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequence(const sdr::contact::DisplayInfo& rDisplayInfo) const;
+
+ // access to the current page content primitive vector which may be used for visualisation
+ const drawinglayer::primitive2d::Primitive2DSequence& getCurrentPageContents() const { return mxCurrentPageContents; }
+
+ virtual void ActionChanged (void);
+
+private:
+ /// Gap between border of page object and inside of selection rectangle.
+ static const sal_Int32 mnSelectionIndicatorOffset;
+ /// Thickness of the selection rectangle.
+ static const sal_Int32 mnSelectionIndicatorThickness;
+ /// Gap between border of page object and inside of focus rectangle.
+ static const sal_Int32 mnFocusIndicatorOffset;
+ /// Size of width and height of the fade effect indicator in pixels.
+ static const sal_Int32 mnFadeEffectIndicatorSize;
+ static const sal_Int32 mnFadeEffectIndicatorOffset;
+ /// Gap between border of page object and number rectangle.
+ static const sal_Int32 mnPageNumberOffset;
+ /// Offset and thickness of the mouse over effect rectangle.
+ static const sal_Int32 mnMouseOverEffectOffset;
+ static const sal_Int32 mnMouseOverEffectThickness;
+
+ /** This flag is set to <TRUE/> when the destructor is called to
+ indicate that further calls made to it must not call outside.
+ */
+ bool mbInDestructor;
+
+ /// The primitive sequence of the page contents, completely scaled
+ /// and prepared for painiting
+ drawinglayer::primitive2d::Primitive2DSequence mxCurrentPageContents;
+
+ ::boost::shared_ptr<cache::PageCache> mpCache;
+
+ ::boost::shared_ptr<controller::Properties> mpProperties;
+
+ BitmapEx GetPreview (
+ const sdr::contact::DisplayInfo& rDisplayInfo,
+ const Rectangle& rNewSizePixel);
+
+ /** Return the bounding box of where the page number is painted (when it
+ is painted).
+ */
+ Rectangle GetPageNumberArea (OutputDevice& rDevice) const;
+};
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx
new file mode 100644
index 000000000000..bebaf347726b
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_VIEW_OVERLAY_HXX
+#define SD_SLIDESORTER_VIEW_OVERLAY_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <osl/mutex.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <tools/gen.hxx>
+#include <vector>
+#include <boost/weak_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+class OutputDevice;
+class Region;
+
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace model {
+class PageEnumeration;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+class SlideSorterController;
+} } }
+
+namespace sdr { namespace overlay {
+class OverlayManager;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+class InsertionIndicatorOverlay;
+class PageObjectViewObjectContact;
+class SelectionRectangleOverlay;
+class SubstitutionOverlay;
+class ViewOverlay;
+
+/** This base class of slide sorter overlays uses the drawing layer overlay
+ support for the display.
+*/
+class OverlayBase
+ : public sdr::overlay::OverlayObject
+{
+public:
+ OverlayBase (ViewOverlay& rViewOverlay);
+ virtual ~OverlayBase (void);
+
+protected:
+ ::osl::Mutex maMutex;
+
+ ViewOverlay& mrViewOverlay;
+
+ /** Make sure that the overlay object is registered at the
+ OverlayManager. This registration is done on demand.
+ */
+ void EnsureRegistration (void);
+ void RemoveRegistration();
+};
+
+
+
+
+/** During internal drag and drop the outlines of the selected slides are
+ painted at the mouse position in dashed lines.
+*/
+class SubstitutionOverlay
+ : public OverlayBase
+{
+public:
+ SubstitutionOverlay (ViewOverlay& rViewOverlay);
+ virtual ~SubstitutionOverlay (void);
+
+ /** Setup the substitution display of the given set of selected pages.
+ The given mouse position is remembered so that it later can be
+ returned by GetPosition(). This is a convenience feature.
+ */
+ void Create (
+ model::PageEnumeration& rSelection,
+ const Point& rPosition);
+
+ /** Clear the substitution display. Until the next call of Create() no
+ substution is painted.
+ */
+ void Clear (void);
+
+ /** Move the substitution display by the given amount of pixels.
+ */
+ void Move (const Point& rOffset);
+ void SetPosition (const Point& rPosition);
+ Point GetPosition (void) const;
+
+ // react on stripe definition change
+ virtual void stripeDefinitionHasChanged();
+
+protected:
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence();
+
+private:
+ Point maPosition;
+ basegfx::B2DPolyPolygon maShapes;
+};
+
+
+
+
+/** Slides can be selected by drawing a selection rectangle in the slide
+ sorter. When the left mouse button is released all slides that are at
+ least partially in the rectangle are selected.
+*/
+class SelectionRectangleOverlay
+ : public OverlayBase
+{
+public:
+ SelectionRectangleOverlay (ViewOverlay& rViewOverlay);
+ virtual ~SelectionRectangleOverlay();
+
+ void Start (const Point& rAnchor);
+ void Update (const Point& rSecondCorner);
+
+ Rectangle GetSelectionRectangle (void);
+
+ // react on stripe definition change
+ virtual void stripeDefinitionHasChanged();
+
+protected:
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence();
+
+private:
+ Point maAnchor;
+ Point maSecondCorner;
+};
+
+
+
+
+/** The insertion indicator is painted as a vertical or horizonal bar
+ in the space between slides.
+*/
+class InsertionIndicatorOverlay
+ : public OverlayBase
+{
+public:
+ InsertionIndicatorOverlay (ViewOverlay& rViewOverlay);
+ virtual ~InsertionIndicatorOverlay();
+
+ /** Given a position in model coordinates this method calculates the
+ insertion marker both as an index in the document and as a rectangle
+ used for drawing the insertion indicator.
+ */
+ void SetPosition (const Point& rPosition);
+
+ sal_Int32 GetInsertionPageIndex (void) const;
+
+protected:
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence();
+
+private:
+ sal_Int32 mnInsertionIndex;
+ Rectangle maBoundingBox;
+
+ void SetPositionAndSize (const Rectangle& rBoundingBox);
+};
+
+
+
+
+/** Paint a frame around the slide preview under the mouse. The actual
+ painting is done by the PageObjectViewObjectContact of the slidesorter.
+*/
+class MouseOverIndicatorOverlay
+ : public OverlayBase
+{
+public:
+ MouseOverIndicatorOverlay (ViewOverlay& rViewOverlay);
+ virtual ~MouseOverIndicatorOverlay (void);
+
+ /** Set the page object for which to paint a mouse over indicator.
+ @param pContact
+ A value of <NULL/> indicates to not paint the mouse over indicator.
+ */
+ void SetSlideUnderMouse (const model::SharedPageDescriptor& rpDescriptor);
+
+protected:
+ // geometry creation for OverlayObject
+ virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence();
+
+private:
+ /** The page under the mouse is stored as weak shared pointer so that
+ model changes can be handled without having the SlideSorterModel
+ inform this class explicitly.
+ */
+ ::boost::weak_ptr<model::PageDescriptor> mpPageUnderMouse;
+
+ view::PageObjectViewObjectContact* GetViewObjectContact (void) const;
+};
+
+
+
+
+/** The view overlay manages and paints some indicators that are painted on
+ top of the regular view content (the page objects). It is separated
+ from the view to allow the indicators to be altered in position and size
+ without repainting the whole view content (inside that the bounding box
+ of the indicator). This is achieved by using the drawing layer overlay
+ support.
+
+ The view overlay itself simply gives access to the more specialized
+ classes that handle individual indicators.
+
+*/
+class ViewOverlay
+{
+public:
+ ViewOverlay (SlideSorter& rSlideSorter);
+ ~ViewOverlay (void);
+
+ SelectionRectangleOverlay& GetSelectionRectangleOverlay (void);
+ MouseOverIndicatorOverlay& GetMouseOverIndicatorOverlay (void);
+ InsertionIndicatorOverlay& GetInsertionIndicatorOverlay (void);
+ SubstitutionOverlay& GetSubstitutionOverlay (void);
+
+ SlideSorter& GetSlideSorter (void) const;
+
+ sdr::overlay::OverlayManager* GetOverlayManager (void) const;
+
+private:
+ SlideSorter& mrSlideSorter;
+ SelectionRectangleOverlay maSelectionRectangleOverlay;
+ MouseOverIndicatorOverlay maMouseOverIndicatorOverlay;
+ InsertionIndicatorOverlay maInsertionIndicatorOverlay;
+ SubstitutionOverlay maSubstitutionOverlay;
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/makefile.mk b/sd/source/ui/slidesorter/makefile.mk
new file mode 100644
index 000000000000..c294bf05ffa0
--- /dev/null
+++ b/sd/source/ui/slidesorter/makefile.mk
@@ -0,0 +1,58 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slidesorter
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlideSorter.obj \
+ $(SLO)$/SlideSorterChildWindow.obj \
+ $(SLO)$/SlideSorterViewShell.obj
+
+EXCEPTIONSFILES=
+
+SRS2NAME = slidesorter
+SRC2FILES = SlsChildWindow.src
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sd/source/ui/slidesorter/model/SlideSorterModel.cxx b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx
new file mode 100644
index 000000000000..27cb286cbd8f
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx
@@ -0,0 +1,445 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "model/SlideSorterModel.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "view/SlideSorterView.hxx"
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+
+#include "ViewShellBase.hxx"
+#include "DrawViewShell.hxx"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "FrameView.hxx"
+
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace slidesorter { namespace model {
+
+namespace {
+ class CompareToXDrawPage
+ {
+ public:
+ CompareToXDrawPage (const Reference<drawing::XDrawPage>& rxSlide) : mxSlide(rxSlide) {}
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ { return rpDescriptor.get()!=NULL && rpDescriptor->GetXDrawPage()==mxSlide; }
+ private:
+ Reference<drawing::XDrawPage> mxSlide;
+ };
+}
+
+
+
+
+SlideSorterModel::SlideSorterModel (SlideSorter& rSlideSorter)
+ : maMutex(),
+ mrSlideSorter(rSlideSorter),
+ mxSlides(),
+ mePageKind(PK_STANDARD),
+ meEditMode(EM_PAGE),
+ maPageDescriptors(0),
+ mpPageObjectFactory(NULL)
+{
+}
+
+
+
+
+SlideSorterModel::~SlideSorterModel (void)
+{
+ ClearDescriptorList ();
+}
+
+
+
+
+SdDrawDocument* SlideSorterModel::GetDocument (void)
+{
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ return mrSlideSorter.GetViewShellBase()->GetDocument();
+ else
+ return NULL;
+}
+
+
+
+
+bool SlideSorterModel::SetEditMode (EditMode eEditMode)
+{
+ bool bEditModeChanged = false;
+ if (meEditMode != eEditMode)
+ {
+ meEditMode = eEditMode;
+ UpdatePageList();
+ ClearDescriptorList();
+ bEditModeChanged = true;
+ }
+ return bEditModeChanged;
+}
+
+
+
+
+EditMode SlideSorterModel::GetEditMode (void) const
+{
+ return meEditMode;
+}
+
+
+
+
+PageKind SlideSorterModel::GetPageType (void) const
+{
+ return mePageKind;
+}
+
+
+
+
+sal_Int32 SlideSorterModel::GetPageCount (void) const
+{
+ return maPageDescriptors.size();
+}
+
+
+
+
+SharedPageDescriptor SlideSorterModel::GetPageDescriptor (
+ const sal_Int32 nPageIndex,
+ const bool bCreate) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ SharedPageDescriptor pDescriptor;
+
+ if (nPageIndex>=0 && nPageIndex<GetPageCount())
+ {
+ pDescriptor = maPageDescriptors[nPageIndex];
+ if (pDescriptor == NULL && bCreate && mxSlides.is())
+ {
+ SdDrawDocument* pModel = const_cast<SlideSorterModel*>(this)->GetDocument();
+ SdPage* pPage = NULL;
+ if (pModel != NULL)
+ {
+ if (meEditMode == EM_PAGE)
+ pPage = pModel->GetSdPage ((USHORT)nPageIndex, mePageKind);
+ else
+ pPage = pModel->GetMasterSdPage ((USHORT)nPageIndex, mePageKind);
+ }
+ pDescriptor.reset(new PageDescriptor (
+ Reference<drawing::XDrawPage>(mxSlides->getByIndex(nPageIndex),UNO_QUERY),
+ pPage,
+ nPageIndex,
+ GetPageObjectFactory()));
+ maPageDescriptors[nPageIndex] = pDescriptor;
+ }
+ }
+
+ return pDescriptor;
+}
+
+
+
+
+sal_Int32 SlideSorterModel::GetIndex (const Reference<drawing::XDrawPage>& rxSlide) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // First try to guess the right index.
+ Reference<beans::XPropertySet> xSet (rxSlide, UNO_QUERY);
+ if (xSet.is())
+ {
+ try
+ {
+ const Any aNumber (xSet->getPropertyValue(::rtl::OUString::createFromAscii("Number")));
+ sal_Int16 nNumber (-1);
+ aNumber >>= nNumber;
+ nNumber -= 1;
+ SharedPageDescriptor pDescriptor (GetPageDescriptor(nNumber, false));
+ if (pDescriptor.get() != NULL
+ && pDescriptor->GetXDrawPage() == rxSlide)
+ {
+ return nNumber;
+ }
+ }
+ catch (uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ // Guess was wrong, iterate over all slides and search for the right
+ // one.
+ const sal_Int32 nCount (maPageDescriptors.size());
+ for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
+ {
+ SharedPageDescriptor pDescriptor (maPageDescriptors[nIndex]);
+
+ // Make sure that the descriptor exists. Without it the given slide
+ // can not be found.
+ if (pDescriptor.get() == NULL)
+ {
+ // Call GetPageDescriptor() to create the missing descriptor.
+ pDescriptor = GetPageDescriptor(nIndex,true);
+ }
+
+ if (pDescriptor->GetXDrawPage() == rxSlide)
+ return nIndex;
+ }
+
+ return -1;
+}
+
+
+
+
+/** For now this method uses a trivial algorithm: throw away all descriptors
+ and create them anew (on demand). The main problem that we are facing
+ when designing a better algorithm is that we can not compare pointers to
+ pages stored in the PageDescriptor objects and those obtained from the
+ document: pages may have been deleted and others may have been created
+ at the exact same memory locations.
+*/
+void SlideSorterModel::Resync (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ ClearDescriptorList ();
+ AdaptSize();
+}
+
+
+
+
+void SlideSorterModel::ClearDescriptorList (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Clear the cache of page descriptors.
+ DescriptorContainer::iterator I;
+ for (I=maPageDescriptors.begin(); I!=maPageDescriptors.end(); I++)
+ {
+ if (I->get() != NULL)
+ {
+ if ( ! I->unique())
+ {
+ OSL_TRACE("SlideSorterModel::ClearDescriptorList: trying to delete page descriptor that is still used with count %d", I->use_count());
+ // No assertion here because that can hang the office when
+ // opening a dialog from here.
+ }
+ I->reset();
+ }
+ }
+}
+
+
+
+
+void SlideSorterModel::SynchronizeDocumentSelection (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->GetPage()->SetSelected (pDescriptor->IsSelected());
+ }
+}
+
+void SlideSorterModel::SetPageObjectFactory(
+ ::std::auto_ptr<controller::PageObjectFactory> pPageObjectFactory)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ mpPageObjectFactory = pPageObjectFactory;
+ // When a NULL pointer was given then create a default factory.
+ const controller::PageObjectFactory& rFactory (GetPageObjectFactory());
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->SetPageObjectFactory(rFactory);
+ }
+}
+
+
+
+
+const controller::PageObjectFactory&
+ SlideSorterModel::GetPageObjectFactory (void) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ if (mpPageObjectFactory.get() == NULL)
+ {
+ // We have to create a new factory. The pointer is mutable so we
+ // are alowed to do so.
+ mpPageObjectFactory = ::std::auto_ptr<controller::PageObjectFactory> (
+ new controller::PageObjectFactory(
+ mrSlideSorter.GetView().GetPreviewCache(),
+ mrSlideSorter.GetController().GetProperties()));
+ }
+ return *mpPageObjectFactory.get();
+}
+
+
+
+
+::osl::Mutex& SlideSorterModel::GetMutex (void)
+{
+ return maMutex;
+}
+
+
+
+
+void SlideSorterModel::SetDocumentSlides (
+ const Reference<container::XIndexAccess>& rxSlides)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Reset the current page so to cause everbody to release references to it.
+ mrSlideSorter.GetController().GetCurrentSlideManager()->CurrentSlideHasChanged(-1);
+
+ mxSlides = rxSlides;
+ Resync();
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ {
+ SdPage* pPage = pViewShell->getCurrentPage();
+ if (pPage != NULL)
+ mrSlideSorter.GetController().GetCurrentSlideManager()->CurrentSlideHasChanged(
+ GetIndex(Reference<drawing::XDrawPage>(pPage->getUnoPage(), UNO_QUERY)));
+ else
+ {
+ // No current page. This can only be when the slide sorter is
+ // the main view shell. Get current slide form frame view.
+ const FrameView* pFrameView = pViewShell->GetFrameView();
+ if (pFrameView != NULL)
+ mrSlideSorter.GetController().GetCurrentSlideManager()->CurrentSlideHasChanged(
+ pFrameView->GetSelectedPage());
+ else
+ {
+ // No frame view. As a last resort use the first slide as
+ // current slide.
+ mrSlideSorter.GetController().GetCurrentSlideManager()->CurrentSlideHasChanged(0);
+ }
+ }
+ }
+}
+
+
+
+
+Reference<container::XIndexAccess> SlideSorterModel::GetDocumentSlides (void) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ return mxSlides;
+}
+
+
+
+
+void SlideSorterModel::UpdatePageList (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ Reference<container::XIndexAccess> xPages;
+
+ // Get the list of pages according to the edit mode.
+ Reference<frame::XController> xController (mrSlideSorter.GetXController());
+ if (xController.is())
+ {
+ switch (meEditMode)
+ {
+ case EM_MASTERPAGE:
+ {
+ Reference<drawing::XMasterPagesSupplier> xSupplier (
+ xController->getModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ xPages = Reference<container::XIndexAccess>(
+ xSupplier->getMasterPages(), UNO_QUERY);
+ }
+ }
+ break;
+
+ case EM_PAGE:
+ {
+ Reference<drawing::XDrawPagesSupplier> xSupplier (
+ xController->getModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ xPages = Reference<container::XIndexAccess>(
+ xSupplier->getDrawPages(), UNO_QUERY);
+ }
+ }
+ break;
+
+ default:
+ // We should never get here.
+ OSL_ASSERT(false);
+ break;
+ }
+ }
+
+ mrSlideSorter.GetController().SetDocumentSlides(xPages);
+}
+
+
+
+
+void SlideSorterModel::AdaptSize (void)
+{
+ if (mxSlides.is())
+ maPageDescriptors.resize(mxSlides->getCount());
+ else
+ maPageDescriptors.resize(0);
+}
+
+} } } // end of namespace ::sd::slidesorter::model
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx
new file mode 100644
index 000000000000..a1a166c4f112
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+
+#include "sdpage.hxx"
+#include "drawdoc.hxx"
+
+#include <svx/svdopage.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+namespace sd { namespace slidesorter { namespace model {
+
+PageDescriptor::PageDescriptor (
+ const Reference<drawing::XDrawPage>& rxPage,
+ SdPage* pPage,
+ const sal_Int32 nIndex,
+ const controller::PageObjectFactory& rPageObjectFactory)
+ : mpPage(pPage),
+ mxPage(rxPage),
+ mnIndex(nIndex),
+ mpPageObjectFactory(&rPageObjectFactory),
+ mpPageObject(NULL),
+ mbIsSelected(false),
+ mbIsVisible(false),
+ mbIsFocused(false),
+ mbIsCurrent(false),
+ mpViewObjectContact(NULL),
+ maModelBorder(0,0,0,0),
+ maPageNumberAreaModelSize(0,0)
+{
+ OSL_ASSERT(mpPage == SdPage::getImplementation(rxPage));
+}
+
+
+
+
+PageDescriptor::~PageDescriptor (void)
+{
+}
+
+
+
+
+SdPage* PageDescriptor::GetPage (void) const
+{
+ return mpPage;
+}
+
+
+
+
+Reference<drawing::XDrawPage> PageDescriptor::GetXDrawPage (void) const
+{
+ return mxPage;
+}
+
+
+
+
+view::PageObject* PageDescriptor::GetPageObject (void)
+{
+ if (mpPageObject==NULL && mpPageObjectFactory!=NULL && mpPage != NULL)
+ {
+ mpPageObject = mpPageObjectFactory->CreatePageObject(mpPage, shared_from_this());
+ }
+
+ return mpPageObject;
+}
+
+
+
+
+void PageDescriptor::ReleasePageObject (void)
+{
+ mpPageObject = NULL;
+}
+
+
+
+
+bool PageDescriptor::IsVisible (void) const
+{
+ return mbIsVisible;
+}
+
+
+
+
+void PageDescriptor::SetVisible (bool bIsVisible)
+{
+ mbIsVisible = bIsVisible;
+}
+
+
+
+
+bool PageDescriptor::Select (void)
+{
+ if ( ! IsSelected())
+ {
+ mbIsSelected = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool PageDescriptor::Deselect (void)
+{
+ if (IsSelected())
+ {
+ mbIsSelected = false;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool PageDescriptor::IsSelected (void) const
+{
+ return mbIsSelected;
+}
+
+
+
+
+bool PageDescriptor::UpdateSelection (void)
+{
+ if (mpPage!=NULL && (mpPage->IsSelected()==TRUE) != mbIsSelected)
+ {
+ mbIsSelected = ! mbIsSelected;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool PageDescriptor::IsFocused (void) const
+{
+ return mbIsFocused;
+}
+
+
+
+
+void PageDescriptor::SetFocus (void)
+{
+ mbIsFocused = true;
+}
+
+
+
+
+void PageDescriptor::RemoveFocus (void)
+{
+ mbIsFocused = false;
+}
+
+
+
+
+view::PageObjectViewObjectContact*
+ PageDescriptor::GetViewObjectContact (void) const
+{
+ return mpViewObjectContact;
+}
+
+
+
+
+void PageDescriptor::SetViewObjectContact (
+ view::PageObjectViewObjectContact* pViewObjectContact)
+{
+ mpViewObjectContact = pViewObjectContact;
+}
+
+
+
+
+const controller::PageObjectFactory&
+ PageDescriptor::GetPageObjectFactory (void) const
+{
+ return *mpPageObjectFactory;
+}
+
+
+
+
+void PageDescriptor::SetPageObjectFactory (
+ const controller::PageObjectFactory& rFactory)
+{
+ mpPageObjectFactory = &rFactory;
+}
+
+
+
+
+void PageDescriptor::SetModelBorder (const SvBorder& rBorder)
+{
+ maModelBorder = rBorder;
+}
+
+
+
+
+SvBorder PageDescriptor::GetModelBorder (void) const
+{
+ return maModelBorder;
+}
+
+
+
+
+void PageDescriptor::SetPageNumberAreaModelSize (const Size& rSize)
+{
+ maPageNumberAreaModelSize = rSize;
+}
+
+
+
+
+Size PageDescriptor::GetPageNumberAreaModelSize (void) const
+{
+ return maPageNumberAreaModelSize;
+}
+
+
+
+
+void PageDescriptor::SetIsCurrentPage (const bool bIsCurrent)
+{
+ mbIsCurrent = bIsCurrent;
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::model
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx b/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx
new file mode 100644
index 000000000000..797175cb85a1
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+
+using namespace ::sd::slidesorter;
+using namespace ::sd::slidesorter::model;
+
+namespace {
+
+class PageEnumerationImpl
+ : public Enumeration<SharedPageDescriptor>
+{
+public:
+ inline PageEnumerationImpl (
+ const SlideSorterModel& rModel,
+ const PageEnumeration::PagePredicate& rPredicate);
+ virtual ~PageEnumerationImpl (void);
+ /** Create a copy of the called enumeration object.
+ */
+ virtual inline ::std::auto_ptr<Enumeration<SharedPageDescriptor> > Clone (void);
+
+ virtual inline bool HasMoreElements (void) const;
+ virtual inline SharedPageDescriptor GetNextElement (void);
+ virtual inline void Rewind (void);
+
+private:
+ const SlideSorterModel& mrModel;
+ const PageEnumeration::PagePredicate maPredicate;
+ int mnIndex;
+
+ /** This constructor sets the internal page index to the given value.
+ It does not call AdvanceToNextValidElement() to skip elements that
+ do not fullfill Predicate.
+ */
+ inline PageEnumerationImpl (
+ const SlideSorterModel& rModel,
+ const PageEnumeration::PagePredicate& rPredicate,
+ int nIndex);
+
+ /** Skip all elements that do not fullfill Predicate starting with the
+ one pointed to by mnIndex.
+ */
+ inline void AdvanceToNextValidElement (void);
+
+ // Default constructor not implemented.
+ PageEnumerationImpl (void);
+ // Assignment operator not implemented.
+ PageEnumerationImpl& operator= (const PageEnumerationImpl&);
+};
+
+} // end of anonymouse namespace
+
+
+
+
+namespace sd { namespace slidesorter { namespace model {
+
+
+PageEnumeration PageEnumeration::Create (
+ const SlideSorterModel& rModel,
+ const PagePredicate& rPredicate)
+{
+ return PageEnumeration(::std::auto_ptr<Enumeration<SharedPageDescriptor> >(
+ new PageEnumerationImpl(rModel, rPredicate)));
+}
+
+
+
+
+PageEnumeration::PageEnumeration (
+ ::std::auto_ptr<Enumeration<SharedPageDescriptor> > pImpl)
+ : mpImpl(pImpl)
+{
+}
+
+
+
+
+PageEnumeration::PageEnumeration (
+ PageEnumeration& rEnumeration,
+ bool bCloneImpl)
+{
+
+ if( bCloneImpl )
+ {
+ mpImpl = rEnumeration.mpImpl->Clone();
+ }
+ else
+ {
+ mpImpl = rEnumeration.mpImpl;
+ }
+}
+
+
+
+
+PageEnumeration::PageEnumeration (const PageEnumeration& rEnumeration )
+: sd::slidesorter::model::Enumeration<sd::slidesorter::model::SharedPageDescriptor>()
+{
+ mpImpl = rEnumeration.mpImpl->Clone();
+}
+
+
+
+
+PageEnumeration::~PageEnumeration (void)
+{
+}
+
+
+
+
+PageEnumeration& PageEnumeration::operator= (
+ const PageEnumeration& rEnumeration)
+{
+ mpImpl = rEnumeration.mpImpl->Clone();
+ return *this;
+}
+
+
+
+
+::std::auto_ptr<Enumeration<SharedPageDescriptor> > PageEnumeration::Clone (void)
+{
+ return ::std::auto_ptr<Enumeration<SharedPageDescriptor> >(
+ new PageEnumeration (*this, true));
+}
+
+
+
+
+bool PageEnumeration::HasMoreElements (void) const
+{
+ return mpImpl->HasMoreElements();
+}
+
+
+
+SharedPageDescriptor PageEnumeration::GetNextElement (void)
+{
+ return mpImpl->GetNextElement();
+}
+
+
+
+
+void PageEnumeration::Rewind (void)
+{
+ return mpImpl->Rewind();
+}
+
+} } } // end of namespace ::sd::slidesorter::model
+
+
+
+
+namespace {
+
+PageEnumerationImpl::PageEnumerationImpl (
+ const SlideSorterModel& rModel,
+ const PageEnumeration::PagePredicate& rPredicate)
+ : mrModel(rModel),
+ maPredicate(rPredicate),
+ mnIndex(0)
+{
+ Rewind();
+}
+
+
+
+
+PageEnumerationImpl::PageEnumerationImpl (
+ const SlideSorterModel& rModel,
+ const PageEnumeration::PagePredicate& rPredicate,
+ int nIndex)
+ : mrModel(rModel),
+ maPredicate(rPredicate),
+ mnIndex(nIndex)
+{
+}
+
+
+
+
+PageEnumerationImpl::~PageEnumerationImpl (void)
+{
+}
+
+
+
+
+::std::auto_ptr<Enumeration<SharedPageDescriptor> >
+ PageEnumerationImpl::Clone (void)
+{
+ return ::std::auto_ptr<Enumeration<SharedPageDescriptor> >(
+ new PageEnumerationImpl(mrModel,maPredicate,mnIndex));
+}
+
+
+
+
+bool PageEnumerationImpl::HasMoreElements (void) const
+{
+ return (mnIndex < mrModel.GetPageCount());
+}
+
+
+
+
+SharedPageDescriptor PageEnumerationImpl::GetNextElement (void)
+{
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnIndex));
+
+ // Go to the following valid element.
+ mnIndex += 1;
+ AdvanceToNextValidElement();
+
+ return pDescriptor;
+}
+
+
+
+
+void PageEnumerationImpl::Rewind (void)
+{
+ // Go to first valid element.
+ mnIndex = 0;
+ AdvanceToNextValidElement();
+}
+
+
+
+
+
+void PageEnumerationImpl::AdvanceToNextValidElement (void)
+{
+ while (mnIndex < mrModel.GetPageCount())
+ {
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnIndex));
+
+ // Test for the predicate being fullfilled.
+ if (pDescriptor.get()!=NULL && maPredicate(pDescriptor))
+ {
+ // This predicate is valid.
+ break;
+ }
+ else
+ {
+ // Advance to next predicate.
+ mnIndex += 1;
+ }
+ }
+}
+
+} // end of anonymous namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx b/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx
new file mode 100644
index 000000000000..15b44b1754ba
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageEnumeration.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include <boost/function.hpp>
+
+namespace sd { namespace slidesorter { namespace model {
+
+
+namespace {
+
+class AllPagesPredicate
+{
+public:
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ {
+ (void)rpDescriptor;
+ return true;
+ }
+};
+
+
+
+
+
+class SelectedPagesPredicate
+{
+public:
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ {
+ return rpDescriptor->IsSelected();
+ }
+};
+
+
+
+
+class VisiblePagesPredicate
+{
+public:
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ {
+ return rpDescriptor->IsVisible();
+ }
+};
+
+}
+
+
+
+
+PageEnumeration PageEnumerationProvider::CreateAllPagesEnumeration (
+ const SlideSorterModel& rModel)
+{
+// AllPagesPredicate aPredicate; // spurious warning on unxsoli4 debug=t
+ return PageEnumeration::Create(rModel, AllPagesPredicate());
+}
+
+
+
+
+PageEnumeration PageEnumerationProvider::CreateSelectedPagesEnumeration (
+ const SlideSorterModel& rModel)
+{
+ return PageEnumeration::Create(
+ rModel,
+ SelectedPagesPredicate());
+}
+
+
+
+
+PageEnumeration PageEnumerationProvider::CreateVisiblePagesEnumeration (
+ const SlideSorterModel& rModel)
+{
+ return PageEnumeration::Create(
+ rModel,
+ VisiblePagesPredicate());
+}
+
+
+} } } // end of namespace ::sd::slidesorter::model
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/model/makefile.mk b/sd/source/ui/slidesorter/model/makefile.mk
new file mode 100644
index 000000000000..9c8979fe3767
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/makefile.mk
@@ -0,0 +1,56 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slsmodel
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlsPageDescriptor.obj \
+ $(SLO)$/SlsPageEnumeration.obj \
+ $(SLO)$/SlsPageEnumerationProvider.obj \
+ $(SLO)$/SlideSorterModel.obj
+
+EXCEPTIONSFILES=
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sd/source/ui/slidesorter/shell/SlideSorter.cxx b/sd/source/ui/slidesorter/shell/SlideSorter.cxx
new file mode 100644
index 000000000000..7fa314ae34fb
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorter.cxx
@@ -0,0 +1,654 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlideSorter.hxx"
+
+#include "SlideSorterChildWindow.hrc"
+#include "SlideSorterViewShell.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "view/SlideSorterView.hxx"
+#include "model/SlideSorterModel.hxx"
+
+#include "glob.hrc"
+#include "DrawController.hxx"
+#include "ViewShellBase.hxx"
+#include "ViewShellManager.hxx"
+#include "Window.hxx"
+
+#include <vcl/scrbar.hxx>
+#include <vcl/svapp.hxx>
+
+#include <sfx2/dispatch.hxx>
+#include "sdresid.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+
+namespace sd { namespace slidesorter {
+
+namespace {
+class ContentWindow : public ::sd::Window
+{
+public:
+ ContentWindow(::Window& rParent, SlideSorter& rSlideSorter);
+ ~ContentWindow (void);
+ void SetCurrentFunction (const FunctionReference& rpFunction);
+ virtual void Paint(const Rectangle& rRect);
+ virtual void KeyInput (const KeyEvent& rEvent);
+ virtual void MouseMove (const MouseEvent& rEvent);
+ virtual void MouseButtonUp (const MouseEvent& rEvent);
+ virtual void MouseButtonDown (const MouseEvent& rEvent);
+ virtual void Command (const CommandEvent& rEvent);
+ virtual long Notify (NotifyEvent& rEvent);
+
+private:
+ SlideSorter& mrSlideSorter;
+ FunctionReference mpCurrentFunction;
+};
+}
+
+
+
+
+//===== SlideSorter ===========================================================
+
+::boost::shared_ptr<SlideSorter> SlideSorter::CreateSlideSorter(
+ ViewShell& rViewShell,
+ const ::boost::shared_ptr<sd::Window>& rpContentWindow,
+ const ::boost::shared_ptr<ScrollBar>& rpHorizontalScrollBar,
+ const ::boost::shared_ptr<ScrollBar>& rpVerticalScrollBar,
+ const ::boost::shared_ptr<ScrollBarBox>& rpScrollBarBox)
+{
+ ::boost::shared_ptr<SlideSorter> pSlideSorter(
+ new SlideSorter(
+ rViewShell,
+ rpContentWindow,
+ rpHorizontalScrollBar,
+ rpVerticalScrollBar,
+ rpScrollBarBox));
+ pSlideSorter->Init();
+ return pSlideSorter;
+}
+
+
+
+
+::boost::shared_ptr<SlideSorter> SlideSorter::CreateSlideSorter (
+ ViewShellBase& rBase,
+ ViewShell* pViewShell,
+ ::Window& rParentWindow)
+{
+ ::boost::shared_ptr<SlideSorter> pSlideSorter(
+ new SlideSorter(
+ rBase,
+ pViewShell,
+ rParentWindow));
+ pSlideSorter->Init();
+ return pSlideSorter;
+}
+
+
+
+
+SlideSorter::SlideSorter (
+ ViewShell& rViewShell,
+ const ::boost::shared_ptr<sd::Window>& rpContentWindow,
+ const ::boost::shared_ptr<ScrollBar>& rpHorizontalScrollBar,
+ const ::boost::shared_ptr<ScrollBar>& rpVerticalScrollBar,
+ const ::boost::shared_ptr<ScrollBarBox>& rpScrollBarBox)
+ : mbIsValid(false),
+ mpSlideSorterController(),
+ mpSlideSorterModel(),
+ mpSlideSorterView(),
+ mxControllerWeak(),
+ mpViewShell(&rViewShell),
+ mpViewShellBase(&rViewShell.GetViewShellBase()),
+ mpContentWindow(rpContentWindow),
+ mpHorizontalScrollBar(rpHorizontalScrollBar),
+ mpVerticalScrollBar(rpVerticalScrollBar),
+ mpScrollBarBox(rpScrollBarBox),
+ mbLayoutPending(true)
+{
+}
+
+
+
+
+SlideSorter::SlideSorter (
+ ViewShellBase& rBase,
+ ViewShell* pViewShell,
+ ::Window& rParentWindow)
+ : mbIsValid(false),
+ mpSlideSorterController(),
+ mpSlideSorterModel(),
+ mpSlideSorterView(),
+ mxControllerWeak(),
+ mpViewShell(pViewShell),
+ mpViewShellBase(&rBase),
+ mpContentWindow(new ContentWindow(rParentWindow,*this )),
+ mpHorizontalScrollBar(new ScrollBar(&rParentWindow,WinBits(WB_HSCROLL | WB_DRAG))),
+ mpVerticalScrollBar(new ScrollBar(&rParentWindow,WinBits(WB_VSCROLL | WB_DRAG))),
+ mpScrollBarBox(new ScrollBarBox(&rParentWindow)),
+ mbLayoutPending(true)
+{
+}
+
+
+
+
+void SlideSorter::Init (void)
+{
+ if (mpViewShellBase != NULL)
+ mxControllerWeak = mpViewShellBase->GetController();
+
+ CreateModelViewController ();
+
+ SetupListeners ();
+
+ // Initialize the window.
+ ::sd::Window* pWindow = GetActiveWindow();
+ if (pWindow != NULL)
+ {
+ ::Window* pParentWindow = pWindow->GetParent();
+ if (pParentWindow != NULL)
+ pParentWindow->SetBackground(Wallpaper());
+ pWindow->SetBackground(Wallpaper());
+ pWindow->SetViewOrigin (Point(0,0));
+ // We do our own scrolling while dragging a page selection.
+ pWindow->SetUseDropScroll (false);
+ // Change the winbits so that the active window accepts the focus.
+ pWindow->SetStyle ((pWindow->GetStyle() & ~WB_DIALOGCONTROL) | WB_TABSTOP);
+ pWindow->Hide();
+
+ // Set view pointer of base class.
+ SetupControls(pParentWindow);
+
+ mbIsValid = true;
+ }
+}
+
+
+
+
+SlideSorter::~SlideSorter (void)
+{
+ mbIsValid = false;
+
+ ReleaseListeners();
+
+ // Reset the auto pointers explicitly to control the order of destruction.
+ mpSlideSorterController.reset();
+ mpSlideSorterView.reset();
+ mpSlideSorterModel.reset();
+
+ mpHorizontalScrollBar.reset();
+ mpVerticalScrollBar.reset();
+ mpScrollBarBox.reset();
+ mpContentWindow.reset();
+}
+
+
+
+
+bool SlideSorter::IsValid (void) const
+{
+ return mbIsValid;
+}
+
+
+
+
+::boost::shared_ptr<ScrollBar> SlideSorter::GetVerticalScrollBar (void) const
+{
+ return mpVerticalScrollBar;
+}
+
+
+
+
+
+::boost::shared_ptr<ScrollBar> SlideSorter::GetHorizontalScrollBar (void) const
+{
+ return mpHorizontalScrollBar;
+}
+
+
+
+
+::boost::shared_ptr<ScrollBarBox> SlideSorter::GetScrollBarFiller (void) const
+{
+ return mpScrollBarBox;
+}
+
+
+
+
+model::SlideSorterModel& SlideSorter::GetModel (void) const
+{
+ OSL_ASSERT(mpSlideSorterModel.get()!=NULL);
+ return *mpSlideSorterModel;
+}
+
+
+
+
+view::SlideSorterView& SlideSorter::GetView (void) const
+{
+ OSL_ASSERT(mpSlideSorterView.get()!=NULL);
+ return *mpSlideSorterView;
+}
+
+
+
+
+controller::SlideSorterController& SlideSorter::GetController (void) const
+{
+ OSL_ASSERT(mpSlideSorterController.get()!=NULL);
+ return *mpSlideSorterController;
+}
+
+
+
+
+Reference<frame::XController> SlideSorter::GetXController (void) const
+{
+ Reference<frame::XController> xController(mxControllerWeak);
+ return xController;
+}
+
+
+
+
+void SlideSorter::Paint (const Rectangle& rRepaintArea)
+{
+ GetController().Paint(
+ rRepaintArea,
+ GetContentWindow().get());
+}
+
+
+
+
+::boost::shared_ptr<sd::Window> SlideSorter::GetContentWindow (void) const
+{
+ return mpContentWindow;
+}
+
+
+
+
+::sd::Window* SlideSorter::GetActiveWindow (void) const
+{
+ if (mpViewShell != NULL)
+ return mpViewShell->GetActiveWindow();
+ else
+ return mpContentWindow.get();
+}
+
+
+
+
+ViewShellBase* SlideSorter::GetViewShellBase (void) const
+{
+ return mpViewShellBase;
+}
+
+
+
+
+ViewShell* SlideSorter::GetViewShell (void) const
+{
+ return mpViewShell;
+}
+
+
+
+
+void SlideSorter::SetupControls (::Window* )
+{
+ GetVerticalScrollBar()->Show();
+ mpSlideSorterController->GetScrollBarManager().LateInitialization();
+}
+
+
+
+
+void SlideSorter::SetupListeners (void)
+{
+ ::sd::Window* pWindow = GetActiveWindow();
+ if (pWindow != NULL)
+ {
+ ::Window* pParentWindow = pWindow->GetParent();
+ if (pParentWindow != NULL)
+ pParentWindow->AddEventListener(
+ LINK(
+ mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+ pWindow->AddEventListener(
+ LINK(
+ mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+ }
+ Application::AddEventListener(
+ LINK(
+ mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+
+ mpSlideSorterController->GetScrollBarManager().Connect();
+}
+
+
+
+
+void SlideSorter::ReleaseListeners (void)
+{
+ mpSlideSorterController->GetScrollBarManager().Disconnect();
+
+ ::sd::Window* pWindow = GetActiveWindow();
+ if (pWindow != NULL)
+ {
+
+ pWindow->RemoveEventListener(
+ LINK(mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+
+ ::Window* pParentWindow = pWindow->GetParent();
+ if (pParentWindow != NULL)
+ pParentWindow->RemoveEventListener(
+ LINK(mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+ }
+ Application::RemoveEventListener(
+ LINK(mpSlideSorterController.get(),
+ controller::SlideSorterController,
+ WindowEventHandler));
+}
+
+
+
+
+void SlideSorter::CreateModelViewController (void)
+{
+ mpSlideSorterModel.reset(CreateModel());
+ DBG_ASSERT (mpSlideSorterModel.get()!=NULL,
+ "Can not create model for slide browser");
+
+ mpSlideSorterView.reset(CreateView());
+ DBG_ASSERT (mpSlideSorterView.get()!=NULL,
+ "Can not create view for slide browser");
+
+ mpSlideSorterController.reset(CreateController());
+ DBG_ASSERT (mpSlideSorterController.get()!=NULL,
+ "Can not create controller for slide browser");
+ mpSlideSorterController->Init();
+}
+
+
+
+
+model::SlideSorterModel* SlideSorter::CreateModel (void)
+{
+ // Get pointers to the document.
+ ViewShellBase* pViewShellBase = GetViewShellBase();
+ if (pViewShellBase != NULL)
+ {
+ OSL_ASSERT (pViewShellBase->GetDocument() != NULL);
+
+ return new model::SlideSorterModel(*this);
+ }
+ else
+ return NULL;
+}
+
+
+
+
+view::SlideSorterView* SlideSorter::CreateView (void)
+{
+ return new view::SlideSorterView (*this);
+}
+
+
+
+
+controller::SlideSorterController* SlideSorter::CreateController (void)
+{
+ controller::SlideSorterController* pController
+ = new controller::SlideSorterController (*this);
+ return pController;
+}
+
+
+
+
+void SlideSorter::ArrangeGUIElements (
+ const Point& rOffset,
+ const Size& rSize)
+{
+ Point aOrigin (rOffset);
+
+ if (rSize.Width()!=0 && rSize.Height()!=0)
+ {
+ // Prevent untimely redraws while the view is not yet correctly
+ // resized.
+ mpSlideSorterView->LockRedraw (TRUE);
+ if (GetActiveWindow() != NULL)
+ GetActiveWindow()->EnablePaint (FALSE);
+
+ // maAllWindowRectangle =
+ mpSlideSorterController->Resize (Rectangle(aOrigin, rSize));
+
+ if (GetActiveWindow() != NULL)
+ GetActiveWindow()->EnablePaint (TRUE);
+
+ mbLayoutPending = false;
+ mpSlideSorterView->LockRedraw (FALSE);
+ }
+ else
+ {
+ // maAllWindowRectangle = Rectangle();
+ }
+}
+
+
+
+
+SvBorder SlideSorter::GetBorder (void)
+{
+ SvBorder aBorder;
+
+ ::boost::shared_ptr<ScrollBar> pScrollBar = GetVerticalScrollBar();
+ if (pScrollBar.get() != NULL && pScrollBar->IsVisible())
+ aBorder.Right() = pScrollBar->GetOutputSizePixel().Width();
+
+ pScrollBar = GetHorizontalScrollBar();
+ if (pScrollBar.get() != NULL && pScrollBar->IsVisible())
+ aBorder.Bottom() = pScrollBar->GetOutputSizePixel().Height();
+
+ return aBorder;
+}
+
+
+
+
+bool SlideSorter::RelocateToWindow (::Window* pParentWindow)
+{
+ ReleaseListeners();
+
+ if (mpViewShell != NULL)
+ mpViewShell->ViewShell::RelocateToParentWindow(pParentWindow);
+
+ SetupControls(mpViewShell->GetParentWindow());
+ SetupListeners();
+
+ // For accessibility we have to shortly hide the content window. This
+ // triggers the construction of a new accessibility object for the new
+ // view shell. (One is created earlier while the construtor of the base
+ // class is executed. At that time the correct accessibility object can
+ // not be constructed.)
+ if (mpContentWindow.get() !=NULL)
+ {
+ mpContentWindow->Hide();
+ mpContentWindow->Show();
+ }
+
+ return true;
+}
+
+
+
+
+void SlideSorter::SetCurrentFunction (const FunctionReference& rpFunction)
+{
+ if (GetViewShell() != NULL)
+ {
+ GetViewShell()->SetCurrentFunction(rpFunction);
+ GetViewShell()->SetOldFunction(rpFunction);
+ }
+ else
+ {
+ ::boost::shared_ptr<ContentWindow> pWindow
+ = ::boost::dynamic_pointer_cast<ContentWindow>(GetContentWindow());
+ if (pWindow.get() != NULL)
+ pWindow->SetCurrentFunction(rpFunction);
+ }
+}
+
+
+
+
+//===== ContentWindow =========================================================
+
+namespace {
+
+ContentWindow::ContentWindow(
+ ::Window& rParent,
+ SlideSorter& rSlideSorter)
+ : ::sd::Window(&rParent),
+ mrSlideSorter(rSlideSorter),
+ mpCurrentFunction()
+{
+ SetDialogControlFlags(GetDialogControlFlags() & ~WINDOW_DLGCTRL_WANTFOCUS);
+ SetStyle(GetStyle() | WB_NOPOINTERFOCUS);
+}
+
+
+
+
+ContentWindow::~ContentWindow (void)
+{
+}
+
+
+
+
+void ContentWindow::SetCurrentFunction (const FunctionReference& rpFunction)
+{
+ mpCurrentFunction = rpFunction;
+}
+
+
+
+
+void ContentWindow::Paint (const Rectangle& rRect)
+{
+ mrSlideSorter.Paint(rRect);
+}
+
+
+
+
+void ContentWindow::KeyInput (const KeyEvent& rEvent)
+{
+ if (mpCurrentFunction.is())
+ mpCurrentFunction->KeyInput(rEvent);
+}
+
+
+
+
+void ContentWindow::MouseMove (const MouseEvent& rEvent)
+{
+ if (mpCurrentFunction.is())
+ mpCurrentFunction->MouseMove(rEvent);
+}
+
+
+
+
+void ContentWindow::MouseButtonUp(const MouseEvent& rEvent)
+{
+ if (mpCurrentFunction.is())
+ mpCurrentFunction->MouseButtonUp(rEvent);
+}
+
+
+
+
+void ContentWindow::MouseButtonDown(const MouseEvent& rEvent)
+{
+ if (mpCurrentFunction.is())
+ mpCurrentFunction->MouseButtonDown(rEvent);
+}
+
+
+
+
+void ContentWindow::Command(const CommandEvent& rEvent)
+{
+ if (mpCurrentFunction.is())
+ mpCurrentFunction->Command(rEvent);
+}
+
+
+
+
+long ContentWindow::Notify (NotifyEvent& rEvent)
+{
+ (void)rEvent;
+ return 0;
+}
+
+
+
+
+} // end of anonymous namespace
+
+
+} } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.cxx b/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.cxx
new file mode 100644
index 000000000000..28334244ca5a
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "SlideSorterChildWindow.hxx"
+
+#include "app.hrc"
+#include "sfx2/app.hxx"
+#include <sfx2/dockwin.hxx>
+
+#include "SlideSorter.hxx"
+
+namespace sd { namespace slidesorter {
+
+SlideSorterChildWindow::SlideSorterChildWindow (
+ ::Window* pParentWindow,
+ USHORT nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo)
+ : SfxChildWindow (pParentWindow, nId)
+{
+ pWindow = new SlideSorter (
+ pBindings,
+ this,
+ pParentWindow);
+ eChildAlignment = SFX_ALIGN_LEFT;
+ static_cast<SfxDockingWindow*>(pWindow)->Initialize (pInfo);
+ // SetHideNotDelete (TRUE);
+}
+
+
+
+
+SlideSorterChildWindow::~SlideSorterChildWindow (void)
+{}
+
+
+SFX_IMPL_DOCKINGWINDOW(SlideSorterChildWindow, SID_SLIDE_BROWSER)
+
+} } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.src b/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.src
new file mode 100644
index 000000000000..490e9dde1c2b
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterChildWindow.src
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "app.hrc"
+#include "SlideSorterChildWindow.hrc"
+
+DockingWindow FLT_WIN_SLIDE_BROWSER
+{
+ HelpID = SID_SLIDE_BROWSER;
+ Border = TRUE ;
+ Hide = FALSE ;
+ SVLook = TRUE ;
+ Sizeable = TRUE ;
+ Moveable = TRUE ;
+ Closeable = TRUE ;
+ Zoomable = TRUE ;
+ Dockable = TRUE ;
+ EnableResizing = TRUE ;
+ Size = MAP_APPFONT ( 140 , 120 ) ;
+ Text = "Slide Browser" ;
+
+ Control TOOLPANEL
+ {
+ Pos = MAP_APPFONT ( 0 , 0 ) ;
+ Size = MAP_APPFONT ( 69, 150 ) ;
+ Border = FALSE;
+ };
+};
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterService.cxx b/sd/source/ui/slidesorter/shell/SlideSorterService.cxx
new file mode 100644
index 000000000000..16c60e9f213f
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterService.cxx
@@ -0,0 +1,650 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlideSorterService.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "DrawController.hxx"
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <cppuhelper/proptypehlp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+using ::rtl::OUString;
+using ::sd::slidesorter::view::SlideSorterView;
+
+namespace sd { namespace slidesorter {
+
+namespace {
+ enum Properties
+ {
+ PropertyDocumentSlides,
+ PropertyHighlightCurrentSlide,
+ PropertyShowSelection,
+ PropertyCenterSelection,
+ PropertySuspendPreviewUpdatesDuringFullScreenPresentation,
+ PropertyOrientationVertical
+ };
+}
+
+
+
+
+//===== Service ===============================================================
+
+Reference<XInterface> SAL_CALL SlideSorterService_createInstance (
+ const Reference<XComponentContext>& rxContext)
+{
+ return Reference<XInterface>(static_cast<drawing::XDrawView*>(new SlideSorterService(rxContext)));
+}
+
+
+
+
+::rtl::OUString SlideSorterService_getImplementationName (void) throw(RuntimeException)
+{
+ return OUString::createFromAscii("com.sun.star.comp.Draw.SlideSorter");
+}
+
+
+
+
+Sequence<rtl::OUString> SAL_CALL SlideSorterService_getSupportedServiceNames (void)
+ throw (RuntimeException)
+{
+ static const ::rtl::OUString sServiceName(
+ ::rtl::OUString::createFromAscii("com.sun.star.drawing.SlideSorter"));
+ return Sequence<rtl::OUString>(&sServiceName, 1);
+}
+
+
+
+
+//===== SlideSorterService ==========================================================
+
+SlideSorterService::SlideSorterService (const Reference<XComponentContext>& rxContext)
+ : SlideSorterServiceInterfaceBase(m_aMutex),
+ mpSlideSorter(),
+ mxParentWindow()
+{
+ (void)rxContext;
+}
+
+
+
+
+SlideSorterService::~SlideSorterService (void)
+{
+}
+
+
+
+
+void SAL_CALL SlideSorterService::disposing (void)
+{
+ mpSlideSorter.reset();
+
+ if (mxParentWindow.is())
+ {
+ mxParentWindow->removeWindowListener(this);
+ }
+}
+
+
+
+
+//----- XInitialization -------------------------------------------------------
+
+void SAL_CALL SlideSorterService::initialize (const Sequence<Any>& rArguments)
+ throw (Exception, RuntimeException)
+{
+ ThrowIfDisposed();
+
+ if (rArguments.getLength() == 3)
+ {
+ try
+ {
+ mxViewId = Reference<XResourceId>(rArguments[0], UNO_QUERY_THROW);
+
+ // Get the XController.
+ Reference<frame::XController> xController (rArguments[1], UNO_QUERY_THROW);
+
+ // Tunnel through the controller to obtain a ViewShellBase.
+ ViewShellBase* pBase = NULL;
+ Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
+ ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
+ xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
+ if (pController != NULL)
+ pBase = pController->GetViewShellBase();
+
+ // Get the parent window.
+ mxParentWindow = Reference<awt::XWindow>(rArguments[2], UNO_QUERY_THROW);
+ ::Window* pParentWindow = VCLUnoHelper::GetWindow(mxParentWindow);
+
+ mxParentWindow->addWindowListener(this);
+
+ if (pBase != NULL && pParentWindow!=NULL)
+ mpSlideSorter = SlideSorter::CreateSlideSorter(
+ *pBase,
+ NULL,
+ *pParentWindow);
+
+ Resize();
+ }
+ catch (RuntimeException&)
+ {
+ throw;
+ }
+ }
+ else
+ {
+ throw RuntimeException(
+ OUString::createFromAscii("SlideSorterService: invalid number of arguments"),
+ static_cast<drawing::XDrawView*>(this));
+ }
+}
+
+
+
+
+//----- XView -----------------------------------------------------------------
+
+Reference<XResourceId> SAL_CALL SlideSorterService::getResourceId (void)
+ throw (RuntimeException)
+{
+ return mxViewId;
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::isAnchorOnly (void)
+ throw (RuntimeException)
+{
+ return sal_False;
+}
+
+
+
+
+//----- XWindowListener -------------------------------------------------------
+
+void SAL_CALL SlideSorterService::windowResized (const awt::WindowEvent& rEvent)
+ throw (RuntimeException)
+{
+ (void)rEvent;
+ ThrowIfDisposed();
+
+ Resize();
+}
+
+
+
+
+
+void SAL_CALL SlideSorterService::windowMoved (const awt::WindowEvent& rEvent)
+ throw (RuntimeException)
+{
+ (void)rEvent;
+}
+
+
+
+
+void SAL_CALL SlideSorterService::windowShown (const lang::EventObject& rEvent)
+ throw (RuntimeException)
+{
+ (void)rEvent;
+ ThrowIfDisposed();
+ Resize();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::windowHidden (const lang::EventObject& rEvent)
+ throw (RuntimeException)
+{
+ (void)rEvent;
+ ThrowIfDisposed();
+}
+
+
+
+
+//----- lang::XEventListener --------------------------------------------------
+
+void SAL_CALL SlideSorterService::disposing (const lang::EventObject& rEvent)
+ throw (RuntimeException)
+{
+ if (rEvent.Source == mxParentWindow)
+ mxParentWindow = NULL;
+}
+
+
+
+
+//----- XDrawView -------------------------------------------------------------
+
+void SAL_CALL SlideSorterService::setCurrentPage(const Reference<drawing::XDrawPage>& rxSlide)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL)
+ mpSlideSorter->GetController().GetCurrentSlideManager()->CurrentSlideHasChanged(
+ mpSlideSorter->GetModel().GetIndex(rxSlide));
+}
+
+
+
+
+Reference<drawing::XDrawPage> SAL_CALL SlideSorterService::getCurrentPage (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL)
+ return mpSlideSorter->GetController().GetCurrentSlideManager()->GetCurrentSlide()->GetXDrawPage();
+ else
+ return NULL;
+}
+
+
+
+
+//----- attributes ------------------------------------------------------------
+
+
+Reference<container::XIndexAccess> SAL_CALL SlideSorterService::getDocumentSlides (void)
+ throw (RuntimeException)
+{
+ return mpSlideSorter->GetModel().GetDocumentSlides();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setDocumentSlides (
+ const Reference<container::XIndexAccess >& rxSlides)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().SetDocumentSlides(rxSlides);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsHighlightCurrentSlide (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsHighlightCurrentSlide();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsHighlightCurrentSlide (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ {
+ mpSlideSorter->GetController().GetProperties()->SetHighlightCurrentSlide(bValue);
+ controller::SlideSorterController::ModelChangeLock aLock (mpSlideSorter->GetController());
+ mpSlideSorter->GetController().HandleModelChange();
+ }
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsShowSelection (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsShowSelection();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsShowSelection (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetShowSelection(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsShowFocus (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsShowFocus();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsShowFocus (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetShowFocus(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsCenterSelection (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsCenterSelection();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsCenterSelection (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetCenterSelection(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsSuspendPreviewUpdatesDuringFullScreenPresentation (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return true;
+ else
+ return mpSlideSorter->GetController().GetProperties()
+ ->IsSuspendPreviewUpdatesDuringFullScreenPresentation();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsSuspendPreviewUpdatesDuringFullScreenPresentation (
+ sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()
+ ->SetSuspendPreviewUpdatesDuringFullScreenPresentation(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsOrientationVertical (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return true;
+ else
+ return mpSlideSorter->GetView().GetOrientation() == SlideSorterView::VERTICAL;
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsOrientationVertical (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetView().SetOrientation(bValue
+ ? SlideSorterView::VERTICAL
+ : SlideSorterView::HORIZONTAL);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsSmoothScrolling (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsSmoothSelectionScrolling();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsSmoothScrolling (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetSmoothSelectionScrolling(bValue);
+}
+
+
+
+
+util::Color SAL_CALL SlideSorterService::getBackgroundColor (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return util::Color();
+ else
+ return util::Color(
+ mpSlideSorter->GetController().GetProperties()->GetBackgroundColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setBackgroundColor (util::Color aBackgroundColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetBackgroundColor(
+ Color(aBackgroundColor));
+}
+
+
+
+
+util::Color SAL_CALL SlideSorterService::getTextColor (void)
+ throw (css::uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return util::Color();
+ else
+ return util::Color(
+ mpSlideSorter->GetController().GetProperties()->GetTextColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setTextColor (util::Color aTextColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetTextColor(
+ Color(aTextColor));
+}
+
+
+
+
+util::Color SAL_CALL SlideSorterService::getSelectionColor (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return util::Color();
+ else
+ return util::Color(
+ mpSlideSorter->GetController().GetProperties()->GetSelectionColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setSelectionColor (util::Color aSelectionColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetSelectionColor(
+ Color(aSelectionColor));
+}
+
+
+
+
+util::Color SAL_CALL SlideSorterService::getHighlightColor (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return util::Color();
+ else
+ return util::Color(
+ mpSlideSorter->GetController().GetProperties()->GetHighlightColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setHighlightColor (util::Color aHighlightColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetHighlightColor(
+ Color(aHighlightColor));
+}
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsUIReadOnly (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return true;
+ else
+ return mpSlideSorter->GetController().GetProperties()->IsUIReadOnly();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsUIReadOnly (sal_Bool bIsUIReadOnly)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetController().GetProperties()->SetUIReadOnly(
+ bIsUIReadOnly);
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+
+void SlideSorterService::Resize (void)
+{
+ if (mxParentWindow.is())
+ {
+ awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
+ mpSlideSorter->ArrangeGUIElements(
+ Point(0,0),
+ Size(aWindowBox.Width, aWindowBox.Height));
+ }
+}
+
+
+
+
+void SlideSorterService::ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (SlideSorterServiceInterfaceBase::rBHelper.bDisposed || SlideSorterServiceInterfaceBase::rBHelper.bInDispose)
+ {
+ throw lang::DisposedException (
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SlideSorterService object has already been disposed")),
+ static_cast<drawing::XDrawView*>(this));
+ }
+}
+
+
+} } // end of namespace ::sd::presenter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterService.hxx b/sd/source/ui/slidesorter/shell/SlideSorterService.hxx
new file mode 100644
index 000000000000..cbbee0e1c94a
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterService.hxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_SERVICE_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_SERVICE_HXX
+
+#include "SlideSorter.hxx"
+
+#include "tools/PropertySet.hxx"
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/drawing/SlideSorter.hpp>
+#include <com/sun/star/drawing/XDrawView.hpp>
+#include <com/sun/star/drawing/framework/XView.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase3.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace css = ::com::sun::star;
+
+namespace sd { namespace slidesorter {
+
+namespace {
+ typedef ::cppu::WeakComponentImplHelper3 <
+ css::drawing::XSlideSorterBase,
+ css::lang::XInitialization,
+ css::awt::XWindowListener
+ > SlideSorterServiceInterfaceBase;
+}
+
+
+/** Implementation of the com.sun.star.drawing.SlideSorter service.
+*/
+class SlideSorterService
+ : private ::boost::noncopyable,
+ protected ::cppu::BaseMutex,
+ public SlideSorterServiceInterfaceBase
+{
+public:
+ explicit SlideSorterService (
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext);
+ virtual ~SlideSorterService (void);
+ virtual void SAL_CALL disposing (void);
+
+
+ // XInitialization
+
+ virtual void SAL_CALL initialize (const css::uno::Sequence<css::uno::Any>& rArguments)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+
+ // XResourceId
+
+ css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void)
+ throw (css::uno::RuntimeException);
+
+ sal_Bool SAL_CALL isAnchorOnly (void)
+ throw (css::uno::RuntimeException);
+
+
+ // XWindowListener
+
+ virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent)
+ throw (css::uno::RuntimeException);
+
+
+ // lang::XEventListener
+ virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
+ throw (css::uno::RuntimeException);
+
+
+ // XDrawView
+
+ virtual void SAL_CALL setCurrentPage(
+ const css::uno::Reference<css::drawing::XDrawPage>& rxSlide)
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void)
+ throw (css::uno::RuntimeException);
+
+
+ // Attributes
+
+ virtual css::uno::Reference<css::container::XIndexAccess> SAL_CALL getDocumentSlides (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setDocumentSlides (
+ const css::uno::Reference<css::container::XIndexAccess >& rxSlides)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsHighlightCurrentSlide (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsHighlightCurrentSlide (::sal_Bool bIsHighlightCurrentSlide)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsShowSelection (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsShowSelection (sal_Bool bIsShowSelection)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsCenterSelection (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsCenterSelection (sal_Bool bIsCenterSelection)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsSuspendPreviewUpdatesDuringFullScreenPresentation (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsSuspendPreviewUpdatesDuringFullScreenPresentation (
+ sal_Bool bIsSuspendPreviewUpdatesDuringFullScreenPresentation)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsOrientationVertical (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsOrientationVertical (sal_Bool bIsOrientationVertical)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsSmoothScrolling (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsSmoothScrolling (sal_Bool bIsOrientationVertical)
+ throw (css::uno::RuntimeException);
+
+ virtual css::util::Color SAL_CALL getBackgroundColor (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setBackgroundColor (css::util::Color aBackgroundColor)
+ throw (css::uno::RuntimeException);
+
+ virtual css::util::Color SAL_CALL getTextColor (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setTextColor (css::util::Color aTextColor)
+ throw (css::uno::RuntimeException);
+
+ virtual css::util::Color SAL_CALL getSelectionColor (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setSelectionColor (css::util::Color aSelectionColor)
+ throw (css::uno::RuntimeException);
+
+ virtual css::util::Color SAL_CALL getHighlightColor (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setHighlightColor (css::util::Color aHighlightColor)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsUIReadOnly (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsUIReadOnly (sal_Bool bIsUIReadOnly)
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL getIsShowFocus (void)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setIsShowFocus (sal_Bool bIsShowFocus)
+ throw (css::uno::RuntimeException);
+
+private:
+ ::boost::shared_ptr<SlideSorter> mpSlideSorter;
+ css::uno::Reference<css::drawing::framework::XResourceId> mxViewId;
+ css::uno::Reference<css::awt::XWindow> mxParentWindow;
+ ::boost::scoped_ptr<cppu::IPropertyArrayHelper> mpPropertyArrayHelper;
+
+ void Resize (void);
+
+ /** This method throws a DisposedException when the object has already been
+ disposed.
+ */
+ void ThrowIfDisposed (void) throw (css::lang::DisposedException);
+};
+
+} } // end of namespace ::sd::slidesorter
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
new file mode 100644
index 000000000000..afdc634c54d2
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
@@ -0,0 +1,787 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "SlideSorterViewShell.hxx"
+#include "ViewShellImplementation.hxx"
+
+#include "SlideSorter.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsClipboard.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumeration.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "ViewShellBase.hxx"
+#include "drawdoc.hxx"
+#include "app.hrc"
+#include "glob.hrc"
+#include "sdattr.hrc"
+#include "sdresid.hxx"
+#include "AccessibleSlideSorterView.hxx"
+#include "DrawDocShell.hxx"
+#include "FrameView.hxx"
+#include "SdUnoSlideView.hxx"
+#include "ViewShellManager.hxx"
+#include "Window.hxx"
+#include <sfx2/app.hxx>
+#include <sfx2/msg.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/request.hxx>
+#include <svx/svxids.hrc>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/drawing/framework/ResourceId.hpp>
+#include <cppuhelper/bootstrap.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace ::sd::slidesorter;
+#define SlideSorterViewShell
+#include "sdslots.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::sd::framework::FrameworkHelper;
+
+namespace sd { namespace slidesorter {
+
+
+SFX_IMPL_INTERFACE(SlideSorterViewShell, SfxShell, SdResId(STR_SLIDESORTERVIEWSHELL))
+{
+}
+
+
+
+TYPEINIT1(SlideSorterViewShell, ViewShell);
+
+
+
+::boost::shared_ptr<SlideSorterViewShell> SlideSorterViewShell::Create (
+ SfxViewFrame* pFrame,
+ ViewShellBase& rViewShellBase,
+ ::Window* pParentWindow,
+ FrameView* pFrameViewArgument)
+{
+ ::boost::shared_ptr<SlideSorterViewShell> pViewShell;
+ try
+ {
+ pViewShell.reset(
+ new SlideSorterViewShell(pFrame,rViewShellBase,pParentWindow,pFrameViewArgument));
+ pViewShell->Initialize();
+ if (pViewShell->mpSlideSorter.get() == NULL)
+ pViewShell.reset();
+ }
+ catch(Exception&)
+ {
+ pViewShell.reset();
+ }
+ return pViewShell;
+}
+
+
+
+
+SlideSorterViewShell::SlideSorterViewShell (
+ SfxViewFrame* pFrame,
+ ViewShellBase& rViewShellBase,
+ ::Window* pParentWindow,
+ FrameView* pFrameViewArgument)
+ : ViewShell (pFrame, pParentWindow, rViewShellBase),
+ mpSlideSorter()
+{
+ meShellType = ST_SLIDE_SORTER;
+
+ SetPool( &GetDoc()->GetPool() );
+ SetUndoManager( GetDoc()->GetDocSh()->GetUndoManager() );
+
+ if (pFrameViewArgument != NULL)
+ mpFrameView = pFrameViewArgument;
+ else
+ mpFrameView = new FrameView(GetDoc());
+ GetFrameView()->Connect();
+
+ SetName (String (RTL_CONSTASCII_USTRINGPARAM("SlideSorterViewShell")));
+
+ pParentWindow->SetStyle(pParentWindow->GetStyle() | WB_DIALOGCONTROL);
+}
+
+
+
+
+SlideSorterViewShell::~SlideSorterViewShell (void)
+{
+ DisposeFunctions();
+
+ try
+ {
+ ::sd::Window* pWindow = GetActiveWindow();
+ if (pWindow!=NULL)
+ {
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XComponent> xComponent (
+ pWindow->GetAccessible(false),
+ ::com::sun::star::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+ }
+ catch( ::com::sun::star::uno::Exception& e )
+ {
+ (void)e;
+ DBG_ERROR("sd::SlideSorterViewShell::~SlideSorterViewShell(), exception caught!" );
+ }
+}
+
+
+
+
+
+void SlideSorterViewShell::Initialize (void)
+{
+ mpSlideSorter = SlideSorter::CreateSlideSorter(
+ *this,
+ mpContentWindow,
+ mpHorizontalScrollBar,
+ mpVerticalScrollBar,
+ mpScrollBarBox);
+ mpView = &mpSlideSorter->GetView();
+
+ // For accessibility we have to shortly hide the content window.
+ // This triggers the construction of a new accessibility object for
+ // the new view shell. (One is created earlier while the construtor
+ // of the base class is executed. At that time the correct
+ // accessibility object can not be constructed.)
+ ::Window* pWindow = mpSlideSorter->GetActiveWindow();
+ if (pWindow != NULL)
+ {
+ pWindow->Hide();
+ pWindow->Show();
+ }
+}
+
+
+
+
+void SlideSorterViewShell::Init (bool bIsMainViewShell)
+{
+ ViewShell::Init(bIsMainViewShell);
+
+ mpSlideSorter->GetModel().UpdatePageList();
+
+ if (mpContentWindow.get() != NULL)
+ mpContentWindow->SetViewShell(this);
+}
+
+
+
+
+SlideSorterViewShell* SlideSorterViewShell::GetSlideSorter (ViewShellBase& rBase)
+{
+ SlideSorterViewShell* pViewShell = NULL;
+
+ // Test the center, left, and then the right pane for showing a slide sorter.
+ ::rtl::OUString aPaneURLs[] = {
+ FrameworkHelper::msCenterPaneURL,
+ FrameworkHelper::msFullScreenPaneURL,
+ FrameworkHelper::msLeftImpressPaneURL,
+ FrameworkHelper::msRightPaneURL,
+ ::rtl::OUString()};
+
+ try
+ {
+ ::boost::shared_ptr<FrameworkHelper> pFrameworkHelper (FrameworkHelper::Instance(rBase));
+ if (pFrameworkHelper->IsValid())
+ for (int i=0; pViewShell==NULL && aPaneURLs[i].getLength()>0; ++i)
+ {
+ pViewShell = dynamic_cast<SlideSorterViewShell*>(
+ pFrameworkHelper->GetViewShell(aPaneURLs[i]).get());
+ }
+ }
+ catch (RuntimeException&)
+ {}
+
+ return pViewShell;
+}
+
+
+
+
+Reference<drawing::XDrawSubController> SlideSorterViewShell::CreateSubController (void)
+{
+ Reference<drawing::XDrawSubController> xSubController;
+
+ if (IsMainViewShell())
+ {
+ // Create uno controller for the main view shell.
+ xSubController = Reference<drawing::XDrawSubController>(
+ new SdUnoSlideView (
+ GetViewShellBase().GetDrawController(),
+ *mpSlideSorter,
+ *GetView()));
+ }
+
+ return xSubController;
+}
+
+
+
+
+/** If there is a valid controller then create a new instance of
+ <type>AccessibleSlideSorterView</type>. Otherwise delegate this call
+ to the base class to return a default object (probably an empty
+ reference).
+*/
+::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible>
+ SlideSorterViewShell::CreateAccessibleDocumentView (::sd::Window* pWindow)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ // When the view is not set then the initialization is not yet complete
+ // and we can not yet provide an accessibility object.
+ if (mpView == NULL || mpSlideSorter.get() == NULL)
+ return NULL;
+
+ ::accessibility::AccessibleSlideSorterView *pAccessibleView =
+ new ::accessibility::AccessibleSlideSorterView(
+ *mpSlideSorter.get(),
+ pWindow->GetAccessibleParentWindow()->GetAccessible(),
+ pWindow);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> xRet(pAccessibleView);
+
+ pAccessibleView->Init();
+
+ return xRet;
+}
+
+
+
+
+SlideSorter& SlideSorterViewShell::GetSlideSorter (void) const
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return *mpSlideSorter;
+}
+
+
+
+
+bool SlideSorterViewShell::RelocateToParentWindow (::Window* pParentWindow)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return mpSlideSorter->RelocateToWindow(pParentWindow);
+}
+
+
+
+
+SfxUndoManager* SlideSorterViewShell::ImpGetUndoManager (void) const
+{
+ SfxShell* pObjectBar = GetViewShellBase().GetViewShellManager()->GetTopShell();
+ if (pObjectBar != NULL)
+ {
+ // When it exists then return the undo manager of the currently
+ // active object bar. The object bar is missing when the
+ // SlideSorterViewShell is not the main view shell.
+ return pObjectBar->GetUndoManager();
+ }
+ else
+ {
+ // Return the undo manager of this shell when there is no object or
+ // tool bar.
+ return const_cast<SlideSorterViewShell*>(this)->GetUndoManager();
+ }
+}
+
+
+
+
+void SlideSorterViewShell::GetFocus (void)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetFocusManager().ShowFocus();
+}
+
+
+
+
+void SlideSorterViewShell::LoseFocus (void)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetFocusManager().HideFocus();
+}
+
+
+
+
+SdPage* SlideSorterViewShell::getCurrentPage(void) const
+{
+ // since SlideSorterViewShell::GetActualPage() currently also
+ // returns master pages, which is a wrong behaviour for GetActualPage(),
+ // we can just use that for now
+ return const_cast<SlideSorterViewShell*>(this)->GetActualPage();
+}
+
+
+
+
+SdPage* SlideSorterViewShell::GetActualPage (void)
+{
+ SdPage* pCurrentPage = NULL;
+
+ // 1. Try to get the current page from the view shell in the center pane
+ // (if we are that not ourself).
+ if ( ! IsMainViewShell())
+ {
+ ::boost::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
+ if (pMainViewShell.get() != NULL)
+ pCurrentPage = pMainViewShell->GetActualPage();
+ }
+
+ if (pCurrentPage == NULL)
+ {
+ model::SharedPageDescriptor pDescriptor (
+ mpSlideSorter->GetController().GetCurrentSlideManager()->GetCurrentSlide());
+ if (pDescriptor.get() != NULL)
+ pCurrentPage = pDescriptor->GetPage();
+ }
+
+ return pCurrentPage;
+}
+
+
+
+
+void SlideSorterViewShell::GetMenuState ( SfxItemSet& rSet)
+{
+ ViewShell::GetMenuState(rSet);
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetSlotManager()->GetMenuState(rSet);
+}
+
+
+
+
+void SlideSorterViewShell::GetClipboardState ( SfxItemSet& rSet)
+{
+ ViewShell::GetMenuState(rSet);
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetSlotManager()->GetClipboardState(rSet);
+}
+
+
+
+
+void SlideSorterViewShell::ExecCtrl (SfxRequest& rRequest)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().ExecCtrl(rRequest);
+}
+
+
+
+
+void SlideSorterViewShell::GetCtrlState (SfxItemSet& rSet)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetCtrlState(rSet);
+}
+
+
+
+
+void SlideSorterViewShell::FuSupport (SfxRequest& rRequest)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().FuSupport(rRequest);
+}
+
+
+
+
+/** We have to handle those slot calls here that need to have access to
+ private or protected members and methods of this class.
+*/
+void SlideSorterViewShell::FuTemporary (SfxRequest& rRequest)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ switch (rRequest.GetSlot())
+ {
+ case SID_MODIFYPAGE:
+ {
+ SdPage* pCurrentPage = GetActualPage();
+ if (pCurrentPage != NULL)
+ mpImpl->ProcessModifyPageSlot (
+ rRequest,
+ pCurrentPage,
+ mpSlideSorter->GetModel().GetPageType());
+ Cancel();
+ rRequest.Done ();
+ }
+ break;
+
+ default:
+ mpSlideSorter->GetController().FuTemporary(rRequest);
+ break;
+ }
+}
+
+
+
+
+void SlideSorterViewShell::GetStatusBarState (SfxItemSet& rSet)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetStatusBarState(rSet);
+}
+
+
+
+
+void SlideSorterViewShell::FuPermanent (SfxRequest& rRequest)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().FuPermanent(rRequest);
+}
+
+
+
+
+void SlideSorterViewShell::GetAttrState (SfxItemSet& rSet)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetAttrState(rSet);
+}
+
+
+
+
+void SlideSorterViewShell::ExecStatusBar (SfxRequest& rRequest)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().ExecStatusBar(rRequest);
+}
+
+
+
+
+void SlideSorterViewShell::PrePaint()
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if (mpSlideSorter.get() != NULL)
+ mpSlideSorter->GetController().PrePaint();
+}
+
+
+
+
+void SlideSorterViewShell::Paint (
+ const Rectangle& rBBox,
+ ::sd::Window* pWindow)
+{
+ SetActiveWindow (pWindow);
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if (mpSlideSorter.get() != NULL)
+ mpSlideSorter->GetController().Paint(rBBox,pWindow);
+}
+
+
+
+
+void SlideSorterViewShell::ArrangeGUIElements (void)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->ArrangeGUIElements(
+ maViewPos,
+ maViewSize);
+}
+
+
+
+
+SvBorder SlideSorterViewShell::GetBorder (bool )
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return mpSlideSorter->GetBorder();
+}
+
+
+
+
+void SlideSorterViewShell::Command (
+ const CommandEvent& rEvent,
+ ::sd::Window* pWindow)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if ( ! mpSlideSorter->GetController().Command (rEvent, pWindow))
+ ViewShell::Command (rEvent, pWindow);
+}
+
+
+
+
+void SlideSorterViewShell::ReadFrameViewData (FrameView* pFrameView)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if (pFrameView != NULL)
+ {
+ view::SlideSorterView& rView (mpSlideSorter->GetView());
+
+ USHORT nSlidesPerRow (pFrameView->GetSlidesPerRow());
+ if (nSlidesPerRow == 0 || ! IsMainViewShell())
+ {
+ // When a value of 0 (automatic) is given or the the slide
+ // sorter is displayed in a side pane then we ignore the value
+ // of the frame view and adapt the number of columns
+ // automatically to the window width.
+ rView.GetLayouter().SetColumnCount(1,5);
+ }
+ else
+ rView.GetLayouter().SetColumnCount(nSlidesPerRow,nSlidesPerRow);
+ mpSlideSorter->GetController().Rearrange(true);
+
+ // DrawMode for 'main' window
+ if (GetActiveWindow()->GetDrawMode() != pFrameView->GetDrawMode() )
+ GetActiveWindow()->SetDrawMode( pFrameView->GetDrawMode() );
+ }
+}
+
+
+
+
+void SlideSorterViewShell::WriteFrameViewData()
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if (mpFrameView != NULL)
+ {
+ view::SlideSorterView& rView (mpSlideSorter->GetView());
+ mpFrameView->SetSlidesPerRow((USHORT)rView.GetLayouter().GetColumnCount());
+
+ // DrawMode for 'main' window
+ if( mpFrameView->GetDrawMode() != GetActiveWindow()->GetDrawMode() )
+ mpFrameView->SetDrawMode( GetActiveWindow()->GetDrawMode() );
+
+ SdPage* pActualPage = GetActualPage();
+ if (pActualPage != NULL)
+ {
+ // The slide sorter is not expected to switch the current page
+ // other then by double clicks. That is handled seperatly.
+ // mpFrameView->SetSelectedPage((pActualPage->GetPageNum()- 1) / 2);
+ }
+ else
+ {
+ // We have no current page to set but at least we can make sure
+ // that the index of the frame view has a legal value.
+ if (mpFrameView->GetSelectedPage() >= mpSlideSorter->GetModel().GetPageCount())
+ mpFrameView->SetSelectedPage((USHORT)mpSlideSorter->GetModel().GetPageCount()-1);
+ }
+ }
+}
+
+
+
+
+void SlideSorterViewShell::SetZoom (long int )
+{
+ // Ignored.
+ // The zoom scale is adapted internally to fit a number of columns in
+ // the window.
+}
+
+void SlideSorterViewShell::SetZoomRect (const Rectangle& rZoomRect)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ Size aPageSize (mpSlideSorter->GetView().GetPageBoundingBox(
+ 0,
+ view::SlideSorterView::CS_MODEL,
+ view::SlideSorterView::BBT_SHAPE).GetSize());
+
+ Rectangle aRect(rZoomRect);
+
+ if (aRect.GetWidth() < aPageSize.Width())
+ {
+ long nWidthDiff = (aPageSize.Width() - aRect.GetWidth()) / 2;
+
+ aRect.Left() -= nWidthDiff;
+ aRect.Right() += nWidthDiff;
+
+ if (aRect.Left() < 0)
+ {
+ aRect.SetPos(Point(0, aRect.Top()));
+ }
+ }
+
+ if (aRect.GetHeight() < aPageSize.Height())
+ {
+ long nHeightDiff = (aPageSize.Height() - aRect.GetHeight()) / 2;
+
+ aRect.Top() -= nHeightDiff;
+ aRect.Bottom() += nHeightDiff;
+
+ if (aRect.Top() < 0)
+ {
+ aRect.SetPos(Point(aRect.Left(), 0));
+ }
+ }
+
+ ViewShell::SetZoomRect(aRect);
+
+ // #106268#
+ GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
+ GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
+}
+
+
+
+
+void SlideSorterViewShell::UpdateScrollBars (void)
+{
+ // Do not call the overwritten method of the base class: We do all the
+ // scroll bar setup by ourselves.
+ mpSlideSorter->GetController().GetScrollBarManager().UpdateScrollBars (false);
+}
+
+
+
+
+void SlideSorterViewShell::StartDrag (
+ const Point& rDragPt,
+ ::Window* pWindow )
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetClipboard().StartDrag (
+ rDragPt,
+ pWindow);
+}
+
+
+
+
+void SlideSorterViewShell::DragFinished (
+ sal_Int8 nDropAction)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetClipboard().DragFinished (nDropAction);
+}
+
+
+
+
+sal_Int8 SlideSorterViewShell::AcceptDrop (
+ const AcceptDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return mpSlideSorter->GetController().GetClipboard().AcceptDrop (
+ rEvt,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+}
+
+
+
+
+sal_Int8 SlideSorterViewShell::ExecuteDrop (
+ const ExecuteDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ USHORT nPage,
+ USHORT nLayer)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return mpSlideSorter->GetController().GetClipboard().ExecuteDrop (
+ rEvt,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+}
+
+
+
+
+::boost::shared_ptr<SlideSorterViewShell::PageSelection>
+ SlideSorterViewShell::GetPageSelection (void) const
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ return mpSlideSorter->GetController().GetPageSelector().GetPageSelection();
+}
+
+
+
+
+void SlideSorterViewShell::SetPageSelection (
+ const ::boost::shared_ptr<PageSelection>& rSelection)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetPageSelector().SetPageSelection(rSelection);
+}
+
+
+
+
+void SlideSorterViewShell::AddSelectionChangeListener (
+ const Link& rCallback)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetSelectionManager()->AddSelectionChangeListener(rCallback);
+}
+
+
+
+
+void SlideSorterViewShell::RemoveSelectionChangeListener (
+ const Link& rCallback)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->GetController().GetSelectionManager()->RemoveSelectionChangeListener(rCallback);
+}
+
+
+
+} } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/shell/makefile.mk b/sd/source/ui/slidesorter/shell/makefile.mk
new file mode 100644
index 000000000000..94209c34dc2b
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/makefile.mk
@@ -0,0 +1,55 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slsshell
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlideSorter.obj \
+ $(SLO)$/SlideSorterService.obj \
+ $(SLO)$/SlideSorterViewShell.obj
+
+EXCEPTIONSFILES=
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sd/source/ui/slidesorter/view/SlideSorterView.cxx b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
new file mode 100644
index 000000000000..134b59e6192a
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
@@ -0,0 +1,824 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlideSorterView.hxx"
+
+#include "ViewShellBase.hxx"
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "ViewShell.hxx"
+#include "SlsViewCacheContext.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsViewOverlay.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+#include "controller/SlsProperties.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "cache/SlsCacheContext.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include "DrawDocShell.hxx"
+
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include "sdresid.hxx"
+#include "glob.hrc"
+
+#include <svl/itempool.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnclit.hxx>
+#include <com/sun/star/presentation/FadeEffect.hpp>
+#include <vcl/svapp.hxx>
+#include <tools/poly.hxx>
+#include <vcl/lineinfo.hxx>
+#include <algorithm>
+#include <svx/sdr/contact/objectcontact.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svl/itempool.hxx>
+#include <svl/itempool.hxx>
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+using namespace ::sd::slidesorter::model;
+
+namespace sd { namespace slidesorter { namespace view {
+
+TYPEINIT1(SlideSorterView, ::sd::View);
+
+
+SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
+ : ::sd::View (
+ rSlideSorter.GetModel().GetDocument(),
+ NULL,
+ rSlideSorter.GetViewShell()),
+ mrSlideSorter(rSlideSorter),
+ mrModel(rSlideSorter.GetModel()),
+ maPageModel(),
+ mpPage(new SdrPage(maPageModel)),
+ mpLayouter (new Layouter ()),
+ mbPageObjectVisibilitiesValid (false),
+ mpPreviewCache(),
+ mpViewOverlay (new ViewOverlay(rSlideSorter)),
+ mnFirstVisiblePageIndex(0),
+ mnLastVisiblePageIndex(-1),
+ mbModelChangedWhileModifyEnabled(true),
+ maPreviewSize(0,0),
+ mbPreciousFlagUpdatePending(true),
+ maPageNumberAreaModelSize(0,0),
+ maModelBorder(),
+ meOrientation(VERTICAL)
+{
+ // Hide the page that contains the page objects.
+ SetPageVisible (FALSE);
+
+ // call FreezeIdRanges() at the pool from the newly constructed SdrModel,
+ // else creating SfxItemSets on it will complain
+ maPageModel.GetItemPool().FreezeIdRanges();
+
+ // add the page to the model (no, this is NOT done by the constructor :-( )
+ maPageModel.InsertPage(mpPage);
+
+ // show page
+ LocalModelHasChanged();
+}
+
+
+
+
+SlideSorterView::~SlideSorterView (void)
+{
+ // Inform the contact objects to disconnect from the preview cache.
+ // Otherwise each dying contact object invalidates its preview. When
+ // the previews are kept for a later re-use than this invalidation is
+ // not wanted.
+ ::boost::shared_ptr<cache::PageCache> pEmptyCache;
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aPageEnumeration.HasMoreElements())
+ {
+ view::PageObjectViewObjectContact* pContact
+ = aPageEnumeration.GetNextElement()->GetViewObjectContact();
+ if (pContact != NULL)
+ pContact->SetCache(pEmptyCache);
+ }
+ mpPreviewCache.reset();
+
+ // hide the page to avoid problems in the view when deleting
+ // visualized objects
+ HideSdrPage();
+
+ // Deletion of the objects and the page will be done in SdrModel
+ // destructor (as long as objects and pages are added)
+}
+
+
+
+
+sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rPosition) const
+{
+ sal_Int32 nIndex (-1);
+
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ {
+ nIndex = mpLayouter->GetIndexAtPoint (pWindow->PixelToLogic (rPosition));
+
+ // Clip the page index against the page count.
+ if (nIndex >= mrModel.GetPageCount())
+ nIndex = -1;
+ }
+
+ return nIndex;
+}
+
+
+
+
+Layouter& SlideSorterView::GetLayouter (void)
+{
+ return *mpLayouter.get();
+}
+
+
+
+
+void SlideSorterView::ModelHasChanged (void)
+{
+ if (mbModelChangedWhileModifyEnabled)
+ {
+ controller::SlideSorterController::ModelChangeLock alock( mrSlideSorter.GetController() );
+ mrSlideSorter.GetController().HandleModelChange();
+ LocalModelHasChanged();
+ }
+}
+
+
+
+
+void SlideSorterView::LocalModelHasChanged(void)
+{
+ mbModelChangedWhileModifyEnabled = false;
+
+ // First call our base class.
+ View::ModelHasChanged ();
+
+ // Then re-set the page as current page that contains the page objects.
+ ShowSdrPage(mpPage);
+
+ // Initialize everything that depends on a page view, now that we have
+ // one.
+ // SetApplicationDocumentColor(
+ // Application::GetSettings().GetStyleSettings().GetWindowColor());
+
+ UpdatePageBorders();
+}
+
+
+
+
+void SlideSorterView::PreModelChange (void)
+{
+ // Reset the slide under the mouse. It will be set to the correct slide
+ // on the next mouse motion.
+ GetOverlay().GetMouseOverIndicatorOverlay().SetSlideUnderMouse(SharedPageDescriptor());
+
+ // Tell the page descriptors of the model that the page objects do not
+ // exist anymore.
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aPageEnumeration.HasMoreElements())
+ aPageEnumeration.GetNextElement()->ReleasePageObject();
+
+ // Remove all page objects from the page.
+ mpPage->Clear();
+}
+
+
+
+
+void SlideSorterView::PostModelChange (void)
+{
+ // In PreModelChange() the page objects have been released. Here we
+ // create new ones.
+ ::osl::MutexGuard aGuard (mrModel.GetMutex());
+
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ UpdatePageBorders();
+ while (aPageEnumeration.HasMoreElements())
+ {
+ SdrPageObj* pPageObject = aPageEnumeration.GetNextElement()->GetPageObject();
+ if (pPageObject != NULL)
+ AddSdrObject(*pPageObject);
+ }
+
+ // The new page objects have to be scaled and positioned.
+ Layout ();
+}
+
+
+
+
+/** At the moment for every model change all page objects are destroyed and
+ re-created again. This can be optimized by accepting hints that
+ describe the type of change so that existing page objects can be
+ reused.
+*/
+void SlideSorterView::HandleModelChange (void)
+{
+ PreModelChange ();
+ PostModelChange();
+}
+
+
+
+
+void SlideSorterView::HandleDrawModeChange (void)
+{
+ UpdatePageBorders();
+
+ // Replace the preview cache with a new and empty one. The
+ // PreviewRenderer that is used by the cache is replaced by this as
+ // well.
+ mpPreviewCache.reset();
+ GetPreviewCache()->InvalidateCache(true);
+ mrModel.SetPageObjectFactory(
+ ::std::auto_ptr<controller::PageObjectFactory>(
+ new controller::PageObjectFactory(
+ GetPreviewCache(),
+ mrSlideSorter.GetController().GetProperties())));
+
+ RequestRepaint();
+}
+
+
+
+
+void SlideSorterView::Resize (void)
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (mrModel.GetPageCount()>0 && pWindow != NULL)
+ {
+ UpdatePageBorders();
+ bool bRearrangeSuccess (false);
+ if (meOrientation == HORIZONTAL)
+ {
+ bRearrangeSuccess = mpLayouter->RearrangeHorizontal (
+ pWindow->GetSizePixel(),
+ mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
+ pWindow,
+ mrModel.GetPageCount());
+ }
+ else
+ {
+ bRearrangeSuccess = mpLayouter->RearrangeVertical (
+ pWindow->GetSizePixel(),
+ mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
+ pWindow);
+ }
+
+ if (bRearrangeSuccess)
+ {
+ Layout();
+ pWindow->Invalidate();
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::Layout ()
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ {
+ // Set the model area, i.e. the smallest rectangle that includes all
+ // page objects.
+ Rectangle aViewBox (mpLayouter->GetPageBox(mrModel.GetPageCount()));
+ pWindow->SetViewOrigin (aViewBox.TopLeft());
+ pWindow->SetViewSize (aViewBox.GetSize());
+
+ Size aPageObjectPixelSize (pWindow->LogicToPixel(mpLayouter->GetPageObjectSize()));
+ if (maPreviewSize != aPageObjectPixelSize && mpPreviewCache.get()!=NULL)
+ {
+ mpPreviewCache->ChangeSize(aPageObjectPixelSize);
+ maPreviewSize = aPageObjectPixelSize;
+ }
+
+ // Iterate over all page objects and place them relative to the
+ // containing page.
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ int nIndex = 0;
+ while (aPageEnumeration.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ SdrPageObj* pPageObject = pDescriptor->GetPageObject();
+ Rectangle aPageObjectBox (mpLayouter->GetPageObjectBox (nIndex));
+ pPageObject->SetSnapRect(aPageObjectBox);
+
+ nIndex += 1;
+ }
+ // Set the page so that it encloses all page objects.
+ mpPage->SetSize (aViewBox.GetSize());
+ }
+
+ InvalidatePageObjectVisibilities ();
+}
+
+
+
+
+void SlideSorterView::InvalidatePageObjectVisibilities (void)
+{
+ mbPageObjectVisibilitiesValid = false;
+}
+
+
+
+
+void SlideSorterView::DeterminePageObjectVisibilities (void)
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ {
+ // Set this flag to true here so that an invalidate during the
+ // visibility calculation can correctly invalidate it again.
+ mbPageObjectVisibilitiesValid = true;
+
+ Rectangle aViewArea (
+ Point(0,0),
+ pWindow->GetSizePixel());
+ aViewArea = pWindow->PixelToLogic (aViewArea);
+ int nFirstIndex =
+ mpLayouter->GetIndexOfFirstVisiblePageObject (aViewArea);
+ int nLastIndex =
+ mpLayouter->GetIndexOfLastVisiblePageObject (aViewArea);
+
+ // For page objects that just dropped off the visible area we
+ // decrease the priority of pending requests for preview bitmaps.
+
+ int nMinIndex = ::std::min (mnFirstVisiblePageIndex, nFirstIndex);
+ int nMaxIndex = ::std::max (mnLastVisiblePageIndex, nLastIndex);
+ if (mnFirstVisiblePageIndex!=nFirstIndex || mnLastVisiblePageIndex!=nLastIndex)
+ mbPreciousFlagUpdatePending |= true;
+ model::SharedPageDescriptor pDescriptor;
+ view::PageObjectViewObjectContact* pContact;
+ for (int nIndex=nMinIndex; nIndex<=nMaxIndex; nIndex++)
+ {
+ // Determine the visibility before and after the change so that
+ // we can handle the page objects for which the visibility has
+ // changed.
+ bool bWasVisible = nIndex>=mnFirstVisiblePageIndex
+ && nIndex<=mnLastVisiblePageIndex;
+ bool bIsVisible = nIndex>=nFirstIndex && nIndex<=nLastIndex;
+
+ // Get the view-object-contact.
+ if (bWasVisible != bIsVisible)
+ {
+ pContact = NULL;
+ pDescriptor = mrModel.GetPageDescriptor(nIndex);
+ if (pDescriptor.get() != NULL)
+ pContact = pDescriptor->GetViewObjectContact();
+
+ if (pDescriptor.get() != NULL)
+ pDescriptor->SetVisible(bIsVisible);
+ }
+
+ }
+
+ if (mnFirstVisiblePageIndex != nFirstIndex
+ || mnLastVisiblePageIndex != nLastIndex)
+ {
+ mnFirstVisiblePageIndex = nFirstIndex;
+ mnLastVisiblePageIndex = nLastIndex;
+
+ // Tell the listeners that the visibility of some objects has changed.
+ ::std::vector<Link> aChangeListeners (maVisibilityChangeListeners);
+ for (::std::vector<Link>::const_iterator
+ iListener=aChangeListeners.begin(),
+ iEnd=aChangeListeners.end();
+ iListener!=iEnd;
+ ++iListener)
+ {
+ iListener->Call(NULL);
+ }
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::UpdatePreciousFlags (void)
+{
+ if (mbPreciousFlagUpdatePending)
+ {
+ mbPreciousFlagUpdatePending = false;
+
+ model::SharedPageDescriptor pDescriptor;
+ ::boost::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
+ sal_Int32 nPageCount (mrModel.GetPageCount());
+
+ for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
+ {
+ pDescriptor = mrModel.GetPageDescriptor(nIndex);
+ if (pDescriptor.get() != NULL)
+ {
+ pCache->SetPreciousFlag(
+ pDescriptor->GetPage(),
+ (nIndex>=mnFirstVisiblePageIndex && nIndex<=mnLastVisiblePageIndex));
+ SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex,
+ (nIndex>=mnFirstVisiblePageIndex && nIndex<=mnLastVisiblePageIndex));
+ }
+ else
+ {
+ // At least one cache entry can not be updated. Remember to
+ // repeat the whole updating later and leave the loop now.
+ mbPreciousFlagUpdatePending = true;
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::SetOrientation (const Orientation eOrientation)
+{
+ meOrientation = eOrientation;
+ RequestRepaint();
+}
+
+
+
+
+SlideSorterView::Orientation SlideSorterView::GetOrientation (void) const
+{
+ return meOrientation;
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (void)
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ pWindow->Invalidate();
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ pWindow->Invalidate(
+ GetPageBoundingBox (
+ rpDescriptor,
+ CS_MODEL,
+ BBT_INFO));
+}
+
+
+
+
+Rectangle SlideSorterView::GetModelArea (void)
+{
+ return Rectangle (
+ Point (0,0),
+ Size (mpPage->GetSize().Width(),mpPage->GetSize().Height()));
+}
+
+
+
+
+Rectangle SlideSorterView::GetPageBoundingBox (
+ const model::SharedPageDescriptor& rpDescriptor,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const
+{
+ Rectangle aBBox;
+ SdrObject* pPageObject = rpDescriptor->GetPageObject();
+ if (pPageObject != NULL)
+ {
+ aBBox = pPageObject->GetCurrentBoundRect();
+ AdaptBoundingBox (aBBox, eCoordinateSystem, eBoundingBoxType);
+ }
+
+ return aBBox;
+}
+
+
+
+
+Rectangle SlideSorterView::GetPageBoundingBox (
+ sal_Int32 nIndex,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const
+{
+ Rectangle aBBox;
+ if (nIndex >= 0 && nIndex<mrModel.GetPageCount())
+ {
+ aBBox = mpLayouter->GetPageObjectBox(nIndex);
+ AdaptBoundingBox (aBBox, eCoordinateSystem, eBoundingBoxType);
+ }
+
+ return aBBox;
+}
+
+
+
+
+void SlideSorterView::CompleteRedraw(OutputDevice* pDevice, const Region& rPaintArea, sdr::contact::ViewObjectContactRedirector* pRedirector)
+{
+ if (mnLockRedrawSmph == 0)
+ {
+ // Update the page visibilities when they have been invalidated.
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+
+ if (mbPreciousFlagUpdatePending)
+ UpdatePreciousFlags();
+
+ // Call the base class InitRedraw even when re-drawing is locked to
+ // let it remember the request for a redraw.
+ View::CompleteRedraw (pDevice, rPaintArea, pRedirector);
+ }
+ else
+ {
+ // In sd::View::CompleteRedraw() this call is recorded and given
+ // region is painted when the view is unlocked.
+ View::CompleteRedraw (pDevice, rPaintArea, pRedirector);
+ }
+}
+
+
+
+
+void SlideSorterView::InvalidateOneWin (::Window& rWindow)
+{
+ // if ( IsInvalidateAllowed() )
+ View::InvalidateOneWin (rWindow);
+}
+
+
+
+
+void SlideSorterView::InvalidateOneWin (
+ ::Window& rWindow,
+ const Rectangle& rPaintArea)
+{
+ // if( IsInvalidateAllowed() )
+ View::InvalidateOneWin (rWindow, rPaintArea);
+}
+
+
+
+
+::sd::Window* SlideSorterView::GetWindow (void) const
+{
+ return static_cast< ::sd::Window*>(GetFirstOutputDevice());
+}
+
+
+
+
+void SlideSorterView::AdaptBoundingBox (
+ Rectangle& rModelPageObjectBoundingBox,
+ CoordinateSystem eCoordinateSystem,
+ BoundingBoxType eBoundingBoxType) const
+{
+ CoordinateSystem aCurrentCoordinateSystem = CS_MODEL;
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL)
+ {
+ if (eBoundingBoxType == BBT_INFO)
+ {
+ // Make the box larger so that it encloses all relevant
+ // displayed information.
+ if (aCurrentCoordinateSystem == CS_MODEL)
+ {
+ // The relevant offsets are given in pixel values. Therefore
+ // transform the box first into screen coordinates.
+ rModelPageObjectBoundingBox
+ = pWindow->LogicToPixel (rModelPageObjectBoundingBox);
+ aCurrentCoordinateSystem = CS_SCREEN;
+ }
+ rModelPageObjectBoundingBox.Left() -= maPagePixelBorder.Left();
+ rModelPageObjectBoundingBox.Right() += maPagePixelBorder.Right();
+ rModelPageObjectBoundingBox.Top() -= maPagePixelBorder.Top();
+ rModelPageObjectBoundingBox.Bottom() += maPagePixelBorder.Bottom();
+ }
+
+ // Make sure that the bounding box is given in the correct coordinate
+ // system.
+ if (eCoordinateSystem != aCurrentCoordinateSystem)
+ {
+ if (eCoordinateSystem == CS_MODEL)
+ rModelPageObjectBoundingBox
+ = pWindow->PixelToLogic (rModelPageObjectBoundingBox);
+ else
+ rModelPageObjectBoundingBox
+ = pWindow->LogicToPixel (rModelPageObjectBoundingBox);
+ }
+ }
+}
+
+
+
+
+::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache (void)
+{
+ ::sd::Window* pWindow = GetWindow();
+ if (pWindow != NULL && mpPreviewCache.get() == NULL)
+ {
+ maPreviewSize = pWindow->LogicToPixel(mpLayouter->GetPageObjectSize());
+ mpPreviewCache.reset(
+ new cache::PageCache(
+ maPreviewSize,
+ cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter.GetModel(), *this))));
+ }
+
+ return mpPreviewCache;
+}
+
+
+
+
+ViewOverlay& SlideSorterView::GetOverlay (void)
+{
+ return *mpViewOverlay.get();
+}
+
+
+
+
+SlideSorterView::PageRange SlideSorterView::GetVisiblePageRange (void)
+{
+ const int nMaxPageIndex (mrModel.GetPageCount() - 1);
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+ return PageRange(
+ ::std::min(mnFirstVisiblePageIndex,nMaxPageIndex),
+ ::std::min(mnLastVisiblePageIndex, nMaxPageIndex));
+}
+
+
+
+
+void SlideSorterView::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
+{
+ ::sd::DrawDocShell* pDocShell = mrModel.GetDocument()->GetDocSh();
+ if (pDocShell!=NULL && pDocShell->IsEnableSetModified())
+ mbModelChangedWhileModifyEnabled = true;
+
+ ::sd::View::Notify(rBroadcaster, rHint);
+}
+
+
+
+
+void SlideSorterView::UpdatePageBorders (void)
+{
+ maPagePixelBorder = SvBorder();
+ ::sd::Window* pWindow = GetWindow();
+ if (mrModel.GetPageCount()>0 && pWindow!=NULL)
+ {
+ // Calculate the border in model coordinates.
+ maPageNumberAreaModelSize = PageObjectViewObjectContact::CalculatePageNumberAreaModelSize (
+ pWindow,
+ mrModel.GetPageCount());
+ maModelBorder = PageObjectViewObjectContact::CalculatePageModelBorder (
+ pWindow,
+ mrModel.GetPageCount());
+
+ // Depending on values in the global properties the border has to be
+ // extended a little bit.
+ ::boost::shared_ptr<controller::Properties> pProperties(
+ mrSlideSorter.GetController().GetProperties());
+ if (pProperties.get()!=NULL && pProperties->IsHighlightCurrentSlide())
+ {
+ Size aBorderSize (pWindow->PixelToLogic (Size(3,3)));
+ maModelBorder.Left() += aBorderSize.Width();
+ maModelBorder.Right() += aBorderSize.Width();
+ maModelBorder.Top() += aBorderSize.Height();
+ maModelBorder.Bottom() += aBorderSize.Height();
+ }
+
+ // Set the border at all page descriptors so that the contact
+ // objects have access to them.
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aPageEnumeration.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ pDescriptor->SetModelBorder(maModelBorder);
+ pDescriptor->SetPageNumberAreaModelSize(maPageNumberAreaModelSize);
+ }
+
+ // Convert the borders to pixel coordinates and store them for later
+ // use.
+ Size aTopLeftBorders(pWindow->LogicToPixel(
+ Size (maModelBorder.Left(), maModelBorder.Top())));
+ Size aBottomRightBorders(pWindow->LogicToPixel(
+ Size (maModelBorder.Right(), maModelBorder.Bottom())));
+ maPagePixelBorder = SvBorder (
+ aTopLeftBorders.Width(),
+ aTopLeftBorders.Height(),
+ aBottomRightBorders.Width(),
+ aBottomRightBorders.Height());
+ }
+
+ // Finally tell the layouter about the borders.
+ mpLayouter->SetBorders (2,5,4,5);
+ mpLayouter->SetPageBorders (
+ maPagePixelBorder.Left(),
+ maPagePixelBorder.Right(),
+ maPagePixelBorder.Top(),
+ maPagePixelBorder.Bottom());
+}
+
+
+
+
+void SlideSorterView::AddSdrObject (SdrObject& rObject)
+{
+ mpPage->InsertObject(&rObject);
+ rObject.SetModel(&maPageModel);
+}
+
+
+
+
+void SlideSorterView::AddVisibilityChangeListener (const Link& rListener)
+{
+ if (::std::find (
+ maVisibilityChangeListeners.begin(),
+ maVisibilityChangeListeners.end(),
+ rListener) == maVisibilityChangeListeners.end())
+ {
+ maVisibilityChangeListeners.push_back(rListener);
+ }
+}
+
+
+
+
+void SlideSorterView::RemoveVisibilityChangeListener(const Link&rListener)
+{
+ maVisibilityChangeListeners.erase (
+ ::std::find (
+ maVisibilityChangeListeners.begin(),
+ maVisibilityChangeListeners.end(),
+ rListener));
+}
+
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsFontProvider.cxx b/sd/source/ui/slidesorter/view/SlsFontProvider.cxx
new file mode 100644
index 000000000000..faaad4c3baed
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsFontProvider.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "view/SlsFontProvider.hxx"
+
+#include "controller/SlideSorterController.hxx"
+
+#include <sfx2/app.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+
+using namespace ::sd::slidesorter;
+
+namespace sd { namespace slidesorter { namespace view {
+
+FontProvider* FontProvider::mpInstance = NULL;
+
+FontProvider& FontProvider::Instance (void)
+{
+ if (mpInstance == NULL)
+ {
+ ::osl::GetGlobalMutex aMutexFunctor;
+ ::osl::MutexGuard aGuard (aMutexFunctor());
+ if (mpInstance == NULL)
+ {
+ // Create an instance of the class and register it at the
+ // SdGlobalResourceContainer so that it is eventually released.
+ FontProvider* pInstance = new FontProvider();
+ SdGlobalResourceContainer::Instance().AddResource (
+ ::std::auto_ptr<SdGlobalResource>(pInstance));
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ mpInstance = pInstance;
+ }
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+
+ // We throw an exception when for some strange reason no instance of
+ // this class exists.
+ if (mpInstance == NULL)
+ throw ::com::sun::star::uno::RuntimeException(::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.IndexedPropertyValues")),
+ NULL);
+
+ return *mpInstance;
+}
+
+
+
+
+FontProvider::FontProvider (void)
+ : maFont(),
+ maMapMode()
+{
+}
+
+
+
+
+FontProvider::~FontProvider (void)
+{
+}
+
+
+
+
+void FontProvider::Invalidate (void)
+{
+ maFont.reset();
+}
+
+
+
+
+FontProvider::SharedFontPointer FontProvider::GetFont (const OutputDevice& rDevice)
+{
+ // Reset the font when the map mode has changed since its creation.
+ if (maMapMode != rDevice.GetMapMode())
+ maFont.reset();
+
+ if (maFont.get() == NULL)
+ {
+ // Initialize the font from the application style settings.
+ maFont.reset(new Font (Application::GetSettings().GetStyleSettings().GetAppFont()));
+ maFont->SetTransparent(TRUE);
+ maFont->SetWeight(WEIGHT_NORMAL);
+
+ // Transform the point size to pixel size.
+ MapMode aFontMapMode (MAP_POINT);
+ Size aFontSize (rDevice.LogicToPixel(maFont->GetSize(), aFontMapMode));
+
+ // Transform the font size to the logical coordinates of the device.
+ maFont->SetSize (rDevice.PixelToLogic(aFontSize));
+
+ // Remember the map mode of the given device to detect different
+ // devices or modified zoom scales on future calls.
+ maMapMode = rDevice.GetMapMode();
+ }
+
+ return maFont;
+}
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsLayouter.cxx b/sd/source/ui/slidesorter/view/SlsLayouter.cxx
new file mode 100644
index 000000000000..d967a191df2b
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsLayouter.cxx
@@ -0,0 +1,761 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlsLayouter.hxx"
+
+#include <vcl/outdev.hxx>
+#include <rtl/math.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+Layouter::Layouter (void)
+ : mnRequestedLeftBorder(10),
+ mnRequestedRightBorder(10),
+ mnRequestedTopBorder(10),
+ mnRequestedBottomBorder(10),
+ mnLeftBorder(10),
+ mnRightBorder(10),
+ mnTopBorder(10),
+ mnBottomBorder(10),
+ mnLeftPageBorder(0),
+ mnRightPageBorder(0),
+ mnTopPageBorder(0),
+ mnBottomPageBorder(0),
+ mnVerticalGap (20),
+ mnHorizontalGap (20),
+ mnInsertionMarkerThickness (4),
+ mnTotalVerticalGap(0),
+ mnTotalHorizontalGap(0),
+ mnMinimalWidth (100),
+ mnPreferredWidth (200),
+ mnMaximalWidth (300),
+ mnMinimalColumnCount (1),
+ mnMaximalColumnCount (5),
+ mnColumnCount (1),
+ maPageObjectModelSize (1,1),
+ maPageObjectPixelSize (1,1)
+{
+}
+
+
+
+
+Layouter::~Layouter (void)
+{
+}
+
+
+void Layouter::SetBorders (
+ sal_Int32 nLeftBorder,
+ sal_Int32 nRightBorder,
+ sal_Int32 nTopBorder,
+ sal_Int32 nBottomBorder)
+{
+ if (nLeftBorder >= 0)
+ mnRequestedLeftBorder.mnScreen = nLeftBorder;
+ if (nRightBorder >= 0)
+ mnRequestedRightBorder.mnScreen = nRightBorder;
+ if (nTopBorder >= 0)
+ mnRequestedTopBorder.mnScreen = nTopBorder;
+ if (nBottomBorder >= 0)
+ mnRequestedBottomBorder.mnScreen = nBottomBorder;
+}
+
+
+
+
+void Layouter::SetPageBorders (
+ sal_Int32 nLeftBorder,
+ sal_Int32 nRightBorder,
+ sal_Int32 nTopBorder,
+ sal_Int32 nBottomBorder)
+{
+ if (nLeftBorder >= 0)
+ mnLeftPageBorder.mnScreen = nLeftBorder;
+ if (nRightBorder >= 0)
+ mnRightPageBorder.mnScreen = nRightBorder;
+ if (nTopBorder >= 0)
+ mnTopPageBorder.mnScreen = nTopBorder;
+ if (nBottomBorder >= 0)
+ mnBottomPageBorder.mnScreen = nBottomBorder;
+}
+
+
+
+
+void Layouter::SetColumnCount (
+ sal_Int32 nMinimalColumnCount,
+ sal_Int32 nMaximalColumnCount)
+{
+ if (nMinimalColumnCount <= nMaximalColumnCount)
+ {
+ mnMinimalColumnCount = nMinimalColumnCount;
+ mnMaximalColumnCount = nMaximalColumnCount;
+ }
+}
+
+
+
+
+bool Layouter::RearrangeHorizontal (
+ const Size& rWindowSize,
+ const Size& rPageObjectSize,
+ OutputDevice* pDevice,
+ const sal_uInt32 nPageCount)
+{
+ if (rWindowSize.Width() > 0
+ && rWindowSize.Height() > 0
+ && rPageObjectSize.Width() > 0
+ && rPageObjectSize.Height() > 0)
+ {
+ mnTotalHorizontalGap.mnScreen = mnHorizontalGap.mnScreen
+ + mnRightPageBorder.mnScreen + mnLeftPageBorder.mnScreen;
+ mnTotalVerticalGap.mnScreen = mnVerticalGap.mnScreen
+ + mnTopPageBorder.mnScreen + mnBottomPageBorder.mnScreen;
+
+ // Calculate the column count.
+ mnColumnCount = nPageCount;
+
+ // Update the border values. The insertion marker has to have space.
+ mnLeftBorder.mnScreen = mnRequestedLeftBorder.mnScreen;
+ mnTopBorder.mnScreen = mnRequestedTopBorder.mnScreen;
+ mnRightBorder.mnScreen = mnRequestedRightBorder.mnScreen;
+ mnBottomBorder.mnScreen = mnRequestedBottomBorder.mnScreen;
+ if (mnColumnCount > 1)
+ {
+ int nMinimumBorderWidth = mnInsertionMarkerThickness.mnScreen
+ + mnHorizontalGap.mnScreen/2;
+ if (mnLeftBorder.mnScreen < nMinimumBorderWidth)
+ mnLeftBorder.mnScreen = nMinimumBorderWidth;
+ if (mnRightBorder.mnScreen < nMinimumBorderWidth)
+ mnRightBorder.mnScreen = nMinimumBorderWidth;
+ }
+ else
+ {
+ int nMinimumBorderHeight = mnInsertionMarkerThickness.mnScreen
+ + mnVerticalGap.mnScreen/2;
+ if (mnTopBorder.mnScreen < nMinimumBorderHeight)
+ mnTopBorder.mnScreen = nMinimumBorderHeight;
+ if (mnBottomBorder.mnScreen < nMinimumBorderHeight)
+ mnBottomBorder.mnScreen = nMinimumBorderHeight;
+ }
+
+ // Calculate the width of each page object.
+ sal_uInt32 nTargetHeight = 0;
+ sal_uInt32 nRowCount = 1;
+ if (mnColumnCount > 0)
+ nTargetHeight = (rWindowSize.Height()
+ - mnTopBorder.mnScreen
+ - mnBottomBorder.mnScreen
+ - nRowCount * (mnTopPageBorder.mnScreen
+ + mnBottomPageBorder.mnScreen)
+ - (nRowCount-1) * mnTotalVerticalGap.mnScreen
+ )
+ / nRowCount;
+ sal_uInt32 nMinimalHeight (
+ mnMinimalWidth * rPageObjectSize.Height() / rPageObjectSize.Width());
+ sal_uInt32 nMaximalHeight (
+ mnMaximalWidth * rPageObjectSize.Height() / rPageObjectSize.Width());
+ if (nTargetHeight < nMinimalHeight)
+ nTargetHeight = nMinimalHeight;
+ if (nTargetHeight > nMaximalHeight)
+ nTargetHeight = nMaximalHeight;
+
+ // Initialize the device with some arbitrary zoom factor just in
+ // case that the current zoom factor is numerically instable when
+ // used in a multiplication.
+ MapMode aMapMode (pDevice->GetMapMode());
+ aMapMode.SetScaleX (Fraction(1,1));
+ aMapMode.SetScaleY (Fraction(1,1));
+ pDevice->SetMapMode (aMapMode);
+
+ // Calculate the resulting scale factor and the page object size in
+ // pixels.
+ maPageObjectModelSize = rPageObjectSize;
+ int nPagePixelHeight (pDevice->LogicToPixel(maPageObjectModelSize).Height());
+
+ // Adapt the layout of the given output device to the new layout of
+ // page objects. The zoom factor is set so that the page objects in
+ // one column fill the screen.
+ Fraction aScaleFactor (nTargetHeight, nPagePixelHeight);
+ SetZoom (aMapMode.GetScaleX() * aScaleFactor, pDevice);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool Layouter::RearrangeVertical (
+ const Size& rWindowSize,
+ const Size& rPageObjectSize,
+ OutputDevice* pDevice)
+{
+ if (rWindowSize.Width() > 0
+ && rWindowSize.Height() > 0
+ && rPageObjectSize.Width() > 0
+ && rPageObjectSize.Height() > 0)
+ {
+ mnTotalHorizontalGap.mnScreen = mnHorizontalGap.mnScreen
+ + mnRightPageBorder.mnScreen + mnLeftPageBorder.mnScreen;
+ mnTotalVerticalGap.mnScreen = mnVerticalGap.mnScreen
+ + mnTopPageBorder.mnScreen + mnBottomPageBorder.mnScreen;
+
+ // Calculate the column count.
+ mnColumnCount = (rWindowSize.Width()
+ - mnRequestedLeftBorder.mnScreen - mnRequestedRightBorder.mnScreen)
+ / (mnPreferredWidth + mnTotalHorizontalGap.mnScreen);
+ if (mnColumnCount < mnMinimalColumnCount)
+ mnColumnCount = mnMinimalColumnCount;
+ if (mnColumnCount > mnMaximalColumnCount)
+ mnColumnCount = mnMaximalColumnCount;
+
+ // Update the border values. The insertion marker has to have space.
+ mnLeftBorder.mnScreen = mnRequestedLeftBorder.mnScreen;
+ mnTopBorder.mnScreen = mnRequestedTopBorder.mnScreen;
+ mnRightBorder.mnScreen = mnRequestedRightBorder.mnScreen;
+ mnBottomBorder.mnScreen = mnRequestedBottomBorder.mnScreen;
+ if (mnColumnCount > 1)
+ {
+ int nMinimumBorderWidth = mnInsertionMarkerThickness.mnScreen
+ + mnHorizontalGap.mnScreen/2;
+ if (mnLeftBorder.mnScreen < nMinimumBorderWidth)
+ mnLeftBorder.mnScreen = nMinimumBorderWidth;
+ if (mnRightBorder.mnScreen < nMinimumBorderWidth)
+ mnRightBorder.mnScreen = nMinimumBorderWidth;
+ }
+ else
+ {
+ int nMinimumBorderHeight = mnInsertionMarkerThickness.mnScreen
+ + mnVerticalGap.mnScreen/2;
+ if (mnTopBorder.mnScreen < nMinimumBorderHeight)
+ mnTopBorder.mnScreen = nMinimumBorderHeight;
+ if (mnBottomBorder.mnScreen < nMinimumBorderHeight)
+ mnBottomBorder.mnScreen = nMinimumBorderHeight;
+ }
+
+ // Calculate the width of each page object.
+ sal_Int32 nTargetWidth = 0;
+ if (mnColumnCount > 0)
+ nTargetWidth = (rWindowSize.Width()
+ - mnLeftBorder.mnScreen
+ - mnRightBorder.mnScreen
+ - mnColumnCount * (mnRightPageBorder.mnScreen
+ + mnLeftPageBorder.mnScreen)
+ - (mnColumnCount-1) * mnTotalHorizontalGap.mnScreen
+ )
+ / mnColumnCount;
+ if (nTargetWidth < mnMinimalWidth)
+ nTargetWidth = mnMinimalWidth;
+ if (nTargetWidth > mnMaximalWidth)
+ nTargetWidth = mnMaximalWidth;
+
+ // Initialize the device with some arbitrary zoom factor just in
+ // case that the current zoom factor is numerically instable when
+ // used in a multiplication.
+ MapMode aMapMode (pDevice->GetMapMode());
+ aMapMode.SetScaleX (Fraction(1,1));
+ aMapMode.SetScaleY (Fraction(1,1));
+ pDevice->SetMapMode (aMapMode);
+
+ // Calculate the resulting scale factor and the page object size in
+ // pixels.
+ maPageObjectModelSize = rPageObjectSize;
+ int nPagePixelWidth (pDevice->LogicToPixel (maPageObjectModelSize).Width());
+
+ // Adapt the layout of the given output device to the new layout of
+ // page objects. The zoom factor is set so that the page objects in
+ // one row fill the screen.
+ Fraction aScaleFactor (nTargetWidth, nPagePixelWidth);
+ SetZoom (aMapMode.GetScaleX() * aScaleFactor, pDevice);
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void Layouter::SetZoom (Fraction nZoomFactor, OutputDevice* pDevice)
+{
+ MapMode aMapMode (pDevice->GetMapMode());
+ aMapMode.SetScaleX (nZoomFactor);
+ aMapMode.SetScaleY (nZoomFactor);
+ maPageObjectPixelSize = pDevice->LogicToPixel (maPageObjectModelSize);
+ pDevice->SetMapMode (aMapMode);
+
+ // Transform frequently used values from pixel to model coordinates.
+
+ Size aTotalGap (pDevice->PixelToLogic (Size (
+ mnTotalHorizontalGap.mnScreen,
+ mnTotalVerticalGap.mnScreen)));
+ mnTotalHorizontalGap.mnModel = aTotalGap.Width();
+ mnTotalVerticalGap.mnModel = aTotalGap.Height();
+
+ Size aGap (pDevice->PixelToLogic (Size (
+ mnHorizontalGap.mnScreen,
+ mnVerticalGap.mnScreen)));
+ mnHorizontalGap.mnModel = aGap.Width();
+ mnVerticalGap.mnModel = aGap.Height();
+
+ Size aTopLeftBorder (pDevice->PixelToLogic (Size (
+ mnLeftBorder.mnScreen,
+ mnTopBorder.mnScreen)));
+ mnLeftBorder.mnModel = aTopLeftBorder.Width();
+ mnTopBorder.mnModel = aTopLeftBorder.Height();
+
+ Size aBottomRightBorder (pDevice->PixelToLogic (Size (
+ mnLeftBorder.mnScreen,
+ mnTopBorder.mnScreen)));
+ mnRightBorder.mnModel = aBottomRightBorder.Width();
+ mnBottomBorder.mnModel = aBottomRightBorder.Height();
+
+ Size aTopLeftPageBorder (pDevice->PixelToLogic (Size (
+ mnLeftPageBorder.mnScreen,
+ mnTopPageBorder.mnScreen)));
+ mnLeftPageBorder.mnModel = aTopLeftPageBorder.Width();
+ mnTopPageBorder.mnModel = aTopLeftPageBorder.Height();
+
+ Size aBottomRightPageBorder (pDevice->PixelToLogic (Size (
+ mnRightPageBorder.mnScreen,
+ mnBottomPageBorder.mnScreen)));
+ mnRightPageBorder.mnModel = aBottomRightPageBorder.Width();
+ mnBottomPageBorder.mnModel = aBottomRightPageBorder.Height();
+
+ mnInsertionMarkerThickness.mnModel = pDevice->PixelToLogic (
+ Size(mnInsertionMarkerThickness.mnScreen,0)).Width();
+}
+
+
+
+
+sal_Int32 Layouter::GetColumnCount (void) const
+{
+ return mnColumnCount;
+}
+
+
+
+
+Size Layouter::GetPageObjectSize (void) const
+{
+ return maPageObjectModelSize;
+}
+
+
+
+
+Rectangle Layouter::GetPageObjectBox (sal_Int32 nIndex) const
+{
+ int nColumn = nIndex % mnColumnCount;
+ int nRow = nIndex / mnColumnCount;
+ return Rectangle (
+ Point (mnLeftBorder.mnModel
+ + nColumn * maPageObjectModelSize.Width()
+ + mnLeftPageBorder.mnModel
+ + (nColumn>0 ? nColumn : 0) * mnTotalHorizontalGap.mnModel,
+ mnTopBorder.mnModel
+ + nRow * maPageObjectModelSize.Height()
+ + mnTopPageBorder.mnModel
+ + (nRow>0 ? nRow : 0) * mnTotalVerticalGap.mnModel),
+ maPageObjectModelSize);
+}
+
+
+
+
+Rectangle Layouter::GetPageBox (sal_Int32 nObjectCount) const
+{
+ sal_Int32 nHorizontalSize = 0;
+ sal_Int32 nVerticalSize = 0;
+ if (mnColumnCount > 0)
+ {
+ sal_Int32 nRowCount = (nObjectCount+mnColumnCount-1) / mnColumnCount;
+ nHorizontalSize =
+ mnLeftBorder.mnModel
+ + mnRightBorder.mnModel
+ + mnColumnCount * maPageObjectModelSize.Width()
+ + mnLeftPageBorder.mnModel + mnRightPageBorder.mnModel;
+ if (mnColumnCount > 1)
+ nHorizontalSize
+ += (mnColumnCount-1) * mnTotalHorizontalGap.mnModel;
+ nVerticalSize =
+ mnTopBorder.mnModel
+ + mnBottomBorder.mnModel
+ + nRowCount * maPageObjectModelSize.Height()
+ + mnTopPageBorder.mnModel + mnBottomPageBorder.mnModel;
+ if (nRowCount > 1)
+ nVerticalSize += (nRowCount-1) * mnTotalVerticalGap.mnModel;
+ }
+
+ return Rectangle (
+ Point(0,0),
+ Size (nHorizontalSize, nVerticalSize)
+ );
+}
+
+
+
+
+Rectangle Layouter::GetInsertionMarkerBox (
+ sal_Int32 nIndex,
+ bool bVertical,
+ bool bLeftOrTop) const
+{
+ Rectangle aBox (GetPageObjectBox (nIndex));
+
+ if (bVertical)
+ {
+ sal_Int32 nHorizontalInsertionMarkerOffset
+ = (mnHorizontalGap.mnModel-mnInsertionMarkerThickness.mnModel) / 2;
+ if (bLeftOrTop)
+ {
+ // Left.
+ aBox.Left() -= mnLeftPageBorder.mnModel
+ + mnHorizontalGap.mnModel
+ - nHorizontalInsertionMarkerOffset;
+ }
+ else
+ {
+ // Right.
+ aBox.Left() = aBox.Right()
+ + mnRightPageBorder.mnModel
+ + nHorizontalInsertionMarkerOffset;
+ }
+ aBox.Right() = aBox.Left() + mnInsertionMarkerThickness.mnModel;
+ }
+ else
+ {
+ sal_Int32 nVerticalInsertionMarkerOffset
+ = (mnVerticalGap.mnModel - mnInsertionMarkerThickness.mnModel) / 2;
+ if (bLeftOrTop)
+ {
+ // Above.
+ aBox.Top() -= mnTopPageBorder.mnModel
+ + mnVerticalGap.mnModel
+ - nVerticalInsertionMarkerOffset;
+ }
+ else
+ {
+ // Below.
+ aBox.Top() = aBox.Bottom()
+ + mnBottomPageBorder.mnModel
+ + nVerticalInsertionMarkerOffset;
+ }
+ aBox.Bottom() = aBox.Top() + mnInsertionMarkerThickness.mnModel;
+ }
+
+ return aBox;
+}
+
+
+
+
+sal_Int32 Layouter::GetIndexOfFirstVisiblePageObject (
+ const Rectangle& aVisibleArea) const
+{
+ sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Top(), true, GM_BOTH);
+ return nRow * mnColumnCount;
+}
+
+
+
+
+sal_Int32 Layouter::GetIndexOfLastVisiblePageObject (
+ const Rectangle& aVisibleArea) const
+{
+ sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Bottom(),
+ true, GM_BOTH);
+ return (nRow+1) * mnColumnCount - 1;
+}
+
+
+
+
+sal_Int32 Layouter::GetIndexAtPoint (
+ const Point& rPosition,
+ bool bIncludePageBorders) const
+{
+ sal_Int32 nRow = GetRowAtPosition (rPosition.Y(),
+ bIncludePageBorders,
+ bIncludePageBorders ? GM_PAGE_BORDER : GM_NONE);
+ sal_Int32 nColumn = GetColumnAtPosition (rPosition.X(),
+ bIncludePageBorders,
+ bIncludePageBorders ? GM_PAGE_BORDER : GM_NONE);
+
+ if (nRow >= 0 && nColumn >= 0)
+ return nRow * mnColumnCount + nColumn;
+ else
+ return -1;
+}
+
+
+
+
+/** Calculation of the insertion index:
+ 1. Determine the row. rPoint has to be in the row between upper and
+ lower border. If it is in a horizontal gap or border an invalid
+ insertion index (-1, which is a valid return value) will be returned.
+ 2. Determine the column. Here both vertical borders and vertical gaps
+ will yield valid return values. The horizontal positions between the
+ center of page objects in column i and the center of page objects in
+ column i+1 will return column i+1 as insertion index.
+
+ When there is only one column and bAllowVerticalPosition is true than
+ take the vertical areas between rows into account as well.
+*/
+sal_Int32 Layouter::GetInsertionIndex (
+ const Point& rPosition,
+ bool bAllowVerticalPosition) const
+{
+ sal_Int32 nIndex = -1;
+
+ sal_Int32 nRow = GetRowAtPosition (rPosition.Y(), true,
+ (mnColumnCount==1 && bAllowVerticalPosition) ? GM_BOTH : GM_BOTH);
+ sal_Int32 nColumn = GetColumnAtPosition (rPosition.X(), true, GM_BOTH);
+
+ if (nRow >= 0 && nColumn >= 0)
+ nIndex = nRow * mnColumnCount + nColumn;
+
+ return nIndex;
+}
+
+
+
+
+Layouter::DoublePoint
+ Layouter::ConvertModelToLayouterCoordinates (
+ const Point& rModelPoint) const
+{
+ sal_Int32 nColumn = GetColumnAtPosition (rModelPoint.X(), true, GM_BOTH);
+ sal_Int32 nColumnWidth
+ = maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel;
+ sal_Int32 nDistanceIntoColumn =
+ rModelPoint.X() - mnLeftBorder.mnModel - mnLeftPageBorder.mnModel
+ - nColumn * nColumnWidth;
+
+ sal_Int32 nRow = GetRowAtPosition (rModelPoint.Y(), true, GM_BOTH);
+ sal_Int32 nRowHeight
+ = maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel;
+ sal_Int32 nDistanceIntoRow =
+ rModelPoint.Y() - mnTopBorder.mnModel - mnTopPageBorder.mnModel
+ - nRow * nRowHeight;
+
+ return DoublePoint (
+ nColumn + double(nDistanceIntoColumn) / double(nColumnWidth),
+ nRow + double(nDistanceIntoRow) / double(nRowHeight));
+}
+
+
+
+
+Point Layouter::ConvertLayouterToModelCoordinates (
+ const DoublePoint & rLayouterPoint) const
+{
+ sal_Int32 nColumn = (sal_Int32) ::rtl::math::round(rLayouterPoint.first,
+ 0,rtl_math_RoundingMode_Floor);
+ sal_Int32 nColumnWidth
+ = maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel;
+ sal_Int32 nDistanceIntoColumn
+ = (sal_Int32)((rLayouterPoint.first - nColumn) * nColumnWidth);
+
+ sal_Int32 nRow = (sal_Int32) ::rtl::math::round(rLayouterPoint.second,
+ 0,rtl_math_RoundingMode_Floor);
+ sal_Int32 nRowHeight
+ = maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel;
+ sal_Int32 nDistanceIntoRow
+ = (sal_Int32)((rLayouterPoint.second - nRow) * nRowHeight);
+
+ return Point (
+ mnLeftBorder.mnModel + mnLeftPageBorder.mnModel
+ + nColumn * nColumnWidth + nDistanceIntoColumn,
+ mnTopBorder.mnModel + mnTopPageBorder.mnModel
+ + nRow * nRowHeight + nDistanceIntoRow);
+}
+
+
+
+
+sal_Int32 Layouter::GetRowAtPosition (
+ sal_Int32 nYPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership) const
+{
+ sal_Int32 nRow = -1;
+
+ const sal_Int32 nY = nYPosition
+ - mnTopBorder.mnModel - mnTopPageBorder.mnModel;
+ if (nY >= 0)
+ {
+ // Vertical distance from one row to the next.
+ const sal_Int32 nRowOffset (
+ maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel);
+
+ // Calculate row consisting of page objects and gap below.
+ nRow = nY / nRowOffset;
+
+ const sal_Int32 nDistanceIntoGap (
+ (nY - nRow*nRowOffset) - maPageObjectModelSize.Height());
+ // When inside the gap below then nYPosition is not over a page
+ // object.
+ if (nDistanceIntoGap > 0)
+ nRow = ResolvePositionInGap (
+ nDistanceIntoGap,
+ eGapMembership,
+ nRow,
+ mnBottomPageBorder.mnModel,
+ mnVerticalGap.mnModel);
+ }
+ else if (bIncludeBordersAndGaps)
+ {
+ // We are in the top border area. Set nRow to the first row when
+ // the top border shall be considered to belong to the first row.
+ nRow = 0;
+ }
+
+ return nRow;
+}
+
+
+
+
+sal_Int32 Layouter::GetColumnAtPosition (
+ sal_Int32 nXPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership) const
+{
+ sal_Int32 nColumn = -1;
+
+ sal_Int32 nX = nXPosition
+ - mnLeftBorder.mnModel - mnLeftPageBorder.mnModel;
+ if (nX >= 0)
+ {
+ // Horizontal distance from one column to the next.
+ const sal_Int32 nColumnOffset (
+ maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel);
+
+ // Calculate row consisting of page objects and gap below.
+ nColumn = nX / nColumnOffset;
+ if (nColumn < 0)
+ nColumn = 0;
+ else if (nColumn >= mnColumnCount)
+ nColumn = mnColumnCount-1;
+
+ const sal_Int32 nDistanceIntoGap (
+ (nX - nColumn*nColumnOffset) - maPageObjectModelSize.Width());
+ // When inside the gap at the right then nXPosition is not over a
+ // page object.
+ if (nDistanceIntoGap > 0)
+ nColumn = ResolvePositionInGap (
+ nDistanceIntoGap,
+ eGapMembership,
+ nColumn,
+ mnRightPageBorder.mnModel,
+ mnHorizontalGap.mnModel);
+ }
+ else if (bIncludeBordersAndGaps)
+ {
+ // We are in the left border area. Set nColumn to the first column
+ // when the left border shall be considered to belong to the first
+ // column.
+ nColumn = 0;
+ }
+ return nColumn;
+}
+
+
+
+
+sal_Int32 Layouter::ResolvePositionInGap (
+ sal_Int32 nDistanceIntoGap,
+ GapMembership eGapMembership,
+ sal_Int32 nIndex,
+ sal_Int32 nLeftOrTopPageBorder,
+ sal_Int32 nGap) const
+{
+ switch (eGapMembership)
+ {
+ case GM_NONE:
+ // The gap is no man's land.
+ nIndex = -1;
+ break;
+
+ case GM_BOTH:
+ {
+ // The lower half of the gap belongs to the next row or column.
+ sal_Int32 nFirstHalfGapWidth = nLeftOrTopPageBorder + nGap / 2;
+ if (nDistanceIntoGap > nFirstHalfGapWidth)
+ nIndex ++;
+ break;
+ }
+
+ case GM_PREVIOUS:
+ // Row or column already at correct value.
+ break;
+
+ case GM_NEXT:
+ // The complete gap belongs to the next row or column.
+ nIndex ++;
+ break;
+
+ case GM_PAGE_BORDER:
+ if (nDistanceIntoGap > nLeftOrTopPageBorder)
+ {
+ if (nDistanceIntoGap > nLeftOrTopPageBorder + nGap)
+ {
+ // Inside the border of the next row or column.
+ nIndex ++;
+ }
+ else
+ {
+ // Inside the gap between the page borders.
+ nIndex = -1;
+ }
+ }
+ break;
+
+ default:
+ nIndex = -1;
+ }
+
+ return nIndex;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsPageObject.cxx b/sd/source/ui/slidesorter/view/SlsPageObject.cxx
new file mode 100644
index 000000000000..a9508e4065e1
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsPageObject.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "view/SlsPageObject.hxx"
+
+#include "model/SlsPageDescriptor.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+
+using namespace ::sdr::contact;
+using namespace ::sd::slidesorter::model;
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+PageObject::PageObject (
+ const Rectangle& rRectangle,
+ SdrPage* _pPage,
+ const SharedPageDescriptor& rpDescriptor)
+ : SdrPageObj(rRectangle, _pPage),
+ mpDescriptor(rpDescriptor)
+{
+}
+
+
+
+
+PageObject::~PageObject (void)
+{
+}
+
+
+
+
+SharedPageDescriptor PageObject::GetDescriptor (void) const
+{
+ return mpDescriptor;
+}
+
+
+
+
+sdr::contact::ViewContact* PageObject::CreateObjectSpecificViewContact()
+{
+ if (mpDescriptor.get() != NULL)
+ return mpDescriptor->GetPageObjectFactory().CreateViewContact(this, mpDescriptor);
+ else
+ return NULL;
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectViewContact.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectViewContact.cxx
new file mode 100644
index 000000000000..a5a74c939e52
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsPageObjectViewContact.cxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlsPageObjectViewContact.hxx"
+
+#include "model/SlsPageDescriptor.hxx"
+#include "controller/SlsPageObjectFactory.hxx"
+
+#include <svx/svdopage.hxx>
+#include <tools/debug.hxx>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+
+using namespace ::sdr::contact;
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+PageObjectViewContact::PageObjectViewContact (
+ SdrPageObj& rPageObj,
+ const model::SharedPageDescriptor& rpDescriptor)
+ : ViewContactOfPageObj (rPageObj),
+ mbInDestructor(false),
+ mpDescriptor(rpDescriptor)
+{
+}
+
+PageObjectViewContact::~PageObjectViewContact (void)
+{
+ // remember that this instance is in destruction
+ mbInDestructor = true;
+}
+
+
+
+ViewObjectContact&
+ PageObjectViewContact::CreateObjectSpecificViewObjectContact(
+ ObjectContact& rObjectContact)
+{
+ OSL_ASSERT(mpDescriptor.get()!=NULL);
+
+ ViewObjectContact* pResult
+ = mpDescriptor->GetPageObjectFactory().CreateViewObjectContact (
+ rObjectContact,
+ *this);
+ DBG_ASSERT (pResult!=NULL,
+ "PageObjectViewContact::CreateObjectSpecificViewObjectContact() was not able to create object.");
+ return *pResult;
+}
+
+const SdrPage* PageObjectViewContact::GetPage (void) const
+{
+ // when this instance itself is in destruction, do no longer
+ // provide the referenced page to VOC childs of this OC. This
+ // happens e.g. in destructor which destroys all child-VOCs which
+ // may in their implementation still reference their VC from
+ // their own destructor
+ if (!mbInDestructor)
+ return GetReferencedPage();
+ else
+ return NULL;
+}
+
+void PageObjectViewContact::ActionChanged (void)
+{
+ ViewContactOfPageObj::ActionChanged();
+}
+
+SdrPageObj& PageObjectViewContact::GetPageObject (void) const
+{
+ return ViewContactOfPageObj::GetPageObj();
+}
+
+drawinglayer::primitive2d::Primitive2DSequence PageObjectViewContact::createViewIndependentPrimitive2DSequence() const
+{
+ // ceate graphical visualisation data. Since this is the view-independent version which should not be used,
+ // create a replacement graphic visualisation here. Use GetLastBoundRect to access the model data directly
+ // which is aOutRect for SdrPageObj.
+ OSL_ASSERT(mpDescriptor.get()!=NULL);
+ Rectangle aModelRectangle(GetPageObj().GetLastBoundRect());
+ const SvBorder aBorder(mpDescriptor->GetModelBorder());
+
+ aModelRectangle.Left() -= aBorder.Left();
+ aModelRectangle.Right() += aBorder.Right();
+ aModelRectangle.Top() -= aBorder.Top();
+ aModelRectangle.Bottom() += aBorder.Bottom();
+
+ const basegfx::B2DRange aModelRange(aModelRectangle.Left(), aModelRectangle.Top(), aModelRectangle.Right(), aModelRectangle.Bottom());
+ const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aModelRange));
+ const basegfx::BColor aYellow(1.0, 1.0, 0.0);
+ const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aYellow));
+
+ return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
+}
+
+} } } // end of namespace ::sd::slidesorter::view
+
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx
new file mode 100644
index 000000000000..903d60674ece
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsPageObjectViewObjectContact.cxx
@@ -0,0 +1,1406 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlsPageObjectViewObjectContact.hxx"
+
+#include "controller/SlsProperties.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewContact.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlsFontProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "res_bmp.hrc"
+#include "tools/IconCache.hxx"
+#include "PreviewRenderer.hxx"
+
+#include "sdpage.hxx"
+#include "sdresid.hxx"
+#include "glob.hrc"
+#include "drawdoc.hxx"
+#include <svx/sdr/contact/displayinfo.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/lineinfo.hxx>
+#include <tools/color.hxx>
+#include <boost/shared_ptr.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <vcl/svapp.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::sdr::contact;
+using namespace ::sd::slidesorter::model;
+
+using drawinglayer::primitive2d::Primitive2DReference;
+using drawinglayer::primitive2d::Primitive2DSequence;
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+const sal_Int32 PageObjectViewObjectContact::mnSelectionIndicatorOffset = 2;
+const sal_Int32 PageObjectViewObjectContact::mnSelectionIndicatorThickness = 3;
+const sal_Int32 PageObjectViewObjectContact::mnFocusIndicatorOffset = 3;
+const sal_Int32 PageObjectViewObjectContact::mnFadeEffectIndicatorOffset = 9;
+const sal_Int32 PageObjectViewObjectContact::mnFadeEffectIndicatorSize = 14;
+const sal_Int32 PageObjectViewObjectContact::mnPageNumberOffset = 9;
+const sal_Int32 PageObjectViewObjectContact::mnMouseOverEffectOffset = 3;
+const sal_Int32 PageObjectViewObjectContact::mnMouseOverEffectThickness = 1;
+
+PageObjectViewObjectContact::PageObjectViewObjectContact (
+ ObjectContact& rObjectContact,
+ ViewContact& rViewContact,
+ const ::boost::shared_ptr<cache::PageCache>& rpCache,
+ const ::boost::shared_ptr<controller::Properties>& rpProperties)
+ : ViewObjectContactOfPageObj(rObjectContact, rViewContact),
+ mbInDestructor(false),
+ mxCurrentPageContents(),
+ mpCache(rpCache),
+ mpProperties(rpProperties)
+{
+ SharedPageDescriptor pDescriptor (GetPageDescriptor());
+ OSL_ASSERT(pDescriptor.get()!=NULL);
+ if (pDescriptor.get() != NULL)
+ pDescriptor->SetViewObjectContact(this);
+}
+
+
+
+
+PageObjectViewObjectContact::~PageObjectViewObjectContact (void)
+{
+ mbInDestructor = true;
+
+ GetPageDescriptor()->SetViewObjectContact(NULL);
+
+ if (mpCache.get() != NULL)
+ {
+ const SdrPage* pPage = GetPage();
+
+ if(pPage)
+ {
+ mpCache->ReleasePreviewBitmap(GetPage());
+ }
+ }
+}
+
+
+
+
+void PageObjectViewObjectContact::SetCache (const ::boost::shared_ptr<cache::PageCache>& rpCache)
+{
+ mpCache = rpCache;
+}
+
+
+
+
+Rectangle PageObjectViewObjectContact::GetBoundingBox (
+ OutputDevice& rDevice,
+ BoundingBoxType eType,
+ CoordinateSystem eCoordinateSystem) const
+{
+ // Most of the bounding boxes are based on the bounding box of the preview.
+ // SdrPageObj is a SdrObject, so use SdrObject::aOutRect as model data
+ const PageObjectViewContact& rPaObVOC(static_cast<PageObjectViewContact&>(GetViewContact()));
+ Rectangle aBoundingBox(rPaObVOC.GetPageObject().GetLastBoundRect());
+
+ CoordinateSystem eCurrentCoordinateSystem (ModelCoordinateSystem);
+ switch(eType)
+ {
+ case PageObjectBoundingBox:
+ {
+ const SvBorder aPageDescriptorBorder(GetPageDescriptor()->GetModelBorder());
+ aBoundingBox.Left() -= aPageDescriptorBorder.Left();
+ aBoundingBox.Top() -= aPageDescriptorBorder.Top();
+ aBoundingBox.Right() += aPageDescriptorBorder.Right();
+ aBoundingBox.Bottom() += aPageDescriptorBorder.Bottom();
+ break;
+ }
+ case PreviewBoundingBox:
+ {
+ // The aBoundingBox already has the right value.
+ break;
+ }
+ case MouseOverIndicatorBoundingBox:
+ {
+ const sal_Int32 nBorderWidth (mnMouseOverEffectOffset+mnMouseOverEffectThickness);
+ const Size aBorderSize (rDevice.PixelToLogic(Size(nBorderWidth,nBorderWidth)));
+ aBoundingBox.Left() -= aBorderSize.Width();
+ aBoundingBox.Top() -= aBorderSize.Height();
+ aBoundingBox.Right() += aBorderSize.Width();
+ aBoundingBox.Bottom() += aBorderSize.Height();
+ break;
+ }
+ case FocusIndicatorBoundingBox:
+ {
+ const sal_Int32 nBorderWidth (mnFocusIndicatorOffset+1);
+ const Size aBorderSize (rDevice.PixelToLogic(Size(nBorderWidth,nBorderWidth)));
+ aBoundingBox.Left() -= aBorderSize.Width();
+ aBoundingBox.Top() -= aBorderSize.Height();
+ aBoundingBox.Right() += aBorderSize.Width();
+ aBoundingBox.Bottom() += aBorderSize.Height();
+ break;
+ }
+ case SelectionIndicatorBoundingBox:
+ {
+ const sal_Int32 nBorderWidth(mnSelectionIndicatorOffset+mnSelectionIndicatorThickness);
+ const Size aBorderSize (rDevice.PixelToLogic(Size(nBorderWidth,nBorderWidth)));
+ aBoundingBox.Left() -= aBorderSize.Width();
+ aBoundingBox.Top() -= aBorderSize.Height();
+ aBoundingBox.Right() += aBorderSize.Width();
+ aBoundingBox.Bottom() += aBorderSize.Height();
+ break;
+ }
+ case PageNumberBoundingBox:
+ {
+ Size aModelOffset = rDevice.PixelToLogic(Size(mnPageNumberOffset,mnPageNumberOffset));
+ Size aNumberSize (GetPageDescriptor()->GetPageNumberAreaModelSize());
+ aBoundingBox = Rectangle (
+ Point (
+ aBoundingBox.Left() - aModelOffset.Width() - aNumberSize.Width(),
+ aBoundingBox.Top()),
+ aNumberSize);
+ break;
+ }
+
+ case NameBoundingBox:
+ break;
+
+ case FadeEffectIndicatorBoundingBox:
+ Size aModelOffset = rDevice.PixelToLogic(Size (0, mnFadeEffectIndicatorOffset));
+ // Flush left just outside the selection rectangle.
+ aBoundingBox = Rectangle (
+ Point (
+ aBoundingBox.Left(),
+ aBoundingBox.Bottom() + aModelOffset.Height()
+ ),
+ rDevice.PixelToLogic (
+ IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR).GetSizePixel())
+ );
+ break;
+ }
+
+ // Make sure the bounding box uses the requested coordinate system.
+ if (eCurrentCoordinateSystem != eCoordinateSystem)
+ {
+ if (eCoordinateSystem == ModelCoordinateSystem)
+ aBoundingBox = Rectangle(
+ rDevice.PixelToLogic(aBoundingBox.TopLeft()),
+ rDevice.PixelToLogic(aBoundingBox.GetSize()));
+ else
+ aBoundingBox = Rectangle(
+ rDevice.LogicToPixel(aBoundingBox.TopLeft()),
+ rDevice.LogicToPixel(aBoundingBox.GetSize()));
+ }
+ return aBoundingBox;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// example implementation for primitive usage for PageObjectViewObjectContact
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <sd_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <svx/sdr/contact/objectcontact.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// All primitives for SdrPageObject visualisation are based on one range which describes
+// the size of the inner rectangle for PagePreview visualisation. Use a common implementation
+// class for all derived SdPageObjectPrimitives. The SdPageObjectBasePrimitive itself
+// is pure virtual
+
+class SdPageObjectBasePrimitive : public drawinglayer::primitive2d::BufferedDecompositionPrimitive2D
+{
+private:
+ // the inner range of the SdPageObject visualisation
+ basegfx::B2DRange maRange;
+
+public:
+ // constructor and destructor
+ SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange);
+ virtual ~SdPageObjectBasePrimitive();
+
+ // data access
+ const basegfx::B2DRange& getPageObjectRange() const { return maRange; }
+
+ // compare operator
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
+};
+
+SdPageObjectBasePrimitive::SdPageObjectBasePrimitive(const basegfx::B2DRange& rRange)
+: drawinglayer::primitive2d::BufferedDecompositionPrimitive2D(),
+ maRange(rRange)
+{
+}
+
+SdPageObjectBasePrimitive::~SdPageObjectBasePrimitive()
+{
+}
+
+bool SdPageObjectBasePrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const SdPageObjectBasePrimitive& rCompare = static_cast< const SdPageObjectBasePrimitive& >(rPrimitive);
+ return (getPageObjectRange() == rCompare.getPageObjectRange());
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SdPageObjectPrimitive for selected visualisation
+
+class SdPageObjectPageBitmapPrimitive : public SdPageObjectBasePrimitive
+{
+private:
+ // the bitmap containing the PagePreview
+ BitmapEx maBitmapEx;
+
+protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive.
+ virtual Primitive2DSequence create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ // constructor and destructor
+ SdPageObjectPageBitmapPrimitive(
+ const basegfx::B2DRange& rRange,
+ const BitmapEx& rBitmapEx);
+ ~SdPageObjectPageBitmapPrimitive();
+
+ // data access
+ const BitmapEx& getBitmapEx() const { return maBitmapEx; }
+
+ // compare operator
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+};
+
+Primitive2DSequence SdPageObjectPageBitmapPrimitive::create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ // add bitmap primitive
+ // to avoid scaling, use the Bitmap pixel size as primitive size
+ basegfx::B2DHomMatrix aBitmapTransform;
+ const Size aBitmapSize(getBitmapEx().GetSizePixel());
+ const basegfx::B2DVector aBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() *
+ basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1));
+
+ // short form for scale and translate transformation
+ aBitmapTransform.set(0L, 0L, aBitmapSizeLogic.getX());
+ aBitmapTransform.set(1L, 1L, aBitmapSizeLogic.getY());
+ aBitmapTransform.set(0L, 2L, getPageObjectRange().getMinX());
+ aBitmapTransform.set(1L, 2L, getPageObjectRange().getMinY());
+
+ // add a BitmapPrimitive2D to the result
+ const Primitive2DReference xReference(
+ new drawinglayer::primitive2d::BitmapPrimitive2D(getBitmapEx(), aBitmapTransform));
+ return Primitive2DSequence(&xReference, 1);
+}
+
+SdPageObjectPageBitmapPrimitive::SdPageObjectPageBitmapPrimitive(
+ const basegfx::B2DRange& rRange,
+ const BitmapEx& rBitmapEx)
+: SdPageObjectBasePrimitive(rRange),
+ maBitmapEx(rBitmapEx)
+{
+}
+
+SdPageObjectPageBitmapPrimitive::~SdPageObjectPageBitmapPrimitive()
+{
+}
+
+bool SdPageObjectPageBitmapPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(SdPageObjectBasePrimitive::operator==(rPrimitive))
+ {
+ const SdPageObjectPageBitmapPrimitive& rCompare = static_cast< const SdPageObjectPageBitmapPrimitive& >(rPrimitive);
+ return (getBitmapEx() == rCompare.getBitmapEx());
+ }
+
+ return false;
+}
+
+ImplPrimitrive2DIDBlock(SdPageObjectPageBitmapPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTPAGEBITMAPPRIMITIVE)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SdPageObjectPrimitive for selected visualisation
+
+class SdPageObjectSelectPrimitive : public SdPageObjectBasePrimitive
+{
+private:
+ /// Gap between border of page object and inside of selection rectangle.
+ static const sal_Int32 mnSelectionIndicatorOffset;
+
+ /// Thickness of the selection rectangle.
+ static const sal_Int32 mnSelectionIndicatorThickness;
+
+protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive.
+ virtual Primitive2DSequence create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ // constructor and destructor
+ SdPageObjectSelectPrimitive(const basegfx::B2DRange& rRange);
+ ~SdPageObjectSelectPrimitive();
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+};
+
+const sal_Int32 SdPageObjectSelectPrimitive::mnSelectionIndicatorOffset(1);
+const sal_Int32 SdPageObjectSelectPrimitive::mnSelectionIndicatorThickness(3);
+
+Primitive2DSequence SdPageObjectSelectPrimitive::create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ Primitive2DSequence xRetval(2);
+
+ // since old Width/Height calculations always added a single pixel value,
+ // it is necessary to create a inner range which is one display unit less
+ // at the bottom right.
+ const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
+ const basegfx::B2DRange aAdaptedInnerRange(
+ getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
+ getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY());
+
+ // PaintSelectionIndicator replacement. Grow by offset first
+ basegfx::B2DRange aDiscreteOuterRange(aAdaptedInnerRange);
+ aDiscreteOuterRange.grow(mnSelectionIndicatorOffset * aDiscretePixel.getX());
+
+ // Remember inner border. Make it one bigger in top left since polygons
+ // do not paint their lower-right corners. Since this is the inner polygon,
+ // the top-left corders are the ones to grow here
+ const basegfx::B2DRange aDiscreteInnerRange(
+ aDiscreteOuterRange.getMinimum() + aDiscretePixel,
+ aDiscreteOuterRange.getMaximum() - aDiscretePixel);
+
+ // grow by line width
+ aDiscreteOuterRange.grow((mnSelectionIndicatorThickness - 1) * aDiscretePixel.getX());
+
+ // create a PolyPolygon from those ranges. For the outer polygon, round edges by
+ // giving a relative radius to the polygon creator (use mnSelectionIndicatorThickness here, too)
+ const double fPixelFactor(aDiscretePixel.getX() * (mnSelectionIndicatorThickness + 2.5));
+ const double fRelativeRadiusX(fPixelFactor / ::std::max(aDiscreteOuterRange.getWidth(), 1.0));
+ const double fRelativeRadiusY(fPixelFactor / ::std::max(aDiscreteOuterRange.getHeight(), 1.0));
+ basegfx::B2DPolyPolygon aFramePolyPolygon;
+ const basegfx::B2DPolygon aRoundedOuterPolygon(basegfx::tools::createPolygonFromRect(aDiscreteOuterRange, fRelativeRadiusX, fRelativeRadiusY));
+
+ aFramePolyPolygon.append(aRoundedOuterPolygon);
+ aFramePolyPolygon.append(basegfx::tools::createPolygonFromRect(aDiscreteInnerRange));
+
+ // add colored PolyPolygon
+ const svtools::ColorConfig aColorConfig;
+ static bool bTestWithBrightColors(false);
+ const basegfx::BColor aFrameColor(bTestWithBrightColors ? basegfx::BColor(0,1,0) : Application::GetSettings().GetStyleSettings().GetMenuHighlightColor().getBColor());
+
+ xRetval[0] = Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(aFramePolyPolygon, aFrameColor));
+
+ // add aRoundedOuterPolygon again as non-filled line polygon to get the roundungs
+ // painted correctly
+ xRetval[1] = Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aRoundedOuterPolygon, aFrameColor));
+
+ return xRetval;
+}
+
+SdPageObjectSelectPrimitive::SdPageObjectSelectPrimitive(const basegfx::B2DRange& rRange)
+: SdPageObjectBasePrimitive(rRange)
+{
+}
+
+SdPageObjectSelectPrimitive::~SdPageObjectSelectPrimitive()
+{
+}
+
+ImplPrimitrive2DIDBlock(SdPageObjectSelectPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTSELECTPRIMITIVE)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SdPageObjectPrimitive for border around bitmap visualisation
+
+class SdPageObjectBorderPrimitive : public SdPageObjectBasePrimitive
+{
+protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive.
+ virtual Primitive2DSequence create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ // constructor and destructor
+ SdPageObjectBorderPrimitive(const basegfx::B2DRange& rRange);
+ ~SdPageObjectBorderPrimitive();
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+};
+
+Primitive2DSequence SdPageObjectBorderPrimitive::create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ // since old Width/Height calculations always added a single pixel value,
+ // it is necessary to create a inner range which is one display unit less
+ // at the bottom right.
+ const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
+ const basegfx::B2DRange aAdaptedInnerRange(
+ getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
+ getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY());
+
+ // Paint_Border replacement. (use aBorderColor)
+ static bool bTestWithBrightColors(false);
+ const svtools::ColorConfig aColorConfig;
+ const basegfx::BColor aBorderColor(bTestWithBrightColors ? basegfx::BColor(1,0,0) : Color(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor).getBColor());
+
+ const Primitive2DReference xReference(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(basegfx::tools::createPolygonFromRect(aAdaptedInnerRange), aBorderColor));
+ return Primitive2DSequence(&xReference, 1);
+}
+
+SdPageObjectBorderPrimitive::SdPageObjectBorderPrimitive(const basegfx::B2DRange& rRange)
+: SdPageObjectBasePrimitive(rRange)
+{
+}
+
+SdPageObjectBorderPrimitive::~SdPageObjectBorderPrimitive()
+{
+}
+
+ImplPrimitrive2DIDBlock(SdPageObjectBorderPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTBORDERPRIMITIVE)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SdPageObjectPrimitive for focus visualisation
+
+class SdPageObjectFocusPrimitive : public SdPageObjectBasePrimitive
+{
+private:
+ /// Gap between border of page object and inside of focus rectangle.
+ static const sal_Int32 mnFocusIndicatorOffset;
+ const bool mbContrastToSelected;
+
+protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive.
+ virtual Primitive2DSequence create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ // constructor and destructor
+ SdPageObjectFocusPrimitive(const basegfx::B2DRange& rRange, const bool bContrast);
+ ~SdPageObjectFocusPrimitive();
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+};
+
+const sal_Int32 SdPageObjectFocusPrimitive::mnFocusIndicatorOffset(2);
+
+Primitive2DSequence SdPageObjectFocusPrimitive::create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ Primitive2DSequence xRetval(2);
+
+ // since old Width/Height calculations always added a single pixel value,
+ // it is necessary to create a inner range which is one display unit less
+ // at the bottom right.
+ const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
+ const basegfx::B2DRange aAdaptedInnerRange(
+ getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
+ getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY());
+
+ // Paint_FocusIndicator replacement. (black and white).
+ // imitate Paint_DottedRectangle: First paint a white rectangle and above it a black dotted one
+ basegfx::B2DRange aFocusIndicatorRange(aAdaptedInnerRange);
+ aFocusIndicatorRange.grow(mnFocusIndicatorOffset * aDiscretePixel.getX());
+
+ // create polygon
+ const basegfx::B2DPolygon aIndicatorPolygon(basegfx::tools::createPolygonFromRect(aFocusIndicatorRange));
+
+ const StyleSettings& rStyleSettings(Application::GetSettings().GetStyleSettings());
+
+ // "background" rectangle
+ const Color aBackgroundColor(mbContrastToSelected ? rStyleSettings.GetMenuHighlightColor() : rStyleSettings.GetWindowColor());
+ xRetval[0] = Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aIndicatorPolygon, Color(COL_WHITE).getBColor()));
+
+ // dotted black rectangle with same geometry
+ ::std::vector< double > aDotDashArray;
+
+ const sal_Int32 nFocusIndicatorWidth (3);
+ aDotDashArray.push_back(nFocusIndicatorWidth *aDiscretePixel.getX());
+ aDotDashArray.push_back(nFocusIndicatorWidth * aDiscretePixel.getX());
+
+ // prepare line and stroke attributes
+ const Color aLineColor(mbContrastToSelected ? rStyleSettings.GetMenuHighlightTextColor() : rStyleSettings.GetWindowTextColor());
+ const drawinglayer::attribute::LineAttribute aLineAttribute(aLineColor.getBColor());
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
+ aDotDashArray, 2.0 * nFocusIndicatorWidth * aDiscretePixel.getX());
+
+
+ xRetval[1] = Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(aIndicatorPolygon, aLineAttribute, aStrokeAttribute));
+
+ return xRetval;
+}
+
+SdPageObjectFocusPrimitive::SdPageObjectFocusPrimitive(const basegfx::B2DRange& rRange, const bool bContrast)
+ : SdPageObjectBasePrimitive(rRange),
+ mbContrastToSelected(bContrast)
+{
+}
+
+SdPageObjectFocusPrimitive::~SdPageObjectFocusPrimitive()
+{
+}
+
+ImplPrimitrive2DIDBlock(SdPageObjectFocusPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTFOCUSPRIMITIVE)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// SdPageObjectPrimitive for fade effect visualisation
+
+class SdPageObjectFadeNameNumberPrimitive : public SdPageObjectBasePrimitive
+{
+private:
+ /// Size of width and height of the fade effect indicator in pixels.
+ static const sal_Int32 mnFadeEffectIndicatorOffset;
+
+ /// Size of width and height of the comments indicator in pixels.
+ static const sal_Int32 mnCommentsIndicatorOffset;
+
+ /// Gap between border of page object and number rectangle.
+ static const sal_Int32 mnPageNumberOffset;
+
+ /// the indicator bitmaps. Static since it is usable outside this primitive
+ /// for size comparisons
+ static BitmapEx* mpFadeEffectIconBitmap;
+ static BitmapEx* mpCommentsIconBitmap;
+
+ /// page name, number and needed infos
+ String maPageName;
+ sal_uInt32 mnPageNumber;
+ Font maPageNameFont;
+ Size maPageNumberAreaModelSize;
+
+ // bitfield
+ bool mbShowFadeEffectIcon : 1;
+ bool mbShowCommentsIcon : 1;
+ bool mbExcluded : 1;
+
+ // private helpers
+ const BitmapEx& getFadeEffectIconBitmap() const;
+
+protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive.
+ virtual Primitive2DSequence create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ // constructor and destructor
+ SdPageObjectFadeNameNumberPrimitive(
+ const basegfx::B2DRange& rRange,
+ const String& rPageName,
+ sal_uInt32 nPageNumber,
+ const Font& rPageNameFont,
+ const Size& rPageNumberAreaModelSize,
+ bool bShowFadeEffectIcon,
+ bool bShowCommentsIcon,
+ bool bExcluded);
+ ~SdPageObjectFadeNameNumberPrimitive();
+
+ // data access
+ const String& getPageName() const { return maPageName; }
+ sal_uInt32 getPageNumber() const { return mnPageNumber; }
+ const Font& getPageNameFont() const { return maPageNameFont; }
+ const Size& getPageNumberAreaModelSize() const { return maPageNumberAreaModelSize; }
+ bool getShowFadeEffectIcon() const { return mbShowFadeEffectIcon; }
+ bool getShowCommentsIcon() const { return mbShowCommentsIcon; }
+ bool getExcluded() const { return mbExcluded; }
+
+ // compare operator
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+};
+
+const sal_Int32 SdPageObjectFadeNameNumberPrimitive::mnFadeEffectIndicatorOffset(9);
+const sal_Int32 SdPageObjectFadeNameNumberPrimitive::mnPageNumberOffset(9);
+BitmapEx* SdPageObjectFadeNameNumberPrimitive::mpFadeEffectIconBitmap = 0;
+
+const BitmapEx& SdPageObjectFadeNameNumberPrimitive::getFadeEffectIconBitmap() const
+{
+ if(mpFadeEffectIconBitmap == NULL)
+ {
+ // prepare FadeEffectIconBitmap on demand
+ const sal_uInt16 nIconId(Application::GetSettings().GetStyleSettings().GetHighContrastMode()
+ ? BMP_FADE_EFFECT_INDICATOR_H
+ : BMP_FADE_EFFECT_INDICATOR);
+ const BitmapEx aFadeEffectIconBitmap(IconCache::Instance().GetIcon(nIconId).GetBitmapEx());
+ const_cast< SdPageObjectFadeNameNumberPrimitive* >(this)->mpFadeEffectIconBitmap = new BitmapEx(aFadeEffectIconBitmap);
+ }
+
+ return *mpFadeEffectIconBitmap;
+}
+
+
+const sal_Int32 SdPageObjectFadeNameNumberPrimitive::mnCommentsIndicatorOffset(9);
+BitmapEx* SdPageObjectFadeNameNumberPrimitive::mpCommentsIconBitmap = 0;
+
+Primitive2DSequence SdPageObjectFadeNameNumberPrimitive::create2DDecomposition(const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ const xub_StrLen nTextLength(getPageName().Len());
+ const sal_uInt32 nCount(
+ (getShowFadeEffectIcon() ? 1 : 0) + // FadeEffect icon
+ (nTextLength ? 1 : 0) + // PageName
+ 1 + // PageNumber (always)
+ (getExcluded() ? 2 : 0) // PageNumber crossed out
+ );
+ sal_uInt32 nInsert(0);
+ Primitive2DSequence xRetval(nCount);
+
+ // since old Width/Height calculations always added a single pixel value,
+ // it is necessary to create a inner range which is one display unit less
+ // at the bottom right.
+ const basegfx::B2DVector aDiscretePixel(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
+ const basegfx::B2DRange aAdaptedInnerRange(
+ getPageObjectRange().getMinX(), getPageObjectRange().getMinY(),
+ getPageObjectRange().getMaxX() - aDiscretePixel.getX(), getPageObjectRange().getMaxY() - aDiscretePixel.getY());
+
+ // preapre TextLayouter
+ drawinglayer::primitive2d::TextLayouterDevice aTextLayouter;
+ aTextLayouter.setFont(getPageNameFont());
+
+ // get font attributes
+ basegfx::B2DVector aTextSizeAttribute;
+ const drawinglayer::attribute::FontAttribute aFontAttribute(
+ drawinglayer::primitive2d::getFontAttributeFromVclFont(
+ aTextSizeAttribute,
+ getPageNameFont(),
+ false,
+ false));
+
+ // prepare locale; this may need some more information in the future
+ const ::com::sun::star::lang::Locale aLocale;
+
+ // prepare font color from System
+ const basegfx::BColor aFontColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor());
+
+ if(getShowFadeEffectIcon())
+ {
+ // prepare fFadeEffect Sizes
+ const basegfx::B2DVector aFadeEffectBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() *
+ basegfx::B2DVector(
+ getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1,
+ getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1));
+
+ // Paint_FadeEffectIndicator replacement.
+ // create transformation. To avoid bitmap scaling, use bitmap size as size
+ basegfx::B2DHomMatrix aBitmapTransform;
+
+ // short form for scale and translate transformation
+ aBitmapTransform.set(0L, 0L, aFadeEffectBitmapSizeLogic.getX());
+ aBitmapTransform.set(1L, 1L, aFadeEffectBitmapSizeLogic.getY());
+ aBitmapTransform.set(0L, 2L, aAdaptedInnerRange.getMinX());
+ aBitmapTransform.set(1L, 2L, aAdaptedInnerRange.getMaxY() + ((mnFadeEffectIndicatorOffset + 1) * aDiscretePixel.getX()));
+
+ xRetval[nInsert++] = Primitive2DReference(
+ new drawinglayer::primitive2d::BitmapPrimitive2D(getFadeEffectIconBitmap(), aBitmapTransform));
+ }
+
+ if(nTextLength)
+ {
+ // prepare fFadeEffect Sizes since it consumes from text size
+ const basegfx::B2DVector aFadeEffectBitmapSizeLogic(rViewInformation.getInverseObjectToViewTransformation() *
+ basegfx::B2DVector(
+ getFadeEffectIconBitmap().GetSizePixel().getWidth() - 1,
+ getFadeEffectIconBitmap().GetSizePixel().getHeight() - 1));
+
+ // Paint_PageName replacement. Get text size
+ const double fTextWidth(aTextLayouter.getTextWidth(getPageName(), 0, nTextLength));
+ const double fTextHeight(getPageNameFont().GetHeight());
+ const double fFadeEffectWidth(aFadeEffectBitmapSizeLogic.getX() * 2.0);
+ const double fFadeEffectTextGap(((mnFadeEffectIndicatorOffset + 2) * aDiscretePixel.getX()));
+ String aPageName(getPageName());
+
+ // calculate text start position
+ double fStartX(
+ aAdaptedInnerRange.getMaxX()
+ - fTextWidth
+ + (aDiscretePixel.getX() * 3.0));
+ const double fStartY(
+ aAdaptedInnerRange.getMaxY()
+ + fTextHeight
+ + fFadeEffectTextGap);
+ const bool bNeedClipping(fStartX < aAdaptedInnerRange.getMinX() + fFadeEffectWidth);
+
+ // if text is too big, clip it
+ if(bNeedClipping)
+ {
+ // new left start
+ fStartX = aAdaptedInnerRange.getMinX() + fFadeEffectWidth;
+
+ // find out how many characters to use
+ const double fAvailableLength(aAdaptedInnerRange.getWidth() - fFadeEffectWidth);
+ static const String aThreePoints(String::CreateFromAscii("..."));
+ const double fWidthThreePoints(aTextLayouter.getTextWidth(aThreePoints, 0, aThreePoints.Len()));
+ xub_StrLen a(1);
+
+ for(; a < (xub_StrLen)nTextLength; a++)
+ {
+ const double fSnippetLength(aTextLayouter.getTextWidth(aPageName, 0, a));
+
+ if(fSnippetLength + fWidthThreePoints > fAvailableLength)
+ {
+ break;
+ }
+ }
+
+ // build new string
+ aPageName = String(aPageName, 0, a - 1);
+ aPageName += aThreePoints;
+ }
+
+ // fill text matrix
+ basegfx::B2DHomMatrix aTextMatrix;
+
+ aTextMatrix.set(0, 0, aTextSizeAttribute.getX());
+ aTextMatrix.set(1, 1, aTextSizeAttribute.getY());
+ aTextMatrix.set(0, 2, fStartX);
+ aTextMatrix.set(1, 2, fStartY);
+
+ // prepare DXTextArray (can be empty one)
+ const ::std::vector< double > aDXArray;
+
+ // create Text primitive and add to target
+ xRetval[nInsert++] = Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix,
+ aPageName,
+ 0,
+ aPageName.Len(),
+ aDXArray,
+ aFontAttribute,
+ aLocale,
+ aFontColor));
+ }
+
+ {
+ // Paint_PageNumber replacement. Get the range where it shall be centered and prepare the string
+ const double fLeft(aAdaptedInnerRange.getMinX() - (mnPageNumberOffset * aDiscretePixel.getX()) - getPageNumberAreaModelSize().Width());
+ const double fTop(aAdaptedInnerRange.getMinY());
+ const basegfx::B2DRange aNumberRange(fLeft, fTop,
+ fLeft + getPageNumberAreaModelSize().Width(), fTop + getPageNumberAreaModelSize().Height());
+ const String aPageNumber(String::CreateFromInt32(getPageNumber()));
+ const xub_StrLen nNumberLen(aPageNumber.Len());
+
+ // Get text size
+ const double fTextWidth(aTextLayouter.getTextWidth(aPageNumber, 0, nNumberLen));
+ const double fTextHeight(getPageNameFont().GetHeight());
+
+ // get text start postion
+ const double fStartX(aNumberRange.getCenterX() - (fTextWidth / 2.0));
+ const double fStartY(aNumberRange.getMinY() + fTextHeight + aDiscretePixel.getX());
+
+ // fill text matrix
+ basegfx::B2DHomMatrix aTextMatrix;
+
+ aTextMatrix.set(0, 0, aTextSizeAttribute.getX());
+ aTextMatrix.set(1, 1, aTextSizeAttribute.getY());
+ aTextMatrix.set(0, 2, fStartX);
+ aTextMatrix.set(1, 2, fStartY);
+
+ // prepare DXTextArray (can be empty one)
+ const ::std::vector< double > aDXArray;
+
+ // create Text primitive
+ xRetval[nInsert++] = Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix,
+ aPageNumber,
+ 0,
+ nNumberLen,
+ aDXArray,
+ aFontAttribute,
+ aLocale,
+ aFontColor));
+
+ if(getExcluded())
+ {
+ // create a box with strikethrough from top left to bottom right
+ const basegfx::BColor aActiveColor(Application::GetSettings().GetStyleSettings().GetActiveColor().getBColor());
+ basegfx::B2DPolygon aStrikethrough;
+
+ aStrikethrough.append(aNumberRange.getMinimum());
+ aStrikethrough.append(aNumberRange.getMaximum());
+
+ xRetval[nInsert++] = Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ basegfx::tools::createPolygonFromRect(aNumberRange), aActiveColor));
+
+ xRetval[nInsert++] = Primitive2DReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ aStrikethrough, aActiveColor));
+ }
+ }
+
+ return xRetval;
+}
+
+SdPageObjectFadeNameNumberPrimitive::SdPageObjectFadeNameNumberPrimitive(
+ const basegfx::B2DRange& rRange,
+ const String& rPageName,
+ sal_uInt32 nPageNumber,
+ const Font& rPageNameFont,
+ const Size& rPageNumberAreaModelSize,
+ bool bShowFadeEffectIcon,
+ bool bShowCommentsIcon,
+ bool bExcluded)
+: SdPageObjectBasePrimitive(rRange),
+ maPageName(rPageName),
+ mnPageNumber(nPageNumber),
+ maPageNameFont(rPageNameFont),
+ maPageNumberAreaModelSize(rPageNumberAreaModelSize),
+ mbShowFadeEffectIcon(bShowFadeEffectIcon),
+ mbShowCommentsIcon(bShowCommentsIcon),
+ mbExcluded(bExcluded)
+{
+}
+
+SdPageObjectFadeNameNumberPrimitive::~SdPageObjectFadeNameNumberPrimitive()
+{
+}
+
+bool SdPageObjectFadeNameNumberPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(SdPageObjectBasePrimitive::operator==(rPrimitive))
+ {
+ const SdPageObjectFadeNameNumberPrimitive& rCompare = static_cast< const SdPageObjectFadeNameNumberPrimitive& >(rPrimitive);
+
+ return (getPageName() == rCompare.getPageName()
+ && getPageNumber() == rCompare.getPageNumber()
+ && getPageNameFont() == rCompare.getPageNameFont()
+ && getPageNumberAreaModelSize() == rCompare.getPageNumberAreaModelSize()
+ && getShowFadeEffectIcon() == rCompare.getShowFadeEffectIcon()
+ && getExcluded() == rCompare.getExcluded());
+ }
+
+ return false;
+}
+
+ImplPrimitrive2DIDBlock(SdPageObjectFadeNameNumberPrimitive, PRIMITIVE2D_ID_SDPAGEOBJECTFADENAMENUMBERPRIMITIVE)
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// createPrimitive2DSequence
+//
+// This method will replace the whole painting mechanism. Task is no longer to paint stuff to an OutDev,
+// but to provide the necessary geometrical information using primitives.
+
+Primitive2DSequence PageObjectViewObjectContact::createPrimitive2DSequence(const sdr::contact::DisplayInfo& rDisplayInfo) const
+{
+ // OutputDevice* pDevice = rDisplayInfo.GetDIOutputDevice();
+ OutputDevice* pDevice = GetObjectContact().TryToGetOutputDevice();
+
+ // get primitive vector from parent class. Do remember the contents for later use; this
+ // is done to create the page content renderer (see PagePrimitiveExtractor in svx) at the
+ // original object and to setup the draw hierarchy there so that changes to VCs of displayed
+ // objects will lead to InvalidatePartOfView-calls which will be forwarded from the helper-OC
+ // to this VOC in calling a ActionChanged().
+ //
+ // This already produces the displayable page content as a primitive sequence, complete with
+ // embedding in the page visualizer, clipping if needed and object and aspect ratio
+ // preparations. It would thus be the base for creating the cached visualisation, too,
+ // by just painting extactly this primitive sequence.
+ //
+ // Currently, this slows down PagePane display heavily. Reason is that the current mechanism
+ // to react on a SdrObject change in an edit view is to react on the ModelChange and to completely
+ // reset the PagePane (delete SdrPageObjs, re-create and layout them). This works, but kicks
+ // the complete sequence of primitive creation at VOCs and VCs and their buffering out of
+ // memory each time. So there are two choices:
+ //
+ // 1, disable getting the sequence of primtives
+ // -> invalidate uses ModelChange
+ // -> cache repaint uses complete view creation and repainting
+ //
+ // 2, create and use the sequence of primitives
+ // -> invalidate would not need ModelChange, no destroy/recreate of SdrObjects, no rearrange,
+ // the invalidate and the following repaint would exactly update the SdrPages involved and
+ // use the DrawingLayer provided ActionChanged() invalidations over the VOCs and VCs
+ // -> cache repaint could use the here offered sequence of primitives to re-create the bitmap
+ // (just hand over the local member to the cache)
+ //
+ // For the moment i will use (1) and disable primitive creation for SdrPageObj contents here
+
+ // const_cast< PageObjectViewObjectContact* >(this)->mxCurrentPageContents = ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo);
+
+ // assert when this call is issued indirectly from the destructor of
+ // this instance. This is not allowed and needs to be looked at
+#ifdef DBG_UTIL
+ if(mbInDestructor)
+ {
+ OSL_ENSURE(false, "Higher call inside PageObjectViewObjectContact in destructor (!)");
+ }
+#endif
+
+ // Check if buffering can and shall be done.
+ if (pDevice != NULL
+ && !GetObjectContact().isOutputToPrinter()
+ && !GetObjectContact().isOutputToRecordingMetaFile()
+ && !mbInDestructor)
+ {
+ // get inner and outer logic rectangles. Use model data directly for creation. Do NOT use getBoundRect()/
+ // getSnapRect() functionality; these will use the sequence of primitives in the long run itself. SdrPageObj
+ // is a SdrObject, so use SdrObject::aOutRect as model data. Access using GetLastBoundRect() to not execute anything
+ PageObjectViewContact& rPaObVOC(static_cast< PageObjectViewContact& >(GetViewContact()));
+ const Rectangle aInnerLogic(rPaObVOC.GetPageObject().GetLastBoundRect());
+
+ // get BitmapEx from cache. Do exactly the same as Paint_Preview() to avoid a repaint loop
+ // caused by slightly different pixel sizes of what the cache sees as pixel size and what is
+ // calculated here in discrete coordinates. This includes to not use LogicToPiyel on the Rectangle,
+ // but to do the same as the GetBoundingBox() implementation
+ const Rectangle aInnerPixel(Rectangle(pDevice->LogicToPixel(aInnerLogic.TopLeft()), pDevice->LogicToPixel(aInnerLogic.GetSize())));
+ BitmapEx aBitmapEx(const_cast< PageObjectViewObjectContact* >(this)->GetPreview(rDisplayInfo, aInnerPixel));
+
+ // prepare inner range
+ const basegfx::B2DRange aInnerRange(aInnerLogic.Left(), aInnerLogic.Top(), aInnerLogic.Right(), aInnerLogic.Bottom());
+
+ // provide default parameters
+ String aPageName;
+ Font aPageNameFont;
+ sal_uInt32 nPageNumber(0);
+ Size aPageNumberAreaModelSize;
+ bool bShowFadeEffectIcon(false);
+ bool bShowCommentsIcon(false);
+ bool bExcluded(false);
+
+ if(GetPage())
+ {
+ const SdPage* pPage = static_cast<const SdPage*>(GetPage());
+
+ // decide if fade effect indicator will be painted
+ if(pPage->getTransitionType() > 0)
+ {
+ bShowFadeEffectIcon = true;
+ }
+
+ bShowCommentsIcon = !pPage->getAnnotations().empty();
+
+ // prepare PageName, PageNumber, font and AreaModelSize
+ aPageName = pPage->GetName();
+ aPageNameFont = *FontProvider::Instance().GetFont(*pDevice);
+ nPageNumber = ((pPage->GetPageNum() - 1) / 2) + 1;
+ aPageNumberAreaModelSize = GetPageDescriptor()->GetPageNumberAreaModelSize();
+
+ if(!aPageName.Len())
+ {
+ aPageName = String(SdResId(STR_PAGE));
+ aPageName += String::CreateFromInt32(nPageNumber);
+ }
+
+ // decide if page is excluded
+ bExcluded = pPage->IsExcluded();
+ }
+
+ // create specialized primitives for focus, select and PagePreview itself
+ const bool bCreateBitmap(!aBitmapEx.IsEmpty());
+ const bool bCreateFocused(GetPageDescriptor()->IsFocused());
+ const bool bCreateSelected(GetPageDescriptor()->IsSelected());
+
+ const sal_uInt32 nCount(
+ (bCreateBitmap ? 1 : 0) + // bitmap itself
+ 1 + // border around bitmap (always)
+ 1 + // FadeEffect, PageName and PageNumber visualisation (always)
+ (bCreateFocused ? 1 : 0) + // create focused
+ (bCreateSelected ? 1 : 0) // create selected
+ );
+ sal_uInt32 nInsert(0);
+ Primitive2DSequence xRetval(nCount);
+
+ if(bCreateBitmap)
+ {
+ // add selection indicator if used
+ xRetval[nInsert++] = Primitive2DReference(new SdPageObjectPageBitmapPrimitive(aInnerRange, aBitmapEx));
+ }
+
+ if(true)
+ {
+ // add border (always)
+ xRetval[nInsert++] = Primitive2DReference(new SdPageObjectBorderPrimitive(aInnerRange));
+ }
+
+ if(true)
+ {
+ // add fade effext, page name and number if used
+ xRetval[nInsert++] = Primitive2DReference(new SdPageObjectFadeNameNumberPrimitive(
+ aInnerRange,
+ aPageName,
+ nPageNumber,
+ aPageNameFont,
+ aPageNumberAreaModelSize,
+ bShowFadeEffectIcon,
+ bShowCommentsIcon,
+ bExcluded));
+ }
+
+ if(bCreateSelected)
+ {
+ // add selection indicator if used
+ xRetval[nInsert++] = Primitive2DReference(new SdPageObjectSelectPrimitive(aInnerRange));
+ }
+
+ if(bCreateFocused)
+ {
+ // add focus indicator if used
+ xRetval[nInsert++] = Primitive2DReference(new SdPageObjectFocusPrimitive(aInnerRange, bCreateSelected));
+ }
+
+ return xRetval;
+ }
+ else
+ {
+ // Call parent. Output to printer or metafile will use vector data, not cached bitmaps
+ return ViewObjectContactOfPageObj::createPrimitive2DSequence(rDisplayInfo);
+ }
+}
+
+BitmapEx PageObjectViewObjectContact::CreatePreview (const DisplayInfo& /*rDisplayInfo*/)
+{
+ const SdPage* pPage = static_cast<const SdPage*>(GetPage());
+ OutputDevice* pDevice = GetObjectContact().TryToGetOutputDevice();
+
+ if(pDevice)
+ {
+ Rectangle aPreviewPixelBox (GetBoundingBox(*pDevice,PreviewBoundingBox,PixelCoordinateSystem));
+
+ PreviewRenderer aRenderer (pDevice);
+ Image aPreview (aRenderer.RenderPage(
+ pPage,
+ aPreviewPixelBox.GetSize(),
+ String()));
+
+ return aPreview.GetBitmapEx();
+ }
+ else
+ {
+ return BitmapEx();
+ }
+}
+
+
+
+
+BitmapEx PageObjectViewObjectContact::GetPreview (
+ const DisplayInfo& rDisplayInfo,
+ const Rectangle& rNewSizePixel)
+{
+ BitmapEx aBitmap;
+
+ try
+ {
+ // assert when this call is issued indirectly from the destructor of
+ // this instance. This is not allowed and needs to be looked at
+ OSL_ENSURE(!mbInDestructor, "Higher call inside PageObjectViewObjectContact in destructor (!)");
+
+ if (!mbInDestructor)
+ {
+ if (mpCache != NULL)
+ {
+ aBitmap = mpCache->GetPreviewBitmap(
+ GetPage(),
+ rNewSizePixel.GetSize());
+ mpCache->SetPreciousFlag(GetPage(), true);
+ }
+ else
+ aBitmap = CreatePreview(rDisplayInfo);
+ }
+ }
+ catch (const ::com::sun::star::uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+
+ return aBitmap;
+}
+
+
+
+
+const SdrPage* PageObjectViewObjectContact::GetPage (void) const
+{
+ return static_cast<PageObjectViewContact&>(GetViewContact()).GetPage();
+}
+
+
+
+
+void PageObjectViewObjectContact::ActionChanged (void)
+{
+ // Even when we are called from destructor we still have to invalide
+ // the preview bitmap in the cache.
+ const SdrPage* pPage = GetPage();
+
+ if(pPage)
+ {
+ SdDrawDocument* pDocument = dynamic_cast<SdDrawDocument*>(pPage->GetModel());
+ if (mpCache!=NULL && pPage!=NULL && pDocument!=NULL)
+ {
+ cache::PageCacheManager::Instance()->InvalidatePreviewBitmap(
+ pDocument->getUnoModel(),
+ pPage);
+ }
+ }
+
+ // call parent
+ ViewObjectContactOfPageObj::ActionChanged();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// helper MouseOverEffectPrimitive
+//
+// Used to allow view-dependent primitive definition. For that purpose, the
+// initially created primitive (here: in createMouseOverEffectPrimitive2DSequence())
+// always has to be view-independent, but the decomposition is made view-dependent.
+// Very simple primitive which just remembers the discrete data and applies
+// it at decomposition time.
+
+class MouseOverEffectPrimitive : public drawinglayer::primitive2d::BufferedDecompositionPrimitive2D
+{
+private:
+ basegfx::B2DRange maLogicRange;
+ sal_uInt32 mnDiscreteOffset;
+ sal_uInt32 mnDiscreteWidth;
+ basegfx::BColor maRGBColor;
+
+protected:
+ virtual drawinglayer::primitive2d::Primitive2DSequence create2DDecomposition(
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
+
+public:
+ MouseOverEffectPrimitive(
+ const basegfx::B2DRange& rLogicRange,
+ sal_uInt32 nDiscreteOffset,
+ sal_uInt32 nDiscreteWidth,
+ const basegfx::BColor& rRGBColor)
+ : drawinglayer::primitive2d::BufferedDecompositionPrimitive2D(),
+ maLogicRange(rLogicRange),
+ mnDiscreteOffset(nDiscreteOffset),
+ mnDiscreteWidth(nDiscreteWidth),
+ maRGBColor(rRGBColor)
+ {}
+
+ // data access
+ const basegfx::B2DRange& getLogicRange() const { return maLogicRange; }
+ sal_uInt32 getDiscreteOffset() const { return mnDiscreteOffset; }
+ sal_uInt32 getDiscreteWidth() const { return mnDiscreteWidth; }
+ const basegfx::BColor& getRGBColor() const { return maRGBColor; }
+
+ virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
+
+ DeclPrimitrive2DIDBlock()
+};
+
+drawinglayer::primitive2d::Primitive2DSequence MouseOverEffectPrimitive::create2DDecomposition(
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation) const
+{
+ // get logic sizes in object coordinate system
+ const double fDiscreteWidth((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
+ const double fOffset(fDiscreteWidth * getDiscreteOffset());
+ const double fWidth(fDiscreteWidth * getDiscreteWidth());
+
+ // create range (one pixel less to get a good fitting)
+ basegfx::B2DRange aRange(
+ getLogicRange().getMinimum(),
+ getLogicRange().getMaximum() - basegfx::B2DTuple(fDiscreteWidth, fDiscreteWidth));
+
+ // grow range
+ aRange.grow(fOffset - (fWidth * 0.5));
+
+ // create fat line with parameters. The formerly hand-painted edge
+ // roundings will now be done using rounded edges of this fat line
+ const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aRange));
+ const drawinglayer::attribute::LineAttribute aLineAttribute(getRGBColor(), fWidth);
+ const drawinglayer::primitive2d::Primitive2DReference xReference(
+ new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
+ aPolygon,
+ aLineAttribute));
+
+ return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
+}
+
+bool MouseOverEffectPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
+{
+ if(drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const MouseOverEffectPrimitive& rCompare = static_cast< const MouseOverEffectPrimitive& >(rPrimitive);
+
+ return (getLogicRange() == rCompare.getLogicRange()
+ && getDiscreteOffset() == rCompare.getDiscreteOffset()
+ && getDiscreteWidth() == rCompare.getDiscreteWidth()
+ && getRGBColor() == rCompare.getRGBColor());
+ }
+
+ return false;
+}
+
+ImplPrimitrive2DIDBlock(MouseOverEffectPrimitive, PRIMITIVE2D_ID_SDMOUSEOVEREFFECTPRIMITIVE)
+
+//////////////////////////////////////////////////////////////////////////////
+
+drawinglayer::primitive2d::Primitive2DSequence PageObjectViewObjectContact::createMouseOverEffectPrimitive2DSequence()
+{
+ drawinglayer::primitive2d::Primitive2DSequence aRetval;
+
+ if(GetPageDescriptor()->IsSelected() && mpProperties.get() && mpProperties->IsShowSelection())
+ {
+ // When the selection frame is visualized the mouse over frame is not
+ // visible and does not have to be created.
+ }
+ else
+ {
+ const PageObjectViewContact& rPaObVOC(static_cast<PageObjectViewContact&>(GetViewContact()));
+ const Rectangle aBoundingBox(rPaObVOC.GetPageObject().GetLastBoundRect());
+ const basegfx::B2DRange aLogicRange(aBoundingBox.Left(), aBoundingBox.Top(), aBoundingBox.Right(), aBoundingBox.Bottom());
+ const basegfx::BColor aSelectionColor(mpProperties->GetSelectionColor().getBColor());
+ const drawinglayer::primitive2d::Primitive2DReference aReference(
+ new MouseOverEffectPrimitive(
+ aLogicRange,
+ mnMouseOverEffectOffset,
+ mnMouseOverEffectThickness,
+ aSelectionColor));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1);
+ }
+
+ return aRetval;
+}
+
+
+
+
+SvBorder PageObjectViewObjectContact::CalculatePageModelBorder (
+ OutputDevice* pDevice,
+ int nPageCount)
+{
+ SvBorder aModelBorder;
+
+ if (pDevice != NULL)
+ {
+ // 1. Initialize the border with the values that do not depend on
+ // the device.
+ Size aTopLeftBorders (pDevice->PixelToLogic (Size (
+ mnPageNumberOffset+1,
+ mnSelectionIndicatorOffset + mnSelectionIndicatorThickness)));
+ Size aBottomRightBorders (pDevice->PixelToLogic (Size (
+ mnSelectionIndicatorOffset + mnSelectionIndicatorThickness,
+ mnFadeEffectIndicatorOffset)));
+ aModelBorder = SvBorder (
+ aTopLeftBorders.Width(),
+ aTopLeftBorders.Height(),
+ aBottomRightBorders.Width(),
+ aBottomRightBorders.Height());
+
+
+ // 2. Add the device dependent values.
+
+ // Calculate the area of the page number.
+ Size aPageNumberModelSize (
+ CalculatePageNumberAreaModelSize (pDevice, nPageCount));
+
+ // Update the border.
+ aModelBorder.Left() += aPageNumberModelSize.Width();
+ // The height of the page number area is the same as the height of
+ // the page name area.
+ aModelBorder.Bottom() += aPageNumberModelSize.Height();
+ }
+
+ return aModelBorder;
+}
+
+
+
+
+Size PageObjectViewObjectContact::CalculatePageNumberAreaModelSize (
+ OutputDevice* pDevice,
+ int nPageCount)
+{
+ // Set the correct font.
+ Font aOriginalFont (pDevice->GetFont());
+ pDevice->SetFont(*FontProvider::Instance().GetFont(*pDevice));
+
+ String sPageNumberTemplate;
+ if (nPageCount < 10)
+ sPageNumberTemplate = String::CreateFromAscii("9");
+ else if (nPageCount < 100)
+ sPageNumberTemplate = String::CreateFromAscii("99");
+ else if (nPageCount < 200)
+ // Just for the case that 1 is narrower than 9.
+ sPageNumberTemplate = String::CreateFromAscii("199");
+ else if (nPageCount < 1000)
+ sPageNumberTemplate = String::CreateFromAscii("999");
+ else
+ sPageNumberTemplate = String::CreateFromAscii("9999");
+ // More then 9999 pages are not handled.
+
+ Size aSize (
+ pDevice->GetTextWidth (sPageNumberTemplate),
+ pDevice->GetTextHeight ());
+
+ pDevice->SetFont (aOriginalFont);
+
+ return aSize;
+}
+
+
+
+
+model::SharedPageDescriptor
+ PageObjectViewObjectContact::GetPageDescriptor (void) const
+{
+ PageObjectViewContact& rViewContact (
+ static_cast<PageObjectViewContact&>(GetViewContact()));
+ PageObject& rPageObject (
+ static_cast<PageObject&>(rViewContact.GetPageObject()));
+ return rPageObject.GetDescriptor();
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx b/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx
new file mode 100644
index 000000000000..77c89b846102
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "precompiled_sd.hxx"
+
+#include "SlsViewCacheContext.hxx"
+
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include "drawdoc.hxx"
+#include "tools/IdleDetection.hxx"
+#include <svx/svdpage.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+#include <vcl/window.hxx>
+#include <svx/sdr/contact/objectcontact.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+ViewCacheContext::ViewCacheContext (
+ model::SlideSorterModel& rModel,
+ SlideSorterView& rView)
+ : mrModel(rModel),
+ mrView(rView)
+{
+}
+
+
+
+
+ViewCacheContext::~ViewCacheContext (void)
+{
+}
+
+
+
+
+void ViewCacheContext::NotifyPreviewCreation (
+ cache::CacheKey aKey,
+ const ::boost::shared_ptr<BitmapEx>& rPreview)
+{
+ (void)rPreview;
+ const model::SharedPageDescriptor pDescriptor (GetDescriptor(aKey));
+ if (pDescriptor.get() != NULL)
+ {
+ // Use direct view-invalidate here and no ActionChanged() at the VC
+ // since the VC is a PageObjectViewObjectContact and in its ActionChanged()
+ // implementation invalidates the cache entry again.
+ view::PageObjectViewObjectContact* pContact = pDescriptor->GetViewObjectContact();
+ if (pContact != NULL)
+ pContact->GetObjectContact().InvalidatePartOfView(pContact->getObjectRange());
+ }
+ else
+ {
+ OSL_ASSERT(pDescriptor.get() != NULL);
+ }
+}
+
+
+
+
+bool ViewCacheContext::IsIdle (void)
+{
+ sal_Int32 nIdleState (tools::IdleDetection::GetIdleState(mrView.GetWindow()));
+ if (nIdleState == tools::IdleDetection::IDET_IDLE)
+ return true;
+ else
+ return false;
+}
+
+
+
+
+bool ViewCacheContext::IsVisible (cache::CacheKey aKey)
+{
+ return GetDescriptor(aKey)->IsVisible();
+}
+
+
+
+
+const SdrPage* ViewCacheContext::GetPage (cache::CacheKey aKey)
+{
+ return static_cast<const SdrPage*>(aKey);
+}
+
+
+
+
+::boost::shared_ptr<std::vector<cache::CacheKey> > ViewCacheContext::GetEntryList (bool bVisible)
+{
+ ::boost::shared_ptr<std::vector<cache::CacheKey> > pKeys (new std::vector<cache::CacheKey>());
+
+ model::PageEnumeration aPageEnumeration (
+ bVisible
+ ? model::PageEnumerationProvider::CreateVisiblePagesEnumeration(mrModel)
+ : model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+
+ while (aPageEnumeration.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ pKeys->push_back(pDescriptor->GetPage());
+ }
+
+ return pKeys;
+}
+
+
+
+
+sal_Int32 ViewCacheContext::GetPriority (cache::CacheKey aKey)
+{
+ return - (static_cast<const SdrPage*>(aKey)->GetPageNum()-1) / 2;
+}
+
+
+
+
+model::SharedPageDescriptor ViewCacheContext::GetDescriptor (cache::CacheKey aKey)
+{
+ sal_uInt16 nPageIndex ((static_cast<const SdrPage*>(aKey)->GetPageNum() - 1) / 2);
+ return mrModel.GetPageDescriptor(nPageIndex);
+}
+
+
+
+
+::com::sun::star::uno::Reference<com::sun::star::uno::XInterface> ViewCacheContext::GetModel (void)
+{
+ if (mrModel.GetDocument() == NULL)
+ return NULL;
+ else
+ return mrModel.GetDocument()->getUnoModel();
+}
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsViewCacheContext.hxx b/sd/source/ui/slidesorter/view/SlsViewCacheContext.hxx
new file mode 100644
index 000000000000..2c2c476f7f56
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsViewCacheContext.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_VIEW_VIEW_CACHE_CONTEXT_HXX
+#define SD_SLIDESORTER_VIEW_VIEW_CACHE_CONTEXT_HXX
+
+#include "cache/SlsCacheContext.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class SlideSorterView;
+
+/** The cache context for the SlideSorter as used by Draw and Impress. See
+ the base class for documentation of the individual methods.
+*/
+class ViewCacheContext : public cache::CacheContext
+{
+public:
+ ViewCacheContext (
+ model::SlideSorterModel& rModel,
+ SlideSorterView& rView);
+ virtual ~ViewCacheContext (void);
+ virtual void NotifyPreviewCreation (cache::CacheKey aKey, const ::boost::shared_ptr<BitmapEx>& rPreview);
+ virtual bool IsIdle (void);
+ virtual bool IsVisible (cache::CacheKey aKey);
+ virtual const SdrPage* GetPage (cache::CacheKey aKey);
+ virtual ::boost::shared_ptr<std::vector<cache::CacheKey> > GetEntryList (bool bVisible);
+ virtual sal_Int32 GetPriority (cache::CacheKey aKey);
+ virtual ::com::sun::star::uno::Reference<com::sun::star::uno::XInterface> GetModel (void);
+
+private:
+ model::SlideSorterModel& mrModel;
+ SlideSorterView& mrView;
+
+ model::SharedPageDescriptor GetDescriptor (cache::CacheKey aKey);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx
new file mode 100644
index 000000000000..029e65197854
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx
@@ -0,0 +1,609 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlsViewOverlay.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumeration.hxx"
+#include "view/SlideSorterView.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObject.hxx"
+#include "view/SlsPageObjectViewObjectContact.hxx"
+#include "ViewShell.hxx"
+#include "ViewShellBase.hxx"
+#include "UpdateLockManager.hxx"
+
+#include "Window.hxx"
+#include "sdpage.hxx"
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <vcl/svapp.hxx>
+
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+
+using namespace ::sdr::overlay;
+
+namespace {
+ const static sal_Int32 gnSubstitutionStripeLength (3);
+}
+
+namespace sd { namespace slidesorter { namespace view {
+
+//===== ViewOverlay =========================================================
+
+ViewOverlay::ViewOverlay (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maSelectionRectangleOverlay(*this),
+ maMouseOverIndicatorOverlay(*this),
+ maInsertionIndicatorOverlay(*this),
+ maSubstitutionOverlay(*this)
+{
+}
+
+
+
+
+ViewOverlay::~ViewOverlay (void)
+{
+}
+
+
+
+
+SelectionRectangleOverlay& ViewOverlay::GetSelectionRectangleOverlay (void)
+{
+ return maSelectionRectangleOverlay;
+}
+
+
+
+
+MouseOverIndicatorOverlay& ViewOverlay::GetMouseOverIndicatorOverlay (void)
+{
+ return maMouseOverIndicatorOverlay;
+}
+
+
+
+
+InsertionIndicatorOverlay& ViewOverlay::GetInsertionIndicatorOverlay (void)
+{
+ return maInsertionIndicatorOverlay;
+}
+
+
+
+
+SubstitutionOverlay& ViewOverlay::GetSubstitutionOverlay (void)
+{
+ return maSubstitutionOverlay;
+}
+
+
+
+
+SlideSorter& ViewOverlay::GetSlideSorter (void) const
+{
+ return mrSlideSorter;
+}
+
+
+
+
+OverlayManager* ViewOverlay::GetOverlayManager (void) const
+{
+ OverlayManager* pOverlayManager = NULL;
+
+ SlideSorterView& rView (mrSlideSorter.GetView());
+ SdrPageView* pPageView = rView.GetSdrPageView();
+ if (pPageView != NULL && pPageView->PageWindowCount()>0)
+ {
+ SdrPageWindow* pPageWindow = pPageView->GetPageWindow(0);
+ if (pPageWindow != NULL)
+ pOverlayManager = pPageWindow->GetOverlayManager();
+ }
+
+ return pOverlayManager;
+}
+
+
+
+
+//===== OverlayBase =========================================================
+
+OverlayBase::OverlayBase (ViewOverlay& rViewOverlay)
+ : OverlayObject(Color(0,0,0)),
+ mrViewOverlay(rViewOverlay)
+{
+ setVisible(false);
+}
+
+
+
+
+OverlayBase::~OverlayBase (void)
+{
+ OSL_ENSURE(!getOverlayManager(), "Please call RemoveRegistration() in the derived class; it's too late to call it in the base class since virtual methods will be missing when called in the destructor.");
+}
+
+
+
+
+void OverlayBase::EnsureRegistration (void)
+{
+ if (getOverlayManager() == NULL)
+ {
+ OverlayManager* pOverlayManager = mrViewOverlay.GetOverlayManager();
+ if (pOverlayManager != NULL)
+ pOverlayManager->add(*this);
+ }
+}
+
+
+
+
+void OverlayBase::RemoveRegistration()
+{
+ OverlayManager* pOverlayManager = getOverlayManager();
+ if (pOverlayManager != NULL)
+ pOverlayManager->remove(*this);
+}
+
+
+
+
+//===== SubstitutionOverlay =================================================
+
+SubstitutionOverlay::SubstitutionOverlay (ViewOverlay& rViewOverlay)
+ : OverlayBase(rViewOverlay),
+ maPosition(0,0),
+ maShapes()
+{
+ allowAntiAliase(false);
+}
+
+
+
+
+SubstitutionOverlay::~SubstitutionOverlay (void)
+{
+ RemoveRegistration();
+}
+
+
+
+
+void SubstitutionOverlay::Create (
+ model::PageEnumeration& rSelection,
+ const Point& rPosition)
+{
+ EnsureRegistration();
+
+ maPosition = rPosition;
+
+ maShapes.clear();
+ while (rSelection.HasMoreElements())
+ {
+ const Rectangle aBox (rSelection.GetNextElement()->GetPageObject()->GetCurrentBoundRect());
+ basegfx::B2DRectangle aB2DBox(
+ aBox.Left(),
+ aBox.Top(),
+ aBox.Right(),
+ aBox.Bottom());
+ maShapes.append(basegfx::tools::createPolygonFromRect(aB2DBox), 4);
+ }
+
+ setVisible(maShapes.count() > 0);
+ // The selection indicator may have been visible already so call
+ // objectChange() to enforce an update.
+ objectChange();
+}
+
+
+
+
+void SubstitutionOverlay::Clear (void)
+{
+ maShapes.clear();
+ setVisible(false);
+}
+
+
+
+
+void SubstitutionOverlay::Move (const Point& rOffset)
+{
+ const basegfx::B2DHomMatrix aTranslation(basegfx::tools::createTranslateB2DHomMatrix(rOffset.X(), rOffset.Y()));
+
+ maShapes.transform(aTranslation);
+ maPosition += rOffset;
+
+ objectChange();
+}
+
+
+
+
+void SubstitutionOverlay::SetPosition (const Point& rPosition)
+{
+ Move(rPosition - GetPosition());
+}
+
+
+
+
+Point SubstitutionOverlay::GetPosition (void) const
+{
+ return maPosition;
+}
+
+
+
+
+drawinglayer::primitive2d::Primitive2DSequence SubstitutionOverlay::createOverlayObjectPrimitive2DSequence()
+{
+ drawinglayer::primitive2d::Primitive2DSequence aRetval;
+ const sal_uInt32 nCount(maShapes.count());
+
+ if(nCount && getOverlayManager())
+ {
+ aRetval.realloc(nCount);
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
+ maShapes.getB2DPolygon(a),
+ aRGBColorA,
+ aRGBColorB,
+ gnSubstitutionStripeLength));
+ }
+ }
+
+ return aRetval;
+}
+
+void SubstitutionOverlay::stripeDefinitionHasChanged()
+{
+ // react on OverlayManager's stripe definition change
+ objectChange();
+}
+
+
+//===== SelectionRectangleOverlay ===========================================
+
+SelectionRectangleOverlay::SelectionRectangleOverlay (ViewOverlay& rViewOverlay)
+ : OverlayBase (rViewOverlay),
+ maAnchor(0,0),
+ maSecondCorner(0,0)
+{
+}
+
+
+
+SelectionRectangleOverlay::~SelectionRectangleOverlay()
+{
+ RemoveRegistration();
+}
+
+
+
+
+Rectangle SelectionRectangleOverlay::GetSelectionRectangle (void)
+{
+ return Rectangle(maAnchor, maSecondCorner);
+}
+
+
+
+
+void SelectionRectangleOverlay::Start (const Point& rAnchor)
+{
+ EnsureRegistration();
+ setVisible(false);
+ maAnchor = rAnchor;
+}
+
+
+
+
+void SelectionRectangleOverlay::Update (const Point& rSecondCorner)
+{
+ maSecondCorner = rSecondCorner;
+ setVisible(true);
+ // The selection rectangle may have been visible already so call
+ // objectChange() to enforce an update.
+ objectChange();
+}
+
+
+
+
+drawinglayer::primitive2d::Primitive2DSequence SelectionRectangleOverlay::createOverlayObjectPrimitive2DSequence()
+{
+ drawinglayer::primitive2d::Primitive2DSequence aRetval;
+ const basegfx::B2DRange aRange(maAnchor.X(), maAnchor.Y(), maSecondCorner.X(), maSecondCorner.Y());
+ const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aRange));
+
+ if(aPolygon.count())
+ {
+ const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor());
+ const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor());
+ const drawinglayer::primitive2d::Primitive2DReference xReference(
+ new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
+ aPolygon,
+ aRGBColorA,
+ aRGBColorB,
+ gnSubstitutionStripeLength));
+
+ aRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
+ }
+
+ return aRetval;
+}
+
+void SelectionRectangleOverlay::stripeDefinitionHasChanged()
+{
+ // react on OverlayManager's stripe definition change
+ objectChange();
+}
+
+
+
+
+//===== InsertionIndicatorOverlay ===========================================
+
+InsertionIndicatorOverlay::InsertionIndicatorOverlay (ViewOverlay& rViewOverlay)
+ : OverlayBase (rViewOverlay),
+ mnInsertionIndex(-1),
+ maBoundingBox()
+{
+}
+
+
+
+
+InsertionIndicatorOverlay::~InsertionIndicatorOverlay()
+{
+ RemoveRegistration();
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetPositionAndSize (const Rectangle& aNewBoundingBox)
+{
+ EnsureRegistration();
+ maBoundingBox = aNewBoundingBox;
+ setVisible( ! maBoundingBox.IsEmpty());
+ // The insertion indicator may have been visible already so call
+ // objectChange() to enforce an update.
+ objectChange();
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetPosition (const Point& rPoint)
+{
+ static const bool bAllowHorizontalInsertMarker = true;
+ Layouter& rLayouter (mrViewOverlay.GetSlideSorter().GetView().GetLayouter());
+ USHORT nPageCount
+ = (USHORT)mrViewOverlay.GetSlideSorter().GetModel().GetPageCount();
+
+ sal_Int32 nInsertionIndex = rLayouter.GetInsertionIndex (rPoint,
+ bAllowHorizontalInsertMarker);
+ if (nInsertionIndex >= nPageCount)
+ nInsertionIndex = nPageCount-1;
+ sal_Int32 nDrawIndex = nInsertionIndex;
+
+ bool bVertical = false;
+ bool bLeftOrTop = false;
+ if (nInsertionIndex >= 0)
+ {
+ // Now that we know where to insert, we still have to determine
+ // where to draw the marker. There are two decisions to make:
+ // 1. Draw a vertical or a horizontal insert marker.
+ // The horizontal one may only be chosen when there is only one
+ // column.
+ // 2. The vertical (standard) insert marker may be painted left to
+ // the insert page or right of the previous one. When both pages
+ // are in the same row this makes no difference. Otherwise the
+ // posiotions are at the left and right ends of two rows.
+
+ Point aPageCenter (rLayouter.GetPageObjectBox (
+ nInsertionIndex).Center());
+
+ if (bAllowHorizontalInsertMarker
+ && rLayouter.GetColumnCount() == 1)
+ {
+ bVertical = false;
+ bLeftOrTop = (rPoint.Y() <= aPageCenter.Y());
+ }
+ else
+ {
+ bVertical = true;
+ bLeftOrTop = (rPoint.X() <= aPageCenter.X());
+ }
+
+ // Add one when the mark was painted below or to the right of the
+ // page object.
+ if ( ! bLeftOrTop)
+ nInsertionIndex += 1;
+ }
+
+ mnInsertionIndex = nInsertionIndex;
+
+ Rectangle aBox;
+ if (mnInsertionIndex >= 0)
+ aBox = rLayouter.GetInsertionMarkerBox (
+ nDrawIndex,
+ bVertical,
+ bLeftOrTop);
+ SetPositionAndSize (aBox);
+}
+
+
+
+
+sal_Int32 InsertionIndicatorOverlay::GetInsertionPageIndex (void) const
+{
+ return mnInsertionIndex;
+}
+
+
+
+
+drawinglayer::primitive2d::Primitive2DSequence InsertionIndicatorOverlay::createOverlayObjectPrimitive2DSequence()
+{
+ drawinglayer::primitive2d::Primitive2DSequence aRetval(2);
+ const basegfx::B2DRange aRange(maBoundingBox.Left(), maBoundingBox.Top(), maBoundingBox.Right(), maBoundingBox.Bottom());
+ const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aRange));
+ const basegfx::BColor aRGBColor(Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetFontColor().getBColor());
+
+ aRetval[0] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColor));
+ aRetval[1] = drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
+ aPolygon,
+ aRGBColor));
+
+ return aRetval;
+}
+
+
+
+
+//===== MouseOverIndicatorOverlay ===========================================
+
+MouseOverIndicatorOverlay::MouseOverIndicatorOverlay (ViewOverlay& rViewOverlay)
+ : OverlayBase (rViewOverlay),
+ mpPageUnderMouse()
+{
+}
+
+
+
+
+MouseOverIndicatorOverlay::~MouseOverIndicatorOverlay (void)
+{
+ RemoveRegistration();
+}
+
+
+
+
+void MouseOverIndicatorOverlay::SetSlideUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ ViewShellBase* pBase = mrViewOverlay.GetSlideSorter().GetViewShellBase();
+ if (pBase==NULL || ! pBase->GetUpdateLockManager()->IsLocked())
+ {
+ model::SharedPageDescriptor pDescriptor;
+ if ( ! mpPageUnderMouse.expired())
+ {
+ try
+ {
+ pDescriptor = model::SharedPageDescriptor(mpPageUnderMouse);
+ }
+ catch (::boost::bad_weak_ptr)
+ {
+ }
+ }
+
+ if (pDescriptor != rpDescriptor)
+ {
+ // Switch to the new (possibly empty) descriptor.
+ mpPageUnderMouse = rpDescriptor;
+
+ EnsureRegistration();
+
+ // Show the indicator when a valid page descriptor is given.
+ setVisible( ! mpPageUnderMouse.expired());
+ // The mouse over indicator may have been visible already so call
+ // objectChange() to enforce an update.
+ objectChange();
+ }
+ }
+}
+
+
+
+
+drawinglayer::primitive2d::Primitive2DSequence MouseOverIndicatorOverlay::createOverlayObjectPrimitive2DSequence()
+{
+ view::PageObjectViewObjectContact* pContact = GetViewObjectContact();
+
+ if(pContact)
+ {
+ return pContact->createMouseOverEffectPrimitive2DSequence();
+ }
+
+ return drawinglayer::primitive2d::Primitive2DSequence();
+}
+
+
+
+
+view::PageObjectViewObjectContact* MouseOverIndicatorOverlay::GetViewObjectContact (void) const
+{
+ if ( ! mpPageUnderMouse.expired())
+ {
+ model::SharedPageDescriptor pDescriptor (mpPageUnderMouse);
+ return pDescriptor->GetViewObjectContact();
+ }
+ return NULL;
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/makefile.mk b/sd/source/ui/slidesorter/view/makefile.mk
new file mode 100644
index 000000000000..388139b1cee9
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..$/..
+
+PROJECTPCH=sd
+PROJECTPCHSOURCE=$(PRJ)$/util$/sd
+PRJNAME=sd
+TARGET=slsview
+ENABLE_EXCEPTIONS=TRUE
+AUTOSEG=true
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/SlsFontProvider.obj \
+ $(SLO)$/SlsPageObject.obj \
+ $(SLO)$/SlsPageObjectViewContact.obj \
+ $(SLO)$/SlsPageObjectViewObjectContact.obj \
+ $(SLO)$/SlsLayouter.obj \
+ $(SLO)$/SlideSorterView.obj \
+ $(SLO)$/SlsViewCacheContext.obj \
+ $(SLO)$/SlsViewOverlay.obj
+
+EXCEPTIONSFILES= \
+ $(SLO)$/SlsPageObjectViewObjectContact.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+