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.cxx706
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCache.hxx238
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx253
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx159
-rw-r--r--sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx102
-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.cxx381
-rw-r--r--sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx171
-rw-r--r--sd/source/ui/slidesorter/cache/SlsPageCache.cxx169
-rw-r--r--sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx492
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessor.cxx259
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx143
-rw-r--r--sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx322
-rw-r--r--sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx78
-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.cxx291
-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.cxx1134
-rw-r--r--sd/source/ui/slidesorter/controller/SlsAnimationFunction.cxx294
-rw-r--r--sd/source/ui/slidesorter/controller/SlsAnimator.cxx398
-rw-r--r--sd/source/ui/slidesorter/controller/SlsClipboard.cxx893
-rw-r--r--sd/source/ui/slidesorter/controller/SlsCommand.hxx48
-rw-r--r--sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx322
-rw-r--r--sd/source/ui/slidesorter/controller/SlsDragAndDropContext.cxx199
-rw-r--r--sd/source/ui/slidesorter/controller/SlsDragAndDropContext.hxx100
-rw-r--r--sd/source/ui/slidesorter/controller/SlsFocusManager.cxx402
-rw-r--r--sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx174
-rw-r--r--sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx75
-rw-r--r--sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx327
-rw-r--r--sd/source/ui/slidesorter/controller/SlsListener.cxx701
-rw-r--r--sd/source/ui/slidesorter/controller/SlsListener.hxx197
-rw-r--r--sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx103
-rw-r--r--sd/source/ui/slidesorter/controller/SlsPageSelector.cxx491
-rw-r--r--sd/source/ui/slidesorter/controller/SlsProperties.cxx276
-rw-r--r--sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx740
-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.cxx2027
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx362
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSelectionObserver.cxx173
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx83
-rw-r--r--sd/source/ui/slidesorter/controller/SlsSlotManager.cxx1345
-rw-r--r--sd/source/ui/slidesorter/controller/SlsTransferable.cxx104
-rw-r--r--sd/source/ui/slidesorter/controller/SlsVisibleAreaManager.cxx305
-rwxr-xr-xsd/source/ui/slidesorter/controller/makefile.mk69
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx108
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx182
-rw-r--r--sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx191
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx346
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx180
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx144
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx235
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx131
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx236
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx153
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsPageObjectFactory.hxx99
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx232
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx146
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx286
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx208
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx170
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx85
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSlideFunction.hxx76
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx127
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsTransferable.hxx87
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx100
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx254
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx56
-rw-r--r--sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx166
-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/model/SlsVisualState.hxx101
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx304
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsButtonBar.hxx362
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsFontProvider.hxx97
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx60
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx71
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx131
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx299
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObject.hxx68
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx145
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx138
-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/SlsResource.hrc111
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsTheme.hxx236
-rw-r--r--sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx97
-rw-r--r--sd/source/ui/slidesorter/makefile.mk58
-rw-r--r--sd/source/ui/slidesorter/model/SlideSorterModel.cxx740
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx292
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx286
-rw-r--r--sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx112
-rw-r--r--sd/source/ui/slidesorter/model/SlsVisualState.cxx236
-rwxr-xr-xsd/source/ui/slidesorter/model/makefile.mk57
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorter.cxx703
-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.cxx646
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterService.hxx219
-rw-r--r--sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx823
-rwxr-xr-xsd/source/ui/slidesorter/shell/makefile.mk55
-rw-r--r--sd/source/ui/slidesorter/view/SlideSorterView.cxx1135
-rw-r--r--sd/source/ui/slidesorter/view/SlsButtonBar.cxx1558
-rw-r--r--sd/source/ui/slidesorter/view/SlsFontProvider.cxx135
-rw-r--r--sd/source/ui/slidesorter/view/SlsFramePainter.cxx265
-rw-r--r--sd/source/ui/slidesorter/view/SlsFramePainter.hxx121
-rw-r--r--sd/source/ui/slidesorter/view/SlsInsertAnimator.cxx537
-rw-r--r--sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx448
-rw-r--r--sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx565
-rw-r--r--sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx99
-rw-r--r--sd/source/ui/slidesorter/view/SlsLayouter.cxx1555
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObject.cxx83
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx287
-rw-r--r--sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx584
-rw-r--r--sd/source/ui/slidesorter/view/SlsResource.hxx50
-rw-r--r--sd/source/ui/slidesorter/view/SlsResource.src314
-rw-r--r--sd/source/ui/slidesorter/view/SlsTheme.cxx536
-rw-r--r--sd/source/ui/slidesorter/view/SlsToolTip.cxx230
-rw-r--r--sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx162
-rw-r--r--sd/source/ui/slidesorter/view/SlsViewCacheContext.hxx73
-rwxr-xr-xsd/source/ui/slidesorter/view/makefile.mk69
128 files changed, 36195 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..531b01e57cc4
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.cxx
@@ -0,0 +1,706 @@
+/* -*- 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 "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 Bitmap& rBitmap, 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; }
+
+ Bitmap GetPreview (void) const { return maPreview; }
+ inline void SetPreview (const Bitmap& rPreview);
+ bool HasPreview (void) const;
+
+ Bitmap GetMarkedPreview (void) const { return maMarkedPreview; }
+ inline void SetMarkedPreview (const Bitmap& rMarkePreview);
+ bool HasMarkedPreview (void) const;
+
+ bool HasReplacement (void) const { return (mpReplacement.get() != NULL); }
+ inline bool HasLosslessReplacement (void) const;
+ void Clear (void) { maPreview.SetEmpty(); maMarkedPreview.SetEmpty();
+ 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:
+ Bitmap maPreview;
+ Bitmap maMarkedPreview;
+ ::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 ::boost::unordered_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;
+}
+
+
+
+
+Bitmap 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, Bitmap(), false);
+ iEntry = mpBitmapContainer->find(rKey);
+ iEntry->second.SetUpToDate(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();
+}
+
+
+
+
+Bitmap BitmapCache::GetMarkedBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+ return iEntry->second.GetMarkedPreview();
+ }
+ else
+ return Bitmap();
+}
+
+
+
+
+void BitmapCache::ReleaseBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator aIterator (mpBitmapContainer->find(rKey));
+ if (aIterator != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(aIterator->second, REMOVE);
+ mpBitmapContainer->erase(aIterator);
+ }
+}
+
+
+
+
+bool BitmapCache::InvalidateBitmap (const CacheKey& rKey)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ iEntry->second.SetUpToDate(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();
+ UpdateCacheSize(iEntry->second, ADD);
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void BitmapCache::InvalidateCache (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry;
+ for (iEntry=mpBitmapContainer->begin(); iEntry!=mpBitmapContainer->end(); ++iEntry)
+ {
+ iEntry->second.Invalidate();
+ }
+ ReCalculateTotalCacheSize();
+}
+
+
+
+
+void BitmapCache::SetBitmap (
+ const CacheKey& rKey,
+ const Bitmap& rPreview,
+ bool bIsPrecious)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetPreview(rPreview);
+ iEntry->second.SetUpToDate(true);
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+ }
+ else
+ {
+ iEntry = mpBitmapContainer->insert(CacheBitmapContainer::value_type (
+ rKey,
+ CacheEntry(rPreview, mnCurrentAccessTime++, bIsPrecious))
+ ).first;
+ }
+
+ if (iEntry != mpBitmapContainer->end())
+ UpdateCacheSize(iEntry->second, ADD);
+}
+
+
+
+
+void BitmapCache::SetMarkedBitmap (
+ const CacheKey& rKey,
+ const Bitmap& rPreview)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ CacheBitmapContainer::iterator iEntry (mpBitmapContainer->find(rKey));
+ if (iEntry != mpBitmapContainer->end())
+ {
+ UpdateCacheSize(iEntry->second, REMOVE);
+ iEntry->second.SetMarkedPreview(rPreview);
+ iEntry->second.SetAccessTime(mnCurrentAccessTime++);
+ 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(Bitmap(), 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)
+ : maPreview(),
+ maMarkedPreview(),
+ mbIsUpToDate(true),
+ mnLastAccessTime(nLastAccessTime),
+ mbIsPrecious(bIsPrecious)
+{
+}
+
+
+
+
+BitmapCache::CacheEntry::CacheEntry(
+ const Bitmap& rPreview,
+ sal_Int32 nLastAccessTime,
+ bool bIsPrecious)
+ : maPreview(rPreview),
+ maMarkedPreview(),
+ mbIsUpToDate(true),
+ mnLastAccessTime(nLastAccessTime),
+ mbIsPrecious(bIsPrecious)
+{
+}
+
+
+
+
+inline void BitmapCache::CacheEntry::Recycle (const CacheEntry& rEntry)
+{
+ if ((rEntry.HasPreview() || rEntry.HasLosslessReplacement())
+ && ! (HasPreview() || HasLosslessReplacement()))
+ {
+ maPreview = rEntry.maPreview;
+ maMarkedPreview = rEntry.maMarkedPreview;
+ mpReplacement = rEntry.mpReplacement;
+ mpCompressor = rEntry.mpCompressor;
+ mnLastAccessTime = rEntry.mnLastAccessTime;
+ mbIsUpToDate = rEntry.mbIsUpToDate;
+ }
+}
+
+
+
+
+inline sal_Int32 BitmapCache::CacheEntry::GetMemorySize (void) const
+{
+ sal_Int32 nSize (0);
+ nSize += maPreview.GetSizeBytes();
+ nSize += maMarkedPreview.GetSizeBytes();
+ if (mpReplacement.get() != NULL)
+ nSize += mpReplacement->GetMemorySize();
+ return nSize;
+}
+
+
+
+
+void BitmapCache::CacheEntry::Compress (const ::boost::shared_ptr<BitmapCompressor>& rpCompressor)
+{
+ if ( ! maPreview.IsEmpty())
+ {
+ if (mpReplacement.get() == NULL)
+ {
+ mpReplacement = rpCompressor->Compress(maPreview);
+
+#ifdef VERBOSE
+ sal_uInt32 nOldSize (maPreview.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;
+ }
+
+ maPreview.SetEmpty();
+ maMarkedPreview.SetEmpty();
+ }
+}
+
+
+
+
+inline void BitmapCache::CacheEntry::Decompress (void)
+{
+ if (mpReplacement.get()!=NULL && mpCompressor.get()!=NULL && maPreview.IsEmpty())
+ {
+ maPreview = mpCompressor->Decompress(*mpReplacement);
+ maMarkedPreview.SetEmpty();
+ if ( ! mpCompressor->IsLossless())
+ mbIsUpToDate = false;
+ }
+}
+
+
+
+inline void BitmapCache::CacheEntry::SetPreview (const Bitmap& rPreview)
+{
+ maPreview = rPreview;
+ maMarkedPreview.SetEmpty();
+ mpReplacement.reset();
+ mpCompressor.reset();
+}
+
+
+
+
+bool BitmapCache::CacheEntry::HasPreview (void) const
+{
+ return ! maPreview.IsEmpty();
+}
+
+
+
+
+inline void BitmapCache::CacheEntry::SetMarkedPreview (const Bitmap& rMarkedPreview)
+{
+ maMarkedPreview = rMarkedPreview;
+}
+
+
+
+
+bool BitmapCache::CacheEntry::HasMarkedPreview (void) const
+{
+ return ! maMarkedPreview.IsEmpty();
+}
+
+
+
+
+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..03610667c1be
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCache.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_BITMAP_CACHE_HXX
+#define SD_SLIDESORTER_BITMAP_CACHE_HXX
+
+class SdrPage;
+
+#include <vcl/bitmapex.hxx>
+#include <osl/mutex.hxx>
+#include <boost/shared_ptr.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/scoped_ptr.hpp>
+
+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/without this 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.
+
+ Additionally to the actual preview there is an optional marked preview.
+ This is used for slides excluded from the slide show which have a preview
+ that shows a mark (some sort of bitmap overlay) to that effect.
+*/
+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.
+ */
+ Bitmap GetBitmap (const CacheKey& rKey);
+
+ /** Return the marked preview bitmap for the given contact object.
+ */
+ Bitmap GetMarkedBitmap (const CacheKey& rKey);
+
+ /** Release the reference to the preview bitmap that is associated with
+ the given key.
+ */
+ void ReleaseBitmap (const CacheKey& rKey);
+
+ /** Mark the specified preview bitmap as not being up-to-date
+ anymore.
+ @return
+ When the key references a page in the cache then
+ return <TRUE/>. When the key is not known then <FALSE/>
+ is returned.
+ */
+ bool 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 Bitmap& rPreview,
+ bool bIsPrecious);
+
+ /** Add or replace a marked bitmap for the given key.
+ */
+ void SetMarkedBitmap (
+ const CacheKey& rKey,
+ const Bitmap& rPreview);
+
+ /** 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;
+
+ ::boost::scoped_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..69cc8f0b377d
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
@@ -0,0 +1,253 @@
+/* -*- 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:
+ Bitmap maPreview;
+ Size maOriginalSize;
+
+ DummyReplacement (const Bitmap& rPreview) : maPreview(rPreview) { }
+ virtual ~DummyReplacement(void) {}
+ virtual sal_Int32 GetMemorySize (void) const { return maPreview.GetSizeBytes(); }
+};
+
+
+
+::boost::shared_ptr<BitmapReplacement> NoBitmapCompression::Compress (const Bitmap& rBitmap) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>(new DummyReplacement(rBitmap));
+}
+
+Bitmap NoBitmapCompression::Decompress (const BitmapReplacement& rBitmapData) const
+{
+ return dynamic_cast<const DummyReplacement&>(rBitmapData).maPreview;
+}
+
+
+
+
+bool NoBitmapCompression::IsLossless (void) const
+{
+ return true;
+}
+
+
+
+
+//===== CompressionByDeletion =================================================
+
+::boost::shared_ptr<BitmapReplacement> CompressionByDeletion::Compress (const Bitmap& ) const
+{
+ return ::boost::shared_ptr<BitmapReplacement>();
+}
+
+
+
+
+Bitmap CompressionByDeletion::Decompress (const BitmapReplacement& ) const
+{
+ // Return a NULL pointer. This will eventually lead to a request for
+ // the creation of a new one.
+ return Bitmap();
+}
+
+
+
+
+bool CompressionByDeletion::IsLossless (void) const
+{
+ return false;
+}
+
+
+
+
+//===== ResolutionReduction ===================================================
+
+/** Store a scaled down bitmap together with the original size.
+*/
+class ResolutionReduction::ResolutionReducedReplacement : public BitmapReplacement
+{
+public:
+ Bitmap maPreview;
+ Size maOriginalSize;
+
+ virtual ~ResolutionReducedReplacement();
+ virtual sal_Int32 GetMemorySize (void) const;
+};
+
+ResolutionReduction::ResolutionReducedReplacement::~ResolutionReducedReplacement()
+{
+}
+
+sal_Int32 ResolutionReduction::ResolutionReducedReplacement::GetMemorySize (void) const
+{
+ return maPreview.GetSizeBytes();
+}
+
+::boost::shared_ptr<BitmapReplacement> ResolutionReduction::Compress (
+ const Bitmap& rBitmap) const
+{
+ ResolutionReducedReplacement* pResult = new ResolutionReducedReplacement();
+ pResult->maPreview = rBitmap;
+ Size aSize (rBitmap.GetSizePixel());
+ pResult->maOriginalSize = aSize;
+ if (aSize.Width()>0 && aSize.Width()<mnWidth)
+ {
+ int nHeight = aSize.Height() * mnWidth / aSize.Width() ;
+ pResult->maPreview.Scale(Size(mnWidth,nHeight));
+ }
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+Bitmap ResolutionReduction::Decompress (const BitmapReplacement& rBitmapData) const
+{
+ Bitmap aResult;
+
+ const ResolutionReducedReplacement* pData (
+ dynamic_cast<const ResolutionReducedReplacement*>(&rBitmapData));
+
+ if ( ! pData->maPreview.IsEmpty())
+ {
+ aResult = pData->maPreview;
+ if (pData->maOriginalSize.Width() > mnWidth)
+ aResult.Scale(pData->maOriginalSize);
+ }
+
+ return aResult;
+}
+
+
+
+
+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 Bitmap& rBitmap) const
+{
+ ::vcl::PNGWriter aWriter (rBitmap);
+ SvMemoryStream aStream (32768, 32768);
+ aWriter.Write(aStream);
+
+ PngReplacement* pResult = new PngReplacement();
+ pResult->maImageSize = rBitmap.GetSizePixel();
+ pResult->mnDataSize = aStream.Tell();
+ pResult->mpData = new char[pResult->mnDataSize];
+ memcpy(pResult->mpData, aStream.GetData(), pResult->mnDataSize);
+
+ return ::boost::shared_ptr<BitmapReplacement>(pResult);
+}
+
+
+
+
+Bitmap PngCompression::Decompress (
+ const BitmapReplacement& rBitmapData) const
+{
+ Bitmap aResult;
+ const PngReplacement* pData (dynamic_cast<const PngReplacement*>(&rBitmapData));
+ if (pData != NULL)
+ {
+ SvMemoryStream aStream (pData->mpData, pData->mnDataSize, STREAM_READ);
+ ::vcl::PNGReader aReader (aStream);
+ aResult = aReader.Read().GetBitmap();
+ }
+
+ return aResult;
+}
+
+
+
+
+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..f978c013d0b3
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.hxx
@@ -0,0 +1,159 @@
+/* -*- 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 Bitmap;
+
+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 Bitmap& rBitmap) 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 Bitmap 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 Bitmap& rpBitmap) const;
+ virtual Bitmap 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 Bitmap& rBitmap) const;
+ virtual Bitmap 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 Bitmap& rpBitmap) const;
+ /** Scale the replacement bitmap up to the original size.
+ */
+ virtual Bitmap 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 Bitmap& rBitmap) const;
+ virtual Bitmap 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..56625d5d9f04
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx
@@ -0,0 +1,102 @@
+/* -*- 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 "SlsBitmapFactory.hxx"
+
+#include "PreviewRenderer.hxx"
+#include "view/SlideSorterView.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include <drawdoc.hxx>
+#include "DrawDocShell.hxx"
+#include <svx/svdtypes.hxx>
+#include <svx/svdpage.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/pngwrite.hxx>
+
+const static sal_Int32 gnSuperSampleFactor (2);
+const static bool gbAllowSuperSampling (false);
+
+
+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)
+{
+}
+
+
+
+
+Bitmap BitmapFactory::CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize,
+ const bool bDoSuperSampling)
+{
+ Size aSize (rPixelSize);
+ if (bDoSuperSampling && gbAllowSuperSampling)
+ {
+ aSize.Width() *= gnSuperSampleFactor;
+ aSize.Height() *= gnSuperSampleFactor;
+ }
+
+ Bitmap aPreview (maRenderer.RenderPage (
+ &rPage,
+ aSize,
+ String(),
+ true,
+ false).GetBitmapEx().GetBitmap());
+ if (bDoSuperSampling && gbAllowSuperSampling)
+ {
+ aPreview.Scale(rPixelSize, BMP_SCALE_INTERPOLATE);
+ }
+
+ return aPreview;
+}
+
+
+} } } // 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..0b858f98565c
--- /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 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);
+
+ Bitmap CreateBitmap (
+ const SdPage& rPage,
+ const Size& rPixelSize,
+ const bool bDoSuperSampling);
+
+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..4e48d5ac2510
--- /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..90a2932ad501
--- /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..2ea515126c3b
--- /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..00a7ad71bdca
--- /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..0677035e31e4
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.cxx
@@ -0,0 +1,381 @@
+/* -*- 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 "SlsQueueProcessor.hxx"
+#include "SlsRequestPriorityClass.hxx"
+#include "SlsRequestFactory.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "controller/SlideSorterController.hxx"
+
+
+namespace sd { namespace slidesorter { namespace cache {
+
+GenericPageCache::GenericPageCache (
+ const Size& rPreviewSize,
+ const bool bDoSuperSampling,
+ const SharedCacheContext& rpCacheContext)
+ : mpBitmapCache(),
+ maRequestQueue(rpCacheContext),
+ mpQueueProcessor(),
+ mpCacheContext(rpCacheContext),
+ maPreviewSize(rPreviewSize),
+ mbDoSuperSampling(bDoSuperSampling)
+{
+ // A large size may indicate an error of the caller. After all we
+ // are creating previews.
+ DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000,
+ "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. "
+ "This may indicate an error.");
+}
+
+
+
+
+GenericPageCache::~GenericPageCache (void)
+{
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Stop();
+ maRequestQueue.Clear();
+ if (mpQueueProcessor.get() != NULL)
+ mpQueueProcessor->Terminate();
+ mpQueueProcessor.reset();
+
+ 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,
+ mbDoSuperSampling,
+ mpCacheContext));
+}
+
+
+
+
+void GenericPageCache::ChangePreviewSize (
+ const Size& rPreviewSize,
+ const bool bDoSuperSampling)
+{
+ if (rPreviewSize!=maPreviewSize || bDoSuperSampling!=mbDoSuperSampling)
+ {
+ // A large size may indicate an error of the caller. After all we
+ // are creating previews.
+ DBG_ASSERT (maPreviewSize.Width()<1000 && maPreviewSize.Height()<1000,
+ "GenericPageCache<>::GetPreviewBitmap(): bitmap requested with large width. "
+ "This may indicate an error.");
+
+ if (mpBitmapCache.get() != NULL)
+ {
+ mpBitmapCache = PageCacheManager::Instance()->ChangeSize(
+ mpBitmapCache, maPreviewSize, rPreviewSize);
+ if (mpQueueProcessor.get() != NULL)
+ {
+ mpQueueProcessor->SetPreviewSize(rPreviewSize, bDoSuperSampling);
+ mpQueueProcessor->SetBitmapCache(mpBitmapCache);
+ }
+ }
+ maPreviewSize = rPreviewSize;
+ mbDoSuperSampling = bDoSuperSampling;
+ }
+}
+
+
+
+
+Bitmap GenericPageCache::GetPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ Bitmap aPreview;
+ bool bMayBeUpToDate = true;
+ ProvideCacheAndProcessor();
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+ if (mpBitmapCache->HasBitmap(pPage))
+ {
+ aPreview = mpBitmapCache->GetBitmap(pPage);
+ const Size aBitmapSize (aPreview.GetSizePixel());
+ if (aBitmapSize != maPreviewSize)
+ {
+ // Scale the bitmap to the desired size when that is possible,
+ // i.e. the bitmap is not empty.
+ if (bResize && aBitmapSize.Width()>0 && aBitmapSize.Height()>0)
+ {
+ aPreview.Scale(maPreviewSize, BMP_SCALE_FAST);
+ }
+ bMayBeUpToDate = false;
+ }
+ else
+ 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, bMayBeUpToDate);
+
+ return aPreview;
+}
+
+
+
+
+Bitmap GenericPageCache::GetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ ProvideCacheAndProcessor();
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+ Bitmap aMarkedPreview (mpBitmapCache->GetMarkedBitmap(pPage));
+ const Size aBitmapSize (aMarkedPreview.GetSizePixel());
+ if (bResize && aBitmapSize != maPreviewSize)
+ {
+ // 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)
+ {
+ aMarkedPreview.Scale(maPreviewSize, BMP_SCALE_FAST);
+ }
+ }
+
+ return aMarkedPreview;
+}
+
+
+
+
+void GenericPageCache::SetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const Bitmap& rMarkedBitmap)
+{
+ OSL_ASSERT(aKey != NULL);
+
+ ProvideCacheAndProcessor();
+ const SdrPage* pPage = mpCacheContext->GetPage(aKey);
+ mpBitmapCache->SetMarkedBitmap(pPage, rMarkedBitmap);
+}
+
+
+
+
+void GenericPageCache::RequestPreviewBitmap (
+ const CacheKey aKey,
+ const 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)
+ {
+ const Bitmap aPreview (mpBitmapCache->GetBitmap(pPage));
+ if (aPreview.IsEmpty() || aPreview.GetSizePixel()!=maPreviewSize)
+ 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);
+ }
+}
+
+
+
+
+bool GenericPageCache::InvalidatePreviewBitmap (const CacheKey aKey)
+{
+ // Invalidate the page in all caches that reference it, not just this one.
+ ::boost::shared_ptr<cache::PageCacheManager> pCacheManager (
+ cache::PageCacheManager::Instance());
+ if (pCacheManager)
+ return pCacheManager->InvalidatePreviewBitmap(
+ mpCacheContext->GetModel(),
+ aKey);
+ else if (mpBitmapCache.get() != NULL)
+ return mpBitmapCache->InvalidateBitmap(mpCacheContext->GetPage(aKey));
+ else
+ return false;
+}
+
+
+
+
+void GenericPageCache::ReleasePreviewBitmap (const 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 (const bool bUpdateCache)
+{
+ if (mpBitmapCache)
+ {
+ // 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 (
+ const CacheKey aKey,
+ const 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..f4dd4900b6ad
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsGenericPageCache.hxx
@@ -0,0 +1,171 @@
+/* -*- 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 <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 a reference to the SlideSorter and
+ thus has access to both view and model. This allows the cache to
+ fill itself with requests for all pages or just the visible ones.
+ @param rPreviewSize
+ The size of the previews is expected in pixel values.
+ @param bDoSuperSampling
+ When <TRUE/> the previews are rendered larger and then scaled
+ down to the requested size to improve image quality.
+ */
+ GenericPageCache (
+ const Size& rPreviewSize,
+ const bool bDoSuperSampling,
+ 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,
+ const bool bDoSuperSampling);
+
+ /** 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 bResize
+ When <TRUE/> then when the available bitmap has not the
+ requested size, it is scaled before it is returned. When
+ <FALSE/> then the bitmap is returned in the wrong size and it is
+ the task of the caller to scale it.
+ @return
+ Returns a bitmap that is either empty, contains a scaled (up or
+ down) version or is the requested bitmap.
+ */
+ Bitmap GetPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize);
+ Bitmap GetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize);
+ void SetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const Bitmap& rMarkedBitmap);
+
+ /** 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 bMayBeUpToDate
+ This flag helps the method to determine whether an existing
+ preview that matches the request is up to date. If the caller
+ knows 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 use <TRUE/>.
+ */
+ void RequestPreviewBitmap (
+ const CacheKey aKey,
+ const bool bMayBeUpToDate = true);
+
+ /** Tell the cache to replace the bitmap associated with the given
+ request data with a new one that reflects recent changes in the
+ content of the page object.
+ @return
+ When the key is kown then return <TRUE/>.
+ */
+ bool InvalidatePreviewBitmap (const CacheKey aKey);
+
+ /** 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 (const 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 (const 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 (const CacheKey aKey, const 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;
+
+ bool mbDoSuperSampling;
+
+ /** 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..7fb9d956834d
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCache.cxx
@@ -0,0 +1,169 @@
+/* -*- 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 bool bDoSuperSampling,
+ const SharedCacheContext& rpCacheContext)
+ : mpImplementation(
+ new GenericPageCache(
+ rPreviewSize,
+ bDoSuperSampling,
+ rpCacheContext))
+{
+}
+
+
+
+
+PageCache::~PageCache (void)
+{
+}
+
+
+
+
+void PageCache::ChangeSize (
+ const Size& rPreviewSize,
+ const bool bDoSuperSampling)
+{
+ mpImplementation->ChangePreviewSize(rPreviewSize, bDoSuperSampling);
+}
+
+
+
+
+Bitmap PageCache::GetPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize)
+{
+ return mpImplementation->GetPreviewBitmap(aKey, bResize);
+}
+
+
+
+
+Bitmap PageCache::GetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize)
+{
+ return mpImplementation->GetMarkedPreviewBitmap(aKey, bResize);
+}
+
+
+
+
+void PageCache::SetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const Bitmap& rMarkedBitmap)
+{
+ mpImplementation->SetMarkedPreviewBitmap(aKey, rMarkedBitmap);
+}
+
+
+
+
+void PageCache::RequestPreviewBitmap (const CacheKey aKey)
+{
+ return mpImplementation->RequestPreviewBitmap(aKey);
+}
+
+
+
+
+void PageCache::InvalidatePreviewBitmap (
+ const CacheKey aKey,
+ const bool bRequestPreview)
+{
+ if (mpImplementation->InvalidatePreviewBitmap(aKey) && bRequestPreview)
+ RequestPreviewBitmap(aKey);
+}
+
+
+
+
+void PageCache::ReleasePreviewBitmap (const CacheKey aKey)
+{
+ mpImplementation->ReleasePreviewBitmap(aKey);
+}
+
+
+
+
+void PageCache::InvalidateCache (const bool bUpdateCache)
+{
+ mpImplementation->InvalidateCache(bUpdateCache);
+}
+
+
+
+
+void PageCache::SetPreciousFlag (
+ const CacheKey aKey,
+ const 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..229db639ceb4
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsPageCacheManager.cxx
@@ -0,0 +1,492 @@
+/* -*- 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 ::boost::unordered_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) const
+ { 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)));
+ 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;
+ }
+ else
+ {
+ OSL_ASSERT(iCacheToChange != mpPageCaches->end());
+ }
+ }
+
+ return pResult;
+}
+
+
+
+
+bool PageCacheManager::InvalidatePreviewBitmap (
+ DocumentKey pDocument,
+ const SdrPage* pKey)
+{
+ bool bHasChanged (false);
+
+ 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)
+ bHasChanged |= 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)
+ bHasChanged |= iCache2->mpCache->InvalidateBitmap(pKey);
+ }
+ }
+
+ return bHasChanged;
+}
+
+
+
+
+void PageCacheManager::InvalidateAllPreviewBitmaps (DocumentKey pDocument)
+{
+ if (pDocument == NULL)
+ return;
+
+ // 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->InvalidateCache();
+
+ // 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->InvalidateCache();
+ }
+}
+
+
+
+
+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();
+}
+
+
+
+
+void PageCacheManager::ReleasePreviewBitmap (const SdrPage* pPage)
+{
+ PageCacheContainer::iterator iCache;
+ for (iCache=mpPageCaches->begin(); iCache!=mpPageCaches->end(); ++iCache)
+ iCache->second->ReleaseBitmap(pPage);
+}
+
+
+
+
+::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..345c3c5d5513
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.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 "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 bool bDoSuperSampling,
+ const SharedCacheContext& rpCacheContext)
+ : maMutex(),
+ maTimer(),
+ mnTimeBetweenHighPriorityRequests (10/*ms*/),
+ mnTimeBetweenLowPriorityRequests (100/*ms*/),
+ mnTimeBetweenRequestsWhenNotIdle (1000/*ms*/),
+ maPreviewSize(rPreviewSize),
+ mbDoSuperSampling(bDoSuperSampling),
+ 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,
+ const bool bDoSuperSampling)
+{
+ maPreviewSize = rPreviewSize;
+ mbDoSuperSampling = bDoSuperSampling;
+}
+
+
+
+
+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 Bitmap aPreview (
+ maBitmapFactory.CreateBitmap(*pSdPage, maPreviewSize, mbDoSuperSampling));
+ mpCache->SetBitmap (pSdPage, aPreview, ePriorityClass!=NOT_VISIBLE);
+
+ // Initiate a repaint of the new preview.
+ mpCacheContext->NotifyPreviewCreation(aKey, aPreview);
+ }
+ }
+ }
+ catch (::com::sun::star::uno::RuntimeException &aException)
+ {
+ (void) aException;
+ OSL_FAIL("RuntimeException caught in QueueProcessor");
+ }
+ catch (::com::sun::star::uno::Exception &aException)
+ {
+ (void) aException;
+ OSL_FAIL("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..55139a300fe3
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessor.hxx
@@ -0,0 +1,143 @@
+/* -*- 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/SlideSorterView.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 bool bDoSuperSampling,
+ 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,
+ const bool bDoSuperSampling);
+
+ /** 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;
+ bool mbDoSuperSampling;
+ 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..e0f519860cad
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsQueueProcessorThread.hxx
@@ -0,0 +1,322 @@
+/* -*- 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)
+{
+ create();
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+ QueueProcessorThread<Queue, Request, Cache, Factory>
+ ::~QueueProcessorThread (void)
+{
+}
+
+
+
+
+template <class Queue, class Request, class Cache, class Factory>
+void SAL_CALL QueueProcessorThread<Queue, Request, Cache, Factory>::run (void)
+{
+ while ( ! mbIsTerminated)
+ {
+ if (mrQueue.IsEmpty())
+ {
+ // Sleep while the queue is empty.
+ suspend();
+ }
+
+ 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;
+ wait (aTimeToWait);
+ }
+
+ else
+ {
+ ProcessQueueEntry();
+ yield ();
+ }
+ }
+}
+
+
+
+
+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::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+ if (mrQueue.IsEmpty())
+ break;
+ }
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard (maMutex);
+ if (mbIsTerminated)
+ break;
+
+ if (mrQueue.IsEmpty())
+ break;
+
+ // Get the requeuest with the highest priority from the queue.
+ nPriorityClass = mrQueue.GetFrontPriorityClass();
+ pRequest = &mrQueue.GetFront();
+ mrQueue.PopFront();
+ bRequestIsValid = true;
+
+ 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)
+{
+ resume ();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::Stop (void)
+{
+ suspend();
+}
+
+
+
+
+template <class Queue,
+ class RequestData,
+ class BitmapCache,
+ class BitmapFactory>
+void QueueProcessorThread<
+ Queue, RequestData, BitmapCache, BitmapFactory
+ >::RemoveRequest (RequestData& rRequest)
+{
+ // 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::Thread::terminate ();
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ 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;
+}
+
+
+
+
+} } } // 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..017f7572ea9c
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestFactory.cxx
@@ -0,0 +1,78 @@
+/* -*- 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 "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..94ca566a66da
--- /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..f710ab1a8c62
--- /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..969e85c3c7f4
--- /dev/null
+++ b/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
@@ -0,0 +1,291 @@
+/* -*- 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 "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..e59f7e3ab3bd
--- /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..0d2e49d31e97
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
@@ -0,0 +1,1134 @@
+/* -*- 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/SlsInsertionIndicatorHandler.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsTransferable.hxx"
+#include "controller/SlsVisibleAreaManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsFontProvider.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsPageObjectPainter.hxx"
+#include "view/SlsTheme.hxx"
+#include "view/SlsToolTip.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;
+using namespace ::basegfx;
+
+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(),
+ mpInsertionIndicatorHandler(new InsertionIndicatorHandler(rSlideSorter)),
+ mpAnimator(new Animator(rSlideSorter)),
+ mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter)),
+ mpListener(),
+ mnModelChangeLockCount(0),
+ mbIsForcedRearrangePending(false),
+ mbPreModelChangeDone(false),
+ mbPostModelChangePending(false),
+ maSelectionBeforeSwitch(),
+ mnCurrentPageBeforeSwitch(0),
+ mpEditModeChangeMasterPage(NULL),
+ maTotalWindowArea(),
+ mnPaintEntranceCount(0),
+ mbIsContextMenuOpen(false)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ OSL_ASSERT(pWindow);
+ if (pWindow)
+ {
+ // 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());
+ pWindow->SetCenterAllowed(false);
+ pWindow->SetMapMode(MapMode(MAP_PIXEL));
+ pWindow->SetViewSize(mrView.GetModelArea().GetSize());
+ }
+}
+
+
+
+
+void SlideSorterController::Init (void)
+{
+ 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->GetCoreSelection();
+ 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;
+ OSL_FAIL( "sd::SlideSorterController::~SlideSorterController(), exception caught!" );
+ }
+
+ // dispose should have been called by now so that nothing is to be done
+ // to shut down cleanly.
+}
+
+
+
+
+void SlideSorterController::Dispose (void)
+{
+ mpInsertionIndicatorHandler->End(Animator::AM_Immediate);
+ mpSelectionManager.reset();
+ mpAnimator->Dispose();
+}
+
+
+
+
+model::SharedPageDescriptor SlideSorterController::GetPageAt (
+ const Point& aWindowPosition)
+{
+ sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aWindowPosition));
+ model::SharedPageDescriptor pDescriptorAtPoint;
+ if (nHitPageIndex >= 0)
+ {
+ pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex);
+
+ // Depending on a property we may have to check that the mouse is no
+ // just over the page object but over the preview area.
+ if (pDescriptorAtPoint
+ && mrSlideSorter.GetProperties()->IsOnlyPreviewTriggersMouseOver()
+ && ! pDescriptorAtPoint->HasState(PageDescriptor::ST_Selected))
+ {
+ // Make sure that the mouse is over the preview area.
+ if ( ! mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
+ pDescriptorAtPoint,
+ view::PageObjectLayouter::Preview,
+ view::PageObjectLayouter::WindowCoordinateSystem).IsInside(aWindowPosition))
+ {
+ pDescriptorAtPoint.reset();
+ }
+ }
+ }
+
+ 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;
+}
+
+
+
+
+::boost::shared_ptr<InsertionIndicatorHandler>
+ SlideSorterController::GetInsertionIndicatorHandler (void) const
+{
+ OSL_ASSERT(mpInsertionIndicatorHandler.get()!=NULL);
+ return mpInsertionIndicatorHandler;
+}
+
+
+
+
+void SlideSorterController::Paint (
+ const Rectangle& rBBox,
+ ::Window* pWindow)
+{
+ if (mnPaintEntranceCount == 0)
+ {
+ ++mnPaintEntranceCount;
+
+ try
+ {
+ 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;
+
+ if (pWindow == NULL)
+ return false;
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == NULL)
+ return false;
+
+ switch (rEvent.GetCommand())
+ {
+ case COMMAND_CONTEXTMENU:
+ {
+ SdPage* pPage = NULL;
+ sal_uInt16 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;
+ }
+ ::boost::scoped_ptr<InsertionIndicatorHandler::ForceShowContext> pContext;
+ 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.
+ mpInsertionIndicatorHandler->Start(false);
+ mpInsertionIndicatorHandler->UpdateIndicatorIcon(
+ dynamic_cast<Transferable*>(SD_MOD()->pTransferClip));
+ mpInsertionIndicatorHandler->UpdatePosition(
+ pWindow->PixelToLogic(rEvent.GetMousePosPixel()),
+ InsertionIndicatorHandler::MoveMode);
+ pContext.reset(new InsertionIndicatorHandler::ForceShowContext(
+ mpInsertionIndicatorHandler));
+ }
+
+ pWindow->ReleaseMouse();
+
+ Point aMenuLocation (0,0);
+ if (rEvent.IsMouseEvent())
+ {
+ // We have to explicitly specify the location of the menu
+ // when the slide sorter is placed in an undocked child
+ // menu. But when it is docked it does not hurt, so we
+ // specify the location always.
+ aMenuLocation = rEvent.GetMousePosPixel();
+ }
+ else
+ {
+ // The event is not a mouse event. Use the center of the
+ // focused page as top left position of the context menu.
+ model::SharedPageDescriptor pDescriptor (
+ GetFocusManager().GetFocusedPageDescriptor());
+ if (pDescriptor.get() != NULL)
+ {
+ Rectangle aBBox (
+ mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
+ pDescriptor,
+ PageObjectLayouter::PageObject,
+ PageObjectLayouter::ModelCoordinateSystem));
+ aMenuLocation = aBBox.Center();
+ }
+ }
+
+ mbIsContextMenuOpen = true;
+ if (pViewShell != NULL)
+ {
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher != NULL)
+ {
+ pDispatcher->ExecutePopup(
+ SdResId(nPopupId),
+ pWindow,
+ &aMenuLocation);
+ mrSlideSorter.GetView().UpdatePageUnderMouse(false);
+ ::rtl::Reference<SelectionFunction> pFunction(GetCurrentSelectionFunction());
+ if (pFunction.is())
+ pFunction->ResetMouseAnchor();
+ }
+ }
+ 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(
+ GetInsertionIndicatorHandler()->GetInsertionPageIndex());
+ }
+ pContext.reset();
+ bEventHasBeenHandled = true;
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ const CommandWheelData* pData = rEvent.GetWheelData();
+ if (pData == NULL)
+ return false;
+ if (pData->IsMod1())
+ {
+ // We do not support zooming with control+mouse wheel.
+ return false;
+ }
+ // Determine whether to scroll horizontally or vertically. This
+ // depends on the orientation of the scroll bar and the
+ // IsHoriz() flag of the event.
+ if ((mrSlideSorter.GetView().GetOrientation()==view::Layouter::HORIZONTAL)
+ == pData->IsHorz())
+ {
+ GetScrollBarManager().Scroll(
+ ScrollBarManager::Orientation_Vertical,
+ ScrollBarManager::Unit_Slide,
+ -pData->GetNotchDelta());
+ }
+ else
+ {
+ GetScrollBarManager().Scroll(
+ ScrollBarManager::Orientation_Horizontal,
+ ScrollBarManager::Unit_Slide,
+ -pData->GetNotchDelta());
+ }
+ mrSlideSorter.GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel(), false);
+
+ 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));
+
+ GetCurrentSlideManager()->PrepareModelChange();
+
+ if (mrSlideSorter.GetContentWindow())
+ mrView.PreModelChange();
+
+ mbPostModelChangePending = true;
+}
+
+
+
+
+void SlideSorterController::PostModelChange (void)
+{
+ mbPostModelChangePending = false;
+ mrModel.Resync();
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ 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(mbIsForcedRearrangePending);
+ }
+
+ 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();
+ SharedSdWindow pActiveWindow (mrSlideSorter.GetContentWindow());
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_ACTIVATE:
+ case VCLEVENT_WINDOW_SHOW:
+ if (pActiveWindow && pWindow == pActiveWindow->GetParent())
+ mrView.RequestRepaint();
+ break;
+
+ case VCLEVENT_WINDOW_HIDE:
+ if (pActiveWindow && pWindow == pActiveWindow->GetParent())
+ mrView.SetPageUnderMouse(SharedPageDescriptor());
+ break;
+
+ case VCLEVENT_WINDOW_GETFOCUS:
+ if (pActiveWindow)
+ if (pWindow == pActiveWindow.get())
+ GetFocusManager().ShowFocus(false);
+ break;
+
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ if (pActiveWindow && pWindow == pActiveWindow.get())
+ {
+ GetFocusManager().HideFocus();
+ mrView.GetToolTip().Hide();
+
+ // Select the current slide so that it is properly
+ // visualized when the focus is moved to the edit view.
+ GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
+ }
+ break;
+
+ case VCLEVENT_APPLICATION_DATACHANGED:
+ {
+ // Invalidate the preview cache.
+ cache::PageCacheManager::Instance()->InvalidateAllCaches();
+
+ // Update the draw mode.
+ sal_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();
+
+ // Update theme colors.
+ mrSlideSorter.GetProperties()->HandleDataChangeEvent();
+ mrSlideSorter.GetTheme()->Update(mrSlideSorter.GetProperties());
+ mrView.HandleDataChangeEvent();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return sal_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)
+ {
+ if (mrSlideSorter.GetContentWindow())
+ {
+ sal_uLong nMode = mrSlideSorter.GetContentWindow()->GetDrawMode();
+ sal_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,
+ (sal_Bool)(nQuality==0)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE,
+ (sal_Bool)(nQuality==1)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE,
+ (sal_Bool)(nQuality==2)));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST,
+ (sal_Bool)(nQuality==3)));
+ }
+ }
+
+ if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SFX_ITEM_AVAILABLE)
+ {
+ rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, sal_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.
+ mrSlideSorter.GetContentWindow()->Invalidate();
+}
+
+
+
+
+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);
+
+ if (aNewContentArea.IsEmpty())
+ return aNewContentArea;
+
+ if (mnModelChangeLockCount>0)
+ {
+ mbIsForcedRearrangePending |= bForce;
+ return aNewContentArea;
+ }
+ else
+ mbIsForcedRearrangePending = false;
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ if (bForce)
+ mrView.UpdateOrientation();
+
+ // Place the scroll bars.
+ aNewContentArea = GetScrollBarManager().PlaceScrollBars(
+ maTotalWindowArea,
+ mrView.GetOrientation() != view::Layouter::VERTICAL,
+ mrView.GetOrientation() != view::Layouter::HORIZONTAL);
+
+ 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);
+
+ // Keep the current slide in the visible area.
+ GetVisibleAreaManager().RequestCurrentSlideVisible();
+
+ mrView.RequestRepaint();
+ }
+
+ return aNewContentArea;
+}
+
+
+
+
+FunctionReference SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest)
+{
+ FunctionReference xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) );
+ return xFunc;
+}
+
+
+
+
+::rtl::Reference<SelectionFunction> SlideSorterController::GetCurrentSelectionFunction (void)
+{
+ FunctionReference pFunction (mrSlideSorter.GetViewShell()->GetCurrentFunction());
+ return ::rtl::Reference<SelectionFunction>(dynamic_cast<SelectionFunction*>(pFunction.get()));
+}
+
+
+
+
+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.
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if ( ! pWindow)
+ return;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
+ xAccessible (pWindow->GetAccessible(sal_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;
+}
+
+
+
+
+void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
+{
+ if (mrModel.GetDocumentSlides() != rxSlides)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+
+ mrModel.SetDocumentSlides(rxSlides);
+ mrView.Layout();
+
+ // Select just the current slide.
+ PageSelector::BroadcastLock aBroadcastLock (*mpPageSelector);
+ mpPageSelector->DeselectAllPages();
+ mpPageSelector->SelectPage(mpCurrentSlideManager->GetCurrentSlide());
+ }
+}
+
+
+
+
+::boost::shared_ptr<Animator> SlideSorterController::GetAnimator (void) const
+{
+ return mpAnimator;
+}
+
+
+
+
+VisibleAreaManager& SlideSorterController::GetVisibleAreaManager (void) const
+{
+ OSL_ASSERT(mpVisibleAreaManager);
+ return *mpVisibleAreaManager;
+}
+
+
+
+
+void SlideSorterController::CheckForMasterPageAssignment (void)
+{
+ if (mrModel.GetPageCount()%2==0)
+ return;
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->UpdateMasterPage())
+ {
+ mrView.GetPreviewCache()->InvalidatePreviewBitmap (
+ pDescriptor->GetPage(),
+ true);
+ }
+ }
+}
+
+
+
+
+//===== 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/SlsAnimationFunction.cxx b/sd/source/ui/slidesorter/controller/SlsAnimationFunction.cxx
new file mode 100644
index 000000000000..71b6c024ae7a
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsAnimationFunction.cxx
@@ -0,0 +1,294 @@
+/*************************************************************************
+ *
+ * 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/SlsAnimationFunction.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+
+
+#include <osl/diagnose.hxx>
+#include <rtl/math.hxx>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+double AnimationFunction::Linear (const double nTime)
+{
+ OSL_ASSERT(nTime>=0.0 && nTime<=1.0);
+ return nTime;
+}
+
+
+
+
+double AnimationFunction::FastInSlowOut_Sine (const double nTime)
+{
+ OSL_ASSERT(nTime>=0.0 && nTime<=1.0);
+
+ const double nResult (sin(nTime * M_PI/2));
+
+ OSL_ASSERT(nResult>=0.0 && nResult<=1.0);
+ return nResult;
+}
+
+
+
+
+double AnimationFunction::FastInSlowOut_Root (const double nTime)
+{
+ OSL_ASSERT(nTime>=0.0 && nTime<=1.0);
+
+ const double nResult (sqrt(nTime));
+
+ OSL_ASSERT(nResult>=0.0 && nResult<=1.0);
+ return nResult;
+}
+
+
+
+
+double AnimationFunction::SlowInSlowOut_0to0_Sine (const double nTime)
+{
+ OSL_ASSERT(nTime>=0.0 && nTime<=1.0);
+
+ const double nResult (sin(nTime * M_PI));
+
+ OSL_ASSERT(nResult>=0.0 && nResult<=1.0);
+ return nResult;
+}
+
+
+
+
+double AnimationFunction::Vibrate_Sine (const double nTime)
+{
+ return sin(nTime*M_PI*8);
+}
+
+
+
+
+Point AnimationFunction::ScalePoint (const Point& rPoint, const double nTime)
+{
+ return Point(
+ sal_Int32(::rtl::math::round(rPoint.X() * nTime)),
+ sal_Int32(::rtl::math::round(rPoint.Y() * nTime)));
+}
+
+
+
+
+double AnimationFunction::Blend (
+ const double nStartValue,
+ const double nEndValue,
+ const double nTime)
+{
+ return nStartValue*(1-nTime) + nEndValue*nTime;
+}
+
+
+
+
+void AnimationFunction::ApplyVisualStateChange (
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const double nTime)
+{
+ if (rpDescriptor)
+ {
+ rpDescriptor->GetVisualState().SetVisualStateBlend(nTime);
+ rView.RequestRepaint(rpDescriptor);
+ }
+}
+
+
+
+
+void AnimationFunction::ApplyLocationOffsetChange (
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const Point aLocationOffset)
+{
+ if (rpDescriptor)
+ {
+ const Rectangle aOldBoundingBox(rpDescriptor->GetBoundingBox());
+ rpDescriptor->GetVisualState().SetLocationOffset(aLocationOffset);
+ rView.RequestRepaint(aOldBoundingBox);
+ rView.RequestRepaint(rpDescriptor);
+ }
+}
+
+
+
+
+void AnimationFunction::ApplyButtonAlphaChange(
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const double nButtonAlpha,
+ const double nButtonBarAlpha)
+{
+ if (rpDescriptor)
+ {
+ rpDescriptor->GetVisualState().SetButtonAlpha(nButtonAlpha);
+ rpDescriptor->GetVisualState().SetButtonBarAlpha(nButtonBarAlpha);
+ rView.RequestRepaint(rpDescriptor);
+ }
+}
+
+
+
+
+//===== AnimationBezierFunction ===============================================
+
+AnimationBezierFunction::AnimationBezierFunction (
+ const double nX1,
+ const double nY1,
+ const double nX2,
+ const double nY2)
+ : mnX1(nX1),
+ mnY1(nY1),
+ mnX2(nX2),
+ mnY2(nY2)
+{
+}
+
+
+
+
+AnimationBezierFunction::AnimationBezierFunction (
+ const double nX1,
+ const double nY1)
+ : mnX1(nX1),
+ mnY1(nY1),
+ mnX2(1-nY1),
+ mnY2(1-nX1)
+{
+}
+
+
+
+
+::basegfx::B2DPoint AnimationBezierFunction::operator() (const double nT)
+{
+ return ::basegfx::B2DPoint(
+ EvaluateComponent(nT, mnX1, mnX2),
+ EvaluateComponent(nT, mnY1, mnY2));
+}
+
+
+
+
+double AnimationBezierFunction::EvaluateComponent (
+ const double nT,
+ const double nV1,
+ const double nV2)
+{
+ const double nS (1-nT);
+
+ // While the control point values 1 and 2 are explicitly given the start
+ // and end values are implicitly given.
+ const double nV0 (0);
+ const double nV3 (1);
+
+ const double nV01 (nS*nV0 + nT*nV1);
+ const double nV12 (nS*nV1 + nT*nV2);
+ const double nV23 (nS*nV2 + nT*nV3);
+
+ const double nV012 (nS*nV01 + nT*nV12);
+ const double nV123 (nS*nV12 + nT*nV23);
+
+ const double nV0123 (nS*nV012 + nT*nV123);
+
+ return nV0123;
+}
+
+
+
+
+//===== AnimationParametricFunction ===========================================
+
+AnimationParametricFunction::AnimationParametricFunction (const ParametricFunction& rFunction)
+ : maY()
+{
+ const sal_Int32 nSampleCount (64);
+
+ // Sample the given parametric function.
+ ::std::vector<basegfx::B2DPoint> aPoints;
+ aPoints.reserve(nSampleCount);
+ for (sal_Int32 nIndex=0; nIndex<nSampleCount; ++nIndex)
+ {
+ const double nT (nIndex/double(nSampleCount-1));
+ aPoints.push_back(basegfx::B2DPoint(rFunction(nT)));
+ }
+
+ // Interpolate at evenly spaced points.
+ maY.clear();
+ maY.reserve(nSampleCount);
+ double nX0 (aPoints[0].getX());
+ double nY0 (aPoints[0].getY());
+ double nX1 (aPoints[1].getX());
+ double nY1 (aPoints[1].getY());
+ sal_Int32 nIndex (1);
+ for (sal_Int32 nIndex2=0; nIndex2<nSampleCount; ++nIndex2)
+ {
+ const double nX (nIndex2 / double(nSampleCount-1));
+ while (nX > nX1 && nIndex<nSampleCount)
+ {
+ nX0 = nX1;
+ nY0 = nY1;
+ nX1 = aPoints[nIndex].getX();
+ nY1 = aPoints[nIndex].getY();
+ ++nIndex;
+ }
+ const double nU ((nX-nX1) / (nX0 - nX1));
+ const double nY (nY0*nU + nY1*(1-nU));
+ maY.push_back(nY);
+ }
+}
+
+
+
+
+double AnimationParametricFunction::operator() (const double nX)
+{
+ const sal_Int32 nIndex0 (nX * maY.size());
+ const double nX0 (nIndex0 / double(maY.size()-1));
+ const sal_uInt32 nIndex1 (nIndex0 + 1);
+ const double nX1 (nIndex1 / double(maY.size()-1));
+
+ if (nIndex0<=0)
+ return maY[0];
+ else if (sal_uInt32(nIndex0)>=maY.size() || nIndex1>=maY.size())
+ return maY[maY.size()-1];
+
+ const double nU ((nX-nX1) / (nX0 - nX1));
+ return maY[nIndex0]*nU + maY[nIndex1]*(1-nU);
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
diff --git a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
new file mode 100644
index 000000000000..6a634b15c9db
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
@@ -0,0 +1,398 @@
+/* -*- 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"
+#include <boost/bind.hpp>
+
+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::AnimationFunctor& rAnimation,
+ const double nStartOffset,
+ const double nDuration,
+ const double nGlobalTime,
+ const Animator::AnimationId nAnimationId,
+ const Animator::FinishFunctor& rFinishFunctor);
+ ~Animation (void);
+ /** Run next animation step. If animation has reached its end it is
+ expired.
+ */
+ bool Run (const double nGlobalTime);
+
+ /** Typically called when an animation has finished, but also from
+ Animator::Disposed(). The finish functor is called and the
+ animation is marked as expired to prevent another run.
+ */
+ void Expire (void);
+ bool IsExpired (void);
+
+ Animator::AnimationFunctor maAnimation;
+ Animator::FinishFunctor maFinishFunctor;
+ const Animator::AnimationId mnAnimationId;
+ const double mnDuration;
+ const double mnEnd;
+ const double mnGlobalTimeAtStart;
+ bool mbIsExpired;
+};
+
+
+
+
+Animator::Animator (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maTimer(),
+ mbIsDisposed(false),
+ maAnimations(),
+ maElapsedTime(),
+ mpDrawLock(),
+ mnNextAnimationId(0)
+{
+ maTimer.SetTimeout(gnResolution);
+ maTimer.SetTimeoutHdl(LINK(this,Animator,TimeoutHandler));
+}
+
+
+
+
+Animator::~Animator (void)
+{
+ if ( ! mbIsDisposed)
+ {
+ OSL_ASSERT(mbIsDisposed);
+ Dispose();
+ }
+}
+
+
+
+
+void Animator::Dispose (void)
+{
+ mbIsDisposed = true;
+
+ AnimationList aCopy (maAnimations);
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
+ (*iAnimation)->Expire();
+
+ maTimer.Stop();
+ if (mpDrawLock)
+ {
+ mpDrawLock->Dispose();
+ mpDrawLock.reset();
+ }
+}
+
+
+
+
+Animator::AnimationId Animator::AddAnimation (
+ const AnimationFunctor& rAnimation,
+ const sal_Int32 nStartOffset,
+ const sal_Int32 nDuration,
+ const FinishFunctor& rFinishFunctor)
+{
+ // When the animator is already disposed then ignore this call
+ // silently (well, we show an assertion, but do not throw an exception.)
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return -1;
+
+ boost::shared_ptr<Animation> pAnimation (
+ new Animation(
+ rAnimation,
+ nStartOffset / 1000.0,
+ nDuration / 1000.0,
+ maElapsedTime.getElapsedTime(),
+ ++mnNextAnimationId,
+ rFinishFunctor));
+ maAnimations.push_back(pAnimation);
+
+ RequestNextFrame();
+
+ return pAnimation->mnAnimationId;
+}
+
+
+
+
+Animator::AnimationId Animator::AddInfiniteAnimation (
+ const AnimationFunctor& rAnimation,
+ const double nDelta)
+{
+ (void)nDelta;
+
+ // When the animator is already disposed then ignore this call
+ // silently (well, we show an assertion, but do not throw an exception.)
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return -1;
+
+ boost::shared_ptr<Animation> pAnimation (
+ new Animation(
+ rAnimation,
+ 0,
+ -1,
+ maElapsedTime.getElapsedTime(),
+ mnNextAnimationId++,
+ FinishFunctor()));
+ maAnimations.push_back(pAnimation);
+
+ RequestNextFrame();
+
+ return pAnimation->mnAnimationId;
+}
+
+
+
+
+void Animator::RemoveAnimation (const Animator::AnimationId nId)
+{
+ OSL_ASSERT( ! mbIsDisposed);
+
+ const AnimationList::iterator iAnimation (::std::find_if(
+ maAnimations.begin(),
+ maAnimations.end(),
+ ::boost::bind(
+ ::std::equal_to<Animator::AnimationId>(),
+ nId,
+ ::boost::bind(&Animation::mnAnimationId, _1))));
+ if (iAnimation != maAnimations.end())
+ {
+ OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
+ (*iAnimation)->Expire();
+ maAnimations.erase(iAnimation);
+ }
+
+ if (maAnimations.empty())
+ {
+ // Reset the animation id when we can.
+ mnNextAnimationId = 0;
+
+ // No more animations => we do not have to suppress painting
+ // anymore.
+ mpDrawLock.reset();
+ }
+}
+
+
+
+
+void Animator::RemoveAllAnimations (void)
+{
+ ::std::for_each(
+ maAnimations.begin(),
+ maAnimations.end(),
+ ::boost::bind(
+ &Animation::Expire,
+ _1));
+ maAnimations.clear();
+ mnNextAnimationId = 0;
+
+ // No more animations => we do not have to suppress painting
+ // anymore.
+ mpDrawLock.reset();
+}
+
+
+
+
+bool Animator::ProcessAnimations (const double nTime)
+{
+ bool bExpired (false);
+
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return bExpired;
+
+
+ AnimationList aCopy (maAnimations);
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
+ {
+ bExpired |= (*iAnimation)->Run(nTime);
+ }
+
+ return bExpired;
+}
+
+
+
+
+void Animator::CleanUpAnimationList (void)
+{
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return;
+
+ AnimationList aActiveAnimations;
+
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=maAnimations.begin(); iAnimation!=maAnimations.end(); ++iAnimation)
+ {
+ if ( ! (*iAnimation)->IsExpired())
+ aActiveAnimations.push_back(*iAnimation);
+ }
+
+ maAnimations.swap(aActiveAnimations);
+}
+
+
+
+
+void Animator::RequestNextFrame (const double nFrameStart)
+{
+ (void)nFrameStart;
+ if ( ! maTimer.IsActive())
+ {
+ // 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 view::SlideSorterView::DrawLock(mrSlideSorter));
+ maTimer.Start();
+ }
+}
+
+
+
+
+IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG)
+{
+ if (mbIsDisposed)
+ return 0;
+
+ if (ProcessAnimations(maElapsedTime.getElapsedTime()))
+ CleanUpAnimationList();
+
+ // Unlock the draw lock. This should lead to a repaint.
+ mpDrawLock.reset();
+
+ if (maAnimations.size() > 0)
+ RequestNextFrame();
+
+ return 0;
+}
+
+
+
+
+//===== Animator::Animation ===================================================
+
+Animator::Animation::Animation (
+ const Animator::AnimationFunctor& rAnimation,
+ const double nStartOffset,
+ const double nDuration,
+ const double nGlobalTime,
+ const Animator::AnimationId nId,
+ const Animator::FinishFunctor& rFinishFunctor)
+ : maAnimation(rAnimation),
+ maFinishFunctor(rFinishFunctor),
+ mnAnimationId(nId),
+ mnDuration(nDuration),
+ mnEnd(nGlobalTime + nDuration + nStartOffset),
+ mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
+ mbIsExpired(false)
+{
+ Run(nGlobalTime);
+}
+
+
+
+
+Animator::Animation::~Animation (void)
+{
+}
+
+
+
+
+bool Animator::Animation::Run (const double nGlobalTime)
+{
+ if ( ! mbIsExpired)
+ {
+ if (mnDuration > 0)
+ {
+ if (nGlobalTime >= mnEnd)
+ {
+ maAnimation(1.0);
+ Expire();
+ }
+ else if (nGlobalTime >= mnGlobalTimeAtStart)
+ {
+ maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
+ }
+ }
+ else if (mnDuration < 0)
+ {
+ // Animations without end have to be expired by their owner.
+ maAnimation(nGlobalTime);
+ }
+ }
+
+ return mbIsExpired;
+}
+
+
+
+
+void Animator::Animation::Expire (void)
+{
+ if ( ! mbIsExpired)
+ {
+ mbIsExpired = true;
+ if (maFinishFunctor)
+ maFinishFunctor();
+ }
+}
+
+
+
+
+bool Animator::Animation::IsExpired (void)
+{
+ return mbIsExpired;
+}
+
+
+
+
+} } } // 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..a7433af91c3c
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
@@ -0,0 +1,893 @@
+/* -*- 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/SlsTheme.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsInsertionIndicatorHandler.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 "controller/SlsTransferable.hxx"
+#include "controller/SlsSelectionObserver.hxx"
+#include "cache/SlsPageCache.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 <svx/svdstr.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 {
+
+class Clipboard::UndoContext
+{
+public:
+ UndoContext (
+ SdDrawDocument* pDocument,
+ const ::boost::shared_ptr<ViewShell>& rpMainViewShell,
+ const ::boost::shared_ptr<view::Theme>& rpTheme)
+ : mpDocument(pDocument),
+ mpMainViewShell(rpMainViewShell)
+ {
+ if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
+ {
+ if (mpMainViewShell && mpMainViewShell->GetShellType() == ViewShell::ST_DRAW)
+ mpDocument->BegUndo(rpTheme->GetString(view::Theme::String_DragAndDropPages));
+ else
+ mpDocument->BegUndo(rpTheme->GetString(view::Theme::String_DragAndDropSlides));
+ }
+ }
+
+ ~UndoContext (void)
+ {
+ if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
+ mpDocument->EndUndo();
+ if (mpMainViewShell && mpMainViewShell->GetViewFrame()!=NULL)
+ {
+ SfxBindings& rBindings = mpMainViewShell->GetViewFrame()->GetBindings();
+ rBindings.Invalidate(SID_UNDO);
+ rBindings.Invalidate(SID_REDO);
+ }
+ }
+private:
+ SdDrawDocument* mpDocument;
+ ::boost::shared_ptr<ViewShell> mpMainViewShell;
+};
+
+
+
+
+Clipboard::Clipboard (SlideSorter& rSlideSorter)
+ : ViewClipboard(rSlideSorter.GetView()),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ maPagesToRemove(),
+ maPagesToSelect(),
+ mbUpdateSelectionPending(false),
+ mpUndoContext(),
+ mpSelectionObserverContext(),
+ mnDragFinishedUserEventId(0)
+{
+}
+
+
+
+
+Clipboard::~Clipboard (void)
+{
+ if (mnDragFinishedUserEventId != 0)
+ Application::RemoveUserEvent(mnDragFinishedUserEventId);
+}
+
+
+
+
+/** 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)
+ {
+ view::SlideSorterView::DrawLock aLock (mrSlideSorter);
+ SelectionObserver::Context aContext (mrSlideSorter);
+ if(xFunc.is())
+ xFunc->DoPaste();
+ else
+ DoPaste();
+ }
+ 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, sal_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.GetContentWindow()->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.
+
+ ::boost::shared_ptr<controller::InsertionIndicatorHandler> pInsertionIndicatorHandler (
+ mrController.GetInsertionIndicatorHandler());
+ if (pInsertionIndicatorHandler->IsActive())
+ {
+ // Use the insertion index of an active insertion indicator.
+ nInsertPosition = pInsertionIndicatorHandler->GetInsertionPageIndex();
+ }
+ else if (mrController.GetSelectionManager()->GetInsertionPosition() >= 0)
+ {
+ // Use the insertion index of an insertion indicator that has been
+ // deactivated a short while ago.
+ nInsertPosition = mrController.GetSelectionManager()->GetInsertionPosition();
+ }
+ else if (mrController.GetFocusManager().IsFocusShowing())
+ {
+ // Use the focus to determine the insertion position.
+ SdInsertPasteDlg aDialog (pWindow);
+ if (aDialog.Execute() == RET_OK)
+ {
+ nInsertPosition = mrController.GetFocusManager().GetFocusedPageIndex();
+ if ( ! aDialog.IsInsertBefore())
+ nInsertPosition ++;
+ }
+ }
+
+ return nInsertPosition;
+}
+
+
+
+
+sal_Int32 Clipboard::PasteTransferable (sal_Int32 nInsertPosition)
+{
+ SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
+ model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
+ bool bMergeMasterPages = !pClipTransferable->HasSourceDoc (rModel.GetDocument());
+ sal_uInt16 nInsertIndex (rModel.GetCoreIndex(nInsertPosition));
+ sal_Int32 nInsertPageCount (0);
+ if (pClipTransferable->HasPageBookmarks())
+ {
+ const List& rBookmarkList = pClipTransferable->GetPageBookmarks();
+ const SolarMutexGuard aGuard;
+
+ nInsertPageCount = (sal_uInt16) rBookmarkList.Count();
+ rModel.GetDocument()->InsertBookmarkAsPage(
+ const_cast<List*>(&rBookmarkList),
+ NULL,
+ sal_False,
+ sal_False,
+ nInsertIndex,
+ sal_False,
+ pClipTransferable->GetPageDocShell(),
+ sal_True,
+ bMergeMasterPages,
+ sal_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 != rModel.GetDocument());
+ nInsertPageCount = pDataDoc->GetSdPageCount( PK_STANDARD );
+ rModel.GetDocument()->InsertBookmarkAsPage(
+ NULL,
+ NULL,
+ sal_False,
+ sal_False,
+ nInsertIndex,
+ sal_False,
+ pDataDocSh,
+ sal_True,
+ bMergeMasterPages,
+ sal_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 (sal_uInt16 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);
+ }
+ }
+ }
+}
+
+
+
+
+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());
+ }
+
+ // Create a small set of representatives of the selection for which
+ // previews are included into the transferable so that an insertion
+ // indicator can be rendered.
+ aSelectedPages.Rewind();
+ ::std::vector<Transferable::Representative> aRepresentatives;
+ aRepresentatives.reserve(3);
+ ::boost::shared_ptr<cache::PageCache> pPreviewCache (
+ mrSlideSorter.GetView().GetPreviewCache());
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ if ( ! pDescriptor || pDescriptor->GetPage()==NULL)
+ continue;
+ Bitmap aPreview (pPreviewCache->GetPreviewBitmap(pDescriptor->GetPage(), false));
+ aRepresentatives.push_back(Transferable::Representative(
+ aPreview,
+ pDescriptor->HasState(model::PageDescriptor::ST_Excluded)));
+ if (aRepresentatives.size() >= 3)
+ break;
+ }
+
+ if (aBookmarkList.Count() > 0)
+ {
+ mrSlideSorter.GetView().BrkAction();
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ SdTransferable* pTransferable = new Transferable (
+ pDocument,
+ NULL,
+ sal_False,
+ dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()),
+ aRepresentatives);
+
+ 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& rPosition,
+ ::Window* pWindow)
+{
+ maPagesToRemove.clear();
+ maPagesToSelect.clear();
+ mbUpdateSelectionPending = false;
+ CreateSlideTransferable(pWindow, sal_True);
+
+ mrController.GetInsertionIndicatorHandler()->UpdatePosition(
+ rPosition,
+ InsertionIndicatorHandler::UnknownMode);
+}
+
+
+
+
+void Clipboard::DragFinished (sal_Int8 nDropAction)
+{
+ SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ if (pDragTransferable != NULL)
+ pDragTransferable->SetView (NULL);
+
+ if (mnDragFinishedUserEventId == 0)
+ {
+ if ( ! Application::PostUserEvent(
+ mnDragFinishedUserEventId,
+ LINK(this, Clipboard, ProcessDragFinished),
+ reinterpret_cast<void*>(nDropAction)))
+ {
+ mnDragFinishedUserEventId = 0;
+ }
+ }
+}
+
+
+
+
+IMPL_LINK(Clipboard, ProcessDragFinished, void*, pUserData)
+{
+ const sal_Int8 nDropAction (static_cast<sal_Int8>(reinterpret_cast<sal_IntPtr>(pUserData)));
+
+ mnDragFinishedUserEventId = 0;
+
+ // Hide the substitution display and insertion indicator.
+ ::rtl::Reference<SelectionFunction> pFunction (mrController.GetCurrentSelectionFunction());
+ if (pFunction.is())
+ pFunction->NotifyDragFinished();
+
+ 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();
+ }
+ mpUndoContext.reset();
+ mpSelectionObserverContext.reset();
+
+ return 1;
+}
+
+
+
+
+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,
+ sal_uInt16 nPage,
+ sal_uInt16 nLayer)
+{
+ sal_Int8 nAction (DND_ACTION_NONE);
+
+ const Clipboard::DropType eDropType (IsDropAccepted());
+
+ switch (eDropType)
+ {
+ case DT_PAGE:
+ {
+ // Accept a drop.
+ nAction = 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()))
+ {
+ nAction = DND_ACTION_COPY;
+ }
+ else if (mrController.GetInsertionIndicatorHandler()->IsInsertionTrivial(nAction))
+ {
+ nAction = DND_ACTION_NONE;
+ }
+
+ // Show the insertion marker and the substitution for a drop.
+ SelectionFunction* pSelectionFunction = dynamic_cast<SelectionFunction*>(
+ mrSlideSorter.GetViewShell()->GetCurrentFunction().get());
+ if (pSelectionFunction != NULL)
+ pSelectionFunction->MouseDragged(rEvent, nAction);
+
+ // Scroll the window when the mouse reaches the window border.
+ // mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
+ }
+ break;
+
+ case DT_SHAPE:
+ nAction = ExecuteOrAcceptShapeDrop(
+ DC_ACCEPT,
+ rEvent.maPosPixel,
+ &rEvent,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+
+ default:
+ nAction = DND_ACTION_NONE;
+ break;
+ }
+
+ return nAction;
+}
+
+
+
+
+sal_Int8 Clipboard::ExecuteDrop (
+ const ExecuteDropEvent& rEvent,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ sal_uInt16 nPage,
+ sal_uInt16 nLayer)
+{
+ sal_Int8 nResult = DND_ACTION_NONE;
+ mpUndoContext.reset();
+
+ switch (IsDropAccepted())
+ {
+ case DT_PAGE:
+ {
+ const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ const Point aEventModelPosition (
+ pTargetWindow->PixelToLogic (rEvent.maPosPixel));
+ const sal_Int32 nXOffset (labs (pDragTransferable->GetStartPos().X()
+ - aEventModelPosition.X()));
+ const sal_Int32 nYOffset (labs (pDragTransferable->GetStartPos().Y()
+ - aEventModelPosition.Y()));
+ bool bContinue =
+ ( pDragTransferable->GetView() != &mrSlideSorter.GetView() )
+ || ( nXOffset >= 2 && nYOffset >= 2 );
+
+ ::boost::shared_ptr<InsertionIndicatorHandler> pInsertionIndicatorHandler(
+ mrController.GetInsertionIndicatorHandler());
+ // Get insertion position and then turn off the insertion indicator.
+ pInsertionIndicatorHandler->UpdatePosition(aEventModelPosition, rEvent.mnAction);
+ // sal_uInt16 nIndex = DetermineInsertPosition(*pDragTransferable);
+
+ // Do not process the insertion when it is trivial,
+ // i.e. would insert pages at their original place.
+ if (pInsertionIndicatorHandler->IsInsertionTrivial(rEvent.mnAction))
+ bContinue = false;
+
+ // Tell the insertion indicator handler to hide before the model
+ // is modified. Doing it later may result in page objects whose
+ // animation state is not properly reset because they are then
+ // in another run then before the model change.
+ pInsertionIndicatorHandler->End(Animator::AM_Immediate);
+
+ if (bContinue)
+ {
+ SlideSorterController::ModelChangeLock aModelChangeLock (mrController);
+
+ // Handle a general drop operation.
+ mpUndoContext.reset(new UndoContext (
+ mrSlideSorter.GetModel().GetDocument(),
+ mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell(),
+ mrSlideSorter.GetTheme()));
+ mpSelectionObserverContext.reset(new SelectionObserver::Context(mrSlideSorter));
+
+ HandlePageDrop(*pDragTransferable);
+ nResult = rEvent.mnAction;
+
+ // We leave the undo context alive for when moving or
+ // copying inside one view then the actions in
+ // NotifyDragFinished should be covered as well as
+ // well as the ones above.
+ }
+
+ // Notify the receiving selection function that drag-and-drop is
+ // finished and the substitution handler can be released.
+ ::rtl::Reference<SelectionFunction> pFunction (
+ mrController.GetCurrentSelectionFunction());
+ if (pFunction.is())
+ pFunction->NotifyDragFinished();
+ }
+ break;
+
+ case DT_SHAPE:
+ nResult = ExecuteOrAcceptShapeDrop(
+ DC_EXECUTE,
+ rEvent.maPosPixel,
+ &rEvent,
+ rTargetHelper,
+ pTargetWindow,
+ nPage,
+ nLayer);
+ break;
+ default:
+ break;
+ }
+
+ return nResult;
+}
+
+
+
+
+void Clipboard::Abort (void)
+{
+ if (mpSelectionObserverContext)
+ {
+ mpSelectionObserverContext->Abort();
+ mpSelectionObserverContext.reset();
+ }
+}
+
+
+
+
+sal_uInt16 Clipboard::DetermineInsertPosition (const SdTransferable& )
+{
+ // 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.
+ const sal_Int32 nInsertionIndex (
+ mrController.GetInsertionIndicatorHandler()->GetInsertionPageIndex());
+
+ // Convert to insertion index to that of an SdModel.
+ if (nInsertionIndex >= 0)
+ return mrSlideSorter.GetModel().GetCoreIndex(nInsertionIndex);
+ else
+ return 0;
+}
+
+
+
+
+sal_uInt16 Clipboard::InsertSlides (
+ const SdTransferable& rTransferable,
+ sal_uInt16 nInsertPosition)
+{
+ sal_uInt16 nInsertedPageCount = ViewClipboard::InsertSlides (
+ rTransferable,
+ nInsertPosition);
+
+ // Remember the inserted pages so that they can be selected when the
+ // operation is finished.
+ maPagesToSelect.clear();
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ if (pDocument != NULL)
+ for (sal_Int32 i=0; i<=nInsertedPageCount; i+=2)
+ maPagesToSelect.push_back(
+ dynamic_cast<SdPage*>(pDocument->GetPage(nInsertPosition+i)));
+
+ 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,
+ sal_uInt16 nPage,
+ sal_uInt16 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)
+ nPage = pDescriptor->GetPageIndex();
+ }
+
+ // 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..7198e0a2b211
--- /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..97de9f7b2c20
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx
@@ -0,0 +1,322 @@
+/* -*- 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 "controller/SlsFocusManager.hxx"
+#include "view/SlideSorterView.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(),
+ maSwitchPageDelayTimer()
+{
+ maSwitchPageDelayTimer.SetTimeout(100);
+ maSwitchPageDelayTimer.SetTimeoutHdl(LINK(this,CurrentSlideManager,SwitchPageCallback));
+}
+
+
+
+
+CurrentSlideManager::~CurrentSlideManager (void)
+{
+}
+
+
+
+
+void CurrentSlideManager::NotifyCurrentSlideChange (const SdPage* pPage)
+{
+ if (pPage != NULL)
+ NotifyCurrentSlideChange(
+ mrSlideSorter.GetModel().GetIndex(
+ Reference<drawing::XDrawPage>(
+ const_cast<SdPage*>(pPage)->getUnoPage(),
+ UNO_QUERY)));
+ else
+ NotifyCurrentSlideChange(-1);
+}
+
+
+
+
+void CurrentSlideManager::NotifyCurrentSlideChange (const sal_Int32 nSlideIndex)
+{
+ if (mnCurrentSlideIndex != nSlideIndex)
+ {
+ ReleaseCurrentSlide();
+ AcquireCurrentSlide(nSlideIndex);
+
+ // Update the selection.
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ if (mpCurrentSlide)
+ {
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(mpCurrentSlide);
+ mrSlideSorter.GetController().GetFocusManager().SetFocusedPage(mpCurrentSlide);
+ }
+ }
+}
+
+
+
+
+void CurrentSlideManager::ReleaseCurrentSlide (void)
+{
+ if (mpCurrentSlide.get() != NULL)
+ mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, false);
+
+ 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)
+ mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, true);
+ }
+}
+
+
+
+
+void CurrentSlideManager::SwitchCurrentSlide (
+ const sal_Int32 nSlideIndex,
+ const bool bUpdateSelection)
+{
+ SwitchCurrentSlide(mrSlideSorter.GetModel().GetPageDescriptor(nSlideIndex), bUpdateSelection);
+}
+
+
+
+
+void CurrentSlideManager::SwitchCurrentSlide (
+ const SharedPageDescriptor& rpDescriptor,
+ const bool bUpdateSelection)
+{
+ if (rpDescriptor.get() != NULL && mpCurrentSlide!=rpDescriptor)
+ {
+ ReleaseCurrentSlide();
+ AcquireCurrentSlide((rpDescriptor->GetPage()->GetPageNum()-1)/2);
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL && pViewShell->IsMainViewShell())
+ {
+ // The slide sorter is the main view.
+ FrameView* pFrameView = pViewShell->GetFrameView();
+ if (pFrameView != NULL)
+ pFrameView->SetSelectedPage(sal::static_int_cast<sal_uInt16>(mnCurrentSlideIndex));
+ mrSlideSorter.GetController().GetPageSelector().SetCoreSelection();
+ }
+
+ // We do not tell the XController/ViewShellBase about the new
+ // slide right away. This is done asynchronously after a short
+ // delay to allow for more slide switches in the slide sorter.
+ // This goes under the assumption that slide switching inside
+ // the slide sorter is fast (no expensive redraw of the new page
+ // (unless the preview of the new slide is not yet preset)) and
+ // that slide switching in the edit view is slow (all shapes of
+ // the new slide have to be repainted.)
+ maSwitchPageDelayTimer.Start();
+
+ // We have to store the (index of the) new current slide at
+ // the tab control because there are other asynchronous
+ // notifications of the slide switching that otherwise
+ // overwrite the correct value.
+ SetCurrentSlideAtTabControl(mpCurrentSlide);
+
+ if (bUpdateSelection)
+ {
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+ }
+ mrSlideSorter.GetController().GetFocusManager().SetFocusedPage(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)
+ {
+ sal_uInt16 nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+ pDrawViewShell->SwitchPage(nPageNumber);
+ pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1);
+ }
+ }
+}
+
+
+
+
+void CurrentSlideManager::SetCurrentSlideAtTabControl (const SharedPageDescriptor& rpDescriptor)
+{
+ OSL_ASSERT(rpDescriptor.get() != NULL);
+
+ ViewShellBase* pBase = mrSlideSorter.GetViewShellBase();
+ if (pBase != NULL)
+ {
+ ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
+ ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell()));
+ if (pDrawViewShell)
+ {
+ sal_uInt16 nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
+ pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1);
+ }
+ }
+}
+
+
+
+
+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 (Exception 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)
+ mrSlideSorter.GetView().SetState(mpCurrentSlide, PageDescriptor::ST_Current, true);
+ }
+}
+
+
+
+
+IMPL_LINK(CurrentSlideManager, SwitchPageCallback, void*, EMPTYARG)
+{
+ if (mpCurrentSlide)
+ {
+ // 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.
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell==NULL || ! pViewShell->IsMainViewShell())
+ SetCurrentSlideAtViewShellBase(mpCurrentSlide);
+ SetCurrentSlideAtXController(mpCurrentSlide);
+ }
+
+ return 1;
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.cxx b/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.cxx
new file mode 100644
index 000000000000..76a5f583f4a5
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.cxx
@@ -0,0 +1,199 @@
+/*************************************************************************
+ *
+ * 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 "SlsDragAndDropContext.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsInsertionIndicatorHandler.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsTransferable.hxx"
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "app.hrc"
+#include <sfx2/bindings.hxx>
+#include <boost/bind.hpp>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+DragAndDropContext::DragAndDropContext (SlideSorter& rSlideSorter)
+ : mpTargetSlideSorter(&rSlideSorter),
+ mnInsertionIndex(-1)
+{
+ ::std::vector<const SdPage*> aPages;
+
+ // No Drag-and-Drop for master pages.
+ if (rSlideSorter.GetModel().GetEditMode() != EM_PAGE)
+ return;
+
+ rSlideSorter.GetController().GetInsertionIndicatorHandler()->UpdateIndicatorIcon(
+ dynamic_cast<Transferable*>(SD_MOD()->pTransferDrag));
+}
+
+
+
+
+DragAndDropContext::~DragAndDropContext (void)
+{
+ SetTargetSlideSorter (NULL, Point(0,0), InsertionIndicatorHandler::UnknownMode, false);
+}
+
+
+
+
+void DragAndDropContext::GetPagesFromBookmarks (
+ ::std::vector<const SdPage*>& rPages,
+ sal_Int32& rnSelectionCount,
+ DrawDocShell* pDocShell,
+ const List& rBookmarks) const
+{
+ if (pDocShell == NULL)
+ return;
+
+ const SdDrawDocument* pDocument = pDocShell->GetDoc();
+ if (pDocument == NULL)
+ return;
+
+ for (sal_uLong nIndex=0,nCount=rBookmarks.Count(); nIndex<nCount; ++nIndex)
+ {
+ const String sPageName (*static_cast<String*>(rBookmarks.GetObject(nIndex)));
+ sal_Bool bIsMasterPage (sal_False);
+ const sal_uInt16 nPageIndex (pDocument->GetPageByName(sPageName, bIsMasterPage));
+ if (nPageIndex == SDRPAGE_NOTFOUND)
+ continue;
+
+ const SdPage* pPage = dynamic_cast<const SdPage*>(pDocument->GetPage(nPageIndex));
+ if (pPage != NULL)
+ rPages.push_back(pPage);
+ }
+ rnSelectionCount = rBookmarks.Count();
+}
+
+
+
+
+void DragAndDropContext::GetPagesFromSelection (
+ ::std::vector<const SdPage*>& rPages,
+ sal_Int32& rnSelectionCount,
+ model::PageEnumeration& rSelection) const
+{
+ // Show a new substitution for the selected page objects.
+ rnSelectionCount = 0;
+
+ while (rSelection.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (rSelection.GetNextElement());
+ if (rPages.size() < 3)
+ rPages.push_back(pDescriptor->GetPage());
+ ++rnSelectionCount;
+ }
+}
+
+
+
+
+void DragAndDropContext::Dispose (void)
+{
+ mnInsertionIndex = -1;
+}
+
+
+
+
+void DragAndDropContext::UpdatePosition (
+ const Point& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode,
+ const bool bAllowAutoScroll)
+{
+ if (mpTargetSlideSorter == NULL)
+ return;
+
+ if (mpTargetSlideSorter->GetProperties()->IsUIReadOnly())
+ return;
+
+ // Convert window coordinates into model coordinates (we need the
+ // window coordinates for auto-scrolling because that remains
+ // constant while scrolling.)
+ SharedSdWindow pWindow (mpTargetSlideSorter->GetContentWindow());
+ const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
+ ::boost::shared_ptr<InsertionIndicatorHandler> pInsertionIndicatorHandler (
+ mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler());
+
+ if ( ! (bAllowAutoScroll
+ && mpTargetSlideSorter->GetController().GetScrollBarManager().AutoScroll(
+ rMousePosition,
+ ::boost::bind(
+ &DragAndDropContext::UpdatePosition, this, rMousePosition, eMode, false))))
+ {
+ pInsertionIndicatorHandler->UpdatePosition(aMouseModelPosition, eMode);
+
+ // Remember the new insertion index.
+ mnInsertionIndex = pInsertionIndicatorHandler->GetInsertionPageIndex();
+ if (pInsertionIndicatorHandler->IsInsertionTrivial(mnInsertionIndex, eMode))
+ mnInsertionIndex = -1;
+ }
+}
+
+
+
+
+void DragAndDropContext::SetTargetSlideSorter (
+ SlideSorter* pSlideSorter,
+ const Point aMousePosition,
+ const InsertionIndicatorHandler::Mode eMode,
+ const bool bIsOverSourceView)
+{
+ if (mpTargetSlideSorter != NULL)
+ {
+ mpTargetSlideSorter->GetController().GetScrollBarManager().StopAutoScroll();
+ mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->End(
+ Animator::AM_Animated);
+ }
+
+ mpTargetSlideSorter = pSlideSorter;
+
+ if (mpTargetSlideSorter != NULL)
+ {
+ mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->Start(
+ bIsOverSourceView);
+ mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->UpdatePosition(
+ aMousePosition,
+ eMode);
+
+ }
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
diff --git a/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.hxx b/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.hxx
new file mode 100644
index 000000000000..7536f88d9474
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsDragAndDropContext.hxx
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *
+ * 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_SUBSTITUTION_HANDLER_HXX
+#define SD_SLIDESORTER_SUBSTITUTION_HANDLER_HXX
+
+#include <tools/gen.hxx>
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "controller/SlsInsertionIndicatorHandler.hxx"
+#include <vector>
+
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** A DragAndDropContext object handles an active drag and drop operation.
+ When the mouse is moved from one slide sorter window to another the
+ target SlideSorter object is exchanged accordingly.
+*/
+class DragAndDropContext
+{
+public:
+ /** Create a substitution display of the currently selected pages or,
+ when provided, the pages in the transferable.
+ */
+ DragAndDropContext (SlideSorter& rSlideSorter);
+ ~DragAndDropContext (void);
+
+ /** Call this method (for example as reaction to ESC key press) to avoid
+ processing (ie moving or inserting) the substition when the called
+ DragAndDropContext object is destroyed.
+ */
+ void Dispose (void);
+
+ /** 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& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode,
+ const bool bAllowAutoScroll = true);
+
+ void SetTargetSlideSorter (
+ SlideSorter* pSlideSorter = NULL,
+ const Point aMousePosition = Point(0,0),
+ const InsertionIndicatorHandler::Mode eMode = InsertionIndicatorHandler::UnknownMode,
+ const bool bIsOverSourceView = false);
+
+private:
+ SlideSorter* mpTargetSlideSorter;
+ model::SharedPageDescriptor mpHitDescriptor;
+ sal_Int32 mnInsertionIndex;
+
+ void GetPagesFromBookmarks (
+ ::std::vector<const SdPage*>& rPages,
+ sal_Int32& rnSelectionCount,
+ DrawDocShell* pDocShell,
+ const List& rBookmarks) const;
+ void GetPagesFromSelection (
+ ::std::vector<const SdPage*>& rPages,
+ sal_Int32& rnSelectionCount,
+ model::PageEnumeration& rSelection) const;
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
new file mode 100644
index 000000000000..03ca44d4b848
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx
@@ -0,0 +1,402 @@
+/* -*- 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/SlsCurrentSlideManager.hxx"
+#include "controller/SlsVisibleAreaManager.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"
+
+#define UNIFY_FOCUS_AND_CURRENT_PAGE
+
+namespace sd { namespace slidesorter { namespace controller {
+
+FocusManager::FocusManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mnPageIndex(0),
+ mbPageIsFocused(false),
+ mbIsVerticalWrapActive(false)
+{
+ if (mrSlideSorter.GetModel().GetPageCount() > 0)
+ mnPageIndex = 0;
+}
+
+
+
+
+FocusManager::~FocusManager (void)
+{
+}
+
+
+
+
+void FocusManager::MoveFocus (FocusMoveDirection eDirection)
+{
+ if (mnPageIndex >= 0 && mbPageIsFocused)
+ {
+ HideFocusIndicator (GetFocusedPageDescriptor());
+
+ const sal_Int32 nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount());
+ const sal_Int32 nPageCount (mrSlideSorter.GetModel().GetPageCount());
+ switch (eDirection)
+ {
+ case FMD_NONE:
+ // Nothing to be done.
+ break;
+
+ case FMD_LEFT:
+ if (mnPageIndex > 0)
+ mnPageIndex -= 1;
+ else if (mbIsVerticalWrapActive)
+ mnPageIndex = nPageCount-1;
+ break;
+
+ case FMD_RIGHT:
+ if (mnPageIndex < nPageCount-1)
+ mnPageIndex += 1;
+ else if (mbIsVerticalWrapActive)
+ mnPageIndex = 0;
+ break;
+
+ case FMD_UP:
+ {
+ const sal_Int32 nCandidate (mnPageIndex - nColumnCount);
+ if (nCandidate < 0)
+ {
+ if (mbIsVerticalWrapActive)
+ {
+ // Wrap arround to the bottom row or the one above
+ // and go to the correct column.
+ const sal_Int32 nLastIndex (nPageCount-1);
+ const sal_Int32 nLastColumn (nLastIndex % nColumnCount);
+ const sal_Int32 nCurrentColumn (mnPageIndex%nColumnCount);
+ if (nLastColumn >= nCurrentColumn)
+ {
+ // The last row contains the current column.
+ mnPageIndex = nLastIndex - (nLastColumn-nCurrentColumn);
+ }
+ else
+ {
+ // Only the second to last row contains the current column.
+ mnPageIndex = nLastIndex - nLastColumn
+ - nColumnCount
+ + nCurrentColumn;
+ }
+ }
+ }
+ else
+ {
+ // Move the focus the previous row.
+ mnPageIndex = nCandidate;
+ }
+ }
+ break;
+
+ case FMD_DOWN:
+ {
+ const sal_Int32 nCandidate (mnPageIndex + nColumnCount);
+ if (nCandidate >= nPageCount)
+ {
+ if (mbIsVerticalWrapActive)
+ {
+ // Wrap arround to the correct column.
+ mnPageIndex = mnPageIndex % nColumnCount;
+ }
+ else
+ {
+ // Do not move the focus.
+ }
+ }
+ else
+ {
+ // Move the focus to the next row.
+ mnPageIndex = nCandidate;
+ }
+ }
+ break;
+ }
+
+ if (mnPageIndex < 0)
+ {
+ OSL_ASSERT(mnPageIndex>=0);
+ mnPageIndex = 0;
+ }
+ else if (mnPageIndex >= nPageCount)
+ {
+ OSL_ASSERT(mnPageIndex<nPageCount);
+ mnPageIndex = nPageCount - 1;
+ }
+
+ 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.GetContentWindow()->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;
+}
+
+
+
+
+void FocusManager::SetFocusedPageToCurrentPage (void)
+{
+ SetFocusedPage(mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
+}
+
+
+
+
+bool FocusManager::IsFocusShowing (void) const
+{
+ return HasFocus() && mbPageIsFocused;
+}
+
+
+
+
+void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, false);
+ }
+}
+
+
+
+
+void FocusManager::ShowFocusIndicator (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bScrollToFocus)
+{
+ if (rpDescriptor.get() != NULL)
+ {
+ mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, true);
+
+ if (bScrollToFocus)
+ {
+ // Scroll the focused page object into the visible area and repaint
+ // it, so that the focus indicator becomes visible.
+ mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
+ }
+ 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..e7fff7b9f52a
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx
@@ -0,0 +1,174 @@
+/* -*- 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());
+ static_cast<view::SlideSorterView*>(mpView)->SetState(
+ pDescriptor,
+ model::PageDescriptor::ST_Excluded,
+ eState==EXCLUDED);
+ }
+ }
+
+ 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);
+ sal_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..6bdf37e4c249
--- /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/SlsInsertionIndicatorHandler.cxx b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx
new file mode 100644
index 000000000000..882adab932a8
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx
@@ -0,0 +1,327 @@
+/*************************************************************************
+ *
+ * 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/SlsInsertionIndicatorHandler.hxx"
+#include "controller/SlsProperties.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsInsertionIndicatorOverlay.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
+
+#include "SlideSorter.hxx"
+
+using namespace ::com::sun::star::datatransfer::dnd::DNDConstants;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+InsertionIndicatorHandler::InsertionIndicatorHandler (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mpInsertAnimator(),
+ mpInsertionIndicatorOverlay(new view::InsertionIndicatorOverlay(rSlideSorter)),
+ maInsertPosition(),
+ meMode(MoveMode),
+ mbIsActive(false),
+ mbIsReadOnly(mrSlideSorter.GetModel().IsReadOnly()),
+ mbIsOverSourceView(true),
+ maIconSize(0,0),
+ mbIsForcedShow(false)
+{
+}
+
+
+
+
+InsertionIndicatorHandler::~InsertionIndicatorHandler (void)
+{
+}
+
+
+
+
+void InsertionIndicatorHandler::Start (const bool bIsOverSourceView)
+{
+ if (mbIsActive)
+ {
+ OSL_ASSERT(!mbIsActive);
+ }
+
+ mbIsReadOnly = mrSlideSorter.GetModel().IsReadOnly();
+ if (mbIsReadOnly)
+ return;
+
+ mbIsActive = true;
+ mbIsOverSourceView = bIsOverSourceView;
+}
+
+
+
+
+void InsertionIndicatorHandler::End (const controller::Animator::AnimationMode eMode)
+{
+ if (mbIsForcedShow || ! mbIsActive || mbIsReadOnly)
+ return;
+
+ GetInsertAnimator()->Reset(eMode);
+
+ mbIsActive = false;
+ // maInsertPosition = view::InsertPosition();
+ meMode = UnknownMode;
+
+ mpInsertionIndicatorOverlay->Hide();
+ mpInsertionIndicatorOverlay.reset(new view::InsertionIndicatorOverlay(mrSlideSorter));
+}
+
+
+
+
+void InsertionIndicatorHandler::ForceShow (void)
+{
+ mbIsForcedShow = true;
+}
+
+
+
+
+void InsertionIndicatorHandler::ForceEnd (void)
+{
+ mbIsForcedShow = false;
+ End(Animator::AM_Immediate);
+}
+
+
+
+
+void InsertionIndicatorHandler::UpdateIndicatorIcon (const Transferable* pTransferable)
+{
+ mpInsertionIndicatorOverlay->Create(pTransferable);
+ maIconSize = mpInsertionIndicatorOverlay->GetSize();
+}
+
+
+
+
+InsertionIndicatorHandler::Mode InsertionIndicatorHandler::GetModeFromDndAction (
+ const sal_Int8 nDndAction)
+{
+ if ((nDndAction & ACTION_MOVE) != 0)
+ return MoveMode;
+ else if ((nDndAction & ACTION_COPY) != 0)
+ return CopyMode;
+ else
+ return UnknownMode;
+}
+
+
+
+
+void InsertionIndicatorHandler::UpdatePosition (
+ const Point& rMouseModelPosition,
+ const Mode eMode)
+{
+ if ( ! mbIsActive)
+ return;
+
+ if (mbIsReadOnly)
+ return;
+
+ SetPosition(rMouseModelPosition, eMode);
+}
+
+
+
+
+void InsertionIndicatorHandler::UpdatePosition (
+ const Point& rMouseModelPosition,
+ const sal_Int8 nDndAction)
+{
+ UpdatePosition(rMouseModelPosition, GetModeFromDndAction(nDndAction));
+}
+
+
+
+
+bool InsertionIndicatorHandler::IsActive (void) const
+{
+ return mbIsActive;
+}
+
+
+
+
+sal_Int32 InsertionIndicatorHandler::GetInsertionPageIndex (void) const
+{
+ if (mbIsReadOnly)
+ return -1;
+ else
+ return maInsertPosition.GetIndex();
+}
+
+
+
+
+void InsertionIndicatorHandler::SetPosition (
+ const Point& rPoint,
+ const Mode eMode)
+{
+ view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
+
+ const view::InsertPosition aInsertPosition (rLayouter.GetInsertPosition(
+ rPoint,
+ maIconSize,
+ mrSlideSorter.GetModel()));
+
+ static sal_Int32 TargetIndex (1);
+ if (aInsertPosition.GetIndex() == TargetIndex)
+ {
+ const view::InsertPosition aPosition (rLayouter.GetInsertPosition(
+ rPoint,
+ maIconSize,
+ mrSlideSorter.GetModel()));
+ const view::InsertPosition aPosition2 (rLayouter.GetInsertPosition(
+ rPoint,
+ maIconSize,
+ mrSlideSorter.GetModel()));
+ }
+
+ if (maInsertPosition != aInsertPosition
+ || meMode != eMode
+ // || ! mpInsertionIndicatorOverlay->IsVisible()
+ )
+ {
+ maInsertPosition = aInsertPosition;
+ meMode = eMode;
+ mbIsInsertionTrivial = IsInsertionTrivial(maInsertPosition.GetIndex(), eMode);
+ if (maInsertPosition.GetIndex()>=0 && ! mbIsInsertionTrivial)
+ {
+ mpInsertionIndicatorOverlay->SetLocation(maInsertPosition.GetLocation());
+
+ GetInsertAnimator()->SetInsertPosition(maInsertPosition);
+ mpInsertionIndicatorOverlay->Show();
+ }
+ else
+ {
+ GetInsertAnimator()->Reset(Animator::AM_Animated);
+ mpInsertionIndicatorOverlay->Hide();
+ }
+ }
+}
+
+
+
+
+::boost::shared_ptr<view::InsertAnimator> InsertionIndicatorHandler::GetInsertAnimator (void)
+{
+ if ( ! mpInsertAnimator)
+ mpInsertAnimator.reset(new view::InsertAnimator(mrSlideSorter));
+ return mpInsertAnimator;
+}
+
+
+
+
+bool InsertionIndicatorHandler::IsInsertionTrivial (
+ const sal_Int32 nInsertionIndex,
+ const Mode eMode) const
+{
+ if (eMode == CopyMode)
+ return false;
+ else if (eMode == UnknownMode)
+ return true;
+
+ if ( ! mbIsOverSourceView)
+ return false;
+
+ // 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())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+
+ // Get the page number and compare it to the last one.
+ const sal_Int32 nPageNumber (pDescriptor->GetPageIndex());
+ if (nCurrentIndex>=0 && nPageNumber>(nCurrentIndex+1))
+ return false;
+ else
+ nCurrentIndex = nPageNumber;
+
+ // Remember indices of the first and last page of the selection.
+ if (nFirstIndex == -1)
+ nFirstIndex = nPageNumber;
+ nLastIndex = nPageNumber;
+ }
+
+ // When we come here then the selection has no holes. 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.
+ if (nInsertionIndex<nFirstIndex || nInsertionIndex>(nLastIndex+1))
+ return false;
+
+ return true;
+}
+
+
+
+
+bool InsertionIndicatorHandler::IsInsertionTrivial (const sal_Int8 nDndAction)
+{
+ return IsInsertionTrivial(GetInsertionPageIndex(), GetModeFromDndAction(nDndAction));
+}
+
+
+
+
+//===== InsertionIndicatorHandler::ForceShowContext ===========================
+
+InsertionIndicatorHandler::ForceShowContext::ForceShowContext (
+ const ::boost::shared_ptr<InsertionIndicatorHandler>& rpHandler)
+ : mpHandler(rpHandler)
+{
+ mpHandler->ForceShow();
+}
+
+
+
+
+InsertionIndicatorHandler::ForceShowContext::~ForceShowContext (void)
+{
+ mpHandler->ForceEnd();
+}
+
+} } } // end of namespace ::sd::slidesorter::controller
diff --git a/sd/source/ui/slidesorter/controller/SlsListener.cxx b/sd/source/ui/slidesorter/controller/SlsListener.cxx
new file mode 100644
index 000000000000..3604f55a8c29
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsListener.cxx
@@ -0,0 +1,701 @@
+/* -*- 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 "SlsListener.hxx"
+
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "ViewShellHint.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsSelectionObserver.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "drawdoc.hxx"
+#include "DrawDocShell.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());
+ StartListening(*mrSlideSorter.GetModel().GetDocument()->GetDocSh());
+ 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()->GetDocSh());
+ 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&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ try
+ {
+ xSet->addPropertyChangeListener(String::CreateFromAscii("IsMasterPageMode"), this);
+ }
+ catch (beans::UnknownPropertyException&)
+ {
+ 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&)
+ {
+ 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));
+ switch (rSdrHint.GetKind())
+ {
+ case HINT_PAGEORDERCHG:
+ if (&rBroadcaster == mrSlideSorter.GetModel().GetDocument())
+ HandleModelChange(rSdrHint.GetPage());
+ break;
+
+ default:
+ break;
+ }
+ }
+ 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;
+ }
+ }
+ else if (rHint.ISA(SfxSimpleHint))
+ {
+ SfxSimpleHint& rSfxSimpleHint (*PTR_CAST(SfxSimpleHint,&rHint));
+ switch (rSfxSimpleHint.GetId())
+ {
+ case SFX_HINT_DOCCHANGED:
+ mrController.CheckForMasterPageAssignment();
+ 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().GetCoreSelection();
+ UpdateEditMode();
+ }
+ break;
+
+
+ case tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED:
+ DisconnectFromController();
+ break;
+
+ case tools::EventMultiplexerEvent::EID_SHAPE_CHANGED:
+ case tools::EventMultiplexerEvent::EID_SHAPE_INSERTED:
+ case tools::EventMultiplexerEvent::EID_SHAPE_REMOVED:
+ HandleShapeModification(static_cast<const SdrPage*>(pEvent->mpUserData));
+ 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().GetCoreSelection();
+ // 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()->NotifyCurrentSlideChange(nCurrentPage-1);
+ }
+ catch (beans::UnknownPropertyException&)
+ {
+ 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().GetCoreSelection();
+ 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&)
+ {
+ // 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::HandleModelChange (const SdrPage* pPage)
+{
+ // Notify model and selection observer about the page. The return value
+ // of the model call acts as filter as to which events to pass to the
+ // selection observer.
+ if (mrSlideSorter.GetModel().NotifyPageEvent(pPage))
+ {
+ // The page of the hint belongs (or belonged) to the model.
+
+ // Tell the cache manager that the preview bitmaps for a deleted
+ // page can be removed from all caches.
+ if (pPage!=NULL && ! pPage->IsInserted())
+ cache::PageCacheManager::Instance()->ReleasePreviewBitmap(pPage);
+
+ mrController.GetSelectionManager()->GetSelectionObserver()->NotifyPageEvent(pPage);
+ }
+
+ // Tell the controller about the model change only when the document is
+ // in a sane state, not just in the middle of a larger change.
+ SdDrawDocument* pDocument (mrSlideSorter.GetModel().GetDocument());
+ if (pDocument != NULL
+ && pDocument->GetMasterSdPageCount(PK_STANDARD) == pDocument->GetMasterSdPageCount(PK_NOTES))
+ {
+ // A model change can make updates of some text fields necessary
+ // (like page numbers and page count.) Invalidate all previews in
+ // the cache to cope with this. Doing this on demand would be a
+ // nice optimization.
+ cache::PageCacheManager::Instance()->InvalidateAllPreviewBitmaps(pDocument->getUnoModel());
+
+ mrController.HandleModelChange();
+ }
+}
+
+
+
+void Listener::HandleShapeModification (const SdrPage* pPage)
+{
+ if (pPage == NULL)
+ return;
+
+ // Invalidate the preview of the page (in all slide sorters that display
+ // it.)
+ ::boost::shared_ptr<cache::PageCacheManager> pCacheManager (cache::PageCacheManager::Instance());
+ if ( ! pCacheManager)
+ return;
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ if (pDocument == NULL)
+ {
+ OSL_ASSERT(pDocument!=NULL);
+ return;
+ }
+ pCacheManager->InvalidatePreviewBitmap(pDocument->getUnoModel(), pPage);
+ mrSlideSorter.GetView().GetPreviewCache()->RequestPreviewBitmap(pPage);
+
+ // When the page is a master page then invalidate the previews of all
+ // pages that are linked to this master page.
+ if (pPage->IsMasterPage())
+ {
+ for (sal_uInt16 nIndex=0,nCount=pDocument->GetSdPageCount(PK_STANDARD);
+ nIndex<nCount;
+ ++nIndex)
+ {
+ const SdPage* pCandidate = pDocument->GetSdPage(nIndex, PK_STANDARD);
+ if (pCandidate!=NULL && pCandidate->TRG_HasMasterPage())
+ {
+ if (&pCandidate->TRG_GetMasterPage() == pPage)
+ pCacheManager->InvalidatePreviewBitmap(pDocument->getUnoModel(), pCandidate);
+ }
+ else
+ {
+ OSL_ASSERT(pCandidate!=NULL && pCandidate->TRG_HasMasterPage());
+ }
+ }
+ }
+}
+
+
+
+
+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..36d24af055fa
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsListener.hxx
@@ -0,0 +1,197 @@
+/* -*- 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);
+
+ /** Handle a change in the order of slides or when the set of slides has
+ changed, i.e. a slide has been created.
+ */
+ void HandleModelChange (const SdrPage* pPage);
+
+ /** Handle a modification to a shape on the given page. When this is a
+ regular page then update its preview. When it is a master page then
+ additionally update the previews of all pages linked to it.
+ */
+ void HandleShapeModification (const SdrPage* pPage);
+
+ /** 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..726371d6ea7d
--- /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..cfd34db8177f
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx
@@ -0,0 +1,491 @@
+/* -*- 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 "controller/SlsAnimator.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsVisibleAreaManager.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>
+#include <boost/bind.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(),
+ mpCurrentPage(),
+ mnUpdateLockCount(0),
+ mbIsUpdateCurrentPagePending(false)
+{
+ CountSelectedPages ();
+}
+
+
+
+
+void PageSelector::SelectAllPages (void)
+{
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+ PageSelector::UpdateLock aLock (*this);
+
+ int nPageCount = mrModel.GetPageCount();
+ for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
+ SelectPage(nPageIndex);
+}
+
+
+
+
+void PageSelector::DeselectAllPages (void)
+{
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+ PageSelector::UpdateLock aLock (*this);
+
+ 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;
+ mpSelectionAnchor.reset();
+}
+
+
+
+
+void PageSelector::GetCoreSelection (void)
+{
+ PageSelector::UpdateLock aLock (*this);
+
+ bool bSelectionHasChanged (true);
+ mnSelectedPageCount = 0;
+ model::PageEnumeration aAllPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->GetCoreSelection())
+ {
+ mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor);
+ mrSlideSorter.GetView().RequestRepaint(pDescriptor);
+ bSelectionHasChanged = true;
+ }
+
+ if (pDescriptor->HasState(PageDescriptor::ST_Selected))
+ mnSelectedPageCount++;
+ }
+
+ if (bSelectionHasChanged)
+ {
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ }
+}
+
+
+
+
+void PageSelector::SetCoreSelection (void)
+{
+ model::PageEnumeration aAllPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->SetCoreSelection();
+ }
+}
+
+
+
+
+void PageSelector::SelectPage (int nPageIndex)
+{
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ SelectPage(pDescriptor);
+}
+
+
+
+
+void PageSelector::SelectPage (const SdPage* pPage)
+{
+ const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
+ SelectPage(pDescriptor);
+}
+
+
+
+
+void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor.get()!=NULL
+ && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, true))
+ {
+ ++mnSelectedPageCount;
+ mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+
+ mpMostRecentlySelectedPage = rpDescriptor;
+ if (mpSelectionAnchor == NULL)
+ mpSelectionAnchor = rpDescriptor;
+
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ UpdateCurrentPage();
+
+ CheckConsistency();
+ }
+}
+
+
+
+
+void PageSelector::DeselectPage (
+ int nPageIndex,
+ const bool bUpdateCurrentPage)
+{
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ DeselectPage(pDescriptor, bUpdateCurrentPage);
+}
+
+
+
+
+void PageSelector::DeselectPage (
+ const SdPage* pPage,
+ const bool bUpdateCurrentPage)
+{
+ const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
+ DeselectPage(pDescriptor, bUpdateCurrentPage);
+}
+
+
+
+
+void PageSelector::DeselectPage (
+ const SharedPageDescriptor& rpDescriptor,
+ const bool bUpdateCurrentPage)
+{
+ if (rpDescriptor.get()!=NULL
+ && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, false))
+ {
+ --mnSelectedPageCount;
+ mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor);
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+ if (mpMostRecentlySelectedPage == rpDescriptor)
+ mpMostRecentlySelectedPage.reset();
+ if (mnBroadcastDisableLevel > 0)
+ mbSelectionChangeBroadcastPending = true;
+ else
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ if (bUpdateCurrentPage)
+ UpdateCurrentPage();
+
+ CheckConsistency();
+ }
+}
+
+
+
+
+void PageSelector::CheckConsistency (void) const
+{
+ int nSelectionCount (0);
+ for (int nPageIndex=0,nPageCount=mrModel.GetPageCount(); nPageIndex<nPageCount; nPageIndex++)
+ {
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ assert(pDescriptor);
+ if (pDescriptor->HasState(PageDescriptor::ST_Selected))
+ ++nSelectionCount;
+ }
+ if (nSelectionCount!=mnSelectedPageCount)
+ {
+ assert(nSelectionCount==mnSelectedPageCount);
+ }
+}
+
+
+
+
+bool PageSelector::IsPageSelected (int nPageIndex)
+{
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor.get() != NULL)
+ return pDescriptor->HasState(PageDescriptor::ST_Selected);
+ else
+ return false;
+}
+
+
+
+
+int PageSelector::GetPageCount (void) const
+{
+ return mrModel.GetPageCount();
+}
+
+
+
+
+int PageSelector::GetSelectedPageCount (void) const
+{
+ return mnSelectedPageCount;
+}
+
+
+
+
+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 (void)
+{
+ if (mnBroadcastDisableLevel > 0)
+ mnBroadcastDisableLevel --;
+ if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
+ {
+ mrController.GetSelectionManager()->SelectionHasChanged();
+ 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->HasState(PageDescriptor::ST_Selected))
+ pSelection->push_back(pDescriptor->GetPage());
+ }
+
+ return pSelection;
+}
+
+
+
+
+void PageSelector::SetPageSelection (
+ const ::boost::shared_ptr<PageSelection>& rpSelection,
+ const bool bUpdateCurrentPage)
+{
+ PageSelection::const_iterator iPage;
+ for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
+ SelectPage(*iPage);
+ if (bUpdateCurrentPage)
+ UpdateCurrentPage();
+}
+
+
+
+
+void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending)
+{
+ if (mnUpdateLockCount > 0)
+ {
+ mbIsUpdateCurrentPagePending = true;
+ return;
+ }
+
+ if ( ! mbIsUpdateCurrentPagePending && bUpdateOnlyWhenPending)
+ return;
+
+ mbIsUpdateCurrentPagePending = false;
+
+ // Make the first selected page the current page.
+ const sal_Int32 nPageCount (GetPageCount());
+ for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
+ {
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
+ if (pDescriptor && pDescriptor->HasState(PageDescriptor::ST_Selected))
+ {
+ // Switching the current slide normally sets also the selection
+ // to just the new current slide. To prevent that, we store
+ // (and at the end of this scope restore) the current selection.
+ ::boost::shared_ptr<PageSelection> pSelection (GetPageSelection());
+
+ mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+
+ // Restore the selection and prevent a recursive call to
+ // UpdateCurrentPage().
+ SetPageSelection(pSelection, false);
+ return;
+ }
+ }
+
+ // No page is selected. Do not change the current slide.
+}
+
+
+
+
+//===== PageSelector::UpdateLock ==============================================
+
+PageSelector::UpdateLock::UpdateLock (SlideSorter& rSlideSorter)
+ : mpSelector(&rSlideSorter.GetController().GetPageSelector())
+{
+ ++mpSelector->mnUpdateLockCount;
+}
+
+
+
+
+PageSelector::UpdateLock::UpdateLock (PageSelector& rSelector)
+ : mpSelector(&rSelector)
+{
+ ++mpSelector->mnUpdateLockCount;
+}
+
+
+
+
+PageSelector::UpdateLock::~UpdateLock (void)
+{
+ Release();
+}
+
+void PageSelector::UpdateLock::Release (void)
+{
+ if (mpSelector != NULL)
+ {
+ --mpSelector->mnUpdateLockCount;
+ OSL_ASSERT(mpSelector->mnUpdateLockCount >= 0);
+ if (mpSelector->mnUpdateLockCount == 0)
+ mpSelector->UpdateCurrentPage(true);
+
+ mpSelector = NULL;
+ }
+}
+
+
+
+
+//===== PageSelector::BroadcastLock ==============================================
+
+PageSelector::BroadcastLock::BroadcastLock (SlideSorter& rSlideSorter)
+ : mrSelector(rSlideSorter.GetController().GetPageSelector())
+{
+ mrSelector.DisableBroadcasting();
+}
+
+
+
+
+PageSelector::BroadcastLock::BroadcastLock (PageSelector& rSelector)
+ : mrSelector(rSelector)
+{
+ mrSelector.DisableBroadcasting();
+}
+
+
+
+
+PageSelector::BroadcastLock::~BroadcastLock (void)
+{
+ mrSelector.EnableBroadcasting();
+}
+
+} } } // 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..88a17a8444ac
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsProperties.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.
+ *
+ ************************************************************************/
+
+#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(true),
+ mbIsSuspendPreviewUpdatesDuringFullScreenPresentation(true),
+ maBackgroundColor(Application::GetSettings().GetStyleSettings().GetWindowColor()),
+ maTextColor(Application::GetSettings().GetStyleSettings().GetActiveTextColor()),
+ maSelectionColor(Application::GetSettings().GetStyleSettings().GetHighlightColor()),
+ maHighlightColor(Application::GetSettings().GetStyleSettings().GetMenuHighlightColor()),
+ mbIsUIReadOnly(false),
+ mbIsOnlyPreviewTriggersMouseOver(true),
+ mbIsHighContrastModeActive(
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode())
+{
+}
+
+
+
+
+Properties::~Properties (void)
+{
+}
+
+
+
+
+void Properties::HandleDataChangeEvent (void)
+{
+ maBackgroundColor = Application::GetSettings().GetStyleSettings().GetWindowColor();
+ maTextColor = Application::GetSettings().GetStyleSettings().GetActiveTextColor();
+ maSelectionColor = Application::GetSettings().GetStyleSettings().GetHighlightColor();
+ maHighlightColor = Application::GetSettings().GetStyleSettings().GetMenuHighlightColor();
+ mbIsHighContrastModeActive
+ = Application::GetSettings().GetStyleSettings().GetHighContrastMode();
+}
+
+
+
+
+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;
+}
+
+
+
+
+bool Properties::IsOnlyPreviewTriggersMouseOver (void) const
+{
+ return mbIsOnlyPreviewTriggersMouseOver;
+}
+
+
+
+
+void Properties::SetOnlyPreviewTriggersMouseOver (const bool bFlag)
+{
+ mbIsOnlyPreviewTriggersMouseOver = bFlag;
+}
+
+
+
+
+bool Properties::IsHighContrastModeActive (void) const
+{
+ return mbIsHighContrastModeActive;
+}
+
+
+} } } // 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..71ac9450ca21
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx
@@ -0,0 +1,740 @@
+/* -*- 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 "controller/SlsVisibleAreaManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsTheme.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 (20,20),
+ mnHorizontalScrollFactor (0.15),
+ mnVerticalScrollFactor (0.25),
+ mpScrollBarFiller(mrSlideSorter.GetScrollBarFiller()),
+ maAutoScrollTimer(),
+ maAutoScrollOffset(0,0),
+ mbIsAutoScrollActive(false),
+ mpContentWindow(mrSlideSorter.GetContentWindow()),
+ maAutoScrollFunctor()
+{
+ // 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(25);
+ 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,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed)
+{
+ Rectangle aRemainingSpace (DetermineScrollBarVisibilities(
+ rAvailableArea,
+ bIsHorizontalScrollBarAllowed,
+ bIsVerticalScrollBarAllowed));
+
+ if (mpHorizontalScrollBar!=NULL && mpHorizontalScrollBar->IsVisible())
+ PlaceHorizontalScrollBar (rAvailableArea);
+
+ if (mpVerticalScrollBar!=NULL && mpVerticalScrollBar->IsVisible())
+ PlaceVerticalScrollBar (rAvailableArea);
+
+ if (mpScrollBarFiller!=NULL && mpScrollBarFiller->IsVisible())
+ PlaceFiller (rAvailableArea);
+
+ return aRemainingSpace;
+}
+
+
+
+
+void ScrollBarManager::PlaceHorizontalScrollBar (const Rectangle& aAvailableArea)
+{
+ // 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)
+{
+ const double nThumbPosition (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(nThumbPosition);
+ mnVerticalPosition = nThumbPosition / double(mpVerticalScrollBar->GetRange().Len());
+}
+
+
+
+
+void ScrollBarManager::PlaceFiller (const Rectangle& aArea)
+{
+ mpScrollBarFiller->SetPosSizePixel(
+ Point(
+ aArea.Right()-mpVerticalScrollBar->GetSizePixel().Width()+1,
+ aArea.Bottom()-mpHorizontalScrollBar->GetSizePixel().Height()+1),
+ Size (
+ mpVerticalScrollBar->GetSizePixel().Width(),
+ mpHorizontalScrollBar->GetSizePixel().Height()));
+}
+
+
+
+
+void ScrollBarManager::UpdateScrollBars (bool bResetThumbPosition, bool bUseScrolling)
+{
+ Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ 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.GetContentWindow()!=NULL)
+ {
+ double nRelativePosition = double(pScrollBar->GetThumbPos())
+ / double(pScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetContentWindow()->SetVisibleXY(-1, nRelativePosition);
+ mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
+ }
+ return sal_True;
+}
+
+
+
+
+IMPL_LINK(ScrollBarManager, HorizontalScrollBarHandler, ScrollBar*, pScrollBar)
+{
+ if (pScrollBar!=NULL
+ && pScrollBar==mpHorizontalScrollBar.get()
+ && pScrollBar->IsVisible()
+ && mrSlideSorter.GetContentWindow()!=NULL)
+ {
+ double nRelativePosition = double(pScrollBar->GetThumbPos())
+ / double(pScrollBar->GetRange().Len());
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+ mrSlideSorter.GetContentWindow()->SetVisibleXY(nRelativePosition, -1);
+ mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
+ }
+ return sal_True;
+}
+
+
+
+
+void ScrollBarManager::SetWindowOrigin (
+ double nHorizontalPosition,
+ double nVerticalPosition)
+{
+ mnHorizontalPosition = nHorizontalPosition;
+ mnVerticalPosition = nVerticalPosition;
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ 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,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed)
+{
+ // Test which combination of scroll bars is the best.
+ bool bShowHorizontal = false;
+ bool bShowVertical = false;
+ if (mrSlideSorter.GetModel().GetPageCount() == 0)
+ {
+ // No pages => no scroll bars.
+ }
+ else if (TestScrollBarVisibilities(false, false, rAvailableArea))
+ {
+ // Nothing to be done.
+ }
+ else if (bIsHorizontalScrollBarAllowed
+ && TestScrollBarVisibilities(true, false, rAvailableArea))
+ {
+ bShowHorizontal = true;
+ }
+ else if (bIsVerticalScrollBarAllowed
+ && TestScrollBarVisibilities(false, true, rAvailableArea))
+ {
+ bShowVertical = true;
+ }
+ else
+ {
+ bShowHorizontal = true;
+ bShowVertical = true;
+ }
+
+ // Make the visibility of the scroll bars permanent.
+ mpVerticalScrollBar->Show(bShowVertical);
+ mpHorizontalScrollBar->Show(bShowHorizontal);
+ mpScrollBarFiller->Show(bShowVertical && 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)
+{
+ model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
+
+ // 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 (mrSlideSorter.GetView().GetLayouter().Rearrange (
+ mrSlideSorter.GetView().GetOrientation(),
+ aBrowserSize,
+ rModel.GetPageDescriptor(0)->GetPage()->GetSize(),
+ rModel.GetPageCount()));
+
+ if (bRearrangeSuccess)
+ {
+ Size aPageSize = mrSlideSorter.GetView().GetLayouter().GetTotalBoundingBox().GetSize();
+ Size aWindowModelSize = mpContentWindow->PixelToLogic(aBrowserSize);
+
+ // The content may be clipped, i.e. not fully visible, in one
+ // direction only when the scroll bar is visible in that direction.
+ if (aPageSize.Width() > aWindowModelSize.Width())
+ if ( ! bHorizontalScrollBarVisible)
+ return false;
+ if (aPageSize.Height() > aWindowModelSize.Height())
+ if ( ! bVerticalScrollBarVisible)
+ return false;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void ScrollBarManager::SetTopLeft (const Point aNewTopLeft)
+{
+ if (( ! mpVerticalScrollBar
+ || mpVerticalScrollBar->GetThumbPos() == aNewTopLeft.Y())
+ && ( ! mpHorizontalScrollBar
+ || mpHorizontalScrollBar->GetThumbPos() == aNewTopLeft.X()))
+ return;
+
+ // Flush pending repaints before scrolling to avoid temporary artifacts.
+ mrSlideSorter.GetContentWindow()->Update();
+
+ if (mpVerticalScrollBar)
+ {
+ mpVerticalScrollBar->SetThumbPos(aNewTopLeft.Y());
+ mnVerticalPosition = aNewTopLeft.Y() / double(mpVerticalScrollBar->GetRange().Len());
+ }
+ if (mpHorizontalScrollBar)
+ {
+ mpHorizontalScrollBar->SetThumbPos(aNewTopLeft.X());
+ mnHorizontalPosition = aNewTopLeft.X() / double(mpHorizontalScrollBar->GetRange().Len());
+ }
+
+ mrSlideSorter.GetContentWindow()->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+}
+
+
+
+
+sal_Int32 ScrollBarManager::GetTop (void) const
+{
+ if (mpVerticalScrollBar != NULL)
+ return mpVerticalScrollBar->GetThumbPos();
+ else
+ return 0;
+}
+
+
+
+
+sal_Int32 ScrollBarManager::GetLeft (void) const
+{
+ if (mpHorizontalScrollBar != NULL)
+ return mpHorizontalScrollBar->GetThumbPos();
+ else
+ return 0;
+}
+
+
+
+
+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)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+
+ 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,
+ const ::boost::function<void(void)>& rAutoScrollFunctor)
+{
+ maAutoScrollFunctor = rAutoScrollFunctor;
+ CalcAutoScrollOffset(rMouseWindowPosition);
+ bool bResult (true);
+ if ( ! mbIsAutoScrollActive)
+ bResult = RepeatAutoScroll();
+
+ return bResult;
+}
+
+
+
+
+void ScrollBarManager::StopAutoScroll (void)
+{
+ maAutoScrollTimer.Stop();
+ mbIsAutoScrollActive = false;
+}
+
+
+
+
+bool ScrollBarManager::RepeatAutoScroll (void)
+{
+ if (maAutoScrollOffset != Size(0,0))
+ {
+ if (mrSlideSorter.GetViewShell() != NULL)
+ {
+ mrSlideSorter.GetViewShell()->Scroll(
+ maAutoScrollOffset.Width(),
+ maAutoScrollOffset.Height());
+ mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
+
+ if (maAutoScrollFunctor)
+ maAutoScrollFunctor();
+
+ mbIsAutoScrollActive = true;
+ maAutoScrollTimer.Start();
+
+ return true;
+ }
+ }
+
+ maAutoScrollFunctor = ::boost::function<void(void)>();
+ mbIsAutoScrollActive = false;
+ return false;
+}
+
+
+
+
+IMPL_LINK(ScrollBarManager, AutoScrollTimeoutHandler, Timer *, EMPTYARG)
+{
+ RepeatAutoScroll();
+
+ return 0;
+}
+
+
+
+
+void ScrollBarManager::Scroll(
+ const Orientation eOrientation,
+ const Unit eUnit,
+ const sal_Int32 nDistance)
+{
+ bool bIsVertical (false);
+ switch (eOrientation)
+ {
+ case Orientation_Horizontal: bIsVertical = false; break;
+ case Orientation_Vertical: bIsVertical = true; break;
+ default:
+ OSL_ASSERT(eOrientation==Orientation_Horizontal || eOrientation==Orientation_Vertical);
+ return;
+ }
+
+ Point aNewTopLeft (
+ mpHorizontalScrollBar ? mpHorizontalScrollBar->GetThumbPos() : 0,
+ mpVerticalScrollBar ? mpVerticalScrollBar->GetThumbPos() : 0);
+ switch (eUnit)
+ {
+ case Unit_Pixel:
+ if (bIsVertical)
+ aNewTopLeft.Y() += nDistance;
+ else
+ aNewTopLeft.X() += nDistance;
+ break;
+
+ case Unit_Slide:
+ {
+ view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
+
+ // Calculate estimate of new location.
+ if (bIsVertical)
+ aNewTopLeft.Y() += nDistance * rLayouter.GetPageObjectSize().Height();
+ else
+ aNewTopLeft.X() += nDistance * rLayouter.GetPageObjectSize().Width();
+
+ // Adapt location to show whole slides.
+ if (bIsVertical)
+ if (nDistance > 0)
+ {
+ const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
+ Point(aNewTopLeft.X(), aNewTopLeft.Y()+mpVerticalScrollBar->GetVisibleSize()),
+ true));
+ aNewTopLeft.Y() = rLayouter.GetPageObjectBox(nIndex,true).Bottom()
+ - mpVerticalScrollBar->GetVisibleSize();
+ }
+ else
+ {
+ const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
+ Point(aNewTopLeft.X(), aNewTopLeft.Y()),
+ true));
+ aNewTopLeft.Y() = rLayouter.GetPageObjectBox(nIndex,true).Top();
+ }
+ else
+ if (nDistance > 0)
+ {
+ const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
+ Point(aNewTopLeft.X()+mpVerticalScrollBar->GetVisibleSize(), aNewTopLeft.Y()),
+ true));
+ aNewTopLeft.X() = rLayouter.GetPageObjectBox(nIndex,true).Right()
+ - mpVerticalScrollBar->GetVisibleSize();
+ }
+ else
+ {
+ const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
+ Point(aNewTopLeft.X(), aNewTopLeft.Y()),
+ true));
+ aNewTopLeft.X() = rLayouter.GetPageObjectBox(nIndex,true).Left();
+ }
+ }
+ }
+ mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
+ SetTopLeft(aNewTopLeft);
+}
+
+
+} } } // 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..174c3b944ab3
--- /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 (sal_uInt16 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..1bc80260ad72
--- /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 (sal_uInt16 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..c52581f990a8
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
@@ -0,0 +1,2027 @@
+/* -*- 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 "SlsDragAndDropContext.hxx"
+#include "controller/SlsTransferable.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/SlsInsertionIndicatorHandler.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsVisibleAreaManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsButtonBar.hxx"
+#include "framework/FrameworkHelper.hxx"
+#include "ViewShellBase.hxx"
+#include "DrawController.hxx"
+#include "Window.hxx"
+#include "sdpage.hxx"
+#include "drawdoc.hxx"
+#include "DrawDocShell.hxx"
+#include "sdxfer.hxx"
+#include "ViewShell.hxx"
+#include "ViewShellBase.hxx"
+#include "FrameView.hxx"
+#include "app.hrc"
+#include "sdresid.hxx"
+#include "strings.hrc"
+#include <vcl/sound.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svdpagv.hxx>
+#include <vcl/msgbox.hxx>
+#include <svx/svxids.hrc>
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
+
+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);
+static const sal_uInt32 MOUSE_DRAG (0x00000800);
+// 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 OVER_BUTTON_AREA (0x00080000);
+static const sal_uInt32 OVER_BUTTON (0x00100000);
+static const sal_uInt32 SHIFT_MODIFIER (0x00200000);
+static const sal_uInt32 CONTROL_MODIFIER (0x00400000);
+
+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 NOT_OVER_PAGE (0x00000000);
+
+// Masks
+static const sal_uInt32 MODIFIER_MASK (SHIFT_MODIFIER | CONTROL_MODIFIER);
+static const sal_uInt32 BUTTON_MASK (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON);
+
+} // end of anonymous namespace
+
+
+
+// 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
+
+namespace sd { namespace slidesorter { namespace controller {
+
+//===== SelectionFunction::EventDescriptor ====================================
+
+class SelectionFunction::EventDescriptor
+{
+public:
+ Point maMousePosition;
+ Point maMouseModelPosition;
+ model::SharedPageDescriptor mpHitDescriptor;
+ SdrPage* mpHitPage;
+ sal_uInt32 mnEventCode;
+ bool mbIsOverButton;
+ InsertionIndicatorHandler::Mode meDragMode;
+ bool mbMakeSelectionVisible;
+ bool mbIsLeaving;
+
+ EventDescriptor (
+ sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter);
+ EventDescriptor (
+ sal_uInt32 nEventType,
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction,
+ SlideSorter& rSlideSorter);
+ EventDescriptor (
+ const KeyEvent& rEvent,
+ SlideSorter& rSlideSorter);
+
+ void SetDragMode (const InsertionIndicatorHandler::Mode eMode);
+
+private:
+ /** 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 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 KeyEvent& rEvent) const;
+
+ /** Compute a numerical code that describes the current state like
+ whether the selection rectangle is visible or whether the page under
+ the mouse or the one that has the focus is selected.
+ */
+ sal_uInt32 EncodeState (void) const;
+};
+
+
+
+
+//===== SelectionFunction::ModeHandler ========================================
+
+class SelectionFunction::ModeHandler
+{
+public:
+ ModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const bool bIsMouseOverIndicatorAllowed);
+ virtual ~ModeHandler (void);
+
+ virtual Mode GetMode (void) const = 0;
+ virtual void Abort (void) = 0;
+ virtual void ProcessEvent (EventDescriptor& rDescriptor);
+
+ /** Set the selection to exactly the specified page and also set it as
+ the current page.
+ */
+ void SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /// Deselect all pages.
+ void DeselectAllPages (void);
+ void SelectOnePage (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);
+
+ void StartDrag (
+ const Point& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode);
+
+ bool IsMouseOverIndicatorAllowed (void) const;
+
+protected:
+ SlideSorter& mrSlideSorter;
+ SelectionFunction& mrSelectionFunction;
+
+ virtual bool ProcessButtonDownEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (EventDescriptor& rDescriptor);
+ virtual bool HandleUnprocessedEvent (EventDescriptor& rDescriptor);
+
+ void ReprocessEvent (EventDescriptor& rDescriptor);
+
+private:
+ const bool mbIsMouseOverIndicatorAllowed;
+};
+
+
+/** This is the default handler for processing events. It activates the
+ multi selection or drag-and-drop when the right conditions are met.
+*/
+class NormalModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ NormalModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction);
+ virtual ~NormalModeHandler (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+
+ void ResetButtonDownLocation (void);
+
+protected:
+ virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ ::boost::optional<Point> maButtonDownLocation;
+
+ /** Select all pages between and including the selection anchor and the
+ specified page.
+ */
+ void RangeSelect (const model::SharedPageDescriptor& rpDescriptor);
+};
+
+
+/** Handle events during a multi selection, which typically is started by
+ pressing the left mouse button when not over a page.
+*/
+class MultiSelectionModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ /** Start a rectangle selection at the given position.
+ */
+ MultiSelectionModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMouseModelPosition,
+ const sal_uInt32 nEventCode);
+ virtual ~MultiSelectionModeHandler (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+ virtual void ProcessEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+ enum SelectionMode { SM_Normal, SM_Add, SM_Toggle };
+
+ void SetSelectionMode (const SelectionMode eSelectionMode);
+ void SetSelectionModeFromModifier (const sal_uInt32 nEventCode);
+
+protected:
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ SelectionMode meSelectionMode;
+ Point maSecondCorner;
+ Pointer maSavedPointer;
+ sal_Int32 mnAnchorIndex;
+ sal_Int32 mnSecondIndex;
+ view::ButtonBar::Lock maButtonBarLock;
+
+ virtual void UpdateModelPosition (const Point& rMouseModelPosition);
+ virtual void UpdateSelection (void);
+
+ /** Update the rectangle selection so that the given position becomes
+ the new second point of the selection rectangle.
+ */
+ void UpdatePosition (
+ const Point& rMousePosition,
+ const bool bAllowAutoScroll);
+
+ void UpdateSelectionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bIsInSelection) const;
+};
+
+
+/** Handle events during drag-and-drop.
+*/
+class DragAndDropModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ DragAndDropModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMousePosition,
+ ::Window* pWindow);
+ virtual ~DragAndDropModeHandler (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+
+protected:
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ ::boost::scoped_ptr<DragAndDropContext> mpDragAndDropContext;
+};
+
+
+/** Handle events while the left mouse button is pressed over the button
+ bar.
+*/
+class ButtonModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ ButtonModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction);
+ virtual ~ButtonModeHandler (void);
+ virtual void Abort (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+
+protected:
+ virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+};
+
+
+
+
+//===== SelectionFunction =====================================================
+
+TYPEINIT1(SelectionFunction, FuPoor);
+
+
+SelectionFunction::SelectionFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+ : FuPoor (
+ rSlideSorter.GetViewShell(),
+ rSlideSorter.GetContentWindow().get(),
+ &rSlideSorter.GetView(),
+ rSlideSorter.GetModel().GetDocument(),
+ rRequest),
+ mrSlideSorter(rSlideSorter),
+ mrController(mrSlideSorter.GetController()),
+ mbDragSelection(false),
+ maInsertionMarkerBox(),
+ mbProcessingMouseButtonDown(false),
+ mnShiftKeySelectionAnchor(-1),
+ mpModeHandler(new NormalModeHandler(rSlideSorter, *this))
+{
+}
+
+
+
+
+SelectionFunction::~SelectionFunction (void)
+{
+ mpModeHandler.reset();
+}
+
+
+
+
+FunctionReference SelectionFunction::Create(
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest)
+{
+ FunctionReference xFunc( new SelectionFunction( rSlideSorter, rRequest ) );
+ return xFunc;
+}
+
+
+
+
+sal_Bool SelectionFunction::MouseButtonDown (const MouseEvent& rEvent)
+{
+ // remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+ aMDPos = rEvent.GetPosPixel();
+ mbProcessingMouseButtonDown = true;
+
+ // mpWindow->CaptureMouse();
+
+ ProcessMouseEvent(BUTTON_DOWN, rEvent);
+
+ return sal_True;
+}
+
+
+
+
+sal_Bool SelectionFunction::MouseMove (const MouseEvent& rEvent)
+{
+ ProcessMouseEvent(MOUSE_MOTION, rEvent);
+ return sal_True;
+}
+
+
+
+
+sal_Bool SelectionFunction::MouseButtonUp (const MouseEvent& rEvent)
+{
+ mrController.GetScrollBarManager().StopAutoScroll ();
+
+ ProcessMouseEvent(BUTTON_UP, rEvent);
+
+ mbProcessingMouseButtonDown = false;
+// mpWindow->ReleaseMouse();
+
+ return sal_True;
+}
+
+
+
+
+void SelectionFunction::NotifyDragFinished (void)
+{
+ SwitchToNormalMode();
+}
+
+
+
+
+sal_Bool SelectionFunction::KeyInput (const KeyEvent& rEvent)
+{
+ view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ PageSelector::UpdateLock aLock (mrSlideSorter);
+ FocusManager& rFocusManager (mrController.GetFocusManager());
+ sal_Bool bResult = sal_False;
+
+ const KeyCode& rCode (rEvent.GetKeyCode());
+ switch (rCode.GetCode())
+ {
+ case KEY_RETURN:
+ {
+ model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (rFocusManager.HasFocus() && pDescriptor && pViewShell!=NULL)
+ {
+ // The Return key triggers different functions depending on
+ // whether the slide sorter is the main view or displayed in
+ // the right pane.
+ if (pViewShell->IsMainViewShell())
+ {
+ mpModeHandler->SetCurrentPage(pDescriptor);
+ mpModeHandler->SwitchView(pDescriptor);
+ }
+ else
+ {
+ pViewShell->GetDispatcher()->Execute(
+ SID_INSERTPAGE,
+ SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
+ }
+ bResult = sal_True;
+ }
+ break;
+ }
+
+ case KEY_TAB:
+ if ( ! rFocusManager.IsFocusShowing())
+ {
+ rFocusManager.ShowFocus();
+ bResult = sal_True;
+ }
+ break;
+
+ case KEY_ESCAPE:
+ // When there is an active multiselection or drag-and-drop
+ // operation then stop that.
+ mpModeHandler->Abort();
+ SwitchToNormalMode();
+ bResult = sal_True;
+ break;
+
+ case KEY_SPACE:
+ {
+ // Toggle the selection state.
+ model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
+ if (pDescriptor && rCode.IsMod1())
+ {
+ if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ mrController.GetPageSelector().DeselectPage(pDescriptor, false);
+ else
+ mrController.GetPageSelector().SelectPage(pDescriptor);
+ }
+ bResult = sal_True;
+ }
+ break;
+
+
+ // Move the focus indicator left.
+ case KEY_LEFT:
+ MoveFocus(FocusManager::FMD_LEFT, rCode.IsShift(), rCode.IsMod1());
+ bResult = sal_True;
+ break;
+
+ // Move the focus indicator right.
+ case KEY_RIGHT:
+ MoveFocus(FocusManager::FMD_RIGHT, rCode.IsShift(), rCode.IsMod1());
+ bResult = sal_True;
+ break;
+
+ // Move the focus indicator up.
+ case KEY_UP:
+ MoveFocus(FocusManager::FMD_UP, rCode.IsShift(), rCode.IsMod1());
+ bResult = sal_True;
+ break;
+
+ // Move the focus indicator down.
+ case KEY_DOWN:
+ MoveFocus(FocusManager::FMD_DOWN, rCode.IsShift(), rCode.IsMod1());
+ bResult = sal_True;
+ break;
+
+ // Go to previous page. No wrap around.
+ case KEY_PAGEUP:
+ GotoNextPage(-1);
+ bResult = sal_True;
+ break;
+
+ // Go to next page. No wrap around..
+ case KEY_PAGEDOWN:
+ GotoNextPage(+1);
+ bResult = sal_True;
+ break;
+
+ case KEY_HOME:
+ GotoPage(0);
+ bResult = sal_True;
+ break;
+
+ case KEY_END:
+ GotoPage(mrSlideSorter.GetModel().GetPageCount()-1);
+ bResult = sal_True;
+ break;
+
+ case KEY_DELETE:
+ case KEY_BACKSPACE:
+ {
+ if (mrSlideSorter.GetProperties()->IsUIReadOnly())
+ break;
+
+ mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE);
+
+ mnShiftKeySelectionAnchor = -1;
+ bResult = sal_True;
+ }
+ break;
+
+ case KEY_F10:
+ if (rCode.IsShift())
+ {
+ mpModeHandler->SelectOnePage(
+ mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ( ! bResult)
+ bResult = FuPoor::KeyInput(rEvent);
+
+ return bResult;
+}
+
+
+
+
+void SelectionFunction::MoveFocus (
+ const FocusManager::FocusMoveDirection eDirection,
+ const bool bIsShiftDown,
+ const bool bIsControlDown)
+{
+ // Remember the anchor of shift key multi selection.
+ if (bIsShiftDown)
+ {
+ if (mnShiftKeySelectionAnchor<0)
+ {
+ model::SharedPageDescriptor pFocusedDescriptor (
+ mrController.GetFocusManager().GetFocusedPageDescriptor());
+ mnShiftKeySelectionAnchor = pFocusedDescriptor->GetPageIndex();
+ }
+ }
+ else if ( ! bIsControlDown)
+ ResetShiftKeySelectionAnchor();
+
+ mrController.GetFocusManager().MoveFocus(eDirection);
+
+ PageSelector& rSelector (mrController.GetPageSelector());
+ model::SharedPageDescriptor pFocusedDescriptor (
+ mrController.GetFocusManager().GetFocusedPageDescriptor());
+ if (bIsShiftDown)
+ {
+ // When shift is pressed then select all pages in the range between
+ // the currently and the previously focused pages, including them.
+ if (pFocusedDescriptor)
+ {
+ sal_Int32 nPageRangeEnd (pFocusedDescriptor->GetPageIndex());
+ model::PageEnumeration aPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ if (pDescriptor)
+ {
+ const sal_Int32 nPageIndex(pDescriptor->GetPageIndex());
+ if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd)
+ || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd))
+ {
+ rSelector.SelectPage(pDescriptor);
+ }
+ else
+ {
+ rSelector.DeselectPage(pDescriptor);
+ }
+ }
+ }
+ }
+ }
+ else if (bIsControlDown)
+ {
+ // When control is pressed then do not alter the selection or the
+ // current page, just move the focus.
+ }
+ else
+ {
+ // Without shift just select the focused page.
+ mpModeHandler->SelectOnePage(pFocusedDescriptor);
+ }
+}
+
+
+
+
+void SelectionFunction::Activate()
+{
+ FuPoor::Activate();
+}
+
+
+
+
+void SelectionFunction::Deactivate()
+{
+ FuPoor::Deactivate();
+}
+
+
+
+void SelectionFunction::ScrollStart (void)
+{
+}
+
+
+
+
+void SelectionFunction::ScrollEnd (void)
+{
+}
+
+
+
+
+void SelectionFunction::DoCut (void)
+{
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
+ {
+ mrController.GetClipboard().DoCut();
+ }
+}
+
+
+
+
+void SelectionFunction::DoCopy (void)
+{
+ mrController.GetClipboard().DoCopy();
+}
+
+
+
+
+void SelectionFunction::DoPaste (void)
+{
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
+ {
+ mrController.GetClipboard().DoPaste();
+ }
+}
+
+
+
+
+bool SelectionFunction::cancel (void)
+{
+ mrController.GetFocusManager().ToggleFocus();
+ return true;
+}
+
+
+
+
+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;
+ GotoPage(nIndex + nOffset);
+ }
+ ResetShiftKeySelectionAnchor();
+}
+
+
+
+
+void SelectionFunction::GotoPage (int nIndex)
+{
+ sal_uInt16 nPageCount = (sal_uInt16)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)
+ mpModeHandler->SetCurrentPage(pNextPageDescriptor);
+ else
+ {
+ OSL_ASSERT(pNextPageDescriptor.get() != NULL);
+ }
+ ResetShiftKeySelectionAnchor();
+}
+
+
+
+
+void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
+{
+ // #95491# remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+
+ EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
+}
+
+
+
+
+void SelectionFunction::MouseDragged (
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction)
+{
+ EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
+}
+
+
+
+
+void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent)
+{
+ EventDescriptor aEventDescriptor (rEvent, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
+}
+
+
+
+
+void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor)
+{
+ // The call to ProcessEvent may switch to another mode handler.
+ // Prevent the untimely destruction of the called handler by aquiring a
+ // temporary reference here.
+ ::boost::shared_ptr<ModeHandler> pModeHandler (mpModeHandler);
+ pModeHandler->ProcessEvent(rDescriptor);
+}
+
+
+
+
+bool Match (
+ const sal_uInt32 nEventCode,
+ const sal_uInt32 nPositivePattern)
+{
+ return (nEventCode & nPositivePattern)==nPositivePattern;
+}
+
+
+
+
+void SelectionFunction::SwitchToNormalMode (void)
+{
+ if (mpModeHandler->GetMode() != NormalMode)
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new NormalModeHandler(mrSlideSorter, *this)));
+}
+
+
+
+
+void SelectionFunction::SwitchToDragAndDropMode (const Point aMousePosition)
+{
+ if (mpModeHandler->GetMode() != DragAndDropMode)
+ {
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new DragAndDropModeHandler(mrSlideSorter, *this, aMousePosition, mpWindow)));
+ }
+}
+
+
+
+
+void SelectionFunction::SwitchToMultiSelectionMode (
+ const Point aMousePosition,
+ const sal_uInt32 nEventCode)
+{
+ if (mpModeHandler->GetMode() != MultiSelectionMode)
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new MultiSelectionModeHandler(mrSlideSorter, *this, aMousePosition, nEventCode)));
+}
+
+
+
+
+bool SelectionFunction::SwitchToButtonMode (void)
+{
+ // Do not show the buttons for draw pages.
+ ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW
+ && mpModeHandler->GetMode() != ButtonMode)
+ {
+ SwitchMode(::boost::shared_ptr<ModeHandler>(new ButtonModeHandler(mrSlideSorter, *this)));
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void SelectionFunction::SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler)
+{
+ // Not all modes allow mouse over indicator.
+ if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed())
+ {
+ if ( ! rpHandler->IsMouseOverIndicatorAllowed())
+ {
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
+ mrSlideSorter.GetView().GetButtonBar().ResetPage();
+ }
+ else
+ mrSlideSorter.GetView().UpdatePageUnderMouse(false);
+ }
+
+ mpModeHandler = rpHandler;
+}
+
+
+
+
+void SelectionFunction::ResetShiftKeySelectionAnchor (void)
+{
+ mnShiftKeySelectionAnchor = -1;
+}
+
+
+
+
+void SelectionFunction::ResetMouseAnchor (void)
+{
+ if (mpModeHandler && mpModeHandler->GetMode() == NormalMode)
+ {
+ ::boost::shared_ptr<NormalModeHandler> pHandler (
+ ::boost::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler));
+ if (pHandler)
+ pHandler->ResetButtonDownLocation();
+ }
+}
+
+
+
+
+//===== EventDescriptor =======================================================
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(rEvent.GetPosPixel()),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(nEventType),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::MoveMode),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
+{
+ maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
+ mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
+ if (mpHitDescriptor)
+ {
+ mpHitPage = mpHitDescriptor->GetPage();
+ }
+
+ mnEventCode |= EncodeMouseEvent(rEvent);
+ mnEventCode |= EncodeState();
+
+ // Detect the mouse leaving the window. When not button is pressed then
+ // we can call IsLeaveWindow at the event. Otherwise we have to make an
+ // explicit test.
+ mbIsLeaving = rEvent.IsLeaveWindow()
+ || ! Rectangle(Point(0,0),
+ rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
+}
+
+
+
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const sal_uInt32 nEventType,
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(rEvent.maPosPixel),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(nEventType),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
+{
+ maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
+ mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
+ if (mpHitDescriptor)
+ {
+ mpHitPage = mpHitDescriptor->GetPage();
+ }
+
+ mnEventCode |= EncodeState();
+
+ // Detect the mouse leaving the window. When not button is pressed then
+ // we can call IsLeaveWindow at the event. Otherwise we have to make an
+ // explicit test.
+ mbIsLeaving = rEvent.mbLeaving
+ || ! Rectangle(Point(0,0),
+ rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
+}
+
+
+
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const KeyEvent& rEvent,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(KEY_EVENT),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::MoveMode),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
+{
+ model::SharedPageDescriptor pHitDescriptor (
+ rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
+ if (pHitDescriptor.get() != NULL)
+ {
+ mpHitPage = pHitDescriptor->GetPage();
+ mpHitDescriptor = pHitDescriptor;
+ }
+
+ mnEventCode |= EncodeKeyEvent(rEvent) | EncodeState();
+}
+
+
+
+
+void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode)
+{
+ meDragMode = eMode;
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent (
+ const MouseEvent& rEvent) const
+{
+ // Initialize with the type of mouse event.
+ sal_uInt32 nEventCode (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 pressed modifier keys.
+ if (rEvent.IsShift())
+ nEventCode |= SHIFT_MODIFIER;
+ if (rEvent.IsMod1())
+ nEventCode |= CONTROL_MODIFIER;
+
+ // Detect whether the mouse is over one of the active elements inside a
+ // page object.
+ if (mbIsOverButton)
+ nEventCode |= OVER_BUTTON;
+
+ return nEventCode;
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeKeyEvent (const KeyEvent& rEvent) const
+{
+ // The key code in the lower 16 bit.
+ sal_uInt32 nEventCode (rEvent.GetKeyCode().GetCode());
+
+ // Detect pressed modifier keys.
+ if (rEvent.GetKeyCode().IsShift())
+ nEventCode |= SHIFT_MODIFIER;
+ if (rEvent.GetKeyCode().IsMod1())
+ nEventCode |= CONTROL_MODIFIER;
+
+ return nEventCode;
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeState (void) const
+{
+ sal_uInt32 nEventCode (0);
+
+ // Detect whether the event has happened over a page object.
+ if (mpHitPage!=NULL && mpHitDescriptor)
+ {
+ if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ nEventCode |= OVER_SELECTED_PAGE;
+ else
+ nEventCode |= OVER_UNSELECTED_PAGE;
+
+ // Detect whether the mouse is over one of the active elements
+ // inside a page object.
+ if (mbIsOverButton)
+ nEventCode |= OVER_BUTTON;
+ }
+
+ return nEventCode;
+}
+
+
+
+
+//===== SelectionFunction::ModeHandler ========================================
+
+SelectionFunction::ModeHandler::ModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const bool bIsMouseOverIndicatorAllowed)
+ : mrSlideSorter(rSlideSorter),
+ mrSelectionFunction(rSelectionFunction),
+ mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed)
+{
+}
+
+
+
+
+SelectionFunction::ModeHandler::~ModeHandler (void)
+{
+}
+
+
+
+
+void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor)
+{
+ mrSelectionFunction.ProcessEvent(rDescriptor);
+}
+
+
+
+
+void SelectionFunction::ModeHandler::ProcessEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+
+ bool bIsProcessed (false);
+ switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG))
+ {
+ case BUTTON_DOWN:
+ bIsProcessed = ProcessButtonDownEvent(rDescriptor);
+ break;
+
+ case BUTTON_UP:
+ bIsProcessed = ProcessButtonUpEvent(rDescriptor);
+ break;
+
+ case MOUSE_MOTION:
+ bIsProcessed = ProcessMotionEvent(rDescriptor);
+ break;
+
+ case MOUSE_DRAG:
+ bIsProcessed = ProcessDragEvent(rDescriptor);
+ break;
+ }
+
+ if ( ! bIsProcessed)
+ HandleUnprocessedEvent(rDescriptor);
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&)
+{
+ mrSelectionFunction.SwitchToNormalMode();
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor)
+{
+ if (mbIsMouseOverIndicatorAllowed)
+ mrSlideSorter.GetView().UpdatePageUnderMouse(
+ rDescriptor.maMousePosition,
+ (rDescriptor.mnEventCode & LEFT_BUTTON) != 0,
+ true);
+
+ if (rDescriptor.mbIsLeaving)
+ {
+ mrSelectionFunction.SwitchToNormalMode();
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+void SelectionFunction::ModeHandler::SetCurrentPage (
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ SelectOnePage(rpDescriptor);
+ mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::ModeHandler::DeselectAllPages (void)
+{
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSelectionFunction.ResetShiftKeySelectionAnchor();
+}
+
+
+
+
+void SelectionFunction::ModeHandler::SelectOnePage (
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::ModeHandler::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(), sal_True);
+ pViewShell->GetFrameView()->SetSelectedPage(
+ (rpDescriptor->GetPage()->GetPageNum()-1)/2);
+ }
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView(
+ framework::FrameworkHelper::msImpressViewURL,
+ framework::FrameworkHelper::msCenterPaneURL);
+ }
+}
+
+
+
+
+void SelectionFunction::ModeHandler::StartDrag (
+ const Point& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode)
+{
+ (void)eMode;
+ // Do not start a drag-and-drop operation when one is already active.
+ // (when dragging pages from one document into another, pressing a
+ // modifier key can trigger a MouseMotion event in the originating
+ // window (focus still in there). Together with the mouse button pressed
+ // (drag-and-drop is active) this triggers the start of drag-and-drop.)
+ if (SD_MOD()->pTransferDrag != NULL)
+ return;
+
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
+ {
+ mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition);
+ }
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::IsMouseOverIndicatorAllowed (void) const
+{
+ return mbIsMouseOverIndicatorAllowed;
+}
+
+
+
+
+//===== NormalModeHandler =====================================================
+
+NormalModeHandler::NormalModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction)
+ : ModeHandler(rSlideSorter, rSelectionFunction, true),
+ maButtonDownLocation()
+{
+}
+
+
+
+
+NormalModeHandler::~NormalModeHandler (void)
+{
+}
+
+
+
+
+SelectionFunction::Mode NormalModeHandler::GetMode (void) const
+{
+ return SelectionFunction::NormalMode;
+}
+
+
+
+
+void NormalModeHandler::Abort (void)
+{
+}
+
+
+
+
+bool NormalModeHandler::ProcessButtonDownEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // Remember the location where the left button is pressed. With
+ // that we can filter away motion events that are caused by key
+ // presses. We also can tune the minimal motion distance that
+ // triggers a drag-and-drop operation.
+ if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0)
+ maButtonDownLocation = rDescriptor.maMousePosition;
+
+ switch (rDescriptor.mnEventCode)
+ {
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ 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(rDescriptor.mpHitDescriptor);
+ SwitchView(rDescriptor.mpHitDescriptor);
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER:
+ // Range selection with the shift modifier.
+ RangeSelect(rDescriptor.mpHitDescriptor);
+ break;
+
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
+ OSL_ASSERT(mrSlideSorter.GetView().GetButtonBar().IsMouseOverButton());
+
+ // Switch to button mode only when the buttons are visible
+ // (or being faded in.)
+ if (mrSlideSorter.GetView().GetButtonBar().IsVisible(rDescriptor.mpHitDescriptor))
+ {
+ if (mrSelectionFunction.SwitchToButtonMode())
+ ReprocessEvent(rDescriptor);
+ }
+ else
+ {
+ // When the buttons are not (yet) visible then behave like
+ // the left button had been clicked over any other part of
+ // the slide.
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ }
+ break;
+
+ // Right button for context menu.
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | 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.
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ rDescriptor.mbMakeSelectionVisible = false;
+ break;
+
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ // Do not change the selection. Just adjust the insertion indicator.
+ rDescriptor.mbMakeSelectionVisible = false;
+ break;
+
+ case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
+ // Remember the current selection so that when a multi selection
+ // is started, we can restore the previous selection.
+ mrSlideSorter.GetModel().SaveCurrentSelection();
+ DeselectAllPages();
+ break;
+
+ case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+ // Remember the current selection so that when a multi selection
+ // is started, we can restore the previous selection.
+ mrSlideSorter.GetModel().SaveCurrentSelection();
+ DeselectAllPages();
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+
+
+bool NormalModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ bool bIsProcessed (true);
+ switch (rDescriptor.mnEventCode)
+ {
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ break;
+
+ // Multi selection with the control modifier.
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER:
+ mrSlideSorter.GetController().GetPageSelector().DeselectPage(
+ rDescriptor.mpHitDescriptor);
+ break;
+
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER:
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(
+ rDescriptor.mpHitDescriptor);
+ mrSlideSorter.GetView().UpdatePageUnderMouse(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMousePosition,
+ false);
+ break;
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
+ break;
+
+ default:
+ bIsProcessed = false;
+ break;
+ }
+ mrSelectionFunction.SwitchToNormalMode();
+ return bIsProcessed;
+}
+
+
+
+
+
+bool NormalModeHandler::ProcessMotionEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if (ModeHandler::ProcessMotionEvent(rDescriptor))
+ return true;
+
+ bool bIsProcessed (true);
+ switch (rDescriptor.mnEventCode)
+ {
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE):
+ // SetCurrentPage(rDescriptor.mpHitDescriptor);
+ // Fallthrough
+
+ // A mouse motion without visible substitution starts that.
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE):
+ {
+ if (maButtonDownLocation)
+ {
+ const sal_Int32 nDistance (maButtonDownLocation
+ ? ::std::max (
+ abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()),
+ abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y()))
+ : 0);
+ if (nDistance > 3)
+ StartDrag(
+ rDescriptor.maMousePosition,
+ (rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0
+ ? InsertionIndicatorHandler::CopyMode
+ : InsertionIndicatorHandler::MoveMode);
+ }
+ }
+ break;
+
+ // A mouse motion not over a page starts a rectangle selection.
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+ mrSelectionFunction.SwitchToMultiSelectionMode(
+ rDescriptor.maMouseModelPosition,
+ rDescriptor.mnEventCode);
+ break;
+
+ default:
+ bIsProcessed = false;
+ break;
+ }
+ return bIsProcessed;
+}
+
+
+
+
+bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition);
+ ReprocessEvent(rDescriptor);
+ return true;
+}
+
+
+
+
+void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
+{
+ PageSelector::UpdateLock aLock (mrSlideSorter);
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+
+ model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor());
+ DeselectAllPages();
+
+ if (pAnchor.get() != NULL)
+ {
+ // Select all pages between the anchor and the given one, including
+ // the two.
+ const sal_uInt16 nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2);
+ const sal_uInt16 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.)
+ const sal_uInt16 nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1);
+ sal_uInt16 nIndex (nAnchorIndex);
+ while (true)
+ {
+ rSelector.SelectPage(nIndex);
+ if (nIndex == nOtherIndex)
+ break;
+ nIndex = nIndex + nStep;
+ }
+ }
+}
+
+
+
+
+void NormalModeHandler::ResetButtonDownLocation (void)
+{
+ maButtonDownLocation = ::boost::optional<Point>();
+}
+
+
+
+
+//===== MultiSelectionModeHandler =============================================
+
+MultiSelectionModeHandler::MultiSelectionModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMouseModelPosition,
+ const sal_uInt32 nEventCode)
+ : ModeHandler(rSlideSorter, rSelectionFunction, false),
+ meSelectionMode(SM_Normal),
+ maSecondCorner(rMouseModelPosition),
+ maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()),
+ mnAnchorIndex(-1),
+ mnSecondIndex(-1),
+ maButtonBarLock(rSlideSorter)
+{
+ const Pointer aSelectionPointer (POINTER_TEXT);
+ mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer);
+ SetSelectionModeFromModifier(nEventCode);
+}
+
+
+
+
+
+MultiSelectionModeHandler::~MultiSelectionModeHandler (void)
+{
+ mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer);
+}
+
+
+
+
+SelectionFunction::Mode MultiSelectionModeHandler::GetMode (void) const
+{
+ return SelectionFunction::MultiSelectionMode;
+}
+
+
+
+
+void MultiSelectionModeHandler::Abort (void)
+{
+ mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
+}
+
+
+
+
+void MultiSelectionModeHandler::ProcessEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // During a multi selection we do not want sudden jumps of the
+ // visible area caused by moving newly selected pages into view.
+ // Therefore disable that temporarily. The disabler object is
+ // released at the end of the event processing, after the focus and
+ // current slide have been updated.
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+
+ ModeHandler::ProcessEvent(rDescriptor);
+}
+
+
+
+
+bool MultiSelectionModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK))
+ {
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool MultiSelectionModeHandler::ProcessMotionEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // The selection rectangle is visible. Handle events accordingly.
+ if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK))
+ {
+ SetSelectionModeFromModifier(rDescriptor.mnEventCode);
+ UpdatePosition(rDescriptor.maMousePosition, true);
+ rDescriptor.mbMakeSelectionVisible = false;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+bool MultiSelectionModeHandler::HandleUnprocessedEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor))
+ {
+ // If the event has not been processed then stop multi selection.
+ mrSelectionFunction.SwitchToNormalMode();
+ ReprocessEvent(rDescriptor);
+ }
+ return true;
+}
+
+
+
+
+void MultiSelectionModeHandler::UpdatePosition (
+ const Point& rMousePosition,
+ const bool bAllowAutoScroll)
+{
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+
+ // Convert window coordinates into model coordinates (we need the
+ // window coordinates for auto-scrolling because that remains
+ // constant while scrolling.)
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
+
+ if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll(
+ rMousePosition,
+ ::boost::bind(
+ &MultiSelectionModeHandler::UpdatePosition,
+ this,
+ rMousePosition,
+ false))))
+ {
+ UpdateModelPosition(aMouseModelPosition);
+ }
+}
+
+
+
+
+void MultiSelectionModeHandler::SetSelectionModeFromModifier (
+ const sal_uInt32 nEventCode)
+{
+ switch (nEventCode & MODIFIER_MASK)
+ {
+ case NO_MODIFIER:
+ SetSelectionMode(SM_Normal);
+ break;
+
+ case SHIFT_MODIFIER:
+ SetSelectionMode(SM_Add);
+ break;
+
+ case CONTROL_MODIFIER:
+ SetSelectionMode(SM_Toggle);
+ break;
+ }
+}
+
+
+
+
+void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode)
+{
+ if (meSelectionMode != eSelectionMode)
+ {
+ meSelectionMode = eSelectionMode;
+ UpdateSelection();
+ }
+}
+
+
+
+
+void MultiSelectionModeHandler::UpdateSelectionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bIsInSelection) const
+{
+ // Determine whether the page was selected before the rectangle
+ // selection was started.
+ const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected));
+
+ // Combine the two selection states depending on the selection mode.
+ bool bSelect (false);
+ switch(meSelectionMode)
+ {
+ case SM_Normal:
+ bSelect = bIsInSelection;
+ break;
+
+ case SM_Add:
+ bSelect = bIsInSelection || bWasSelected;
+ break;
+
+ case SM_Toggle:
+ if (bIsInSelection)
+ bSelect = !bWasSelected;
+ else
+ bSelect = bWasSelected;
+ break;
+ }
+
+ // Set the new selection state.
+ if (bSelect)
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+ else
+ mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor);
+}
+
+
+
+
+void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition)
+{
+ maSecondCorner = rMouseModelPosition;
+ UpdateSelection();
+}
+
+
+
+
+void MultiSelectionModeHandler::UpdateSelection (void)
+{
+ view::SlideSorterView::DrawLock aLock (mrSlideSorter);
+
+ model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
+ const sal_Int32 nPageCount (rModel.GetPageCount());
+
+ const sal_Int32 nIndexUnderMouse (
+ mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint (
+ maSecondCorner,
+ false,
+ false));
+ if (nIndexUnderMouse>=0 && nIndexUnderMouse<nPageCount)
+ {
+ if (mnAnchorIndex < 0)
+ mnAnchorIndex = nIndexUnderMouse;
+ mnSecondIndex = nIndexUnderMouse;
+
+ Range aRange (mnAnchorIndex, mnSecondIndex);
+ aRange.Justify();
+
+ for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
+ {
+ UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.IsInside(nIndex));
+ }
+ }
+}
+
+
+
+
+//===== DragAndDropModeHandler ================================================
+
+DragAndDropModeHandler::DragAndDropModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMousePosition,
+ ::Window* pWindow)
+ : ModeHandler(rSlideSorter, rSelectionFunction, false)
+{
+ SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ if (pDragTransferable==NULL && mrSlideSorter.GetViewShell() != NULL)
+ {
+ SlideSorterViewShell* pSlideSorterViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pSlideSorterViewShell != NULL)
+ pSlideSorterViewShell->StartDrag(rMousePosition, pWindow);
+ pDragTransferable = SD_MOD()->pTransferDrag;
+ }
+
+ mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter));
+ mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start(
+ pDragTransferable != NULL
+ && pDragTransferable->GetView()==&mrSlideSorter.GetView());
+}
+
+
+
+
+DragAndDropModeHandler::~DragAndDropModeHandler (void)
+{
+ if (mpDragAndDropContext)
+ {
+ // Disconnect the substitution handler from this selection function.
+ mpDragAndDropContext->SetTargetSlideSorter();
+ mpDragAndDropContext.reset();
+ }
+ mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated);
+}
+
+
+
+
+SelectionFunction::Mode DragAndDropModeHandler::GetMode (void) const
+{
+ return SelectionFunction::DragAndDropMode;
+}
+
+
+
+
+void DragAndDropModeHandler::Abort (void)
+{
+ mrSlideSorter.GetController().GetClipboard().Abort();
+ if (mpDragAndDropContext)
+ mpDragAndDropContext->Dispose();
+ // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
+}
+
+
+
+
+bool DragAndDropModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON))
+ {
+ // The following Process() call may lead to the desctruction
+ // of rDescriptor.mpHitDescriptor so release our reference to it.
+ rDescriptor.mpHitDescriptor.reset();
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ OSL_ASSERT(mpDragAndDropContext);
+
+ if (rDescriptor.mbIsLeaving)
+ {
+ mrSelectionFunction.SwitchToNormalMode();
+ }
+ else if (mpDragAndDropContext)
+ {
+ mpDragAndDropContext->UpdatePosition(
+ rDescriptor.maMousePosition,
+ rDescriptor.meDragMode);
+ }
+
+ return true;
+}
+
+
+
+
+//===== ButtonModeHandler =====================================================
+
+ButtonModeHandler::ButtonModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction)
+ : ModeHandler(rSlideSorter, rSelectionFunction, true)
+{
+}
+
+
+
+
+ButtonModeHandler::~ButtonModeHandler (void)
+{
+}
+
+
+
+
+SelectionFunction::Mode ButtonModeHandler::GetMode (void) const
+{
+ return SelectionFunction::ButtonMode;
+}
+
+
+
+
+void ButtonModeHandler::Abort (void)
+{
+}
+
+
+
+
+bool ButtonModeHandler::ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode)
+ {
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
+ // Remember page and button index. When mouse button is
+ // released over same page and button then invoke action of that
+ // button.
+ mrSlideSorter.GetView().GetButtonBar().ProcessButtonDownEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
+
+
+bool ButtonModeHandler::ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode & BUTTON_MASK)
+ {
+ case LEFT_BUTTON:
+ mrSlideSorter.GetView().GetButtonBar().ProcessButtonUpEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition);
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+bool ButtonModeHandler::ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode & (MOUSE_MOTION | BUTTON_MASK))
+ {
+ case MOUSE_MOTION | LEFT_BUTTON:
+ mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition,
+ true);
+ return true;
+
+ case MOUSE_MOTION:
+ mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition,
+ false);
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+} } } // 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..2eff162d5f53
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx
@@ -0,0 +1,362 @@
+/* -*- 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 "SlsCommand.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "controller/SlsAnimationFunction.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsSelectionObserver.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.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 {
+
+
+class SelectionManager::PageInsertionListener
+ : public SfxListener
+{
+public:
+
+};
+
+
+SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mrController(rSlideSorter.GetController()),
+ maSelectionBeforeSwitch(),
+ mbIsMakeSelectionVisiblePending(true),
+ mnInsertionPosition(-1),
+ mnAnimationId(Animator::NotAnAnimationId),
+ maRequestedTopLeft(),
+ mpPageInsertionListener(),
+ mpSelectionObserver(new SelectionObserver(rSlideSorter))
+{
+}
+
+
+
+
+SelectionManager::~SelectionManager (void)
+{
+ if (mnAnimationId != Animator::NotAnAnimationId)
+ mrController.GetAnimator()->RemoveAnimation(mnAnimationId);
+}
+
+
+
+
+void SelectionManager::DeleteSelectedPages (const bool bSelectFollowingPage)
+{
+ // Create some locks to prevent updates of the model, view, selection
+ // state while modifying any of them.
+ SlideSorterController::ModelChangeLock aLock (mrController);
+ SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ PageSelector::UpdateLock aSelectionLock (mrSlideSorter);
+
+ // 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;
+ sal_Int32 nNewCurrentSlide (-1);
+ while (aPageEnumeration.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ aSelectedPages.push_back(pDescriptor->GetPage());
+ if (bSelectFollowingPage || nNewCurrentSlide<0)
+ nNewCurrentSlide = pDescriptor->GetPageIndex();
+ }
+ if (aSelectedPages.empty())
+ return;
+
+ // Determine the slide to select (and thereby make the current slide)
+ // after the deletion.
+ if (bSelectFollowingPage)
+ nNewCurrentSlide -= aSelectedPages.size() - 1;
+ else
+ --nNewCurrentSlide;
+
+ // 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();
+
+ // Set the new current slide.
+ if (nNewCurrentSlide < 0)
+ nNewCurrentSlide = 0;
+ else if (nNewCurrentSlide >= mrSlideSorter.GetModel().GetPageCount())
+ nNewCurrentSlide = mrSlideSorter.GetModel().GetPageCount()-1;
+ mrController.GetPageSelector().CountSelectedPages();
+ mrController.GetPageSelector().SelectPage(nNewCurrentSlide);
+ mrController.GetFocusManager().SetFocusedPage(nNewCurrentSlide);
+}
+
+
+
+
+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;
+
+ const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
+
+ Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
+ xPages->remove(xPage);
+ }
+ }
+ catch( Exception& )
+ {
+ OSL_FAIL("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;
+
+ const sal_uInt16 nPage (model::FromCoreIndex((*aI)->GetPageNum()));
+
+ Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
+ xPages->remove(xPage);
+ }
+ }
+ catch( Exception& )
+ {
+ OSL_FAIL("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
+ }
+}
+
+
+
+
+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;
+ }
+}
+
+
+
+
+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));
+}
+
+
+
+
+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 = model::FromCoreIndex(nPosition) + 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;
+}
+
+
+
+
+::boost::shared_ptr<SelectionObserver> SelectionManager::GetSelectionObserver (void) const
+{
+ return mpSelectionObserver;
+}
+
+} } } // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionObserver.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionObserver.cxx
new file mode 100644
index 000000000000..b40bd667131c
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionObserver.cxx
@@ -0,0 +1,173 @@
+/*************************************************************************
+ *
+ * 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 "controller/SlideSorterController.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsSelectionObserver.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include <svx/svdmodel.hxx>
+#include "drawdoc.hxx"
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+SelectionObserver::Context::Context (SlideSorter& rSlideSorter)
+ : mpSelectionObserver(
+ rSlideSorter.GetController().GetSelectionManager()->GetSelectionObserver())
+{
+ if (mpSelectionObserver)
+ mpSelectionObserver->StartObservation();
+}
+
+
+
+
+SelectionObserver::Context::~Context(void)
+{
+ if (mpSelectionObserver)
+ mpSelectionObserver->EndObservation();
+}
+
+
+
+
+void SelectionObserver::Context::Abort(void)
+{
+ if (mpSelectionObserver)
+ {
+ mpSelectionObserver->AbortObservation();
+ mpSelectionObserver.reset();
+ }
+}
+
+
+
+
+//===== SelectionObserver =====================================================
+
+SelectionObserver::SelectionObserver (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mpDocument(mrSlideSorter.GetModel().GetDocument()),
+ mbIsOvservationActive(false),
+ maInsertedPages(),
+ maDeletedPages()
+{
+}
+
+
+
+
+SelectionObserver::~SelectionObserver (void)
+{
+}
+
+
+
+
+void SelectionObserver::NotifyPageEvent (const SdrPage* pSdrPage)
+{
+ if ( ! mbIsOvservationActive)
+ return;
+
+ const SdPage* pPage = dynamic_cast<const SdPage*>(pSdrPage);
+ if (pPage == NULL)
+ return;
+
+ if (pPage->IsInserted())
+ maInsertedPages.push_back(pPage);
+ else
+ {
+ ::std::vector<const SdPage*>::iterator iPage(
+ ::std::find(maInsertedPages.begin(), maInsertedPages.end(), pPage));
+ if (iPage != maInsertedPages.end())
+ maInsertedPages.erase(iPage);
+
+ maDeletedPages.push_back(pPage->GetPageNum());
+ }
+}
+
+
+
+void SelectionObserver::StartObservation (void)
+{
+ OSL_ASSERT(!mbIsOvservationActive);
+ maInsertedPages.clear();
+ maDeletedPages.clear();
+ mbIsOvservationActive = true;
+}
+
+
+
+
+void SelectionObserver::AbortObservation (void)
+{
+ OSL_ASSERT(mbIsOvservationActive);
+ mbIsOvservationActive = false;
+ maInsertedPages.clear();
+ maDeletedPages.clear();
+}
+
+
+
+
+void SelectionObserver::EndObservation (void)
+{
+ OSL_ASSERT(mbIsOvservationActive);
+ mbIsOvservationActive = false;
+
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+ rSelector.DeselectAllPages();
+ if ( ! maInsertedPages.empty())
+ {
+ // Select the inserted pages.
+ for (::std::vector<const SdPage*>::const_iterator
+ iPage(maInsertedPages.begin()),
+ iEnd(maInsertedPages.end());
+ iPage!=iEnd;
+ ++iPage)
+ {
+ rSelector.SelectPage(*iPage);
+ }
+ maInsertedPages.clear();
+ }
+ maDeletedPages.clear();
+
+ aUpdateLock.Release();
+ mrSlideSorter.GetController().GetFocusManager().SetFocusedPageToCurrentPage();
+
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
diff --git a/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx
new file mode 100644
index 000000000000..d34fcbd4992a
--- /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.GetContentWindow().get(),
+ &rSlideSorter.GetView(),
+ rSlideSorter.GetModel().GetDocument(),
+ rRequest)
+{
+}
+
+void SlideFunction::ScrollStart (void)
+{
+}
+
+void SlideFunction::ScrollEnd (void)
+{
+}
+
+sal_Bool SlideFunction::MouseMove(const MouseEvent& )
+{
+ return sal_False;
+}
+
+sal_Bool SlideFunction::MouseButtonUp(const MouseEvent& )
+{
+ return sal_False;
+
+}
+
+sal_Bool SlideFunction::MouseButtonDown(const MouseEvent& )
+{
+ return sal_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..ad756c9727ae
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx
@@ -0,0 +1,1345 @@
+/* -*- 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 <editeng/outlobj.hxx>
+
+#include "controller/SlsSlotManager.hxx"
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsClipboard.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsInsertionIndicatorHandler.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsSelectionManager.hxx"
+#include "controller/SlsSelectionObserver.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 "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>
+
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::presentation;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+namespace {
+
+/** The state of a set of slides with respect to being excluded from the
+ slide show.
+*/
+enum SlideExclusionState {UNDEFINED, EXCLUDED, INCLUDED, MIXED};
+
+/** Return for the given set of slides whether they included are
+ excluded from the slide show.
+*/
+SlideExclusionState GetSlideExclusionState (model::PageEnumeration& rPageSet);
+
+} // end of anonymous namespace
+
+
+
+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:
+ ChangeSlideExclusionState(model::SharedPageDescriptor(), true);
+ break;
+
+ case SID_SHOW_SLIDE:
+ ChangeSlideExclusionState(model::SharedPageDescriptor(), false);
+ break;
+
+ case SID_PAGES_PER_ROW:
+ if (rRequest.GetArgs() != NULL)
+ {
+ SFX_REQUEST_ARG(rRequest, pPagesPerRow, SfxUInt16Item,
+ SID_PAGES_PER_ROW, sal_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.GetContentWindow().get(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_CUSTOMSHOW_DLG:
+ FuCustomShowDlg::Create (
+ pShell,
+ mrSlideSorter.GetContentWindow().get(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_EXPAND_PAGE:
+ FuExpandPage::Create (
+ pShell,
+ mrSlideSorter.GetContentWindow().get(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_SUMMARY_PAGE:
+ FuSummaryPage::Create (
+ pShell,
+ mrSlideSorter.GetContentWindow().get(),
+ &mrSlideSorter.GetView(),
+ pDocument,
+ rRequest);
+ break;
+
+ case SID_INSERTPAGE:
+ case SID_INSERT_MASTER_PAGE:
+ InsertSlide(rRequest);
+ rRequest.Done();
+ break;
+
+ case SID_DUPLICATE_PAGE:
+ DuplicateSelectedSlides(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)
+ {
+ view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ SlideSorterController::ModelChangeLock aModelLock (mrSlideSorter.GetController());
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+ SelectionObserver::Context aContext (mrSlideSorter);
+ pViewShell->ImpSidUndo (sal_False, rRequest);
+ }
+ break;
+ }
+
+ case SID_REDO:
+ {
+ SlideSorterViewShell* pViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pViewShell != NULL)
+ {
+ view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ SlideSorterController::ModelChangeLock aModelLock (mrSlideSorter.GetController());
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+ SelectionObserver::Context aContext (mrSlideSorter);
+ pViewShell->ImpSidRedo (sal_False, rRequest);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+
+
+
+void SlotManager::ExecCtrl (SfxRequest& rRequest)
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ sal_uInt16 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);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while (nWhich)
+ {
+ sal_uInt16 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,
+ (sal_uInt16)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())
+ {
+ sal_uInt16 nSId = pShell->GetCurrentFunction()->GetSlotID();
+
+ rSet.Put( SfxBoolItem( nSId, sal_True ) );
+ }
+ rSet.Put( SfxBoolItem( SID_DRAWINGMODE, sal_False ) );
+ rSet.Put( SfxBoolItem( SID_DIAMODE, sal_True ) );
+ rSet.Put( SfxBoolItem( SID_OUTLINEMODE, sal_False ) );
+ rSet.Put( SfxBoolItem( SID_NOTESMODE, sal_False ) );
+ rSet.Put( SfxBoolItem( SID_HANDOUTMODE, sal_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 )
+ {
+ if( !pObj->IsEmptyPresObj() )
+ {
+ bDisable = false;
+ }
+ else
+ {
+ // check if the object is in edit, than its temporarely not empty
+ SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj );
+ if( pTextObj )
+ {
+ OutlinerParaObject* pParaObj = pTextObj->GetEditOutlinerParaObject();
+ if( pParaObj )
+ {
+ delete pParaObj;
+ 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 ) )
+ {
+ sal_Bool bDisable = sal_True;
+ model::PageEnumeration aAllPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter.GetModel()));
+ while (aAllPages.HasMoreElements())
+ {
+ SdPage* pPage = aAllPages.GetNextElement()->GetPage();
+
+ if( !pPage->IsExcluded() )
+ bDisable = sal_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()));
+ const SlideExclusionState eState (GetSlideExclusionState(aSelectedPages));
+ switch (eState)
+ {
+ case MIXED:
+ // Show both entries.
+ break;
+
+ case EXCLUDED:
+ rSet.DisableItem(SID_HIDE_SLIDE);
+ break;
+
+ case INCLUDED:
+ rSet.DisableItem(SID_SHOW_SLIDE);
+ break;
+
+ case 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);
+ }
+
+ // Disable some slots when in master page mode.
+ if (eEditMode == EM_MASTERPAGE)
+ {
+ if (rSet.GetItemState(SID_INSERTPAGE) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_INSERTPAGE);
+ if (rSet.GetItemState(SID_DUPLICATE_PAGE) == SFX_ITEM_AVAILABLE)
+ rSet.DisableItem(SID_DUPLICATE_PAGE);
+ }
+}
+
+
+
+
+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;
+ sal_uInt16 nFirstPage;
+ sal_uInt16 nSelectedPages = (sal_uInt16)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()));
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ if (pDescriptor)
+ {
+ pPage = pDescriptor->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.GetContentWindow().get(),
+ 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( sal_uInt16 nPageId, const String & rName )
+{
+ sal_Bool bOutDummy;
+ SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
+ if( pDocument->GetPageByName( rName, bOutDummy ) != SDRPAGE_NOTFOUND )
+ return false;
+
+ SdPage* pPageToRename = NULL;
+ PageKind ePageKind = mrSlideSorter.GetModel().GetPageType();
+
+ ::svl::IUndoManager* 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();
+ sal_uInt8 nBackground = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRND )), sal_False );
+ sal_uInt8 nBgObj = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRNDOBJ )), sal_False );
+ SetOfByte aVisibleLayers = pPageToRename->TRG_GetMasterPageVisibleLayers();
+
+ // (#67720#)
+ ModifyPageUndoAction* pAction = new ModifyPageUndoAction(
+ 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 && ( sal_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( sal_True );
+
+ // inform navigator about change
+ SfxBoolItem aItem( SID_NAVIGATOR_INIT, sal_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)
+{
+ const sal_Int32 nInsertionIndex (GetInsertionPosition());
+
+ PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
+
+ SdPage* pNewPage = NULL;
+ if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
+ {
+ SlideSorterViewShell* pShell = dynamic_cast<SlideSorterViewShell*>(
+ mrSlideSorter.GetViewShell());
+ if (pShell != NULL)
+ {
+ pNewPage = pShell->CreateOrDuplicatePage (
+ rRequest,
+ mrSlideSorter.GetModel().GetPageType(),
+ nInsertionIndex>=0
+ ? mrSlideSorter.GetModel().GetPageDescriptor(nInsertionIndex)->GetPage()
+ : NULL);
+ }
+ }
+ 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.
+ pNewPage = pDocument->GetMasterSdPage(
+ (sal_uInt16)(nInsertionIndex+1), PK_STANDARD);
+ pNewPage->CreateTitleAndLayout (sal_True,sal_True);
+ }
+ }
+ }
+ if (pNewPage == NULL)
+ return;
+
+ // When a new page has been inserted then select it, make it the
+ // current page, and focus it.
+ view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(pNewPage);
+}
+
+
+
+
+void SlotManager::DuplicateSelectedSlides (SfxRequest& rRequest)
+{
+ // Create a list of the pages that are to be duplicated. The process of
+ // duplication alters the selection.
+ sal_Int32 nInsertPosition (0);
+ ::std::vector<SdPage*> aPagesToDuplicate;
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ if (pDescriptor && pDescriptor->GetPage())
+ {
+ aPagesToDuplicate.push_back(pDescriptor->GetPage());
+ nInsertPosition = pDescriptor->GetPage()->GetPageNum()+2;
+ }
+ }
+
+ // Duplicate the pages in aPagesToDuplicate and collect the newly
+ // created pages in aPagesToSelect.
+ const bool bUndo (aPagesToDuplicate.size()>1 && mrSlideSorter.GetView().IsUndoEnabled());
+ if (bUndo)
+ mrSlideSorter.GetView().BegUndo(String(SdResId(STR_INSERTPAGE)));
+
+ ::std::vector<SdPage*> aPagesToSelect;
+ for(::std::vector<SdPage*>::const_iterator
+ iPage(aPagesToDuplicate.begin()),
+ iEnd(aPagesToDuplicate.end());
+ iPage!=iEnd;
+ ++iPage, nInsertPosition+=2)
+ {
+ aPagesToSelect.push_back(
+ mrSlideSorter.GetViewShell()->CreateOrDuplicatePage(
+ rRequest, PK_STANDARD, *iPage, nInsertPosition));
+ }
+ aPagesToDuplicate.clear();
+
+ if (bUndo)
+ mrSlideSorter.GetView().EndUndo();
+
+ // Set the selection to the pages in aPagesToSelect.
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+ rSelector.DeselectAllPages();
+ ::std::for_each (
+ aPagesToSelect.begin(),
+ aPagesToSelect.end(),
+ ::boost::bind(
+ static_cast<void (PageSelector::*)(const SdPage*)>(&PageSelector::SelectPage),
+ rSelector,
+ _1));
+}
+
+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;
+}
+
+
+
+
+void SlotManager::ChangeSlideExclusionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bExcludeSlide)
+{
+ if (rpDescriptor)
+ {
+ mrSlideSorter.GetView().SetState(
+ rpDescriptor,
+ model::PageDescriptor::ST_Excluded,
+ bExcludeSlide);
+ }
+ else
+ {
+ model::PageEnumeration aSelectedPages (
+ model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aSelectedPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ mrSlideSorter.GetView().SetState(
+ pDescriptor,
+ model::PageDescriptor::ST_Excluded,
+ bExcludeSlide);
+ }
+ }
+
+ SfxBindings& rBindings (mrSlideSorter.GetViewShell()->GetViewFrame()->GetBindings());
+ rBindings.Invalidate(SID_PRESENTATION);
+ rBindings.Invalidate(SID_REHEARSE_TIMINGS);
+ rBindings.Invalidate(SID_HIDE_SLIDE);
+ rBindings.Invalidate(SID_SHOW_SLIDE);
+ mrSlideSorter.GetModel().GetDocument()->SetChanged();
+}
+
+
+
+
+sal_Int32 SlotManager::GetInsertionPosition (void)
+{
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+
+ // The insertion indicator is preferred. After all the user explicitly
+ // used it to define the insertion position.
+ if (mrSlideSorter.GetController().GetInsertionIndicatorHandler()->IsActive())
+ {
+ // Select the page before the insertion indicator.
+ return mrSlideSorter.GetController().GetInsertionIndicatorHandler()->GetInsertionPageIndex()
+ - 1;
+ }
+
+ // Is there a stored insertion position?
+ else if (mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() >= 0)
+ {
+ return mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() - 1;
+ }
+
+ // Use the index of the last selected slide.
+ else if (rSelector.GetSelectedPageCount() > 0)
+ {
+ for (int nIndex=rSelector.GetPageCount()-1; nIndex>=0; --nIndex)
+ if (rSelector.IsPageSelected(nIndex))
+ return nIndex;
+
+ // We should never get here.
+ OSL_ASSERT(false);
+ return rSelector.GetPageCount() - 1;
+ }
+
+ // Select the last page when there is at least one page.
+ else if (rSelector.GetPageCount() > 0)
+ {
+ return rSelector.GetPageCount() - 1;
+ }
+
+ // Hope for the best that CreateOrDuplicatePage() can cope with an empty
+ // selection.
+ else
+ {
+ // We should never get here because there has to be at least one page.
+ OSL_ASSERT(false);
+ return -1;
+ }
+}
+
+
+
+
+void SlotManager::NotifyEditModeChange (void)
+{
+ SfxBindings& rBindings (mrSlideSorter.GetViewShell()->GetViewFrame()->GetBindings());
+ rBindings.Invalidate(SID_PRESENTATION);
+ rBindings.Invalidate(SID_INSERTPAGE);
+ rBindings.Invalidate(SID_DUPLICATE_PAGE);
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+
+namespace {
+
+
+
+SlideExclusionState GetSlideExclusionState (model::PageEnumeration& rPageSet)
+{
+ SlideExclusionState eState (UNDEFINED);
+ sal_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 anonymous namespace
+
+} } } // 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..aa94aad2c56a
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx
@@ -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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sd.hxx"
+
+#include "controller/SlsTransferable.hxx"
+
+#include "SlideSorterViewShell.hxx"
+#include "View.hxx"
+
+namespace sd { namespace slidesorter { namespace controller {
+
+Transferable::Transferable (
+ SdDrawDocument* pSrcDoc,
+ ::sd::View* pWorkView,
+ sal_Bool bInitOnGetData,
+ SlideSorterViewShell* pViewShell,
+ const ::std::vector<Representative>& rRepresentatives)
+ : SdTransferable (pSrcDoc, pWorkView, bInitOnGetData),
+ mpViewShell(pViewShell),
+ maRepresentatives(rRepresentatives)
+{
+ 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);
+}
+
+
+
+
+const ::std::vector<Transferable::Representative>& Transferable::GetRepresentatives (void) const
+{
+ return maRepresentatives;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/controller/SlsVisibleAreaManager.cxx b/sd/source/ui/slidesorter/controller/SlsVisibleAreaManager.cxx
new file mode 100644
index 000000000000..76e9e411e81e
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlsVisibleAreaManager.cxx
@@ -0,0 +1,305 @@
+/*************************************************************************
+ *
+ * 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/SlsVisibleAreaManager.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsAnimationFunction.hxx"
+#include "controller/SlsScrollBarManager.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+namespace {
+ class VisibleAreaScroller
+ {
+ public:
+ VisibleAreaScroller (
+ SlideSorter& rSlideSorter,
+ const Point aStart,
+ const Point aEnd);
+ void operator() (const double nValue);
+ private:
+ SlideSorter& mrSlideSorter;
+ Point maStart;
+ const Point maEnd;
+ const ::boost::function<double(double)> maAccelerationFunction;
+ };
+
+} // end of anonymous namespace
+
+
+
+VisibleAreaManager::VisibleAreaManager (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maVisibleRequests(),
+ mnScrollAnimationId(Animator::NotAnAnimationId),
+ maRequestedVisibleTopLeft(),
+ meRequestedAnimationMode(Animator::AM_Immediate),
+ mbIsCurrentSlideTrackingActive(true),
+ mnDisableCount(0)
+{
+}
+
+
+
+
+VisibleAreaManager::~VisibleAreaManager (void)
+{
+}
+
+
+
+
+void VisibleAreaManager::ActivateCurrentSlideTracking (void)
+{
+ mbIsCurrentSlideTrackingActive = true;
+}
+
+
+
+
+void VisibleAreaManager::DeactivateCurrentSlideTracking (void)
+{
+ mbIsCurrentSlideTrackingActive = false;
+}
+
+
+
+
+void VisibleAreaManager::RequestVisible (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bForce)
+{
+ if (rpDescriptor)
+ {
+ if (mnDisableCount == 0)
+ {
+ maVisibleRequests.push_back(
+ mrSlideSorter.GetView().GetLayouter().GetPageObjectBox(
+ rpDescriptor->GetPageIndex(),
+ true));
+ }
+ if (bForce && ! mbIsCurrentSlideTrackingActive)
+ ActivateCurrentSlideTracking();
+ MakeVisible();
+ }
+}
+
+
+
+
+void VisibleAreaManager::RequestCurrentSlideVisible (void)
+{
+ if (mbIsCurrentSlideTrackingActive && mnDisableCount==0)
+ RequestVisible(
+ mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
+}
+
+
+
+
+void VisibleAreaManager::MakeVisible (void)
+{
+ if (maVisibleRequests.empty())
+ return;
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if ( ! pWindow)
+ return;
+ const Point aCurrentTopLeft (pWindow->PixelToLogic(Point(0,0)));
+
+ const ::boost::optional<Point> aNewVisibleTopLeft (GetRequestedTopLeft());
+ maVisibleRequests.clear();
+ if ( ! aNewVisibleTopLeft)
+ return;
+
+ // We now know what the visible area shall be. Scroll accordingly
+ // unless that is not already the visible area or a running scroll
+ // animation has it as its target area.
+ if (mnScrollAnimationId!=Animator::NotAnAnimationId
+ && maRequestedVisibleTopLeft==aNewVisibleTopLeft)
+ return;
+
+ // Stop a running animation.
+ if (mnScrollAnimationId != Animator::NotAnAnimationId)
+ mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(mnScrollAnimationId);
+
+ maRequestedVisibleTopLeft = aNewVisibleTopLeft.get();
+ VisibleAreaScroller aAnimation(
+ mrSlideSorter,
+ aCurrentTopLeft,
+ maRequestedVisibleTopLeft);
+ if (meRequestedAnimationMode==Animator::AM_Animated
+ && mrSlideSorter.GetProperties()->IsSmoothSelectionScrolling())
+ {
+ mnScrollAnimationId = mrSlideSorter.GetController().GetAnimator()->AddAnimation(
+ aAnimation,
+ 0,
+ 300);
+ }
+ else
+ {
+ // Execute the animation at its final value.
+ aAnimation(1.0);
+ }
+ meRequestedAnimationMode = Animator::AM_Immediate;
+}
+
+
+
+
+::boost::optional<Point> VisibleAreaManager::GetRequestedTopLeft (void) const
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if ( ! pWindow)
+ return ::boost::optional<Point>();
+
+ // Get the currently visible area and the model area.
+ const Rectangle aVisibleArea (pWindow->PixelToLogic(
+ Rectangle(
+ Point(0,0),
+ pWindow->GetOutputSizePixel())));
+ const Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
+
+ sal_Int32 nVisibleTop (aVisibleArea.Top());
+ const sal_Int32 nVisibleWidth (aVisibleArea.GetWidth());
+ sal_Int32 nVisibleLeft (aVisibleArea.Left());
+ const sal_Int32 nVisibleHeight (aVisibleArea.GetHeight());
+
+ // Find the longest run of boxes whose union fits into the visible area.
+ Rectangle aBoundingBox;
+ for (::std::vector<Rectangle>::const_iterator
+ iBox(maVisibleRequests.begin()),
+ iEnd(maVisibleRequests.end());
+ iBox!=iEnd;
+ ++iBox)
+ {
+ if (nVisibleTop+nVisibleHeight <= iBox->Bottom())
+ nVisibleTop = iBox->Bottom()-nVisibleHeight;
+ if (nVisibleTop > iBox->Top())
+ nVisibleTop = iBox->Top();
+
+ if (nVisibleLeft+nVisibleWidth <= iBox->Right())
+ nVisibleLeft = iBox->Right()-nVisibleWidth;
+ if (nVisibleLeft > iBox->Left())
+ nVisibleLeft = iBox->Left();
+
+ // Make sure the visible area does not move outside the model area.
+ if (nVisibleTop + nVisibleHeight > aModelArea.Bottom())
+ nVisibleTop = aModelArea.Bottom() - nVisibleHeight;
+ if (nVisibleTop < aModelArea.Top())
+ nVisibleTop = aModelArea.Top();
+
+ if (nVisibleLeft + nVisibleWidth > aModelArea.Right())
+ nVisibleLeft = aModelArea.Right() - nVisibleWidth;
+ if (nVisibleLeft < aModelArea.Left())
+ nVisibleLeft = aModelArea.Left();
+ }
+
+ const Point aRequestedTopLeft (nVisibleLeft, nVisibleTop);
+ if (aRequestedTopLeft == aVisibleArea.TopLeft())
+ return ::boost::optional<Point>();
+ else
+ return ::boost::optional<Point>(aRequestedTopLeft);
+}
+
+
+
+
+//===== VisibleAreaManager::TemporaryDisabler =================================
+
+VisibleAreaManager::TemporaryDisabler::TemporaryDisabler (SlideSorter& rSlideSorter)
+ : mrVisibleAreaManager(rSlideSorter.GetController().GetVisibleAreaManager())
+{
+ ++mrVisibleAreaManager.mnDisableCount;
+}
+
+
+
+
+VisibleAreaManager::TemporaryDisabler::~TemporaryDisabler (void)
+{
+ --mrVisibleAreaManager.mnDisableCount;
+}
+
+
+
+//===== VerticalVisibleAreaScroller ===========================================
+
+namespace {
+
+const static sal_Int32 gnMaxScrollDistance = 300;
+
+VisibleAreaScroller::VisibleAreaScroller (
+ SlideSorter& rSlideSorter,
+ const Point aStart,
+ const Point aEnd)
+ : mrSlideSorter(rSlideSorter),
+ maStart(aStart),
+ maEnd(aEnd),
+ maAccelerationFunction(
+ controller::AnimationParametricFunction(
+ controller::AnimationBezierFunction (0.1,0.6)))
+{
+ // When the distance to scroll is larger than a threshold then first
+ // jump to within this distance of the final value and start the
+ // animation from there.
+ if (abs(aStart.X()-aEnd.X()) > gnMaxScrollDistance)
+ {
+ if (aStart.X() < aEnd.X())
+ maStart.X() = aEnd.X()-gnMaxScrollDistance;
+ else
+ maStart.X() = aEnd.X()+gnMaxScrollDistance;
+ }
+ if (abs(aStart.Y()-aEnd.Y()) > gnMaxScrollDistance)
+ {
+ if (aStart.Y() < aEnd.Y())
+ maStart.Y() = aEnd.Y()-gnMaxScrollDistance;
+ else
+ maStart.Y() = aEnd.Y()+gnMaxScrollDistance;
+ }
+}
+
+
+
+
+void VisibleAreaScroller::operator() (const double nTime)
+{
+ const double nLocalTime (maAccelerationFunction(nTime));
+ mrSlideSorter.GetController().GetScrollBarManager().SetTopLeft(
+ Point(
+ sal_Int32(0.5 + maStart.X() * (1.0 - nLocalTime) + maEnd.X() * nLocalTime),
+ sal_Int32 (0.5 + maStart.Y() * (1.0 - nLocalTime) + maEnd.Y() * nLocalTime)));
+}
+
+} // end of anonymous namespace
+
+} } } // end of namespace ::sd::slidesorter::controller
diff --git a/sd/source/ui/slidesorter/controller/makefile.mk b/sd/source/ui/slidesorter/controller/makefile.mk
new file mode 100755
index 000000000000..460ef16ed3f1
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/makefile.mk
@@ -0,0 +1,69 @@
+#*************************************************************************
+#
+# 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)$/SlsAnimationFunction.obj \
+ $(SLO)$/SlsClipboard.obj \
+ $(SLO)$/SlsCurrentSlideManager.obj \
+ $(SLO)$/SlsDragAndDropContext.obj \
+ $(SLO)$/SlsFocusManager.obj \
+ $(SLO)$/SlsInsertionIndicatorHandler.obj\
+ $(SLO)$/SlsListener.obj \
+ $(SLO)$/SlsPageSelector.obj \
+ $(SLO)$/SlsProperties.obj \
+ $(SLO)$/SlsScrollBarManager.obj \
+ $(SLO)$/SlsSelectionCommand.obj \
+ $(SLO)$/SlsSelectionFunction.obj \
+ $(SLO)$/SlsSelectionManager.obj \
+ $(SLO)$/SlsSelectionObserver.obj \
+ $(SLO)$/SlsSlotManager.obj \
+ $(SLO)$/SlsTransferable.obj \
+ $(SLO)$/SlsVisibleAreaManager.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..aaf99ad19886
--- /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 SdrPage;
+class Bitmap;
+
+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 Bitmap& 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..026235861e66
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx
@@ -0,0 +1,182 @@
+/* -*- 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 <tools/gen.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <vcl/bitmap.hxx>
+
+
+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 bool bDoSuperSampling,
+ const SharedCacheContext& rpCacheContext);
+
+ ~PageCache (void);
+
+ void ChangeSize(
+ const Size& rPreviewSize,
+ const bool bDoSuperSampling);
+
+ /** 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 in the right
+ size 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 bResize
+ When <TRUE/> then when the available bitmap has not the
+ requested size, it is scaled before it is returned. When
+ <FALSE/> then the bitmap is returned in the wrong size and it is
+ the task of the caller to scale it.
+ @return
+ Returns a bitmap that is either empty, contains a scaled (up or
+ down) version or is the requested bitmap.
+ */
+ Bitmap GetPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize);
+
+ Bitmap GetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const bool bResize);
+ void SetMarkedPreviewBitmap (
+ const CacheKey aKey,
+ const Bitmap& rBitmap);
+
+ /** 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.
+ */
+ void RequestPreviewBitmap (const CacheKey aKey);
+
+ /** Tell the cache that the bitmap associated with the given request
+ data is not up-to-date anymore. This will invalidate all previews
+ in other caches that represent the same page as well.
+ @param bRequestPreview
+ When <TRUE/> then a new preview is requested and will lead
+ eventually to a repaint of the associated page object.
+ */
+ void InvalidatePreviewBitmap (
+ const CacheKey aKey,
+ const bool bRequestPreview);
+
+ /** 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 (const 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 (const 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 (const CacheKey aKey, const 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..0e9407b6db75
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx
@@ -0,0 +1,191 @@
+/* -*- 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.
+ */
+ bool InvalidatePreviewBitmap (
+ DocumentKey pDocument,
+ const SdrPage* pPage);
+
+ /** Invalidate the preview bitmaps for all slides that belong to the
+ specified document. This is necessary after model changes that
+ affect e.g. page number fiels.
+ */
+ void InvalidateAllPreviewBitmaps (DocumentKey pDocument);
+
+ /** 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);
+
+ /** Call this method when a page has been deleted and its preview
+ is not needed anymore.
+ */
+ void ReleasePreviewBitmap (const SdrPage* pPage);
+
+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..4e7628450ca3
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
@@ -0,0 +1,346 @@
+/* -*- 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 <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 InsertionIndicatorHandler;
+class Listener;
+class PageSelector;
+class ScrollBarManager;
+class SelectionFunction;
+class SelectionManager;
+class SelectionObserver;
+class SlotManager;
+class VisibleAreaManager;
+
+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);
+
+ void Dispose (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. This takes the IsOnlyPreviewTriggersMouseOver
+ property into account.
+ @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;
+ ::boost::shared_ptr<InsertionIndicatorHandler> GetInsertionIndicatorHandler (void) const;
+
+ /** 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);
+
+ /** When the current function of the view shell is the slide sorter
+ selection function then return a reference to it. Otherwise return
+ an empty reference.
+ */
+ ::rtl::Reference<SelectionFunction> GetCurrentSelectionFunction (void);
+
+ /** 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;
+
+ /** 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;
+
+ VisibleAreaManager& GetVisibleAreaManager (void) const;
+
+ void CheckForMasterPageAssignment (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SlideSorterModel& mrModel;
+ view::SlideSorterView& mrView;
+ ::boost::scoped_ptr<PageSelector> mpPageSelector;
+ ::boost::scoped_ptr<FocusManager> mpFocusManager;
+ ::boost::shared_ptr<SlotManager> mpSlotManager;
+ ::boost::scoped_ptr<controller::Clipboard> mpClipboard;
+ ::boost::scoped_ptr<ScrollBarManager> mpScrollBarManager;
+ mutable ::boost::shared_ptr<CurrentSlideManager> mpCurrentSlideManager;
+ ::boost::shared_ptr<SelectionManager> mpSelectionManager;
+ ::boost::shared_ptr<InsertionIndicatorHandler> mpInsertionIndicatorHandler;
+ ::boost::shared_ptr<Animator> mpAnimator;
+ ::boost::scoped_ptr<VisibleAreaManager> mpVisibleAreaManager;
+
+ // 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 mbIsForcedRearrangePending;
+
+ 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;
+
+ /** 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/SlsAnimationFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx
new file mode 100644
index 000000000000..38d0b2b22749
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx
@@ -0,0 +1,180 @@
+/*************************************************************************
+ *
+ * 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_ANIMATION_FUNCTION_HXX
+#define SD_SLIDESORTER_CONTROLLER_ANIMATION_FUNCTION_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <basegfx/point/b2dpoint.hxx>
+#include <boost/noncopyable.hpp>
+#include <boost/function.hpp>
+#include <tools/gen.hxx>
+#include <vector>
+
+namespace sd { namespace slidesorter { namespace view {
+class SlideSorterView;
+} } }
+
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** A collection of functions that are usefull when creating animations.
+ They are collected here until a better place is found.
+*/
+class AnimationFunction
+ : private ::boost::noncopyable
+{
+public:
+ /** Acceleration function that maps [0,1] to [0,1] linearly, ie it
+ returns the given time value unaltered.
+ */
+ static double Linear (const double nTime);
+
+ /** Acceleration function that maps [0,1] to [0,1]. Speed starts fast
+ and ends slow following the sine function.
+ */
+ static double FastInSlowOut_Sine (const double nTime);
+
+ /** Acceleration function that maps [0,1] to [0,1]. Speed starts fast
+ and ends slow following the square root function.
+ */
+ static double FastInSlowOut_Root (const double nTime);
+
+ /** Acceleration function that maps [0,1] to [0,0]. Speed starts slow,
+ rises, drops and ends slow following the sine function.
+ */
+ static double SlowInSlowOut_0to0_Sine (const double nTime);
+
+ /** Acceleration function that maps [0,1] to [0,0]. Speed starts slow,
+ rises and drops several times and ends slow following multiple
+ cycles of the the sine function.
+ */
+ static double Vibrate_Sine (const double nTime);
+
+ /** Scale point linearly.
+ */
+ static Point ScalePoint (const Point& rPoint, const double nTime);
+
+ /** Blend two points together according to the given weight.
+ */
+ static double Blend (const double nStartValue, const double nEndValue, const double nWeight);
+
+ /** Apply a gradual visual state change. The kind of change, i.e. the
+ previous and the new states are expected to be already set. This
+ method only adjusts the blending of the visual representation from
+ one state to the other.
+ */
+ static void ApplyVisualStateChange (
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const double nTime);
+
+ /** Apply a gradual change of a previously set offset to the location of
+ a page object.
+ */
+ static void ApplyLocationOffsetChange (
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const Point aLocationOffset);
+
+ /** Apply a gradual change the alpha value from the old value to a
+ new value (set prior to this call.)
+ */
+ static void ApplyButtonAlphaChange(
+ const model::SharedPageDescriptor& rpDescriptor,
+ view::SlideSorterView& rView,
+ const double nButtonAlpha,
+ const double nButtonBarAlpha);
+};
+
+
+
+
+class AnimationBezierFunction
+{
+public:
+ /** Create a cubic bezier curve whose start and end points are given
+ implicitly as P0=(0,0) and P3=(1,1).
+ */
+ AnimationBezierFunction (
+ const double nX1,
+ const double nY1,
+ const double nX2,
+ const double nY2);
+
+ /** Create a cubic bezier curve whose start and end points are given
+ implicitly as P0=(0,0) and P3=(1,1). The second control point is
+ implicitly given as P2=(1-nY1,1-nX1).
+ */
+ AnimationBezierFunction (
+ const double nX1,
+ const double nY1);
+
+ ::basegfx::B2DPoint operator() (const double nT);
+
+private:
+ const double mnX1;
+ const double mnY1;
+ const double mnX2;
+ const double mnY2;
+
+ double EvaluateComponent (
+ const double nT,
+ const double nV1,
+ const double nV2);
+};
+
+
+
+
+/** Turn a parametric function into one whose y-Values depend on its
+ x-Values. Note a lot of interpolation takes place. The resulting
+ accuracy should be good enough for the purpose of acceleration
+ function for animations.
+*/
+class AnimationParametricFunction
+{
+public:
+ typedef ::boost::function<basegfx::B2DPoint(double)> ParametricFunction;
+ AnimationParametricFunction (const ParametricFunction& rFunction);
+
+ double operator() (const double nX);
+
+private:
+ /** y-Values of the parametric function given to the constructor
+ evaluated (and interpolated) for evenly spaced x-Values.
+ */
+ ::std::vector<double> maY;
+};
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
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..e06bc6ca6708
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx
@@ -0,0 +1,144 @@
+/* -*- 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 "view/SlideSorterView.hxx"
+#include <canvas/elapsedtime.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:
+ /** In some circumstances we have to avoid animation and jump to the
+ final animation state immediately. Use this enum instead of a bool
+ to be more expressive.
+ */
+ enum AnimationMode { AM_Animated, AM_Immediate };
+
+ Animator (SlideSorter& rSlideSorter);
+ ~Animator (void);
+
+ /** When disposed the animator will stop its work immediately and not
+ process any timer events anymore.
+ */
+ void Dispose (void);
+
+ /** An animation object is called with values between 0 and 1 as single
+ argument to its operator() method.
+ */
+ typedef ::boost::function1<void, double> AnimationFunctor;
+ typedef ::boost::function0<void> FinishFunctor;
+
+ typedef sal_Int32 AnimationId;
+ static const AnimationId NotAnAnimationId = -1;
+
+ /** 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 nStartOffset
+ Time in milli seconds before the animation is started.
+ @param nDuration
+ The duration in milli seconds.
+ */
+ AnimationId AddAnimation (
+ const AnimationFunctor& rAnimation,
+ const sal_Int32 nStartOffset,
+ const sal_Int32 nDuration,
+ const FinishFunctor& rFinishFunctor = FinishFunctor());
+
+ AnimationId AddInfiniteAnimation (
+ const AnimationFunctor& rAnimation,
+ const double nDelta);
+
+ /** Abort and remove an animation. In order to reduce the bookkeeping
+ on the caller side, it is OK to call this method with an animation
+ function that is not currently being animated. Such a call is
+ silently ignored.
+ */
+ void RemoveAnimation (const AnimationId nAnimationId);
+
+ /** A typical use case for this method is the temporary shutdown of the
+ slidesorter when the slide sorter bar is put into a cache due to a
+ change of the edit mode.
+ */
+ void RemoveAllAnimations (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+ Timer maTimer;
+ bool mbIsDisposed;
+ class Animation;
+ typedef ::std::vector<boost::shared_ptr<Animation> > AnimationList;
+ AnimationList maAnimations;
+ ::canvas::tools::ElapsedTime maElapsedTime;
+
+ ::boost::scoped_ptr<view::SlideSorterView::DrawLock> mpDrawLock;
+
+ AnimationId mnNextAnimationId;
+
+ DECL_LINK(TimeoutHandler, Timer*);
+
+ /** Execute one step of every active animation.
+ @param nTime
+ Time measured in milli seconds with some arbitrary reference point.
+ @return
+ When one or more animation has finished then <TRUE/> is
+ returned. Call CleanUpAnimationList() in this case.
+ */
+ bool ProcessAnimations (const double nTime);
+
+ /** Remove animations that have expired.
+ */
+ void CleanUpAnimationList (void);
+
+ void RequestNextFrame (const double nFrameStart = 0);
+};
+
+
+} } } // 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..fc97dd32829a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx
@@ -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.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CLIPBOARD
+#define SD_SLIDESORTER_CLIPBOARD
+
+#include "ViewClipboard.hxx"
+#include "controller/SlsSelectionObserver.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,
+ sal_uInt16 nPage = SDRPAGE_NOTFOUND,
+ sal_uInt16 nLayer = SDRPAGE_NOTFOUND );
+
+ sal_Int8 ExecuteDrop (
+ const ExecuteDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow = NULL,
+ sal_uInt16 nPage = SDRPAGE_NOTFOUND,
+ sal_uInt16 nLayer = SDRPAGE_NOTFOUND);
+
+ void Abort (void);
+
+protected:
+ virtual sal_uInt16 DetermineInsertPosition (
+ const SdTransferable& rTransferable);
+
+ virtual sal_uInt16 InsertSlides (
+ const SdTransferable& rTransferable,
+ sal_uInt16 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 (sal_False).
+ */
+ bool mbUpdateSelectionPending;
+
+ /** Used when a drop is executed to combine all undo actions into one.
+ Typically created in ExecuteDrop() and released in DragFinish().
+ */
+ class UndoContext;
+ ::boost::scoped_ptr<UndoContext> mpUndoContext;
+
+ ::boost::scoped_ptr<SelectionObserver::Context> mpSelectionObserverContext;
+ sal_uLong mnDragFinishedUserEventId;
+
+ 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,
+ sal_uInt16 nPage,
+ sal_uInt16 nLayer);
+
+ /** Asynchronous part of DragFinished. The argument is the sal_Int8
+ nDropAction, disguised as void*.
+ */
+ DECL_LINK(ProcessDragFinished, void*);
+};
+
+} } } // 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..8bc96827c02e
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx
@@ -0,0 +1,131 @@
+/* -*- 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 <vcl/timer.hxx>
+#include <tools/link.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.
+
+ Switching pages is triggered only after a little delay. This allows
+ fast travelling through a larger set of slides without having to wait
+ for the edit view to update its content after every slide change.
+*/
+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 NotifyCurrentSlideChange (const sal_Int32 nSlideIndex);
+ void NotifyCurrentSlideChange (const SdPage* pPage);
+
+ /** 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.
+ @param nSlideIndex
+ Zero based index in the range [0,number-of-slides).
+ @param bUpdateSelection
+ When <TRUE/> then the page selection is cleared and only the new
+ current slide is selected.
+ */
+ void SwitchCurrentSlide (
+ const sal_Int32 nSlideIndex,
+ const bool bUpdateSelection = false);
+ void SwitchCurrentSlide (
+ const model::SharedPageDescriptor& rpSlide,
+ const bool bUpdateSelection = false);
+
+ /** 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;
+ /** Timer to control the delay after which to ask
+ XController/ViewShellBase to switch to another slide.
+ */
+ Timer maSwitchPageDelayTimer;
+
+ bool IsCurrentSlideIsValid (void);
+ void SetCurrentSlideAtViewShellBase (const model::SharedPageDescriptor& rpSlide);
+ void SetCurrentSlideAtTabControl (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);
+
+ DECL_LINK(SwitchPageCallback,void*);
+};
+
+
+} } } // 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..d077e64d5fbb
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx
@@ -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.
+ *
+ ************************************************************************/
+
+#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;
+
+ /** 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);
+
+ void SetFocusedPageToCurrentPage (void);
+
+ /** 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;
+
+ /** When vertical wrap is active then pressing UP in the top row moves
+ the focus to the bottom row, DOWN in the bottom row moves the focus
+ to the top row.
+ */
+ bool mbIsVerticalWrapActive;
+
+ /** 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/SlsInsertionIndicatorHandler.hxx b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx
new file mode 100644
index 000000000000..e257c5729b10
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx
@@ -0,0 +1,153 @@
+/*************************************************************************
+ *
+ * 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_INSERTION_INDICATOR_HANDLER_HXX
+#define SD_SLIDESORTER_INSERTION_INDICATOR_HANDLER_HXX
+
+#include "view/SlsInsertAnimator.hxx"
+
+#include "view/SlsLayouter.hxx"
+
+namespace sd { namespace slidesorter { class SlideSorter; } }
+namespace sd { namespace slidesorter { namespace model {
+class PageEnumeration;
+} } }
+namespace sd { namespace slidesorter { namespace view {
+class InsertAnimator;
+class InsertionIndicatorOverlay;
+} } }
+
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class Transferable;
+
+
+/** Manage the visibility and location of the insertion indicator. Its
+ actual display is controlled by the InsertionIndicatorOverlay.
+*/
+class InsertionIndicatorHandler
+{
+public:
+ InsertionIndicatorHandler (SlideSorter& rSlideSorter);
+ ~InsertionIndicatorHandler (void);
+
+ enum Mode { CopyMode, MoveMode, UnknownMode };
+ static Mode GetModeFromDndAction (const sal_Int8 nDndAction);
+
+ /** Activate the insertion marker at the given coordinates.
+ */
+ void Start (const bool bIsOverSourceView);
+
+ /** Deactivate the insertion marker.
+ */
+ void End (const controller::Animator::AnimationMode eMode);
+
+ /** This context make sure that the insertion indicator is shown
+ (provided that the clipboard is not empty) while the context is
+ alive. Typically used while a context menu is displayed.
+ */
+ class ForceShowContext
+ {
+ public:
+ ForceShowContext (const ::boost::shared_ptr<InsertionIndicatorHandler>& rpHandler);
+ ~ForceShowContext (void);
+ private:
+ const ::boost::shared_ptr<InsertionIndicatorHandler> mpHandler;
+ };
+
+ /** Update the indicator icon from the current transferable (from the
+ clipboard or an active drag and drop operation.)
+ */
+ void UpdateIndicatorIcon (const Transferable* pTransferable);
+
+ /** Set the position of the insertion marker to the given coordinates.
+ */
+ void UpdatePosition (
+ const Point& rMouseModelPosition,
+ const Mode eMode);
+ void UpdatePosition (
+ const Point& rMouseModelPosition,
+ const sal_Int8 nDndAction);
+
+ /** Return whether the insertion marker is active.
+ */
+ bool IsActive (void) const;
+
+ /** Return the insertion index that corresponds with the current
+ graphical location of the insertion indicator.
+ */
+ sal_Int32 GetInsertionPageIndex (void) const;
+
+ /** Determine whether moving the current selection to the current
+ position of the insertion marker would alter the document. This
+ would be the case when the selection is not consecutive or would be
+ moved to a position outside and not adjacent to the selection.
+ */
+ bool IsInsertionTrivial (
+ const sal_Int32 nInsertionIndex,
+ const Mode eMode) const;
+ /** This method is like the other variant. It operates implicitly
+ on the current insertion index as would be returned by
+ GetInsertionPageIndex().
+ */
+ bool IsInsertionTrivial (const sal_Int8 nDndAction);
+
+private:
+ SlideSorter& mrSlideSorter;
+ ::boost::shared_ptr<view::InsertAnimator> mpInsertAnimator;
+ ::boost::shared_ptr<view::InsertionIndicatorOverlay> mpInsertionIndicatorOverlay;
+ view::InsertPosition maInsertPosition;
+ Mode meMode;
+ bool mbIsInsertionTrivial;
+ bool mbIsActive;
+ bool mbIsReadOnly;
+ bool mbIsOverSourceView;
+ Size maIconSize;
+ bool mbIsForcedShow;
+
+ void SetPosition (
+ const Point& rPoint,
+ const Mode eMode);
+ ::boost::shared_ptr<view::InsertAnimator> GetInsertAnimator (void);
+
+ /** Make the insertion indicator visible (that is the show part) and
+ keep it visible, even when the mouse leaves the window (that is the
+ force part). We need this when a context menu is displayed (mouse
+ over the popup menu triggers a mouse leave event) while the
+ insertion indicator remains visible in the background.
+
+ In effect all calls to End() are ignored until ForceEnd() is called.
+ */
+ void ForceShow (void);
+ void ForceEnd (void);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
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..db39444aea1f
--- /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..2aa7ee13f873
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
@@ -0,0 +1,232 @@
+/* -*- 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 corresponding pages of the SdPage objects and issue
+ redraw requests where necessary.
+ */
+ void GetCoreSelection (void);
+
+ /** Update the selection state of the SdPage objects to be the same as
+ that of the correspinding page descriptors.
+ */
+ void SetCoreSelection (void);
+
+ /** Select the specified descriptor. The selection state of the other
+ descriptors is not affected.
+ */
+ void SelectPage (int nPageIndex);
+ /** Select the descriptor that is associated with the given page. The
+ selection state of the other descriptors is not affected.
+ */
+ void SelectPage (const SdPage* pPage);
+ /** Select the specified descriptor. The selection state of the other
+ descriptors is not affected.
+ */
+ 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.
+ @param bUpdateCurrentPage
+ When <TRUE/> then the current page is updated to the first slide
+ of the remaining selection.
+ */
+ void DeselectPage (
+ int nPageIndex,
+ const bool bUpdateCurrentPage = true);
+ void DeselectPage (
+ const SdPage* pPage,
+ const bool bUpdateCurrentPage = true);
+ void DeselectPage (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bUpdateCurrentPage = true);
+
+ /** 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;
+
+ /** 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.
+ @param bUpdateCurrentPage
+ When <TRUE/> (the default value) then after setting the
+ selection update the current page to the first page of the
+ selection.
+ When called from withing UpdateCurrentPage() then this flag is
+ used to prevent a recursion loop.
+ */
+ void SetPageSelection (
+ const ::boost::shared_ptr<PageSelection>& rSelection,
+ const bool bUpdateCurrentPage = true);
+
+ /** Call this method after the the model has changed to set the number
+ of selected pages.
+ */
+ void CountSelectedPages (void);
+
+ /** Use the UpdateLock whenever you do a complex selection, i.e. call
+ more than one method in a row. An active lock prevents intermediate
+ changes of the current slide.
+ */
+ class UpdateLock
+ {
+ public:
+ UpdateLock (SlideSorter& rSlideSorter);
+ UpdateLock (PageSelector& rPageSelector);
+ ~UpdateLock (void);
+ void Release (void);
+ private:
+ PageSelector* mpSelector;
+ };
+
+ class BroadcastLock
+ {
+ public:
+ BroadcastLock (SlideSorter& rSlideSorter);
+ BroadcastLock (PageSelector& rPageSelector);
+ ~BroadcastLock (void);
+ private:
+ PageSelector& mrSelector;
+ };
+
+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;
+ sal_Int32 mnUpdateLockCount;
+ bool mbIsUpdateCurrentPagePending;
+
+ /** 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 (void);
+
+ /** Disable the broadcasting of selection change events. Subsequent
+ changes of the selection will set a flag that triggers the sending
+ of events when EnableBroadcasting() is called.
+ */
+ void DisableBroadcasting (void);
+
+ void UpdateCurrentPage (const bool bUpdateOnlyWhenPending = false);
+
+ void CheckConsistency (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/SlsProperties.hxx b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
new file mode 100644
index 000000000000..2e9a183c36d4
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
@@ -0,0 +1,146 @@
+/* -*- 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);
+
+ /** Call this method after receiving a VCLEVENT_APPLICATION_DATACHANGED
+ event.
+ */
+ void HandleDataChangeEvent (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);
+
+ /** The mouse over effect (and whether a mouse motion starts a multi
+ selection or a drag-and-drop) can be triggered by just the preview
+ area or the whole page object area.
+ */
+ bool IsOnlyPreviewTriggersMouseOver (void) const;
+ void SetOnlyPreviewTriggersMouseOver (const bool bFlag);
+
+ bool IsHighContrastModeActive (void) const;
+
+private:
+ bool mbIsHighlightCurrentSlide;
+ bool mbIsShowSelection;
+ bool mbIsShowFocus;
+ bool mbIsCenterSelection;
+ bool mbIsSmoothSelectionScrolling;
+ bool mbIsSuspendPreviewUpdatesDuringFullScreenPresentation;
+ Color maBackgroundColor;
+ Color maTextColor;
+ Color maSelectionColor;
+ Color maHighlightColor;
+ bool mbIsUIReadOnly;
+ bool mbIsOnlyPreviewTriggersMouseOver;
+ bool mbIsHighContrastModeActive;
+};
+
+} } } // 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..2894650da197
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx
@@ -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.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_SLIDE_SORTER_SCROLL_BAR_MANAGER_HXX
+#define SD_SLIDESORTER_SLIDE_SORTER_SCROLL_BAR_MANAGER_HXX
+
+#include "SlideSorter.hxx"
+
+#include <tools/link.hxx>
+#include <tools/gen.hxx>
+#include <vcl/timer.hxx>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.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 horizontal
+ and/or vertical scroll bar is enabled.
+ @param rAvailableArea
+ The scroll bars will be placed inside this rectangle. It is
+ expected to be given in pixel relative to its parent.
+ @param bIsHorizontalScrollBarAllowed
+ Only when this flag is <TRUE/> the horizontal scroll may be
+ displayed.
+ @param bIsVerticalScrollBarAllowed
+ Only when this flag is <TRUE/> the horizontal scroll may be
+ displayed.
+ @return
+ Returns the space that remains after the scroll bars are
+ placed.
+ */
+ Rectangle PlaceScrollBars (
+ const Rectangle& rAvailableArea,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed);
+
+ /** Update the vertical and horizontal scroll bars so that the visible
+ area has the given top and left values.
+ */
+ void SetTopLeft (const Point aNewTopLeft);
+
+ sal_Int32 GetTop (void) const;
+
+ sal_Int32 GetLeft (void) const;
+
+ /** 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.
+ @param rMouseWindowPosition
+ The mouse position for which the scroll amount is calculated.
+ @param rAutoScrollFunctor
+ Every time when the window is scrolled then this functor is executed.
+ @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,
+ const ::boost::function<void(void)>& rAutoScrollFunctor);
+
+ void StopAutoScroll (void);
+
+ enum Orientation { Orientation_Horizontal, Orientation_Vertical };
+ enum Unit { Unit_Pixel, Unit_Slide };
+ /** Scroll the slide sorter by setting the thumbs of the scroll bars and
+ by moving the content of the content window.
+ @param eOrientation
+ Defines whether to scroll horizontally or vertically.
+ @param eUnit
+ Defines whether the distance is a pixel value or the number of
+ slides to scroll.
+ */
+ void Scroll(
+ const Orientation eOrientation,
+ const Unit eUnit,
+ const sal_Int32 nDistance);
+
+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;
+ bool mbIsAutoScrollActive;
+
+ /** The content window is the one whose view port is controlled by the
+ scroll bars.
+ */
+ SharedSdWindow mpContentWindow;
+
+ ::boost::function<void(void)> maAutoScrollFunctor;
+
+ 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,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed);
+
+ /** 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..9e399d7262f8
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx
@@ -0,0 +1,208 @@
+/* -*- 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 "model/SlsSharedPageDescriptor.hxx"
+#include "controller/SlsFocusManager.hxx"
+#include "controller/SlsInsertionIndicatorHandler.hxx"
+#include "fupoor.hxx"
+#include <svtools/transfer.hxx>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+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 DragAndDropContext;
+
+
+class SelectionFunction
+ : public FuPoor,
+ private ::boost::noncopyable
+{
+public:
+ TYPEINFO();
+
+ static FunctionReference Create( SlideSorter& rSlideSorter, SfxRequest& rRequest );
+
+ // Mouse- & Key-Events
+ virtual sal_Bool KeyInput(const KeyEvent& rKEvt);
+ virtual sal_Bool MouseMove(const MouseEvent& rMEvt);
+ virtual sal_Bool MouseButtonUp(const MouseEvent& rMEvt);
+ virtual sal_Bool MouseButtonDown(const MouseEvent& rMEvt);
+
+ virtual void Activate();
+ virtual void Deactivate();
+
+ 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();
+
+ void MouseDragged (
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction);
+
+ /** Turn of substitution display and insertion indicator.
+ */
+ void NotifyDragFinished (void);
+
+ /** Call when drag-and-drop or multi selection is started or stopped in
+ order to update permission of mouse over indication.
+ */
+ void UpdateMouseOverIndicationPermission (void);
+
+ class EventDescriptor;
+ class ModeHandler;
+ friend class ModeHandler;
+ enum Mode
+ {
+ NormalMode,
+ MultiSelectionMode,
+ DragAndDropMode,
+ ButtonMode
+ };
+ void SwitchToNormalMode (void);
+ void SwitchToDragAndDropMode(const Point aMousePosition);
+ void SwitchToMultiSelectionMode (const Point aMousePosition, const sal_uInt32 nEventCode);
+ bool SwitchToButtonMode (void);
+
+ void ResetShiftKeySelectionAnchor (void);
+ /** Special case handling for when the context menu is hidden. This
+ method will reinitialize the current mouse position to prevent the
+ mouse motion during the time the context menu is displayed from
+ being interpreted as drag-and-drop start.
+ */
+ void ResetMouseAnchor (void);
+
+protected:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ SelectionFunction (
+ SlideSorter& rSlideSorter,
+ SfxRequest& rRequest);
+
+ virtual ~SelectionFunction();
+
+private:
+
+ /// 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;
+
+ bool mbIsDeselectionPending;
+
+ /** Remember the slide where the shift key was pressed and started a
+ multiselection via keyboard.
+ */
+ sal_Int32 mnShiftKeySelectionAnchor;
+
+ /** The selection function can be in one of several mutually
+ exclusive modes.
+ */
+ ::boost::shared_ptr<ModeHandler> mpModeHandler;
+
+ /** 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);
+
+ /** Make the slide with the given index the new current slide.
+ @param nIndex
+ Index of the new current slide. When the new index is outside
+ the range of valid page numbers it is clipped to that range.
+ */
+ void GotoPage (int nIndex);
+
+ 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().
+
+ void ProcessEvent (EventDescriptor& rEvent);
+
+ void MoveFocus (
+ const FocusManager::FocusMoveDirection eDirection,
+ const bool bIsShiftDown,
+ const bool bIsControlDown);
+
+ void StopDragAndDrop (void);
+
+ void SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
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..05bb8ef9a895
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx
@@ -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.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_CONTROLLER_SELECTION_MANAGER_HXX
+#define SD_SLIDESORTER_CONTROLLER_SELECTION_MANAGER_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "controller/SlsAnimator.hxx"
+#include <sal/types.h>
+#include <tools/gen.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <vector>
+
+class Link;
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+
+class SlideSorterController;
+class SelectionObserver;
+
+/** 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.
+ @param bSelectFollowingPage
+ When <TRUE/> then after deleting the selected pages make the
+ slide after the last selected page the new current page.
+ When <FALSE/> then make the first slide before the selected
+ pages the new current slide.
+ */
+ void DeleteSelectedPages (const bool bSelectFollowingPage = true);
+
+ /** 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);
+
+ /** 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);
+
+ ::boost::shared_ptr<SelectionObserver> GetSelectionObserver (void) const;
+
+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;
+
+ /** Animation id for a scroll animation the will eventually set the top
+ and left of the visible area to maRequestedTopLeft.
+ */
+ Animator::AnimationId mnAnimationId;
+ Point maRequestedTopLeft;
+
+ class PageInsertionListener;
+ ::boost::scoped_ptr<PageInsertionListener> mpPageInsertionListener;
+
+ ::boost::shared_ptr<SelectionObserver> mpSelectionObserver;
+
+ /** 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);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx
new file mode 100644
index 000000000000..0fb45b403af1
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * 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_OBSERVER_HXX
+#define SD_SLIDESORTER_CONTROLLER_SELECTION_OBSERVER_HXX
+
+#include <tools/gen.hxx>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+class SdDrawDocument;
+class SdrPage;
+
+namespace sd { namespace slidesorter { namespace controller {
+
+/** Observe insertions and deletions of pages between calls to
+ StartObservation() and EndObservation(). When the later is called
+ the selection is set to just the newly inserted pages.
+*/
+class SelectionObserver
+{
+public:
+ SelectionObserver (SlideSorter& rSlideSorter);
+ virtual ~SelectionObserver (void);
+
+ void NotifyPageEvent (const SdrPage* pPage);
+ void StartObservation (void);
+ void AbortObservation (void);
+ void EndObservation (void);
+
+ /** Use this little class instead of calling StartObservation and
+ EndObservation directly so that EndObservation is not forgotten or
+ omitted due to an exception or some break or return in the middle of
+ code.
+ */
+ class Context
+ {
+ public:
+ Context (SlideSorter& rSlideSorter);
+ ~Context(void);
+ void Abort (void);
+ private:
+ ::boost::shared_ptr<SelectionObserver> mpSelectionObserver;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+ SdDrawDocument* mpDocument;
+ bool mbIsOvservationActive;
+
+ ::std::vector<const SdPage*> maInsertedPages;
+ ::std::vector<sal_Int32> maDeletedPages;
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
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..774e4c09cc7c
--- /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 sal_Bool MouseMove (const MouseEvent& rMEvt);
+ virtual sal_Bool MouseButtonUp (const MouseEvent& rMEvt);
+ virtual sal_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..c21df03ad6d4
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx
@@ -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.
+ *
+ ************************************************************************/
+#ifndef SD_SLIDESORTER_SLOT_MANAGER_HXX
+#define SD_SLIDESORTER_SLOT_MANAGER_HXX
+
+#include "model/SlsSharedPageDescriptor.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);
+
+ /** Exclude or include one slide or all selected slides.
+ @param rpDescriptor
+ When the pointer is empty then apply the new state to all
+ selected pages. Otherwise apply the new state to just the
+ specified state.
+ */
+ void ChangeSlideExclusionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bExcludeSlide);
+
+ /** Call this after a change from normal mode to master mode or back.
+ The affected slots are invalidated.
+ */
+ void NotifyEditModeChange (void);
+
+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( sal_uInt16 nPageId, const String& rName);
+
+ /** Handle SID_INSERTPAGE slot calls.
+ */
+ void InsertSlide (SfxRequest& rRequest);
+
+ void DuplicateSelectedSlides (SfxRequest& rRequest);
+
+ /** Use one of several ways to determine where to insert a new page.
+ This can be the current selection or the insertion indicator.
+ */
+ sal_Int32 GetInsertionPosition (void);
+
+ 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/controller/SlsTransferable.hxx b/sd/source/ui/slidesorter/inc/controller/SlsTransferable.hxx
new file mode 100644
index 000000000000..321823f6c14e
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsTransferable.hxx
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * 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 { 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:
+ class Representative
+ {
+ public:
+ Representative (const Bitmap& rBitmap, const bool bIsExcluded)
+ : maBitmap(rBitmap), mbIsExcluded(bIsExcluded) {}
+ Representative (const Representative& rOther)
+ : maBitmap(rOther.maBitmap), mbIsExcluded(rOther.mbIsExcluded) {}
+ Representative operator= (Representative const& rOther)
+ { if (&rOther != this) {maBitmap = rOther.maBitmap; mbIsExcluded = rOther.mbIsExcluded; }
+ return *this;
+ }
+
+ Bitmap maBitmap;
+ bool mbIsExcluded;
+ };
+
+
+ Transferable (
+ SdDrawDocument* pSrcDoc,
+ ::sd::View* pWorkView,
+ sal_Bool bInitOnGetData,
+ SlideSorterViewShell* pViewShell,
+ const ::std::vector<Representative>& rRepresentatives);
+
+ virtual ~Transferable (void);
+
+ virtual void DragFinished (sal_Int8 nDropAction);
+
+ const ::std::vector<Representative>& GetRepresentatives (void) const;
+
+private:
+ SlideSorterViewShell* mpViewShell;
+ const ::std::vector<Representative> maRepresentatives;
+
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
+};
+
+} } } // end of namespace ::sd::slidesorter::controller
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx
new file mode 100644
index 000000000000..cdaf9b1588ea
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *
+ * 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_VISIBLE_AREA_MANAGER_HXX
+#define SD_SLIDESORTER_VISIBLE_AREA_MANAGER_HXX
+
+#include "controller/SlsAnimator.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+
+namespace sd { namespace slidesorter { namespace controller {
+
+
+/** Manage requests for scrolling page objects into view.
+*/
+class VisibleAreaManager
+ : public ::boost::noncopyable
+{
+public:
+ VisibleAreaManager (SlideSorter& rSlideSorter);
+ ~VisibleAreaManager (void);
+
+ void ActivateCurrentSlideTracking (void);
+ void DeactivateCurrentSlideTracking (void);
+
+ /** Request the current slide to be moved into the visible area.
+ This request is only obeyed when the current slide tracking is
+ active.
+ @see ActivateCurrentSlideTracking() and DeactivateCurrentSlideTracking()
+ */
+ void RequestCurrentSlideVisible (void);
+
+ /** Request to make the specified page object visible.
+ */
+ void RequestVisible (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bForce = false);
+
+ /** Temporarily disable the update of the visible area.
+ */
+ class TemporaryDisabler
+ {
+ public:
+ TemporaryDisabler (SlideSorter& rSlideSorter);
+ ~TemporaryDisabler (void);
+ private:
+ VisibleAreaManager& mrVisibleAreaManager;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** List of rectangle that someone wants to be moved into the visible
+ area.
+ Cleared on every call to ForgetVisibleRequests() and MakeVisible().
+ */
+ ::std::vector<Rectangle> maVisibleRequests;
+
+ /** Animation id for a scroll animation that sets the top
+ and left of the visible area to maRequestedVisibleTopLeft.
+ */
+ Animator::AnimationId mnScrollAnimationId;
+ Point maRequestedVisibleTopLeft;
+ Animator::AnimationMode meRequestedAnimationMode;
+ bool mbIsCurrentSlideTrackingActive;
+ int mnDisableCount;
+
+ void MakeVisible (void);
+ ::boost::optional<Point> GetRequestedTopLeft (void) const;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
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..d059b48624d2
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx
@@ -0,0 +1,254 @@
+/* -*- 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 <vcl/region.hxx>
+
+#include <memory>
+#include <vector>
+#include <functional>
+
+namespace css = ::com::sun::star;
+
+class SdrPage;
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace controller {
+class PageObjectFactory;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+
+class DocumentPageContainer;
+
+inline sal_Int32 FromCoreIndex (const sal_uInt16 nCoreIndex) { return (nCoreIndex-1)/2; }
+inline sal_uInt16 ToCoreIndex (const sal_Int32 nIndex) { return nIndex*2+1; }
+
+/** 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);
+ void Init (void);
+
+ virtual ~SlideSorterModel (void);
+ void Dispose (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);
+
+ /** Set the edit mode to that currently used by the controller.
+ */
+ bool SetEditModeFromController (void);
+ 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;
+
+ /** Return a page descriptor for the given SdrPage. 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 SdrPage 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 SdrPage* pPage) const;
+
+ /** Return an index for accessing an SdrModel that corresponds to the
+ given SlideSorterModel index. In many cases we just have to apply
+ the n*2+1 magic. Only when a special model is set, like a custom
+ slide show, then the returned value is different.
+ */
+ sal_uInt16 GetCoreIndex (const sal_Int32 nIndex) 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);
+
+ /** Set the selection of the called model to exactly that of the document.
+ */
+ void SynchronizeModelSelection (void);
+
+ /** 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);
+
+ bool IsReadOnly (void) const;
+
+ /** The current selection is saved by copying the ST_Selected state into
+ ST_WasSelected for slides.
+ */
+ void SaveCurrentSelection (void);
+
+ /** The current selection is restored from the ST_WasSelected state from
+ the slides.
+ @returns
+ The returned region has to be repainted to reflect the updated
+ selection states.
+ */
+ Region RestoreSelection (void);
+
+ /** Typically called from controller::Listener this method handles the
+ insertion and deletion of single pages.
+ @return
+ Returns <TRUE/> when the given page is relevant for the current
+ page kind and edit mode.
+ */
+ bool NotifyPageEvent (const SdrPage* pPage);
+
+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;
+
+ /** Resize the descriptor container according to current values of
+ page kind and edit mode.
+ */
+ void AdaptSize (void);
+
+ SdPage* GetPage (const sal_Int32 nCoreIndex) const;
+ void InsertSlide (SdPage* pPage);
+ void DeleteSlide (const SdPage* pPage);
+ void UpdateIndices (const sal_Int32 nFirstIndex);
+};
+
+} } } // 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..fe4b1cc12506
--- /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..ab699d729356
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx
@@ -0,0 +1,166 @@
+/* -*- 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 "model/SlsVisualState.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>
+#include <boost/scoped_ptr.hpp>
+
+
+class SdPage;
+class SdrPage;
+
+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);
+
+ ~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;
+
+ /** Returns the index of the page as it is displayed in the view as page
+ number. The value may differ from the index returned by the
+ XDrawPage when there are hidden slides and the XIndexAccess used to
+ access the model filters them out.
+ */
+ sal_Int32 GetPageIndex (void) const;
+ void SetPageIndex (const sal_Int32 nIndex);
+
+ bool UpdateMasterPage (void);
+
+ enum State { ST_Visible, ST_Selected, ST_WasSelected,
+ ST_Focused, ST_MouseOver, ST_Current, ST_Excluded };
+
+ bool HasState (const State eState) const;
+
+ bool SetState (const State eState, const bool bStateValue);
+
+ /** 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 GetCoreSelection (void);
+
+ /** Set the selection flags of the SdPage objects to the corresponding
+ selection states of the page descriptors.
+ */
+ void SetCoreSelection (void);
+
+ VisualState& GetVisualState (void);
+
+ Rectangle GetBoundingBox (void) const;
+ Point GetLocation (const bool bIgnoreLocation = false) const;
+ void SetBoundingBox (const Rectangle& rBoundingBox);
+
+private:
+ SdPage* mpPage;
+ css::uno::Reference<css::drawing::XDrawPage> mxPage;
+ SdrPage const* mpMasterPage;
+
+ /** This index is displayed as page number in the view. It may or may
+ not be the actual page index.
+ */
+ sal_Int32 mnIndex;
+
+ Rectangle maBoundingBox;
+ VisualState maVisualState;
+
+ bool mbIsSelected : 1;
+ bool mbWasSelected : 1;
+ bool mbIsVisible : 1;
+ bool mbIsFocused : 1;
+ bool mbIsCurrent : 1;
+ bool mbIsMouseOver : 1;
+
+
+ // 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..36a49f720589
--- /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..6f9923308374
--- /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..93bcf89215e6
--- /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/model/SlsVisualState.hxx b/sd/source/ui/slidesorter/inc/model/SlsVisualState.hxx
new file mode 100644
index 000000000000..03b242fdd29a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/model/SlsVisualState.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * 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_VISUAL_STATE_HXX
+#define SD_SLIDESORTER_VISUAL_STATE_HXX
+
+#include <sal/types.h>
+#include <tools/gen.hxx>
+#include <boost/function.hpp>
+
+namespace sd { namespace slidesorter { namespace model {
+
+class PageDescriptor;
+
+/** This class gives access to values related to the visualization of page
+ objects. This includes animation state when blending from one state to
+ another.
+*/
+class VisualState
+{
+public:
+ enum State {
+ VS_Selected,
+ VS_Focused,
+ VS_Current,
+ VS_Excluded,
+ VS_None };
+
+ VisualState (const sal_Int32 nPageId);
+ ~VisualState (void);
+
+ State GetCurrentVisualState (void) const;
+ State GetOldVisualState (void) const;
+ void SetVisualState (const State eState);
+ double GetVisualStateBlend (void) const;
+ void SetVisualStateBlend (const double nBlend);
+
+ void UpdateVisualState (const PageDescriptor& rDescriptor);
+
+ void SetMouseOverState (const bool bIsMouseOver);
+
+ sal_Int32 GetStateAnimationId (void) const;
+ void SetStateAnimationId (const sal_Int32 nAnimationId);
+
+ Point GetLocationOffset (void) const;
+ bool SetLocationOffset (const Point& rPoint);
+ sal_Int32 GetLocationAnimationId (void) const;
+ void SetLocationAnimationId (const sal_Int32 nAnimationId);
+
+ double GetButtonAlpha (void) const;
+ void SetButtonAlpha (const double nAlpha);
+ double GetButtonBarAlpha (void) const;
+ void SetButtonBarAlpha (const double nAlpha);
+ sal_Int32 GetButtonAlphaAnimationId (void) const;
+ void SetButtonAlphaAnimationId (const sal_Int32 nAnimationId);
+
+ sal_Int32 mnPageId; // For debugging
+
+private:
+ State meCurrentVisualState;
+ State meOldVisualState;
+ double mnVisualStateBlend;
+ sal_Int32 mnStateAnimationId;
+ bool mbOldMouseOverState;
+ bool mbCurrentMouseOverState;
+
+ Point maLocationOffset;
+ sal_Int32 mnLocationAnimationId;
+
+ double mnButtonAlpha;
+ double mnButtonBarAlpha;
+ sal_Int32 mnButtonAlphaAnimationId;
+};
+
+} } } // end of namespace ::sd::slidesorter::model
+
+#endif
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..099f6544f861
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx
@@ -0,0 +1,304 @@
+/* -*- 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 "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsILayerPainter.hxx"
+
+#include "View.hxx"
+#include <sfx2/viewfrm.hxx>
+#include "pres.hxx"
+#include <tools/gen.hxx>
+#include <svx/svdmodel.hxx>
+#include <vcl/region.hxx>
+#include <vcl/outdev.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <memory>
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+class Point;
+
+namespace sd { namespace slidesorter { namespace controller {
+class SlideSorterController;
+class Properties;
+} } }
+
+namespace sd { namespace slidesorter { namespace cache {
+class PageCache;
+} } }
+
+namespace sd { namespace slidesorter { namespace model {
+class SlideSorterModel;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class ButtonBar;
+class LayeredDevice;
+class Layouter;
+class PageObjectPainter;
+class SelectionPainter;
+class ToolTip;
+
+
+class SlideSorterView
+ : public sd::View,
+ public ::boost::noncopyable
+{
+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);
+ void Init (void);
+
+ virtual ~SlideSorterView (void);
+ void Dispose (void);
+
+ /** Set the general way of layouting the page objects. Note that this
+ method does not trigger any repaints or layouts.
+ */
+ bool SetOrientation (const Layouter::Orientation eOrientation);
+ Layouter::Orientation GetOrientation (void) const;
+
+ void RequestRepaint (void);
+ void RequestRepaint (const model::SharedPageDescriptor& rDescriptor);
+ void RequestRepaint (const Rectangle& rRepaintBox);
+ void RequestRepaint (const Region& rRepaintRegion);
+
+ Rectangle GetModelArea (void);
+
+ /** 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 = NULL);
+ void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea);
+
+ virtual void ConfigurationChanged (
+ utl::ConfigurationBroadcaster* pBroadcaster,
+ sal_uInt32 nHint);
+
+ void HandleDataChangeEvent (void);
+
+ 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.
+ */
+ // ::boost::shared_ptr<sd::Window> GetWindow (void) const;
+
+ ::boost::shared_ptr<cache::PageCache> GetPreviewCache (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);
+
+ /** 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.
+ */
+ Pair 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);
+
+ /** The page under the mouse is not highlighted in some contexts. Call
+ this method on context changes.
+ */
+ void UpdatePageUnderMouse (bool bAnimate);
+ void UpdatePageUnderMouse (
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate = true);
+ void UpdatePageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate = true);
+ void SetPageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate = true);
+
+ bool SetState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const model::PageDescriptor::State eState,
+ const bool bStateValue,
+ const bool bAnimate = true);
+
+ void UpdateOrientation (void);
+
+ ::boost::shared_ptr<PageObjectPainter> GetPageObjectPainter (void);
+ ::boost::shared_ptr<LayeredDevice> GetLayeredDevice (void) const;
+
+ class DrawLock
+ {
+ public:
+ DrawLock (view::SlideSorterView& rView, const SharedSdWindow& rpWindow);
+ DrawLock (SlideSorter& rSlideSorter);
+ ~DrawLock (void);
+ /** When the DrawLock is disposed then it will not request a repaint
+ on destruction.
+ */
+ void Dispose (void);
+ private:
+ view::SlideSorterView& mrView;
+ SharedSdWindow mpWindow;
+ };
+
+ ButtonBar& GetButtonBar (void) const;
+ ToolTip& GetToolTip (void) const;
+
+protected:
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SlideSorterModel& mrModel;
+ bool mbIsDisposed;
+ ::std::auto_ptr<Layouter> mpLayouter;
+ bool mbPageObjectVisibilitiesValid;
+ ::boost::shared_ptr<cache::PageCache> mpPreviewCache;
+ ::boost::shared_ptr<LayeredDevice> mpLayeredDevice;
+ Range maVisiblePageRange;
+ bool mbModelChangedWhileModifyEnabled;
+ Size maPreviewSize;
+ bool mbPreciousFlagUpdatePending;
+ Layouter::Orientation meOrientation;
+ ::boost::shared_ptr<controller::Properties> mpProperties;
+ model::SharedPageDescriptor mpPageUnderMouse;
+ sal_Int32 mnButtonUnderMouse;
+ ::boost::shared_ptr<PageObjectPainter> mpPageObjectPainter;
+ ::boost::shared_ptr<SelectionPainter> mpSelectionPainter;
+ Region maRedrawRegion;
+ SharedILayerPainter mpBackgroundPainter;
+ ::boost::scoped_ptr<ButtonBar> mpButtonBar;
+ ::boost::scoped_ptr<ToolTip> mpToolTip;
+ bool mbIsRearrangePending;
+ ::std::vector<Link> maVisibilityChangeListeners;
+
+ /** Determine the visibility of all page objects.
+ */
+ void DeterminePageObjectVisibilities (void);
+
+ void UpdatePreciousFlags (void);
+ void RequestRearrange (void);
+ void Rearrange (void);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/view/SlsButtonBar.hxx b/sd/source/ui/slidesorter/inc/view/SlsButtonBar.hxx
new file mode 100644
index 000000000000..460c915f8a56
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsButtonBar.hxx
@@ -0,0 +1,362 @@
+/*************************************************************************
+ *
+ * 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_BUTTON_BAR_HXX
+#define SD_SLIDESORTER_VIEW_BUTTON_BAR_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include <tools/gen.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <boost/scoped_ptr.hpp>
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+class Theme;
+
+class Button;
+typedef ::boost::shared_ptr<Button> SharedButton;
+
+/** This is a container of buttons and a coordinating controller.
+ The last means that it receives mouse events and forwards them to
+ the right button.
+*/
+class ButtonBar
+{
+public:
+ ButtonBar (SlideSorter& rSlideSorter);
+ ~ButtonBar (void);
+
+ void ProcessButtonDownEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation);
+ void ProcessButtonUpEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation);
+ void ProcessMouseMotionEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation,
+ const bool bIsMouseButtonDown);
+
+ void ResetPage (void);
+
+ /** Return the number of buttons that are to be displayed in page
+ objects which the mouse hovers over.
+ @param bIsExcluded
+ When this flag is <TRUE/> then return the number of
+ buttons that is to be displayed for pages that are
+ excluded from the slide show.
+ */
+ sal_Int32 GetButtonCount (const bool bIsExcluded) const;
+
+ /** Return the specified button.
+ @param nIndex
+ Valid values lie in the range [0,GetButtonCount()).
+ @param bIsExcluded
+ When this flag is <TRUE/> then return a button that is to
+ be displayed for pages that are excluded from the slide
+ show.
+ @return
+ Returns an empty pointer when the given index is not valid.
+ */
+ ::boost::shared_ptr<Button> GetButton (
+ const bool bIsExcluded,
+ const sal_Int32 nIndex) const;
+
+ bool IsMouseOverBar (void) const;
+
+ /** Paint the specified page object. When this is not the same as the
+ one under the mouse (mpDescriptor) then the buttons are all
+ painted in their normal state.
+ */
+ void Paint (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpPageDescriptor);
+
+ bool IsMouseOverButton (void) const;
+
+ void RequestLayout (void);
+
+ /** Return the help text for the button under the mouse.
+ @return
+ When the mouse is not over a button then an empty string
+ is returned.
+ */
+ ::rtl::OUString GetButtonHelpText (void) const;
+
+ /** Request the button bar to be shown.
+ @param bAnimate
+ This flag controls whether to just show the button bar (<FALSE/>)
+ or to fade it in smoothly (<TRUE/>.)
+ */
+ void RequestFadeIn (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate);
+
+ /** Request the button bar to be hidden.
+ @param bAnimate
+ This flag controls whether to just hide the button bar (<FALSE/>)
+ or to fade it out smoothly (<TRUE/>.)
+ */
+ void RequestFadeOut (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate);
+
+ /** Return whether the button bar is visible for the givn descriptor (or
+ being faded in.)
+ */
+ bool IsVisible (const model::SharedPageDescriptor& rpDescriptor);
+
+ void HandleDataChangeEvent (void);
+
+ class BackgroundTheme;
+
+ /** While at least one Lock object exists the button bar will not be
+ displayed. Used, e.g. during a mouse multiselection to avoid
+ confusing and unhelpfull visual signals.
+ */
+ class Lock
+ {
+ public:
+ Lock (SlideSorter& rSlideSorter);
+ ~Lock (void);
+ private:
+ ButtonBar& mrButtonBar;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+ Size maPageObjectSize;
+ Rectangle maButtonBoundingBox;
+ Point maBackgroundLocation;
+ model::SharedPageDescriptor mpDescriptor;
+ bool mbIsExcluded;
+ boost::shared_ptr<Button> mpButtonUnderMouse;
+ // The button on which the mouse button was pressed.
+ boost::shared_ptr<Button> mpDownButton;
+ ::std::vector<SharedButton> maRegularButtons;
+ ::std::vector<SharedButton> maExcludedButtons;
+ BitmapEx maNormalBackground;
+ BitmapEx maButtonDownBackground;
+ bool mbIsMouseOverBar;
+ ::boost::scoped_ptr<BackgroundTheme> mpBackgroundTheme;
+ int mnLockCount;
+
+ /** Remember the specified page. If it differs from mpDescriptor then
+ the buttons are placed anew.
+ @return
+ The returned flag indicates wether the mpDescriptor member
+ is set to a new value.
+ */
+ bool SetPage (const model::SharedPageDescriptor& rpDescriptor);
+ SharedButton GetButtonAt (const Point aModelLocation);
+ bool SetButtonUnderMouse (const SharedButton& rButton = SharedButton());
+ void PaintButtonBackground (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpPageDescriptor,
+ const Point aOffset);
+ void LayoutButtons (const Size aPageModelSize);
+ bool LayoutButtons (void);
+ BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const;
+ bool IsMouseOverBar (const Point aModelLocation) const;
+ void StartFadeAnimation (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const double nTargetAlpha,
+ const bool bFadeIn);
+
+ void AcquireLock (void);
+ void ReleaseLock (void);
+};
+
+
+
+
+class Button
+{
+public:
+ Button (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsHelpText);
+ virtual ~Button (void);
+
+ enum State { State_Normal, State_Hover, State_Down };
+ enum IconSize { IconSize_Large, IconSize_Medium, IconSize_Small };
+
+ /** Set a new state.
+ @return
+ When the new state is different from the old state
+ then <TRUE/> is returned.
+ */
+ bool SetState (const State eState);
+ State GetState (void) const;
+
+ virtual void Place (const Rectangle aButtonBarBox) = 0;
+ virtual void Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const = 0;
+ virtual void ProcessClick (const model::SharedPageDescriptor& rpDescriptor) = 0;
+
+ /** Return the bounding box of the layouted button.
+ */
+ Rectangle GetBoundingBox (void) const;
+ /** Return the minimum size required to completely paint the
+ button.
+ */
+ virtual Size GetSize (void) const = 0;
+ virtual Size GetSize (const IconSize eIconSize) const = 0;
+ ::rtl::OUString GetHelpText (void) const;
+ bool IsDown (void) const;
+ void SetActiveState (const bool bIsActive);
+ bool IsActive (void) const;
+ void SetIconSize (const IconSize eIconSize);
+ IconSize GetIconSize (void) const;
+ /** By default a button is always enabled. Override to change this.
+ */
+ virtual bool IsEnabled (void) const;
+
+protected:
+ SlideSorter& mrSlideSorter;
+ State meState;
+ Rectangle maBoundingBox;
+ const ::rtl::OUString msHelpText;
+ // Buttons that lie (partly) outside the button bar are deactivated.
+ bool mbIsActive;
+ IconSize meIconSize;
+};
+
+
+
+class TextButton : public Button
+{
+public:
+ TextButton (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsText,
+ const ::rtl::OUString& rsHelpText);
+
+ virtual void Place (const Rectangle aButtonBarBox);
+ virtual void Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const;
+ virtual Size GetSize (void) const;
+ virtual Size GetSize (const IconSize eIconSize) const;
+
+private:
+ const ::rtl::OUString msText;
+};
+
+
+
+class ImageButton : public Button
+{
+public:
+ ImageButton (
+ SlideSorter& rSlideSorter,
+ const BitmapEx& rLargeIcon,
+ const BitmapEx& rLargeHoverIcon,
+ const BitmapEx& rMediumIcon,
+ const BitmapEx& rMediumHoverIcon,
+ const BitmapEx& rSmallIcon,
+ const BitmapEx& rSmallHoverIcon,
+ const ::rtl::OUString& rsHelpText);
+
+ virtual void Place (const Rectangle aButtonBarBox);
+ virtual void Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const;
+ virtual Size GetSize (void) const;
+ virtual Size GetSize (const IconSize eIconSize) const;
+
+private:
+ const BitmapEx maLargeIcon;
+ const BitmapEx maLargeHoverIcon;
+ const BitmapEx maMediumIcon;
+ const BitmapEx maMediumHoverIcon;
+ const BitmapEx maSmallIcon;
+ const BitmapEx maSmallHoverIcon;
+};
+
+
+class UnhideButton : public ImageButton
+{
+public:
+ UnhideButton (SlideSorter& rSlideSorter);
+
+protected:
+ virtual void ProcessClick (const model::SharedPageDescriptor& rpDescriptor);
+};
+
+
+class StartShowButton : public ImageButton
+{
+public:
+ StartShowButton (SlideSorter& rSlideSorter);
+ virtual bool IsEnabled (void) const;
+
+protected:
+ virtual void ProcessClick (const model::SharedPageDescriptor& rpDescriptor);
+};
+
+
+class HideButton : public ImageButton
+{
+public:
+ HideButton (SlideSorter& rSlideSorter);
+
+protected:
+ virtual void ProcessClick (const model::SharedPageDescriptor& rpDescriptor);
+};
+
+
+class DuplicateButton : public ImageButton
+{
+public:
+ DuplicateButton (SlideSorter& rSlideSorter);
+ virtual bool IsEnabled (void) const;
+
+protected:
+ virtual void ProcessClick (const model::SharedPageDescriptor& rpDescriptor);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
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..82487471edb0
--- /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/SlsILayerPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx
new file mode 100644
index 000000000000..853890ee5894
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx
@@ -0,0 +1,60 @@
+/*************************************************************************
+ *
+ * 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_LAYER_PAINTER_HXX
+#define SD_SLIDESORTER_VIEW_LAYER_PAINTER_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <sal/types.h>
+
+class OutputDevice;
+class Rectangle;
+
+namespace sd { namespace slidesorter { namespace view {
+
+class ILayerInvalidator
+{
+public:
+ virtual void Invalidate (const Rectangle& rInvalidationBox) = 0;
+};
+typedef ::boost::shared_ptr<ILayerInvalidator> SharedILayerInvalidator;
+
+class ILayerPainter
+{
+public:
+ virtual void SetLayerInvalidator (
+ const SharedILayerInvalidator& rpInvalidator) = 0;
+ virtual void Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea) = 0;
+};
+typedef ::boost::shared_ptr<ILayerPainter> SharedILayerPainter;
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx b/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx
new file mode 100644
index 000000000000..cfd789818408
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx
@@ -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.
+ *
+ ************************************************************************/
+
+#ifndef SD_SLIDESORTER_VIEW_INSERT_ANIMATOR_HXX
+#define SD_SLIDESORTER_VIEW_INSERT_ANIMATOR_HXX
+
+#include "controller/SlsAnimator.hxx"
+#include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace sd { namespace slidesorter { namespace view {
+
+class InsertPosition;
+
+
+/** Animate the positions of page objects to make room at the insert
+ position while a move or copy operation takes place.
+*/
+class InsertAnimator
+ : private ::boost::noncopyable
+{
+public:
+ InsertAnimator (SlideSorter& rSlideSorter);
+
+ /** Set the position at which we have to make room for the display of an
+ icon.
+ */
+ void SetInsertPosition (const InsertPosition& rInsertPosition);
+
+ enum ResetMode { RM_Normal, RM_AbortAnimations };
+ /** Restore the normal position of all page objects.
+ @param eMode
+ This flag controls wether to start an animation that ends in the
+ normal positions of all slides (AM_Animated) or to restore the
+ normal positions immediately (AM_Immediate).
+ */
+ void Reset (const controller::Animator::AnimationMode eMode);
+
+private:
+ class Implementation;
+ ::boost::shared_ptr<Implementation> mpImplementation;
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx b/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx
new file mode 100644
index 000000000000..a9a640d978cf
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * 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_INSERTION_INDICATOR_OVERLAY_HXX
+#define SD_SLIDESORTER_INSERTION_INDICATOR_OVERLAY_HXX
+
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "view/SlsILayerPainter.hxx"
+#include "controller/SlsTransferable.hxx"
+
+#include <tools/gen.hxx>
+#include <vcl/bitmapex.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <vector>
+
+class OutputDevice;
+class SdPage;
+
+namespace sd { namespace slidesorter {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace model {
+class PageEnumeration;
+} } }
+
+namespace sd { namespace slidesorter { namespace controller {
+class Transferable;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class FramePainter;
+class LayeredDevice;
+
+/** The insertion indicator is painted as a vertical or horizonal bar
+ in the space between slides.
+*/
+class InsertionIndicatorOverlay
+ : public ILayerPainter,
+ public ::boost::enable_shared_from_this<InsertionIndicatorOverlay>
+{
+public:
+ InsertionIndicatorOverlay (SlideSorter& rSlideSorter);
+ virtual ~InsertionIndicatorOverlay (void);
+
+ virtual void SetLayerInvalidator (const SharedILayerInvalidator& rpInvalidator);
+
+ void Create (const controller::Transferable* pTransferable);
+
+ /** Given a position in model coordinates this method calculates the
+ insertion marker both as an index in the document and as a location
+ used for drawing the insertion indicator.
+ */
+ void SetLocation (const Point& rPosition);
+
+ Size GetSize (void) const;
+
+ virtual void Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea);
+
+ bool IsVisible (void) const;
+ void Hide (void);
+ void Show (void);
+
+ Rectangle GetBoundingBox (void) const;
+
+private:
+ SlideSorter& mrSlideSorter;
+ bool mbIsVisible;
+ const sal_Int32 mnLayerIndex;
+ SharedILayerInvalidator mpLayerInvalidator;
+ // Center of the insertion indicator.
+ Point maLocation;
+ BitmapEx maIcon;
+ Point maIconOffset;
+ ::boost::scoped_ptr<FramePainter> mpShadowPainter;
+
+ void SetPositionAndSize (const Rectangle& rBoundingBox);
+ void SelectRepresentatives (
+ model::PageEnumeration& rSelection,
+ ::std::vector<model::SharedPageDescriptor>& rDescriptors) const;
+ Point PaintRepresentatives (
+ OutputDevice& rContent,
+ const Size aPreviewSize,
+ const sal_Int32 nOffset,
+ const ::std::vector<controller::Transferable::Representative>& rPages) const;
+ void PaintPageCount (
+ OutputDevice& rDevice,
+ const sal_Int32 nSelectionCount,
+ const Size aPreviewSize,
+ const Point aFirstPageOffset) const;
+ /** Setup the insertion indicator by creating the icon. It consists of
+ scaled down previews of some of the selected pages.
+ */
+ void Create (
+ const ::std::vector<controller::Transferable::Representative>& rPages,
+ const sal_Int32 nSelectionCount);
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
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..997b8159db0b
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx
@@ -0,0 +1,299 @@
+/* -*- 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 "SlideSorter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsTheme.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 {
+
+class InsertPosition;
+
+
+
+/** 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:
+ enum Orientation { HORIZONTAL, VERTICAL, GRID };
+
+ Layouter (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<Theme>& rpTheme);
+ ~Layouter (void);
+
+ ::boost::shared_ptr<PageObjectLayouter> GetPageObjectLayouter (void) const;
+ /** 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 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 eOrientation
+ This defines the generaly layout and specifies whether there may
+ be more than one row or more than one column.
+ @param rWindowSize
+ The size of the window in pixels that the slide sorter is
+ displayed in. This can differ from the size of mpWindow during
+ detection of whether or not the scroll bars should be visible.
+ @param rPreviewModelSize
+ Size of each page in model coordinates.
+ @param rpWindow
+ The map mode of this window 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 Rearrange (
+ const Orientation eOrientation,
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize,
+ const sal_uInt32 nPageCount);
+
+ /** Change the zoom factor. This does not change the general layout
+ (number of columns).
+ */
+ void _SetZoom (double nZoomFactor);
+ void _SetZoom (Fraction nZoomFactor);
+
+ /** Return the number of columns.
+ */
+ sal_Int32 GetColumnCount (void) const;
+
+ sal_Int32 GetRowCount (void) const;
+
+ sal_Int32 GetRow (const sal_Int32 nIndex) const;
+
+ sal_Int32 GetColumn (const sal_Int32 nIndex) const;
+
+ sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) 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 window coordinates of the nIndex-th page
+ object.
+ */
+ Rectangle GetPageObjectBox (
+ const sal_Int32 nIndex,
+ const bool bIncludeBorderAndGap = false) const;
+
+ /** Return the bounding box in model coordinates of the page that
+ contains the given amount of page objects.
+ */
+ Rectangle GetTotalBoundingBox (void) const;
+
+ /** Return the index of the first fully or partially visible page
+ object. This takes into account only the vertical dimension.
+ @return
+ The second index may be larger than the number of existing
+ page objects.
+ */
+ Range GetRangeOfVisiblePageObjects (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.
+ @param bClampToValidRange
+ When <TRUE/> then values outside the valid range [0,mnPageCount)
+ are mapped to 0 (when smaller than 0) or mnPageCount-1 when
+ equal to or larger than mnPageCount.
+ When <FALSE/> then -1 is returned for values outside the valid range.
+ @return
+ The returned index may be larger than the number of existing
+ page objects.
+ */
+ sal_Int32 GetIndexAtPoint (
+ const Point& rModelPosition,
+ const bool bIncludePageBorders = false,
+ const bool bClampToValidRange = true) const;
+
+ /** Return an object that describes the logical and visual properties of
+ where to do an insert operation when the user would release the the
+ mouse button at the given position after a drag operation and of
+ where and how to display an insertion indicator.
+ @param rModelPosition
+ 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 rIndicatorSize
+ The size of the insertion indicator. This size is used to adapt
+ the location when at the left or right of a row or at the top or
+ bottom of a column.
+ @param rModel
+ The model is used to get access to the selection states of the
+ pages. This in turn is used to determine the visual bounding
+ boxes.
+ */
+ InsertPosition GetInsertPosition (
+ const Point& rModelPosition,
+ const Size& rIndicatorSize,
+ model::SlideSorterModel& rModel) const;
+
+ Range GetValidHorizontalSizeRange (void) const;
+ Range GetValidVerticalSizeRange (void) const;
+
+ class Implementation;
+
+private:
+ ::boost::scoped_ptr<Implementation> mpImplementation;
+ SharedSdWindow mpWindow;
+};
+
+
+
+
+
+/** Collect all values concerning the logical and visual properties of the
+ insertion position that is used for drag-and-drop and copy-and-past.
+*/
+class InsertPosition
+{
+public:
+ InsertPosition (void);
+ InsertPosition& operator= (const InsertPosition& rInsertPosition);
+ bool operator== (const InsertPosition& rInsertPosition) const;
+ bool operator!= (const InsertPosition& rInsertPosition) const;
+
+ void SetLogicalPosition (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn,
+ const sal_Int32 nIndex,
+ const bool bIsAtRunStart,
+ const bool bIsAtRunEnd,
+ const bool bIsExtraSpaceNeeded);
+ void SetGeometricalPosition(
+ const Point aLocation,
+ const Point aLeadingOffset,
+ const Point aTrailingOffset);
+
+ sal_Int32 GetRow (void) const { return mnRow; }
+ sal_Int32 GetColumn (void) const { return mnColumn; }
+ sal_Int32 GetIndex (void) const { return mnIndex; }
+ Point GetLocation (void) const { return maLocation; }
+ Point GetLeadingOffset (void) const { return maLeadingOffset; }
+ Point GetTrailingOffset (void) const { return maTrailingOffset; }
+ bool IsAtRunStart (void) const { return mbIsAtRunStart; }
+ bool IsAtRunEnd (void) const { return mbIsAtRunEnd; }
+ bool IsExtraSpaceNeeded (void) const { return mbIsExtraSpaceNeeded; }
+
+private:
+ sal_Int32 mnRow;
+ sal_Int32 mnColumn;
+ sal_Int32 mnIndex;
+ bool mbIsAtRunStart : 1;
+ bool mbIsAtRunEnd : 1;
+ bool mbIsExtraSpaceNeeded : 1;
+ Point maLocation;
+ Point maLeadingOffset;
+ Point maTrailingOffset;
+};
+
+
+
+} } } // 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..27207ed9570b
--- /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/SlsPageObjectLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx
new file mode 100644
index 000000000000..8e61a8b1b47c
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *
+ * 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_LAYOUTER_HXX
+#define SD_SLIDESORTER_PAGE_OBJECT_LAYOUTER_HXX
+
+#include "SlideSorter.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+#include "tools/gen.hxx"
+#include <vcl/image.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+/** In contrast to the Layouter that places page objects in the view, the
+ PageObjectLayouter places the parts of individual page objects like page
+ number area, borders, preview.
+*/
+class PageObjectLayouter
+{
+public:
+ /** Create a new PageObjectLayouter object.
+ @param rPageObjectSize
+ In general either the width or the height will be 0 in order to
+ signal that this size component has to be calculated from the other.
+ This calculation will make the preview as large as possible.
+ @param nPageCount
+ The page count is used to determine how wide the page number
+ area has to be, how many digits to except for the largest page number.
+ */
+ PageObjectLayouter(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const Size& rPageObjectWindowSize,
+ const Size& rPreviewModelSize,
+ const SharedSdWindow& rpWindow,
+ const sal_Int32 nPageCount);
+ ~PageObjectLayouter(void);
+
+ enum Part {
+ // The focus indicator is painted outside the actual page object.
+ FocusIndicator,
+ // This is the outer bounding box that includes the preview, page
+ // number, title.
+ PageObject,
+ // Bounding box of the actual preview.
+ Preview,
+ // Bounding box of the mouse indicator indicator frame.
+ MouseOverIndicator,
+ // Bounding box of the page number.
+ PageNumber,
+ // Bounding box of the pane name.
+ Name,
+ // Indicator whether or not there is a slide transition associated
+ // with this slide.
+ TransitionEffectIndicator
+ };
+ /** Two coordinate systems are supported. They differ only in
+ translation not in scale. Both relate to pixel values in the window.
+ A position in the model coordinate system does not change when the window content is
+ scrolled up or down. In the window coordinate system (relative
+ to the top left point of the window)scrolling leads to different values.
+ */
+ enum CoordinateSystem {
+ WindowCoordinateSystem,
+ ModelCoordinateSystem
+ };
+
+ /** Return the bounding box of the page object or one of its graphical
+ parts.
+ @param rWindow
+ This device is used to translate between model and window
+ coordinates.
+ @param rpPageDescriptor
+ The page for which to calculate the bounding box. This may be
+ NULL. When it is NULL then a generic bounding box is calculated
+ for the location (0,0).
+ @param ePart
+ 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 (
+ const model::SharedPageDescriptor& rpPageDescriptor,
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem);
+ Rectangle GetBoundingBox (
+ const Point& rPageObjectLocation,
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem);
+ Size GetSize (
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem);
+
+ Image GetTransitionEffectIcon (void) const;
+
+private:
+ SharedSdWindow mpWindow;
+ Size maPageObjectSize;
+ double mnModelToWindowScale;
+ Rectangle maFocusIndicatorBoundingBox;
+ Rectangle maPageObjectBoundingBox;
+ Rectangle maPageNumberAreaBoundingBox;
+ Rectangle maPreviewBoundingBox;
+ Rectangle maTransitionEffectBoundingBox;
+ const Image maTransitionEffectIcon;
+ const ::boost::shared_ptr<Font> mpPageNumberFont;
+
+ Size GetPageNumberAreaSize (const int nPageCount);
+ Rectangle CalculatePreviewBoundingBox (
+ Size& rPageObjectSize,
+ const Size& rPreviewModelSize,
+ const sal_Int32 nPageNumberAreaWidth,
+ const sal_Int32 nFocusIndicatorWidth);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx
new file mode 100644
index 000000000000..e4e28a2e38b2
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * 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_PAINTER_HEADER
+#define SD_SLIDESORTER_PAGE_OBJECT_PAINTER_HEADER
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsTheme.hxx"
+#include <boost/scoped_ptr.hpp>
+
+namespace sd { namespace slidesorter { namespace cache {
+class PageCache;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+class ButtonBar;
+class Layouter;
+class PageObjectLayouter;
+class FramePainter;
+
+class PageObjectPainter
+{
+public:
+ PageObjectPainter (const SlideSorter& rSlideSorter);
+ ~PageObjectPainter (void);
+
+ void PaintPageObject (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor);
+
+ void NotifyResize (const bool bForce = false);
+
+ /** Called when the theme changes, either because it is replaced with
+ another or because the system colors have changed. So, even when
+ the given theme is the same object as the one already in use by this
+ painter everything that depends on the theme is updated.
+ */
+ void SetTheme (const ::boost::shared_ptr<view::Theme>& rpTheme);
+
+ /** Return a preview bitmap for the given page descriptor. When the
+ page is excluded from the show then the preview is marked
+ accordingly.
+ @rpDescriptor
+ Defines the page for which to return the preview.
+ @pReferenceDevice
+ When not <NULL/> then this reference device is used to created a
+ compatible bitmap.
+ @return
+ The returned bitmap may have a different size then the preview area.
+ */
+ Bitmap GetPreviewBitmap (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const OutputDevice* pReferenceDevice) const;
+
+private:
+ const Layouter& mrLayouter;
+ ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
+ ::boost::shared_ptr<cache::PageCache> mpCache;
+ ::boost::shared_ptr<controller::Properties> mpProperties;
+ ::boost::shared_ptr<view::Theme> mpTheme;
+ ::boost::shared_ptr<Font> mpPageNumberFont;
+ ::boost::scoped_ptr<FramePainter> mpShadowPainter;
+ ::boost::scoped_ptr<FramePainter> mpFocusBorderPainter;
+ Bitmap maNormalBackground;
+ Bitmap maSelectionBackground;
+ Bitmap maFocusedSelectionBackground;
+ Bitmap maFocusedBackground;
+ Bitmap maMouseOverBackground;
+ Bitmap maMouseOverFocusedBackground;
+ Bitmap maMouseOverSelectedAndFocusedBackground;
+ ::rtl::OUString msUnhideString;
+ ButtonBar& mrButtonBar;
+
+ void PaintBackground (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor);
+ void PaintPreview (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const;
+ void PaintPageNumber (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const;
+ void PaintTransitionEffect (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const;
+ void PaintBorder (
+ OutputDevice& rDevice,
+ const Theme::GradientColorType eColorType,
+ const Rectangle& rBox) const;
+ Bitmap& GetBackgroundForState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const OutputDevice& rTemplateDevice);
+ Bitmap& GetBackground(
+ Bitmap& rBackground,
+ Theme::GradientColorType eType,
+ const OutputDevice& rTemplateDevice,
+ const bool bHasFocusBorder);
+ Bitmap CreateBackgroundBitmap(
+ const OutputDevice& rReferenceDevice,
+ const Theme::GradientColorType eType,
+ const bool bHasFocusBorder) const;
+ Bitmap CreateMarkedPreview(
+ const Size& rSize,
+ const Bitmap& rPreview,
+ const BitmapEx& rOverlay,
+ const OutputDevice* pReferenceDevice) const;
+};
+
+} } } // end of namespace sd::slidesorter::view
+
+#endif
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..815a9382b682
--- /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..4040d31aa694
--- /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/SlsResource.hrc b/sd/source/ui/slidesorter/inc/view/SlsResource.hrc
new file mode 100644
index 000000000000..2b85a37d35dc
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsResource.hrc
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * 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_ICONS_HRC
+#define SD_SLIDESORTER_ICONS_HRC
+
+#include "glob.hrc"
+
+#define IMAGE_COMMAND1_LARGE 1
+#define IMAGE_COMMAND1_LARGE_HOVER 2
+#define IMAGE_COMMAND1_MEDIUM 3
+#define IMAGE_COMMAND1_MEDIUM_HOVER 4
+#define IMAGE_COMMAND1_SMALL 5
+#define IMAGE_COMMAND1_SMALL_HOVER 6
+
+#define IMAGE_COMMAND1_LARGE_HC 7
+#define IMAGE_COMMAND1_LARGE_HOVER_HC 8
+#define IMAGE_COMMAND1_MEDIUM_HC 9
+#define IMAGE_COMMAND1_MEDIUM_HOVER_HC 10
+#define IMAGE_COMMAND1_SMALL_HC 11
+#define IMAGE_COMMAND1_SMALL_HOVER_HC 12
+
+
+#define IMAGE_COMMAND2_LARGE 20
+#define IMAGE_COMMAND2_LARGE_HOVER 21
+#define IMAGE_COMMAND2_MEDIUM 22
+#define IMAGE_COMMAND2_MEDIUM_HOVER 23
+#define IMAGE_COMMAND2_SMALL 24
+#define IMAGE_COMMAND2_SMALL_HOVER 25
+
+#define IMAGE_COMMAND2_LARGE_HC 26
+#define IMAGE_COMMAND2_LARGE_HOVER_HC 27
+#define IMAGE_COMMAND2_MEDIUM_HC 28
+#define IMAGE_COMMAND2_MEDIUM_HOVER_HC 29
+#define IMAGE_COMMAND2_SMALL_HC 30
+#define IMAGE_COMMAND2_SMALL_HOVER_HC 31
+
+#define IMAGE_COMMAND2B_LARGE 40
+#define IMAGE_COMMAND2B_LARGE_HOVER 41
+#define IMAGE_COMMAND2B_MEDIUM 42
+#define IMAGE_COMMAND2B_MEDIUM_HOVER 43
+#define IMAGE_COMMAND2B_SMALL 44
+#define IMAGE_COMMAND2B_SMALL_HOVER 45
+
+#define IMAGE_COMMAND2B_LARGE_HC 46
+#define IMAGE_COMMAND2B_LARGE_HOVER_HC 47
+#define IMAGE_COMMAND2B_MEDIUM_HC 48
+#define IMAGE_COMMAND2B_MEDIUM_HOVER_HC 49
+#define IMAGE_COMMAND2B_SMALL_HC 50
+#define IMAGE_COMMAND2B_SMALL_HOVER_HC 51
+
+
+#define IMAGE_COMMAND3_LARGE 60
+#define IMAGE_COMMAND3_LARGE_HOVER 61
+#define IMAGE_COMMAND3_MEDIUM 62
+#define IMAGE_COMMAND3_MEDIUM_HOVER 63
+#define IMAGE_COMMAND3_SMALL 64
+#define IMAGE_COMMAND3_SMALL_HOVER 65
+
+#define IMAGE_COMMAND3_LARGE_HC 66
+#define IMAGE_COMMAND3_LARGE_HOVER_HC 67
+#define IMAGE_COMMAND3_MEDIUM_HC 68
+#define IMAGE_COMMAND3_MEDIUM_HOVER_HC 69
+#define IMAGE_COMMAND3_SMALL_HC 70
+#define IMAGE_COMMAND3_SMALL_HOVER_HC 71
+
+#define IMAGE_BUTTONBAR_LARGE 80
+#define IMAGE_BUTTONBAR_LARGE_HC 81
+#define IMAGE_BUTTONBAR_MEDIUM 82
+#define IMAGE_BUTTONBAR_MEDIUM_HC 83
+#define IMAGE_BUTTONBAR_SMALL 84
+#define IMAGE_BUTTONBAR_SMALL_HC 85
+
+#define IMAGE_SHADOW 90
+#define IMAGE_INSERT_SHADOW 91
+#define IMAGE_HIDE_SLIDE_OVERLAY 92
+#define IMAGE_FOCUS_BORDER 93
+
+#define STRING_DRAG_AND_DROP_PAGES 101
+#define STRING_DRAG_AND_DROP_SLIDES 102
+
+#define STRING_COMMAND1 110
+#define STRING_COMMAND2_A 111
+#define STRING_COMMAND2_B 112
+#define STRING_COMMAND3 113
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx
new file mode 100644
index 000000000000..0781d8ea3519
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * 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_THEME_HXX
+#define SD_SLIDESORTER_VIEW_THEME_HXX
+
+#include "model/SlsVisualState.hxx"
+
+#include <vcl/bitmapex.hxx>
+#include <vcl/font.hxx>
+#include <vcl/gradient.hxx>
+#include <tools/color.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+
+namespace sd { namespace slidesorter { namespace controller {
+class Properties;
+} } }
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+/** Collection of colors and styles that are used to paint the slide sorter
+ view.
+*/
+class Theme
+{
+public:
+ Theme (const ::boost::shared_ptr<controller::Properties>& rpProperties);
+
+ /** Call this method to update some colors as response to a change of
+ a system color change.
+ */
+ void Update (
+ const ::boost::shared_ptr<controller::Properties>& rpProperties);
+
+ // BitmapEx GetInsertIndicatorIcon (void) const;
+
+ enum FontType {
+ Font_PageNumber,
+ Font_PageCount,
+ Font_Button
+ };
+ static ::boost::shared_ptr<Font> GetFont (
+ const FontType eType,
+ const OutputDevice& rDevice);
+
+ enum ColorType {
+ Color_Background,
+ Color_ButtonBackground,
+ Color_ButtonText,
+ Color_ButtonTextHover,
+ Color_PageNumberDefault,
+ Color_PageNumberHover,
+ Color_PageNumberHighContrast,
+ Color_PageNumberBrightBackground,
+ Color_PageNumberDarkBackground,
+ Color_Selection,
+ Color_PreviewBorder,
+ Color_PageCountFontColor,
+ _ColorType_Size_
+ };
+ ColorData GetColor (const ColorType eType);
+ void SetColor (const ColorType eType, const ColorData aColorData);
+
+ enum GradientColorType {
+ Gradient_NormalPage,
+ Gradient_SelectedPage,
+ Gradient_SelectedAndFocusedPage,
+ Gradient_MouseOverPage,
+ Gradient_MouseOverSelectedAndFocusedPage,
+ Gradient_FocusedPage,
+ Gradient_ButtonBackground,
+ _GradientColorType_Size_
+ };
+ enum GradientColorClass {
+ Border1,
+ Border2,
+ Fill1,
+ Fill2,
+ Base
+ };
+ ColorData GetGradientColor (
+ const GradientColorType eType,
+ const GradientColorClass eClass);
+ sal_Int32 GetGradientOffset (
+ const GradientColorType eType,
+ const GradientColorClass eClass);
+ void SetGradient (
+ const GradientColorType eType,
+ const ColorData aBaseColor,
+ const sal_Int32 nSaturationOverride,
+ const sal_Int32 nBrightnessOverride,
+ const sal_Int32 nFillStartOffset,
+ const sal_Int32 nFillEndOffset,
+ const sal_Int32 nBorderStartOffset,
+ const sal_Int32 nBorderEndOffset);
+ sal_Int32 GetGradientSaturationOverride (const GradientColorType eType);
+ sal_Int32 GetGradientBrightnessOverride (const GradientColorType eType);
+ void SetGradientSaturationOverride (const GradientColorType eType, const sal_Int32 nValue);
+ void SetGradientBrightnessOverride (const GradientColorType eType, const sal_Int32 nValue);
+
+ enum IconType
+ {
+ Icon_RawShadow,
+ Icon_RawInsertShadow,
+ Icon_HideSlideOverlay,
+ Icon_FocusBorder,
+ Icon_ButtonBarLarge,
+ Icon_ButtonBarMedium,
+ Icon_ButtonBarSmall,
+ Icon_Command1Large,
+ Icon_Command1LargeHover,
+ Icon_Command1Medium,
+ Icon_Command1MediumHover,
+ Icon_Command1Small,
+ Icon_Command1SmallHover,
+ Icon_Command2Large,
+ Icon_Command2LargeHover,
+ Icon_Command2Medium,
+ Icon_Command2MediumHover,
+ Icon_Command2Small,
+ Icon_Command2SmallHover,
+ Icon_Command2BLarge,
+ Icon_Command2BLargeHover,
+ Icon_Command2BMedium,
+ Icon_Command2BMediumHover,
+ Icon_Command2BSmall,
+ Icon_Command2BSmallHover,
+ Icon_Command3Large,
+ Icon_Command3LargeHover,
+ Icon_Command3Medium,
+ Icon_Command3MediumHover,
+ Icon_Command3Small,
+ Icon_Command3SmallHover,
+ _IconType_Size_
+ };
+ const BitmapEx& GetIcon (const IconType eType);
+
+ enum IntegerValueType
+ {
+ Integer_ButtonCornerRadius,
+ Integer_ButtonMaxAlpha,
+ Integer_ButtonBarMaxAlpha,
+ Integer_ButtonPaintType,
+ Integer_ButtonBorder,
+ Integer_ButtonGap,
+ Integer_ButtonFadeInDelay,
+ Integer_ButtonFadeInDuration,
+ Integer_ButtonFadeOutDelay,
+ Integer_ButtonFadeOutDuration,
+ Integer_ToolTipDelay,
+ Integer_FocusIndicatorWidth,
+ _IntegerValueType_Size_
+ };
+ sal_Int32 GetIntegerValue (const IntegerValueType eType) const;
+ void SetIntegerValue (const IntegerValueType eType, const sal_Int32 nValue);
+
+ enum StringType
+ {
+ String_Unhide,
+ String_DragAndDropPages,
+ String_DragAndDropSlides,
+ String_Command1,
+ String_Command2,
+ String_Command2B,
+ String_Command3,
+ _StringType_Size_
+ };
+ ::rtl::OUString GetString (const StringType eType) const;
+
+private:
+ bool mbIsHighContrastMode;
+ class GradientDescriptor
+ {
+ public:
+ ColorData maBaseColor;
+
+ sal_Int32 mnSaturationOverride;
+ sal_Int32 mnBrightnessOverride;
+
+ ColorData maFillColor1;
+ ColorData maFillColor2;
+ ColorData maBorderColor1;
+ ColorData maBorderColor2;
+
+ sal_Int32 mnFillOffset1;
+ sal_Int32 mnFillOffset2;
+ sal_Int32 mnBorderOffset1;
+ sal_Int32 mnBorderOffset2;
+ };
+ ColorData maBackgroundColor;
+ ColorData maPageBackgroundColor;
+ ::std::vector<GradientDescriptor> maGradients;
+ ::std::vector<BitmapEx> maIcons;
+ ::std::vector<ColorData> maColor;
+ ::std::vector<sal_Int32> maIntegerValues;
+ ::std::vector<rtl::OUString> maStrings;
+
+ GradientDescriptor& GetGradient (const GradientColorType eType);
+ /** Guarded initialization of the specified icon in the maIcons
+ container. Call only while a LocalResource object is active.
+ */
+ void InitializeIcon (const IconType eType, sal_uInt16 nResourceId);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx b/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx
new file mode 100644
index 000000000000..48a4c7c3d272
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * 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_TOOL_TIP_HXX
+#define SD_SLIDESORTER_VIEW_TOOL_TIP_HXX
+
+#include "SlideSorter.hxx"
+#include "model/SlsSharedPageDescriptor.hxx"
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** Manage the display of tool tips. The tool tip text changes when the
+ mouse is moved from slide to slide or from button to button.
+ After the mouse enters a slide the first display of the tool tip is
+ delayed for a short time in order to not draw attention from the slide
+ or its button bar.
+*/
+class ToolTip
+{
+public:
+ ToolTip (SlideSorter& rSlideSorter);
+ ~ToolTip (void);
+
+ /** Set a new page. This modifies the default help text. After a page
+ change a timer is started to delay the display of the tool tip for
+ the new page.
+ @param rpPage
+ When this is empty then the tool tip is hidden.
+ */
+ void SetPage (const model::SharedPageDescriptor& rpPage);
+
+ /** Set and show the default help text.
+ */
+ void ShowDefaultHelpText (const ::rtl::OUString& rsHelpText);
+
+ /** Show a previously set default help text.
+ */
+ void ShowDefaultHelpText (void);
+
+ /** Show a temporary help text.
+ */
+ void ShowHelpText (const ::rtl::OUString& rsHelpText);
+
+ /** Hide the tool tip.
+ @return
+ Returns whether the tool tip was visible at the time this method
+ was called.
+ */
+ bool Hide (void);
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SharedPageDescriptor mpDescriptor;
+ ::rtl::OUString msDefaultHelpText;
+ ::rtl::OUString msCurrentHelpText;
+ sal_uLong mnHelpWindowHandle;
+ Timer maTimer;
+
+ /** Request to show the tool tip.
+ @param bForce
+ When <TRUE/> then the tool tip is show right away. Otherwise it
+ is shown after a short delay.
+ */
+ void Show (const bool bForce);
+ void DoShow (void);
+
+ DECL_LINK(DelayTrigger, void*);
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
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..57c887d6f02c
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx
@@ -0,0 +1,740 @@
+/* -*- 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/SlsProperties.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSlotManager.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 "DrawDocShell.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;
+ };
+
+ bool PrintModel (const SlideSorterModel& rModel)
+ {
+ for (sal_Int32 nIndex=0,nCount=rModel.GetPageCount(); nIndex<nCount; ++nIndex)
+ {
+ SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
+ if (pDescriptor)
+ {
+ OSL_TRACE("%d %d %d %d %x",
+ nIndex,
+ pDescriptor->GetPageIndex(),
+ pDescriptor->GetVisualState().mnPageId,
+ FromCoreIndex(pDescriptor->GetPage()->GetPageNum()),
+ pDescriptor->GetPage());
+ }
+ else
+ {
+ OSL_TRACE("%d", nIndex);
+ }
+ }
+
+ return true;
+ }
+ bool CheckModel (const SlideSorterModel& rModel)
+ {
+ for (sal_Int32 nIndex=0,nCount=rModel.GetPageCount(); nIndex<nCount; ++nIndex)
+ {
+ SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
+ if ( ! pDescriptor)
+ {
+ PrintModel(rModel);
+ OSL_ASSERT(pDescriptor);
+ return false;
+ }
+ if (nIndex != pDescriptor->GetPageIndex())
+ {
+ PrintModel(rModel);
+ OSL_ASSERT(nIndex == pDescriptor->GetPageIndex());
+ return false;
+ }
+ if (nIndex != pDescriptor->GetVisualState().mnPageId)
+ {
+ PrintModel(rModel);
+ OSL_ASSERT(nIndex == pDescriptor->GetVisualState().mnPageId);
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+
+
+
+SlideSorterModel::SlideSorterModel (SlideSorter& rSlideSorter)
+ : maMutex(),
+ mrSlideSorter(rSlideSorter),
+ mxSlides(),
+ mePageKind(PK_STANDARD),
+ meEditMode(EM_PAGE),
+ maPageDescriptors(0)
+{
+}
+
+
+
+
+SlideSorterModel::~SlideSorterModel (void)
+{
+ ClearDescriptorList ();
+}
+
+
+
+
+void SlideSorterModel::Init (void)
+{
+}
+
+
+
+
+void SlideSorterModel::Dispose (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())
+ {
+ SdPage* pPage = GetPage(nPageIndex);
+ pDescriptor.reset(new PageDescriptor (
+ Reference<drawing::XDrawPage>(mxSlides->getByIndex(nPageIndex),UNO_QUERY),
+ pPage,
+ nPageIndex));
+ 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(RTL_CONSTASCII_USTRINGPARAM("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;
+}
+
+
+
+
+sal_Int32 SlideSorterModel::GetIndex (const SdrPage* pPage) const
+{
+ if (pPage == NULL)
+ return -1;
+
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // First try to guess the right index.
+ sal_Int16 nNumber ((pPage->GetPageNum()-1)/2);
+ SharedPageDescriptor pDescriptor (GetPageDescriptor(nNumber, false));
+ if (pDescriptor.get() != NULL
+ && pDescriptor->GetPage() == pPage)
+ {
+ return nNumber;
+ }
+
+ // 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)
+ {
+ 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->GetPage() == pPage)
+ return nIndex;
+ }
+
+ return -1;
+}
+
+
+
+
+sal_uInt16 SlideSorterModel::GetCoreIndex (const sal_Int32 nIndex) const
+{
+ SharedPageDescriptor pDescriptor (GetPageDescriptor(nIndex));
+ if (pDescriptor)
+ return pDescriptor->GetPage()->GetPageNum();
+ else
+ return mxSlides->getCount()*2+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);
+
+ // Check if document and this model really differ.
+ bool bIsUpToDate (true);
+ SdDrawDocument* pDocument = GetDocument();
+ if (pDocument!=NULL && maPageDescriptors.size()==pDocument->GetSdPageCount(mePageKind))
+ {
+ for (sal_Int32 nIndex=0,nCount=maPageDescriptors.size(); nIndex<nCount; ++nIndex)
+ {
+ if (maPageDescriptors[nIndex]
+ && maPageDescriptors[nIndex]->GetPage()
+ != GetPage(nIndex))
+ {
+ OSL_TRACE("page %d differs\n", nIndex);
+ bIsUpToDate = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bIsUpToDate = false;
+ OSL_TRACE("models differ");
+ }
+
+ if ( ! bIsUpToDate)
+ {
+ SynchronizeDocumentSelection(); // Try to make the current selection persistent.
+ ClearDescriptorList ();
+ AdaptSize();
+ SynchronizeModelSelection();
+ mrSlideSorter.GetController().GetPageSelector().CountSelectedPages();
+ }
+ CheckModel(*this);
+}
+
+
+
+
+void SlideSorterModel::ClearDescriptorList (void)
+{
+ DescriptorContainer aDescriptors;
+
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ aDescriptors.swap(maPageDescriptors);
+ }
+
+ for (DescriptorContainer::iterator iDescriptor=aDescriptors.begin(), iEnd=aDescriptors.end();
+ iDescriptor!=iEnd;
+ ++iDescriptor)
+ {
+ if (iDescriptor->get() != NULL)
+ {
+ if ( ! iDescriptor->unique())
+ {
+ OSL_TRACE("SlideSorterModel::ClearDescriptorList: trying to delete page descriptor that is still used with count %d", iDescriptor->use_count());
+ // No assertion here because that can hang the office when
+ // opening a dialog from here.
+ }
+ iDescriptor->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->HasState(PageDescriptor::ST_Selected));
+ }
+}
+
+
+
+
+void SlideSorterModel::SynchronizeModelSelection (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->SetState(PageDescriptor::ST_Selected, pDescriptor->GetPage()->IsSelected());
+ }
+}
+
+
+
+
+::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()->NotifyCurrentSlideChange(-1);
+
+ mxSlides = rxSlides;
+ Resync();
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ {
+ SdPage* pPage = pViewShell->getCurrentPage();
+ if (pPage != NULL)
+ mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
+ pPage);
+ 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()->NotifyCurrentSlideChange(
+ pFrameView->GetSelectedPage());
+ else
+ {
+ // No frame view. As a last resort use the first slide as
+ // current slide.
+ mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
+ sal_Int32(0));
+ }
+ }
+ }
+
+ mrSlideSorter.GetController().GetSlotManager()->NotifyEditModeChange();
+}
+
+
+
+
+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);
+}
+
+
+
+
+bool SlideSorterModel::IsReadOnly (void) const
+{
+ if (mrSlideSorter.GetViewShellBase() != NULL
+ && mrSlideSorter.GetViewShellBase()->GetDocShell())
+ return mrSlideSorter.GetViewShellBase()->GetDocShell()->IsReadOnly();
+ else
+ return true;
+}
+
+
+
+
+void SlideSorterModel::SaveCurrentSelection (void)
+{
+ PageEnumeration aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ pDescriptor->SetState(
+ PageDescriptor::ST_WasSelected,
+ pDescriptor->HasState(PageDescriptor::ST_Selected));
+ }
+}
+
+
+
+
+Region SlideSorterModel::RestoreSelection (void)
+{
+ Region aRepaintRegion;
+ PageEnumeration aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ if (pDescriptor->SetState(
+ PageDescriptor::ST_Selected,
+ pDescriptor->HasState(PageDescriptor::ST_WasSelected)))
+ {
+ aRepaintRegion.Union(pDescriptor->GetBoundingBox());
+ }
+ }
+ return aRepaintRegion;
+}
+
+
+
+
+bool SlideSorterModel::NotifyPageEvent (const SdrPage* pSdrPage)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ SdPage* pPage = const_cast<SdPage*>(dynamic_cast<const SdPage*>(pSdrPage));
+ if (pPage == NULL)
+ return false;
+
+ // We are only interested in pages that are currently served by this
+ // model.
+ if (pPage->GetPageKind() != mePageKind)
+ return false;
+ if (pPage->IsMasterPage() != (meEditMode==EM_MASTERPAGE))
+ return false;
+
+ if (pPage->IsInserted())
+ InsertSlide(pPage);
+ else
+ DeleteSlide(pPage);
+ CheckModel(*this);
+
+ return true;
+}
+
+
+
+
+void SlideSorterModel::InsertSlide (SdPage* pPage)
+{
+ // Find the index at which to insert the given page.
+ sal_uInt16 nCoreIndex (pPage->GetPageNum());
+ sal_Int32 nIndex (FromCoreIndex(nCoreIndex));
+ if (pPage != GetPage(nIndex))
+ return;
+
+ // Check that the pages in the document before and after the given page
+ // are present in this model.
+ if (nIndex>0)
+ if (GetPage(nIndex-1) != GetPageDescriptor(nIndex-1)->GetPage())
+ return;
+ if (size_t(nIndex)<maPageDescriptors.size()-1)
+ if (GetPage(nIndex+1) != GetPageDescriptor(nIndex)->GetPage())
+ return;
+
+ // Insert the given page at index nIndex
+ maPageDescriptors.insert(
+ maPageDescriptors.begin()+nIndex,
+ SharedPageDescriptor(
+ new PageDescriptor (
+ Reference<drawing::XDrawPage>(mxSlides->getByIndex(nIndex),UNO_QUERY),
+ pPage,
+ nIndex)));
+
+ // Update page indices.
+ UpdateIndices(nIndex+1);
+ OSL_TRACE("page inserted");
+}
+
+
+
+
+void SlideSorterModel::DeleteSlide (const SdPage* pPage)
+{
+ const sal_Int32 nIndex (GetIndex(pPage));
+ if (maPageDescriptors[nIndex])
+ if (maPageDescriptors[nIndex]->GetPage() != pPage)
+ return;
+
+ maPageDescriptors.erase(maPageDescriptors.begin()+nIndex);
+ UpdateIndices(nIndex);
+ OSL_TRACE("page removed");
+}
+
+
+
+
+void SlideSorterModel::UpdateIndices (const sal_Int32 nFirstIndex)
+{
+ for (sal_Int32 nDescriptorIndex=0,nCount=maPageDescriptors.size();
+ nDescriptorIndex<nCount;
+ ++nDescriptorIndex)
+ {
+ SharedPageDescriptor& rpDescriptor (maPageDescriptors[nDescriptorIndex]);
+ if (rpDescriptor)
+ {
+ if (nDescriptorIndex < nFirstIndex)
+ {
+ if (rpDescriptor->GetPageIndex()!=nDescriptorIndex)
+ {
+ OSL_ASSERT(rpDescriptor->GetPageIndex()==nDescriptorIndex);
+ }
+ }
+ else
+ {
+ rpDescriptor->SetPageIndex(nDescriptorIndex);
+ }
+ }
+ }
+}
+
+
+
+
+SdPage* SlideSorterModel::GetPage (const sal_Int32 nSdIndex) const
+{
+ SdDrawDocument* pModel = const_cast<SlideSorterModel*>(this)->GetDocument();
+ if (pModel != NULL)
+ {
+ if (meEditMode == EM_PAGE)
+ return pModel->GetSdPage ((sal_uInt16)nSdIndex, mePageKind);
+ else
+ return pModel->GetMasterSdPage ((sal_uInt16)nSdIndex, mePageKind);
+ }
+ else
+ return NULL;
+}
+
+
+} } } // 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..bb1beb58f2ff
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx
@@ -0,0 +1,292 @@
+/* -*- 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 "sdpage.hxx"
+#include "drawdoc.hxx"
+
+#include <svx/svdopage.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/sdr/contact/viewcontact.hxx>
+#include <svx/sdr/contact/viewobjectcontact.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)
+ : mpPage(pPage),
+ mxPage(rxPage),
+ mpMasterPage(NULL),
+ mnIndex(nIndex),
+ maBoundingBox(),
+ maVisualState(nIndex),
+ mbIsSelected(false),
+ mbWasSelected(false),
+ mbIsVisible(false),
+ mbIsFocused(false),
+ mbIsCurrent(false),
+ mbIsMouseOver(false)
+{
+ OSL_ASSERT(mpPage);
+ OSL_ASSERT(mpPage == SdPage::getImplementation(rxPage));
+ if (mpPage!=NULL && mpPage->TRG_HasMasterPage())
+ mpMasterPage = &mpPage->TRG_GetMasterPage();
+}
+
+
+
+
+PageDescriptor::~PageDescriptor (void)
+{
+}
+
+
+
+
+SdPage* PageDescriptor::GetPage (void) const
+{
+ return mpPage;
+}
+
+
+
+
+Reference<drawing::XDrawPage> PageDescriptor::GetXDrawPage (void) const
+{
+ return mxPage;
+}
+
+
+
+
+sal_Int32 PageDescriptor::GetPageIndex (void) const
+{
+ return mnIndex;
+}
+
+
+
+
+void PageDescriptor::SetPageIndex (const sal_Int32 nNewIndex)
+{
+ mnIndex = nNewIndex;
+ maVisualState.mnPageId = nNewIndex;
+}
+
+
+
+
+bool PageDescriptor::UpdateMasterPage (void)
+{
+ const SdrPage* pMaster = NULL;
+ if (mpPage!=NULL && mpPage->TRG_HasMasterPage())
+ pMaster = &mpPage->TRG_GetMasterPage();
+ if (mpMasterPage != pMaster)
+ {
+ mpMasterPage = pMaster;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool PageDescriptor::HasState (const State eState) const
+{
+ switch (eState)
+ {
+ case ST_Visible:
+ return mbIsVisible;
+
+ case ST_Selected:
+ return mbIsSelected;
+
+ case ST_WasSelected:
+ return mbWasSelected;
+
+ case ST_Focused:
+ return mbIsFocused;
+
+ case ST_MouseOver:
+ return mbIsMouseOver;
+
+ case ST_Current:
+ return mbIsCurrent;
+
+ case ST_Excluded:
+ return mpPage!=NULL && mpPage->IsExcluded();
+
+ default:
+ OSL_ASSERT(false);
+ return false;
+ }
+}
+
+
+
+
+bool PageDescriptor::SetState (const State eState, const bool bNewStateValue)
+{
+ bool bModified (false);
+ switch (eState)
+ {
+ case ST_Visible:
+ bModified = (bNewStateValue!=mbIsVisible);
+ if (bModified)
+ mbIsVisible = bNewStateValue;
+ break;
+
+ case ST_Selected:
+ bModified = (bNewStateValue!=mbIsSelected);
+ if (bModified)
+ mbIsSelected = bNewStateValue;
+ break;
+
+ case ST_WasSelected:
+ bModified = (bNewStateValue!=mbWasSelected);
+ if (bModified)
+ mbWasSelected = bNewStateValue;
+ break;
+
+ case ST_Focused:
+ bModified = (bNewStateValue!=mbIsFocused);
+ if (bModified)
+ mbIsFocused = bNewStateValue;
+ break;
+
+ case ST_MouseOver:
+ bModified = (bNewStateValue!=mbIsMouseOver);
+ if (bModified)
+ mbIsMouseOver = bNewStateValue;
+ break;
+
+ case ST_Current:
+ bModified = (bNewStateValue!=mbIsCurrent);
+ if (bModified)
+ mbIsCurrent = bNewStateValue;
+ break;
+
+ case ST_Excluded:
+ // This is a state of the page and has to be handled differently
+ // from the view-only states.
+ if (mpPage != NULL)
+ if (bNewStateValue != (mpPage->IsExcluded()==sal_True))
+ {
+ mpPage->SetExcluded(bNewStateValue);
+ bModified = true;
+ }
+ break;
+ }
+
+ if (bModified)
+ maVisualState.UpdateVisualState(*this);
+ return bModified;
+}
+
+
+
+
+VisualState& PageDescriptor::GetVisualState (void)
+{
+ return maVisualState;
+}
+
+
+
+
+bool PageDescriptor::GetCoreSelection (void)
+{
+ if (mpPage!=NULL && (mpPage->IsSelected()==sal_True) != mbIsSelected)
+ return SetState(ST_Selected, !mbIsSelected);
+ else
+ return false;
+}
+
+
+
+
+void PageDescriptor::SetCoreSelection (void)
+{
+ if (mpPage != NULL)
+ if (HasState(ST_Selected))
+ mpPage->SetSelected(sal_True);
+ else
+ mpPage->SetSelected(sal_False);
+ else
+ {
+ OSL_ASSERT(mpPage!=NULL);
+ }
+}
+
+
+
+
+Rectangle PageDescriptor::GetBoundingBox (void) const
+{
+ Rectangle aBox (maBoundingBox);
+ const Point aOffset (maVisualState.GetLocationOffset());
+ aBox.Move(aOffset.X(), aOffset.Y());
+ return aBox;
+}
+
+
+
+
+Point PageDescriptor::GetLocation (const bool bIgnoreOffset) const
+{
+ if (bIgnoreOffset)
+ return maBoundingBox.TopLeft();
+ else
+ return maBoundingBox.TopLeft() + maVisualState.GetLocationOffset();
+}
+
+
+
+
+void PageDescriptor::SetBoundingBox (const Rectangle& rBoundingBox)
+{
+ maBoundingBox = rBoundingBox;
+}
+
+
+
+} } } // 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..3eac80cbd5b0
--- /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..98240924a75c
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx
@@ -0,0 +1,112 @@
+/* -*- 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) const
+ {
+ (void)rpDescriptor;
+ return true;
+ }
+};
+
+
+
+
+
+class SelectedPagesPredicate
+{
+public:
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ {
+ return rpDescriptor->HasState(PageDescriptor::ST_Selected);
+ }
+};
+
+
+
+
+class VisiblePagesPredicate
+{
+public:
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ {
+ return rpDescriptor->HasState(PageDescriptor::ST_Visible);
+ }
+};
+
+}
+
+
+
+
+PageEnumeration PageEnumerationProvider::CreateAllPagesEnumeration (
+ const SlideSorterModel& rModel)
+{
+ 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/SlsVisualState.cxx b/sd/source/ui/slidesorter/model/SlsVisualState.cxx
new file mode 100644
index 000000000000..3dee5e914ab9
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlsVisualState.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * 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/SlsVisualState.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "controller/SlsAnimator.hxx"
+
+namespace sd { namespace slidesorter { namespace model {
+
+VisualState::VisualState (const sal_Int32 nPageId)
+ : mnPageId(nPageId),
+ meCurrentVisualState(VS_None),
+ meOldVisualState(VS_None),
+ mnVisualStateBlend(1.0),
+ mnStateAnimationId(controller::Animator::NotAnAnimationId),
+ maLocationOffset(0,0),
+ mnLocationAnimationId(controller::Animator::NotAnAnimationId),
+ mnButtonAlpha(1.0),
+ mnButtonBarAlpha(1.0),
+ mnButtonAlphaAnimationId(controller::Animator::NotAnAnimationId)
+{
+}
+
+
+
+
+VisualState::~VisualState (void)
+{
+ if (mnStateAnimationId != controller::Animator::NotAnAnimationId
+ || mnLocationAnimationId != controller::Animator::NotAnAnimationId)
+ {
+ OSL_ASSERT(mnStateAnimationId == controller::Animator::NotAnAnimationId);
+ OSL_ASSERT(mnLocationAnimationId == controller::Animator::NotAnAnimationId);
+ }
+}
+
+
+
+
+VisualState::State VisualState::GetCurrentVisualState (void) const
+{
+ return meCurrentVisualState;
+}
+
+
+
+
+VisualState::State VisualState::GetOldVisualState (void) const
+{
+ return meOldVisualState;
+}
+
+
+
+
+void VisualState::SetVisualState (const State eState)
+{
+ meOldVisualState = meCurrentVisualState;
+ meCurrentVisualState = eState;
+ mnVisualStateBlend = 1.0;
+}
+
+
+
+
+double VisualState::GetVisualStateBlend (void) const
+{
+ return mnVisualStateBlend;
+}
+
+
+
+
+void VisualState::SetVisualStateBlend (const double nBlend)
+{
+ mnVisualStateBlend = nBlend;
+}
+
+
+
+
+void VisualState::UpdateVisualState (const PageDescriptor& rDescriptor)
+{
+ if (rDescriptor.HasState(PageDescriptor::ST_Excluded))
+ SetVisualState(VS_Excluded);
+ else if (rDescriptor.HasState(PageDescriptor::ST_Current))
+ SetVisualState(VS_Current);
+ else if (rDescriptor.HasState(PageDescriptor::ST_Focused))
+ SetVisualState(VS_Focused);
+ else if (rDescriptor.HasState(PageDescriptor::ST_Selected))
+ SetVisualState(VS_Selected);
+ else
+ SetVisualState(VS_None);
+
+ SetMouseOverState(rDescriptor.HasState(PageDescriptor::ST_MouseOver));
+}
+
+
+
+
+void VisualState::SetMouseOverState (const bool bIsMouseOver)
+{
+ mbOldMouseOverState = mbCurrentMouseOverState;
+ mbCurrentMouseOverState = bIsMouseOver;
+}
+
+
+
+
+sal_Int32 VisualState::GetStateAnimationId (void) const
+{
+ return mnStateAnimationId;
+}
+
+
+
+
+void VisualState::SetStateAnimationId (const sal_Int32 nAnimationId)
+{
+ mnStateAnimationId = nAnimationId;
+}
+
+
+
+
+Point VisualState::GetLocationOffset (void) const
+{
+ return maLocationOffset;
+}
+
+
+
+
+bool VisualState::SetLocationOffset (const Point& rOffset)
+{
+ if (maLocationOffset != rOffset)
+ {
+ maLocationOffset = rOffset;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+sal_Int32 VisualState::GetLocationAnimationId (void) const
+{
+ return mnLocationAnimationId;
+}
+
+
+
+
+void VisualState::SetLocationAnimationId (const sal_Int32 nAnimationId)
+{
+ mnLocationAnimationId = nAnimationId;
+}
+
+
+
+
+double VisualState::GetButtonAlpha (void) const
+{
+ return mnButtonAlpha;
+}
+
+
+
+
+void VisualState::SetButtonAlpha (const double nAlpha)
+{
+ mnButtonAlpha = nAlpha;
+}
+
+
+
+
+double VisualState::GetButtonBarAlpha (void) const
+{
+ return mnButtonBarAlpha;
+}
+
+
+
+
+void VisualState::SetButtonBarAlpha (const double nAlpha)
+{
+ mnButtonBarAlpha = nAlpha;
+}
+
+
+
+
+sal_Int32 VisualState::GetButtonAlphaAnimationId (void) const
+{
+ return mnButtonAlphaAnimationId;
+}
+
+
+
+
+void VisualState::SetButtonAlphaAnimationId (const sal_Int32 nAnimationId)
+{
+ mnButtonAlphaAnimationId = nAnimationId;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::model
diff --git a/sd/source/ui/slidesorter/model/makefile.mk b/sd/source/ui/slidesorter/model/makefile.mk
new file mode 100755
index 000000000000..0347d05a8100
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/makefile.mk
@@ -0,0 +1,57 @@
+#*************************************************************************
+#
+# 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)$/SlsVisualState.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..0c75e7a047dc
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorter.cxx
@@ -0,0 +1,703 @@
+/* -*- 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 "controller/SlsProperties.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsTheme.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),
+ mbOwnesContentWindow(false),
+ mpHorizontalScrollBar(rpHorizontalScrollBar),
+ mpVerticalScrollBar(rpVerticalScrollBar),
+ mpScrollBarBox(rpScrollBarBox),
+ mbLayoutPending(true),
+ mpProperties(new controller::Properties()),
+ mpTheme(new view::Theme(mpProperties))
+{
+}
+
+
+
+
+SlideSorter::SlideSorter (
+ ViewShellBase& rBase,
+ ViewShell* pViewShell,
+ ::Window& rParentWindow)
+ : mbIsValid(false),
+ mpSlideSorterController(),
+ mpSlideSorterModel(),
+ mpSlideSorterView(),
+ mxControllerWeak(),
+ mpViewShell(pViewShell),
+ mpViewShellBase(&rBase),
+ mpContentWindow(new ContentWindow(rParentWindow,*this )),
+ mbOwnesContentWindow(true),
+ mpHorizontalScrollBar(new ScrollBar(&rParentWindow,WinBits(WB_HSCROLL | WB_DRAG))),
+ mpVerticalScrollBar(new ScrollBar(&rParentWindow,WinBits(WB_VSCROLL | WB_DRAG))),
+ mpScrollBarBox(new ScrollBarBox(&rParentWindow)),
+ mbLayoutPending(true),
+ mpProperties(new controller::Properties()),
+ mpTheme(new view::Theme(mpProperties))
+{
+}
+
+
+
+
+void SlideSorter::Init (void)
+{
+ if (mpViewShellBase != NULL)
+ mxControllerWeak = mpViewShellBase->GetController();
+
+ // Reinitialize colors in Properties with window specific values.
+ if (mpContentWindow)
+ {
+ mpProperties->SetBackgroundColor(
+ mpContentWindow->GetSettings().GetStyleSettings().GetWindowColor());
+ mpProperties->SetTextColor(
+ mpContentWindow->GetSettings().GetStyleSettings().GetWindowTextColor());
+ mpProperties->SetSelectionColor(
+ mpContentWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor());
+ mpProperties->SetHighlightColor(
+ mpContentWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor());
+ }
+
+ CreateModelViewController ();
+
+ SetupListeners ();
+
+ // Initialize the window.
+ SharedSdWindow pContentWindow (GetContentWindow());
+ if (pContentWindow)
+ {
+ ::Window* pParentWindow = pContentWindow->GetParent();
+ if (pParentWindow != NULL)
+ pParentWindow->SetBackground(Wallpaper());
+ pContentWindow->SetBackground(Wallpaper());
+ pContentWindow->SetViewOrigin (Point(0,0));
+ // We do our own scrolling while dragging a page selection.
+ pContentWindow->SetUseDropScroll (false);
+ // Change the winbits so that the active window accepts the focus.
+ pContentWindow->SetStyle ((pContentWindow->GetStyle() & ~WB_DIALOGCONTROL) | WB_TABSTOP);
+ pContentWindow->Hide();
+
+ // Set view pointer of base class.
+ SetupControls(pParentWindow);
+
+ mbIsValid = true;
+ }
+}
+
+
+
+
+SlideSorter::~SlideSorter (void)
+{
+ mbIsValid = false;
+
+ ReleaseListeners();
+
+ // Dispose model, view and controller to avoid calls between them when
+ // they are being destructed and one or two of them are already gone.
+ mpSlideSorterController->Dispose();
+ mpSlideSorterView->Dispose();
+ mpSlideSorterModel->Dispose();
+
+ // Reset the auto pointers explicitly to control the order of destruction.
+ mpSlideSorterController.reset();
+ mpSlideSorterView.reset();
+ mpSlideSorterModel.reset();
+
+ mpHorizontalScrollBar.reset();
+ mpVerticalScrollBar.reset();
+ mpScrollBarBox.reset();
+
+ if (mbOwnesContentWindow)
+ {
+ OSL_ASSERT(mpContentWindow.unique());
+ }
+ else
+ {
+ // Assume that outside this class only the owner holds a reference
+ // to the content window.
+ OSL_ASSERT(mpContentWindow.use_count()==2);
+ }
+ 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());
+}
+
+
+
+
+::SharedSdWindow SlideSorter::GetContentWindow (void) const
+{
+ return mpContentWindow;
+}
+
+
+
+
+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)
+{
+ SharedSdWindow pWindow (GetContentWindow());
+ if (pWindow)
+ {
+ ::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();
+
+ SharedSdWindow pWindow (GetContentWindow());
+ if (pWindow)
+ {
+ 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");
+
+ // Now that model, view, and controller are constructed, do the
+ // initialization that relies on all three being in place.
+ mpSlideSorterModel->Init();
+ mpSlideSorterController->Init();
+ mpSlideSorterView->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
+ && GetContentWindow()
+ && GetContentWindow()->IsVisible())
+ {
+ // Prevent untimely redraws while the view is not yet correctly
+ // resized.
+ view::SlideSorterView::DrawLock aLock (*this);
+ GetContentWindow()->EnablePaint (sal_False);
+
+ mpSlideSorterController->Resize (Rectangle(aOrigin, rSize));
+
+ GetContentWindow()->EnablePaint (sal_True);
+
+ mbLayoutPending = false;
+ }
+}
+
+
+
+
+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)
+{
+ // Stop all animations for they have been started for the old window.
+ mpSlideSorterController->GetAnimator()->RemoveAllAnimations();
+
+ 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. But because at that time the correct
+ // accessibility object can not be constructed we do that now.)
+ 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
+ {
+ ContentWindow* pWindow = dynamic_cast<ContentWindow*>(GetContentWindow().get());
+ if (pWindow != NULL)
+ pWindow->SetCurrentFunction(rpFunction);
+ }
+}
+
+
+
+
+::boost::shared_ptr<controller::Properties> SlideSorter::GetProperties (void) const
+{
+ OSL_ASSERT(mpProperties);
+ return mpProperties;
+}
+
+
+
+
+::boost::shared_ptr<view::Theme> SlideSorter::GetTheme (void) const
+{
+ OSL_ASSERT(mpTheme);
+ return mpTheme;
+}
+
+
+
+
+//===== 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..e78fa4218c74
--- /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,
+ sal_uInt16 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 (sal_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..829b18d63a97
--- /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..de3affaa1f5d
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterService.cxx
@@ -0,0 +1,646 @@
+/* -*- 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 "view/SlsLayouter.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::Layouter;
+
+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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.SlideSorter"));
+}
+
+
+
+
+Sequence<rtl::OUString> SAL_CALL SlideSorterService_getSupportedServiceNames (void)
+ throw (RuntimeException)
+{
+ static const ::rtl::OUString sServiceName(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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()->NotifyCurrentSlideChange(
+ 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->GetProperties()->IsHighlightCurrentSlide();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsHighlightCurrentSlide (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ {
+ mpSlideSorter->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->GetProperties()->IsShowSelection();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsShowSelection (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetProperties()->SetShowSelection(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsShowFocus (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetProperties()->IsShowFocus();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsShowFocus (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetProperties()->SetShowFocus(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsCenterSelection (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetProperties()->IsCenterSelection();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsCenterSelection (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetProperties()->SetCenterSelection(bValue);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsSuspendPreviewUpdatesDuringFullScreenPresentation (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return true;
+ else
+ return mpSlideSorter->GetProperties()
+ ->IsSuspendPreviewUpdatesDuringFullScreenPresentation();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsSuspendPreviewUpdatesDuringFullScreenPresentation (
+ sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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() != Layouter::HORIZONTAL;
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsOrientationVertical (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->GetView().SetOrientation(bValue
+ ? Layouter::GRID
+ : Layouter::HORIZONTAL);
+}
+
+
+
+
+sal_Bool SAL_CALL SlideSorterService::getIsSmoothScrolling (void)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() == NULL || ! mpSlideSorter->IsValid())
+ return false;
+ else
+ return mpSlideSorter->GetProperties()->IsSmoothSelectionScrolling();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsSmoothScrolling (sal_Bool bValue)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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->GetProperties()->GetBackgroundColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setBackgroundColor (util::Color aBackgroundColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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->GetProperties()->GetTextColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setTextColor (util::Color aTextColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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->GetProperties()->GetSelectionColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setSelectionColor (util::Color aSelectionColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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->GetProperties()->GetHighlightColor().GetColor());
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setHighlightColor (util::Color aHighlightColor)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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->GetProperties()->IsUIReadOnly();
+}
+
+
+
+
+void SAL_CALL SlideSorterService::setIsUIReadOnly (sal_Bool bIsUIReadOnly)
+ throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ if (mpSlideSorter.get() != NULL && mpSlideSorter->IsValid())
+ mpSlideSorter->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..12f6d629266c
--- /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..7719008b3fe2
--- /dev/null
+++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx
@@ -0,0 +1,823 @@
+/* -*- 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 "controller/SlsSelectionFunction.hxx"
+#include "controller/SlsProperties.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,
+ const bool bIsCenterPane)
+{
+ (void)bIsCenterPane;
+
+ ::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(),
+ mbIsArrangeGUIElementsPending(true)
+{
+ 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;
+ OSL_FAIL("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.)
+ SharedSdWindow pWindow (mpSlideSorter->GetContentWindow());
+ if (pWindow)
+ {
+ 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)
+{
+ // 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;
+
+ OSL_ASSERT(mpSlideSorter.get()!=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);
+ if ( ! mpSlideSorter)
+ return false;
+
+ if (pParentWindow == NULL)
+ WriteFrameViewData();
+ const bool bSuccess (mpSlideSorter->RelocateToWindow(pParentWindow));
+ if (pParentWindow != NULL)
+ ReadFrameViewData(mpFrameView);
+
+ return bSuccess;
+}
+
+
+
+
+::svl::IUndoManager* 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();
+ }
+
+ if (pCurrentPage == NULL)
+ {
+
+ }
+
+ 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::Paint (
+ const Rectangle& rBBox,
+ ::sd::Window* pWindow)
+{
+ SetActiveWindow (pWindow);
+ OSL_ASSERT(mpSlideSorter);
+ if (mpSlideSorter)
+ mpSlideSorter->GetController().Paint(rBBox,pWindow);
+}
+
+
+
+
+void SlideSorterViewShell::ArrangeGUIElements (void)
+{
+ if (IsActive())
+ {
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ mpSlideSorter->ArrangeGUIElements(maViewPos, maViewSize);
+ mbIsArrangeGUIElementsPending = false;
+ }
+ else
+ mbIsArrangeGUIElementsPending = true;
+}
+
+
+
+
+void SlideSorterViewShell::Activate (sal_Bool bIsMDIActivate)
+{
+ ViewShell::Activate(bIsMDIActivate);
+ if (mbIsArrangeGUIElementsPending)
+ ArrangeGUIElements();
+}
+
+
+
+
+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());
+
+ sal_uInt16 nSlidesPerRow (pFrameView->GetSlidesPerRow());
+ if (nSlidesPerRow > 0
+ && rView.GetOrientation() == view::Layouter::GRID
+ && IsMainViewShell())
+ {
+ rView.GetLayouter().SetColumnCount(nSlidesPerRow,nSlidesPerRow);
+ }
+ if (IsMainViewShell())
+ mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
+ mpFrameView->GetSelectedPage());
+ mpSlideSorter->GetController().Rearrange(true);
+
+ // DrawMode for 'main' window
+ if (GetActiveWindow()->GetDrawMode() != pFrameView->GetDrawMode() )
+ GetActiveWindow()->SetDrawMode( pFrameView->GetDrawMode() );
+ }
+
+ // When this slide sorter is not displayed in the main window then we do
+ // not share the same frame view and have to find other ways to acquire
+ // certain values.
+ if ( ! IsMainViewShell())
+ {
+ ::boost::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
+ if (pMainViewShell.get() != NULL)
+ mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
+ pMainViewShell->getCurrentPage());
+ }
+}
+
+
+
+
+void SlideSorterViewShell::WriteFrameViewData (void)
+{
+ OSL_ASSERT(mpSlideSorter.get()!=NULL);
+ if (mpFrameView != NULL)
+ {
+ view::SlideSorterView& rView (mpSlideSorter->GetView());
+ mpFrameView->SetSlidesPerRow((sal_uInt16)rView.GetLayouter().GetColumnCount());
+
+ // DrawMode for 'main' window
+ if( mpFrameView->GetDrawMode() != GetActiveWindow()->GetDrawMode() )
+ mpFrameView->SetDrawMode( GetActiveWindow()->GetDrawMode() );
+
+ SdPage* pActualPage = GetActualPage();
+ if (pActualPage != NULL)
+ {
+ if (IsMainViewShell())
+ mpFrameView->SetSelectedPage((pActualPage->GetPageNum()- 1) / 2);
+ // else
+ // The slide sorter is not expected to switch the current page
+ // other then by double clicks. That is handled seperatly.
+ }
+ 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((sal_uInt16)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().GetLayouter().GetPageObjectSize());
+
+ 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);
+
+ 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,
+ sal_uInt16 nPage,
+ sal_uInt16 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,
+ sal_uInt16 nPage,
+ sal_uInt16 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 100755
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..8bbe698205a6
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
@@ -0,0 +1,1135 @@
+/* -*- 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 "SlsLayeredDevice.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsPageObjectPainter.hxx"
+#include "view/SlsILayerPainter.hxx"
+#include "view/SlsButtonBar.hxx"
+#include "view/SlsToolTip.hxx"
+#include "controller/SlideSorterController.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 "taskpane/SlideSorterCacheDisplay.hxx"
+#include "DrawDocShell.hxx"
+#include "PaneDockingWindow.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 <vcl/svapp.hxx>
+#include <vcl/scrbar.hxx>
+#include <tools/poly.hxx>
+#include <vcl/lineinfo.hxx>
+#include <algorithm>
+#include <svx/sdrpagewindow.hxx>
+#include <svl/itempool.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <canvas/elapsedtime.hxx>
+
+//#define DEBUG_TIMING
+#include <svl/itempool.hxx>
+#ifdef DEBUG_TIMING
+#include <vector>
+#endif
+#include <boost/foreach.hpp>
+
+
+using namespace std;
+using namespace ::sd::slidesorter::model;
+using namespace ::drawinglayer::primitive2d;
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+ /** Wrapper around the SlideSorterView that supports the IPainter
+ interface and that allows the LayeredDevice to hold the
+ SlideSorterView (held as scoped_ptr by the SlideSorter) as
+ shared_ptr.
+ */
+ class Painter : public ILayerPainter
+ {
+ public:
+ Painter (SlideSorterView& rView) : mrView(rView) {}
+ virtual ~Painter (void) {}
+
+ virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea)
+ {
+ mrView.Paint(rDevice,rRepaintArea);
+ }
+
+ virtual void SetLayerInvalidator (const SharedILayerInvalidator&) {}
+
+ private:
+ SlideSorterView& mrView;
+ };
+}
+
+
+
+class BackgroundPainter
+ : public ILayerPainter,
+ public ::boost::noncopyable
+{
+public:
+ BackgroundPainter (const Color aBackgroundColor) : maBackgroundColor(aBackgroundColor) {}
+ virtual ~BackgroundPainter (void) {}
+
+ virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea)
+ {
+ rDevice.SetFillColor(maBackgroundColor);
+ rDevice.SetLineColor();
+ rDevice.DrawRect(rRepaintArea);
+ }
+
+ virtual void SetLayerInvalidator (const SharedILayerInvalidator&) {}
+
+ void SetColor (const Color aColor) { maBackgroundColor = aColor; }
+
+private:
+ Color maBackgroundColor;
+};
+
+
+
+TYPEINIT1(SlideSorterView, ::sd::View);
+
+SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
+ : ::sd::View (
+ rSlideSorter.GetModel().GetDocument(),
+ rSlideSorter.GetContentWindow().get(),
+ rSlideSorter.GetViewShell()),
+ mrSlideSorter(rSlideSorter),
+ mrModel(rSlideSorter.GetModel()),
+ mbIsDisposed(false),
+ mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
+ mbPageObjectVisibilitiesValid (false),
+ mpPreviewCache(),
+ mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())),
+ maVisiblePageRange(-1,-1),
+ mbModelChangedWhileModifyEnabled(true),
+ maPreviewSize(0,0),
+ mbPreciousFlagUpdatePending(true),
+ meOrientation(Layouter::GRID),
+ mpProperties(rSlideSorter.GetProperties()),
+ mpPageUnderMouse(),
+ mnButtonUnderMouse(-1),
+ mpPageObjectPainter(),
+ mpSelectionPainter(),
+ mpBackgroundPainter(
+ new BackgroundPainter(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
+ mpButtonBar(new ButtonBar(mrSlideSorter)),
+ mpToolTip(new ToolTip(mrSlideSorter)),
+ mbIsRearrangePending(true),
+ maVisibilityChangeListeners()
+{
+ // Hide the page that contains the page objects.
+ SetPageVisible (sal_False);
+
+
+ // Register the background painter on level 1 to avoid the creation of a
+ // background buffer.
+ mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
+
+ // Wrap a shared_ptr-held-wrapper around this view and register it as
+ // painter at the layered device. There is no explicit destruction: in
+ // the SlideSorterView destructor the layered device is destroyed and
+ // with it the only reference to the wrapper which therefore is also
+ // destroyed.
+ SharedILayerPainter pPainter (new Painter(*this));
+
+ // The painter is placed on level 1 to avoid buffering. This should be
+ // a little faster during animations because the previews are painted
+ // directly into the window, not via the buffer.
+ mpLayeredDevice->RegisterPainter(pPainter, 1);
+}
+
+
+
+
+SlideSorterView::~SlideSorterView (void)
+{
+ if ( ! mbIsDisposed)
+ {
+ OSL_ASSERT(mbIsDisposed);
+ Dispose();
+ }
+}
+
+
+
+
+void SlideSorterView::Init (void)
+{
+ HandleModelChange();
+}
+
+
+
+
+void SlideSorterView::Dispose (void)
+{
+ mpSelectionPainter.reset();
+
+ mpLayeredDevice->Dispose();
+ mpPreviewCache.reset();
+
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+
+ // 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)
+
+ OSL_ASSERT(mpLayeredDevice.unique());
+ mpLayeredDevice.reset();
+
+ mbIsDisposed = true;
+}
+
+
+
+
+sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
+{
+ sal_Int32 nIndex (-1);
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
+
+ // 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)
+{
+ // Ignore this call. Rely on hints sent by the model to get informed of
+ // model changes.
+}
+
+
+
+
+void SlideSorterView::LocalModelHasChanged(void)
+{
+ mbModelChangedWhileModifyEnabled = false;
+
+ // First call our base class.
+ View::ModelHasChanged ();
+}
+
+
+
+
+void SlideSorterView::PreModelChange (void)
+{
+ // Reset the slide under the mouse. It will be re-set in PostModelChange().
+ SetPageUnderMouse(SharedPageDescriptor());
+}
+
+
+
+
+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));
+
+ // The new page objects have to be scaled and positioned.
+ RequestRearrange();
+ RequestRepaint();
+}
+
+
+
+
+/** 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)
+{
+ // 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);
+
+ RequestRepaint();
+}
+
+
+
+
+void SlideSorterView::HandleDataChangeEvent (void)
+{
+ GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
+
+ // Update the color used by the background painter.
+ ::boost::shared_ptr<BackgroundPainter> pPainter (
+ ::boost::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
+ if (pPainter)
+ pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
+
+ if (mpButtonBar)
+ mpButtonBar->HandleDataChangeEvent();
+
+ RequestRepaint();
+}
+
+
+
+
+void SlideSorterView::Resize (void)
+{
+ UpdateOrientation();
+
+ mpLayeredDevice->Resize();
+ RequestRearrange();
+}
+
+
+
+
+void SlideSorterView::RequestRearrange (void)
+{
+ mbIsRearrangePending = true;
+ Rearrange();
+}
+
+
+
+
+void SlideSorterView::Rearrange (void)
+{
+ if ( ! mbIsRearrangePending)
+ return;
+ if (mrModel.GetPageCount() <= 0)
+ return;
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if ( ! pWindow)
+ return;
+ const Size aWindowSize (pWindow->GetSizePixel());
+ if (aWindowSize.Width()<=0 || aWindowSize.Height()<=0)
+ return;
+
+ const bool bRearrangeSuccess (
+ mpLayouter->Rearrange (
+ meOrientation,
+ aWindowSize,
+ mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
+ mrModel.GetPageCount()));
+ if (bRearrangeSuccess)
+ {
+ mbIsRearrangePending = false;
+ Layout();
+ UpdatePageUnderMouse(false);
+ // RequestRepaint();
+ }
+}
+
+
+
+
+void SlideSorterView::UpdateOrientation (void)
+{
+ // The layout of slides depends on whether the slide sorter is
+ // displayed in the center or the side pane.
+ if (mrSlideSorter.GetViewShell()->IsMainViewShell())
+ SetOrientation(Layouter::GRID);
+ else
+ {
+ // Get access to the docking window.
+ ::Window* pWindow = mrSlideSorter.GetContentWindow().get();
+ PaneDockingWindow* pDockingWindow = NULL;
+ while (pWindow!=NULL && pDockingWindow==NULL)
+ {
+ pDockingWindow = dynamic_cast<PaneDockingWindow*>(pWindow);
+ pWindow = pWindow->GetParent();
+ }
+
+ if (pDockingWindow != NULL)
+ {
+ const long nScrollBarSize (
+ Application::GetSettings().GetStyleSettings().GetScrollBarSize());
+ switch (pDockingWindow->GetOrientation())
+ {
+ case PaneDockingWindow::HorizontalOrientation:
+ if (SetOrientation(Layouter::HORIZONTAL))
+ {
+ const Range aRange (mpLayouter->GetValidVerticalSizeRange());
+ pDockingWindow->SetValidSizeRange(Range(
+ aRange.Min() + nScrollBarSize,
+ aRange.Max() + nScrollBarSize));
+ }
+ break;
+
+ case PaneDockingWindow::VerticalOrientation:
+ if (SetOrientation(Layouter::VERTICAL))
+ {
+ const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
+ pDockingWindow->SetValidSizeRange(Range(
+ aRange.Min() + nScrollBarSize,
+ aRange.Max() + nScrollBarSize));
+ }
+ break;
+
+ case PaneDockingWindow::UnknownOrientation:
+ if (SetOrientation(Layouter::GRID))
+ {
+ const sal_Int32 nAdditionalSize (10);
+ pDockingWindow->SetMinOutputSizePixel(Size(
+ mpLayouter->GetValidHorizontalSizeRange().Min()
+ + nScrollBarSize
+ + nAdditionalSize,
+ mpLayouter->GetValidVerticalSizeRange().Min()
+ + nScrollBarSize
+ + nAdditionalSize));
+ }
+ return;
+ }
+ }
+ else
+ {
+ // We are not placed in a docking window. One possible reason
+ // is that the slide sorter is temporarily into a cache and was
+ // reparented to a non-docking window.
+ SetOrientation(Layouter::GRID);
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::Layout ()
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ // Set the model area, i.e. the smallest rectangle that includes all
+ // page objects.
+ const Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
+ pWindow->SetViewOrigin (aViewBox.TopLeft());
+ pWindow->SetViewSize (aViewBox.GetSize());
+
+ ::boost::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
+ mpLayouter->GetPageObjectLayouter());
+ if (pPageObjectLayouter)
+ {
+ const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetSize(
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::WindowCoordinateSystem));
+ if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
+ {
+ mpPreviewCache->ChangeSize(aNewPreviewSize, true);
+ maPreviewSize = aNewPreviewSize;
+ }
+ }
+
+ // Iterate over all page objects and place them relative to the
+ // containing page.
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aPageEnumeration.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex()));
+ }
+
+ GetPageObjectPainter()->NotifyResize();
+ }
+
+ InvalidatePageObjectVisibilities ();
+}
+
+
+
+
+void SlideSorterView::InvalidatePageObjectVisibilities (void)
+{
+ mbPageObjectVisibilitiesValid = false;
+}
+
+
+
+
+void SlideSorterView::DeterminePageObjectVisibilities (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ // Set this flag to true here so that an invalidate during the
+ // visibility calculation can correctly invalidate it again.
+ mbPageObjectVisibilitiesValid = true;
+
+ Rectangle aViewArea (pWindow->PixelToLogic(Rectangle(Point(0,0),pWindow->GetSizePixel())));
+ const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
+ const Range aUnion(
+ ::std::min(maVisiblePageRange.Min(), aRange.Min()),
+ ::std::max(maVisiblePageRange.Max(), aRange.Max()));
+
+ // For page objects that just dropped off the visible area we
+ // decrease the priority of pending requests for preview bitmaps.
+ if (maVisiblePageRange != aRange)
+ mbPreciousFlagUpdatePending |= true;
+
+ model::SharedPageDescriptor pDescriptor;
+ for (int nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
+ {
+ pDescriptor = mrModel.GetPageDescriptor(nIndex);
+ if (pDescriptor.get() != NULL)
+ SetState(
+ pDescriptor,
+ PageDescriptor::ST_Visible,
+ aRange.IsInside(nIndex));
+ }
+
+ // Broadcast a change of the set of visible page objects.
+ if (maVisiblePageRange != aRange)
+ {
+ maVisiblePageRange = aRange;
+
+ // Tell the listeners that the visibility of some objects has
+ // changed.
+ ::std::vector<Link>& aChangeListeners (maVisibilityChangeListeners);
+ for (::std::vector<Link>::const_iterator
+ iLink(aChangeListeners.begin()),
+ iEnd(aChangeListeners.end());
+ iLink!=iEnd;
+ ++iLink)
+ {
+ iLink->Call(NULL);
+ }
+ }
+
+
+ // Restore the mouse over state.
+ UpdatePageUnderMouse(true);
+ }
+}
+
+
+
+
+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(),
+ maVisiblePageRange.IsInside(nIndex));
+ SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex,
+ maVisiblePageRange.IsInside(nIndex));
+ }
+ 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;
+ }
+ }
+ }
+}
+
+
+
+
+bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
+{
+ if (meOrientation != eOrientation)
+ {
+ meOrientation = eOrientation;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+Layouter::Orientation SlideSorterView::GetOrientation (void) const
+{
+ return meOrientation;
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(
+ Rectangle(
+ pWindow->PixelToLogic(Point(0,0)),
+ pWindow->PixelToLogic(pWindow->GetSizePixel())));
+ pWindow->Invalidate();
+ }
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor)
+ RequestRepaint(rpDescriptor->GetBoundingBox());
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (const Rectangle& rRepaintBox)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
+ pWindow->Invalidate(rRepaintBox);
+ }
+}
+
+
+
+void SlideSorterView::RequestRepaint (const Region& rRepaintRegion)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
+ pWindow->Invalidate(rRepaintRegion);
+ }
+}
+
+
+
+
+Rectangle SlideSorterView::GetModelArea (void)
+{
+ return mpLayouter->GetTotalBoundingBox();
+}
+
+
+#ifdef DEBUG_TIMING
+static ::canvas::tools::ElapsedTime gaTimer;
+static const size_t gFrameTimeCount (10);
+static size_t gFrameTimeIndex (0);
+static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
+static double gFrameTimeSum (0);
+static const Rectangle gFrameTimeBox (10,10,150,20);
+static double gnLastFrameStart = 0;
+#endif
+
+void SlideSorterView::CompleteRedraw (
+ OutputDevice* pDevice,
+ const Region& rPaintArea,
+ sdr::contact::ViewObjectContactRedirector* pRedirector)
+{
+ (void)pRedirector;
+#ifdef DEBUG_TIMING
+ const double nStartTime (gaTimer.getElapsedTime());
+ OSL_TRACE("SlideSorterView::CompleteRedraw start at %f, %s",
+ nStartTime,
+ mnLockRedrawSmph ? "locked" : "");
+#endif
+
+ if (pDevice == NULL || pDevice!=mrSlideSorter.GetContentWindow().get())
+ return;
+
+ // The parent implementation of CompleteRedraw is called only when
+ // painting is locked. We do all the painting ourself. When painting
+ // is locked the parent implementation keeps track of the repaint
+ // requests and later, when painting is unlocked, calls CompleteRedraw
+ // for all missed repaints.
+
+ if (mnLockRedrawSmph == 0)
+ {
+ mrSlideSorter.GetContentWindow()->IncrementLockCount();
+ if (mpLayeredDevice->HandleMapModeChange())
+ DeterminePageObjectVisibilities();
+ mpLayeredDevice->Repaint(rPaintArea);
+ mrSlideSorter.GetContentWindow()->DecrementLockCount();
+ }
+ else
+ {
+ maRedrawRegion.Union(rPaintArea);
+ }
+
+#ifdef DEBUG_TIMING
+ const double nEndTime (gaTimer.getElapsedTime());
+ OSL_TRACE("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000);
+ gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
+ gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
+ gnLastFrameStart = nStartTime;
+ gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
+ gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
+
+
+ mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
+ mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
+ mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
+ mrSlideSorter.GetContentWindow()->DrawText(
+ gFrameTimeBox,
+ ::rtl::OUString::valueOf(1 / (gFrameTimeSum / gFrameTimeCount)),
+ TEXT_DRAW_RIGHT | TEXT_DRAW_VCENTER);
+ // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
+#endif
+}
+
+
+
+
+void SlideSorterView::Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea)
+{
+ if ( ! mpPageObjectPainter)
+ if ( ! GetPageObjectPainter())
+ return;
+
+ // Update the page visibilities when they have been invalidated.
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+
+ if (mbPreciousFlagUpdatePending)
+ UpdatePreciousFlags();
+
+ if (mbIsRearrangePending)
+ Rearrange();
+
+ // Paint all page objects that are fully or partially inside the
+ // repaint region.
+ const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
+ for (sal_Int32 nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
+ {
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
+ if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
+ continue;
+
+ mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
+ }
+}
+
+
+
+
+void SlideSorterView::ConfigurationChanged (
+ utl::ConfigurationBroadcaster* pBroadcaster,
+ sal_uInt32 nHint)
+{
+ // Some changes of the configuration (some of the colors for example)
+ // may affect the previews. Throw away the old ones and create new ones.
+ cache::PageCacheManager::Instance()->InvalidateAllCaches();
+
+ ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
+ RequestRepaint();
+
+}
+
+
+
+
+::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow && mpPreviewCache.get() == NULL)
+ {
+ mpPreviewCache.reset(
+ new cache::PageCache(
+ mpLayouter->GetPageObjectSize(),
+ false,
+ cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter))));
+ }
+
+ return mpPreviewCache;
+}
+
+
+
+
+Pair SlideSorterView::GetVisiblePageRange (void)
+{
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+ return maVisiblePageRange;
+}
+
+
+
+
+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));
+}
+
+
+
+
+ButtonBar& SlideSorterView::GetButtonBar (void) const
+{
+ OSL_ASSERT(mpButtonBar);
+ return *mpButtonBar;
+}
+
+
+
+
+ToolTip& SlideSorterView::GetToolTip (void) const
+{
+ OSL_ASSERT(mpToolTip);
+ return *mpToolTip;
+}
+
+
+
+
+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::UpdatePageUnderMouse (bool bAnimate)
+{
+ ::boost::shared_ptr<ScrollBar> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
+ ::boost::shared_ptr<ScrollBar> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
+ if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->IsTracking())
+ || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->IsTracking()))
+ {
+ // One of the scroll bars is tracking mouse movement. Do not
+ // highlight the slide under the mouse in this case.
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+ return;
+ }
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
+ {
+ const Window::PointerState aPointerState (pWindow->GetPointerState());
+ const Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
+ if (aWindowBox.IsInside(aPointerState.maPos))
+ {
+ UpdatePageUnderMouse (
+ aPointerState.maPos,
+ (aPointerState.mnState & MOUSE_LEFT)!=0,
+ bAnimate);
+ return;
+ }
+ }
+
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+}
+
+
+
+
+void SlideSorterView::UpdatePageUnderMouse (
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate)
+{
+ UpdatePageUnderMouse(
+ mrSlideSorter.GetController().GetPageAt(rMousePosition),
+ rMousePosition,
+ bIsMouseButtonDown,
+ bAnimate);
+}
+
+
+
+
+void SlideSorterView::UpdatePageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate)
+{
+ // Update the page under the mouse.
+ SetPageUnderMouse(rpDescriptor, bAnimate);
+
+ // Tell the button bar about the new mouse position.
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
+
+ ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW)
+ {
+ const bool bIsMouseOverButtonBar (GetButtonBar().IsMouseOverBar());
+ GetButtonBar().ProcessMouseMotionEvent(rpDescriptor, aMouseModelPosition, bIsMouseButtonDown);
+ // Set the help text of the slide when the mouse was moved from the
+ // button bar back over the preview.
+ if (rpDescriptor
+ && GetButtonBar().IsMouseOverBar() != bIsMouseOverButtonBar
+ && bIsMouseOverButtonBar)
+ {
+ mpToolTip->ShowDefaultHelpText();
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::SetPageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if (mpPageUnderMouse != rpDescriptor)
+ {
+ if (mpPageUnderMouse)
+ SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false, bAnimate);
+
+ mpPageUnderMouse = rpDescriptor;
+
+ if (mpPageUnderMouse)
+ SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true, bAnimate);
+
+ // Change the quick help text to display the name of the page under
+ // the mouse.
+ mpToolTip->SetPage(rpDescriptor);
+ }
+}
+
+
+
+
+bool SlideSorterView::SetState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const PageDescriptor::State eState,
+ const bool bStateValue,
+ const bool bAnimate)
+{
+ model::SharedPageDescriptor pDescriptor (rpDescriptor);
+ if ( ! pDescriptor)
+ return false;
+
+ const bool bModified (pDescriptor->SetState(eState, bStateValue));
+ if ( ! bModified)
+ return false;
+
+ // When the page object is not visible (i.e. not on the screen then
+ // nothing has to be painted.
+ if (pDescriptor->HasState(PageDescriptor::ST_Visible))
+ {
+ // For most states a change of that state leads to visible
+ // difference and we have to request a repaint.
+ if (eState != PageDescriptor::ST_WasSelected)
+ RequestRepaint(pDescriptor);
+ }
+
+ ::boost::shared_ptr<ViewShell> pMainViewShell(mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW)
+ {
+ // Fade in or out the buttons.
+ if (eState == PageDescriptor::ST_MouseOver)
+ {
+ if (bStateValue)
+ GetButtonBar().RequestFadeIn(rpDescriptor, bAnimate);
+ else
+ GetButtonBar().RequestFadeOut(rpDescriptor, bAnimate);
+ }
+ }
+
+ return bModified;
+}
+
+
+
+
+::boost::shared_ptr<PageObjectPainter> SlideSorterView::GetPageObjectPainter (void)
+{
+ if ( ! mpPageObjectPainter)
+ mpPageObjectPainter.reset(new PageObjectPainter(mrSlideSorter));
+ return mpPageObjectPainter;
+}
+
+
+
+
+::boost::shared_ptr<LayeredDevice> SlideSorterView::GetLayeredDevice (void) const
+{
+ return mpLayeredDevice;
+}
+
+
+
+
+//===== SlideSorterView::DrawLock =============================================
+
+SlideSorterView::DrawLock::DrawLock (
+ view::SlideSorterView& rView,
+ const SharedSdWindow& rpWindow)
+ : mrView(rView),
+ mpWindow(rpWindow)
+{
+ if (mrView.mnLockRedrawSmph == 0)
+ mrView.maRedrawRegion.SetEmpty();
+ ++mrView.mnLockRedrawSmph;
+}
+
+
+
+
+SlideSorterView::DrawLock::DrawLock (SlideSorter& rSlideSorter)
+ : mrView(rSlideSorter.GetView()),
+ mpWindow(rSlideSorter.GetContentWindow())
+{
+ if (mrView.mnLockRedrawSmph == 0)
+ mrView.maRedrawRegion.SetEmpty();
+ ++mrView.mnLockRedrawSmph;
+}
+
+
+
+
+SlideSorterView::DrawLock::~DrawLock (void)
+{
+ OSL_ASSERT(mrView.mnLockRedrawSmph>0);
+ --mrView.mnLockRedrawSmph;
+ if (mrView.mnLockRedrawSmph == 0)
+ if (mpWindow)
+ {
+ mpWindow->Invalidate(mrView.maRedrawRegion);
+ mpWindow->Update();
+ }
+}
+
+
+
+
+void SlideSorterView::DrawLock::Dispose (void)
+{
+ mpWindow.reset();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsButtonBar.cxx b/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
new file mode 100644
index 000000000000..f338a998c56f
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
@@ -0,0 +1,1558 @@
+/*************************************************************************
+ *
+ * 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/SlsButtonBar.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "view/SlsTheme.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsToolTip.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "controller/SlsAnimationFunction.hxx"
+#include "app.hrc"
+#include "drawdoc.hxx"
+#include <svx/svxids.hrc>
+#include <sfx2/dispatch.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <com/sun/star/presentation/XPresentation2.hpp>
+#include <boost/bind.hpp>
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::presentation::XPresentation2;
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** Base class for the painter of the background bar onto which the buttons
+ are painted. It also provides some size information.
+*/
+class ButtonBar::BackgroundTheme
+{
+public:
+ BackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ /** Set the preview bounding box, the maximal area in which to display
+ buttons. A call to this method triggers a call to Layout().
+ */
+ void SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox);
+ Button::IconSize GetIconSize (void) const;
+
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const = 0;
+ virtual Point GetBackgroundLocation (void) = 0;
+ virtual Rectangle GetButtonArea (void) = 0;
+
+protected:
+ ::boost::shared_ptr<Theme> mpTheme;
+ Rectangle maPreviewBoundingBox;
+ Size maMinimumLargeButtonAreaSize;
+ Size maMinimumMediumButtonAreaSize;
+ Size maMinimumSmallButtonAreaSize;
+ Button::IconSize meIconSize;
+
+ virtual void Layout (void) = 0;
+
+private:
+ void UpdateMinimumIconSizes(const ::std::vector<SharedButton>& rButtons);
+};
+
+
+namespace {
+ /** Rectangular button bar that covers the whole width of the preview.
+ */
+ class RectangleBackgroundTheme : public ButtonBar::BackgroundTheme
+ {
+ public:
+ RectangleBackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const;
+ virtual Point GetBackgroundLocation (void);
+ virtual Rectangle GetButtonArea (void);
+ protected:
+ virtual void Layout (void);
+ private:
+ sal_Int32 mnBarHeight;
+ };
+
+ /** Button bar is composed of three images, the left and right end of
+ the bar and the center image. Buttons are only placed over the
+ center image. The center image is painted as is, it is not scaled.
+ */
+ class BitmapBackgroundTheme : public ButtonBar::BackgroundTheme
+ {
+ public:
+ BitmapBackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const;
+ virtual Point GetBackgroundLocation (void);
+ virtual Rectangle GetButtonArea (void);
+ protected:
+ virtual void Layout (void);
+ private:
+ Rectangle maButtonArea;
+ Point maBackgroundLocation;
+ };
+
+ /** The source mask is essentially multiplied with the given alpha value.
+ The result is writen to the result mask.
+ */
+ void AdaptTransparency (AlphaMask& rMask, const AlphaMask& rSourceMask, const double nAlpha)
+ {
+ BitmapWriteAccess* pBitmap = rMask.AcquireWriteAccess();
+ const BitmapReadAccess* pSourceBitmap = const_cast<AlphaMask&>(rSourceMask).AcquireReadAccess();
+
+ if (pBitmap!=NULL && pSourceBitmap!=NULL)
+ {
+ const sal_Int32 nWidth (pBitmap->Width());
+ const sal_Int32 nHeight (pBitmap->Height());
+
+ for (sal_Int32 nY = 0; nY<nHeight; ++nY)
+ for (sal_Int32 nX = 0; nX<nWidth; ++nX)
+ {
+ const sal_uInt8 nValue (255 - pSourceBitmap->GetPixel(nY, nX).GetBlueOrIndex());
+ const sal_uInt8 nNewValue (nValue * (1-nAlpha));
+ pBitmap->SetPixel(nY, nX, 255-nNewValue);
+ }
+ }
+ }
+
+} // end of anonymous namespace
+
+
+//===== ButtonBar::Lock =======================================================
+
+ButtonBar::Lock::Lock (SlideSorter& rSlideSorter)
+ : mrButtonBar(rSlideSorter.GetView().GetButtonBar())
+{
+ mrButtonBar.AcquireLock();
+}
+
+
+
+
+ButtonBar::Lock::~Lock (void)
+{
+ mrButtonBar.ReleaseLock();
+}
+
+
+
+
+//===== ButtonBar =============================================================
+
+ButtonBar::ButtonBar (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maPageObjectSize(0,0),
+ maButtonBoundingBox(),
+ maBackgroundLocation(),
+ mpDescriptor(),
+ mbIsExcluded(false),
+ mpButtonUnderMouse(),
+ mpDownButton(),
+ maRegularButtons(),
+ maExcludedButtons(),
+ maNormalBackground(),
+ maButtonDownBackground(),
+ mbIsMouseOverBar(false),
+ mpBackgroundTheme(),
+ mnLockCount(0)
+{
+ HandleDataChangeEvent();
+}
+
+
+
+
+ButtonBar::~ButtonBar (void)
+{
+}
+
+
+
+
+void ButtonBar::ProcessButtonDownEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation)
+{
+ SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+ if (mpButtonUnderMouse)
+ mpButtonUnderMouse->SetState(Button::State_Down);
+ mpDownButton = mpButtonUnderMouse;
+
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+}
+
+
+
+
+void ButtonBar::ProcessButtonUpEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation)
+{
+ SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+ if (mpButtonUnderMouse)
+ {
+ mpButtonUnderMouse->SetState(Button::State_Hover);
+ if (mpButtonUnderMouse == mpDownButton)
+ {
+ // This is done only when the buttons are sufficiently visible.
+ if (mpDescriptor->GetVisualState().GetButtonAlpha()<0.7)
+ {
+ mpButtonUnderMouse->ProcessClick(mpDescriptor);
+ mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
+ ProcessMouseMotionEvent (rpDescriptor, aMouseModelLocation, false);
+ }
+ }
+ }
+ mpDownButton.reset();
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+}
+
+
+
+
+void ButtonBar::ProcessMouseMotionEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation,
+ const bool bIsMouseButtonDown)
+{
+ model::SharedPageDescriptor pOldDescriptor (mpDescriptor);
+ bool bPageHasChanged (false);
+ bool bButtonHasChanged (false);
+ bool bButtonStateHasChanged (false);
+
+ // Update the page object for which to manage the buttons.
+ bPageHasChanged = SetPage(rpDescriptor);
+ mbIsMouseOverBar = IsMouseOverBar(aMouseModelLocation);
+
+ // Update button under mouse.
+ if (rpDescriptor)
+ {
+ bButtonHasChanged = SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+
+ if (mpButtonUnderMouse)
+ {
+ // When the mouse button is down, mark the button under the
+ // mouse only as pressed when it is the same button the mouse
+ // button was pressed over, and where the button release would
+ // lead to a click action.
+ if (bIsMouseButtonDown)
+ {
+ if (mpButtonUnderMouse==mpDownButton)
+ bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Down);
+ }
+ else
+ bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Hover);
+ }
+ }
+
+ // Show a quick help text when the mouse is over a button.
+ if (bButtonHasChanged)
+ {
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ if (mpButtonUnderMouse)
+ mrSlideSorter.GetView().GetToolTip().ShowHelpText(mpButtonUnderMouse->GetHelpText());
+ else
+ mrSlideSorter.GetView().GetToolTip().ShowDefaultHelpText();
+ }
+ }
+
+ if (bPageHasChanged || bButtonHasChanged || bButtonStateHasChanged)
+ {
+ if (pOldDescriptor)
+ mrSlideSorter.GetView().RequestRepaint(pOldDescriptor);
+ if (mpDescriptor && pOldDescriptor!=mpDescriptor)
+ mrSlideSorter.GetView().RequestRepaint(mpDescriptor);
+ }
+}
+
+
+
+
+void ButtonBar::ResetPage (void)
+{
+ SetPage(model::SharedPageDescriptor());
+}
+
+
+
+
+bool ButtonBar::SetPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (mpDescriptor != rpDescriptor)
+ {
+ mpDescriptor = rpDescriptor;
+
+ if (mpDescriptor)
+ mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
+ else
+ mbIsExcluded = false;
+ SetButtonUnderMouse();
+ mpDownButton.reset();
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+sal_Int32 ButtonBar::GetButtonCount (const bool bIsExcluded) const
+{
+ if (bIsExcluded)
+ return maExcludedButtons.size();
+ else
+ return maRegularButtons.size();
+}
+
+
+
+
+::boost::shared_ptr<Button> ButtonBar::GetButton (
+ const bool bIsExcluded,
+ const sal_Int32 nIndex) const
+{
+ const ::std::vector<boost::shared_ptr<Button> >& rButtons (bIsExcluded
+ ? maExcludedButtons
+ : maRegularButtons);
+
+ if (nIndex<0 || sal_uInt32(nIndex)>=rButtons.size())
+ {
+ OSL_ASSERT(nIndex<0 || sal_uInt32(nIndex)>=rButtons.size());
+ return ::boost::shared_ptr<Button>();
+ }
+ else
+ return rButtons[sal_uInt32(nIndex)];
+}
+
+
+
+
+SharedButton ButtonBar::GetButtonAt (const Point aModelLocation)
+{
+ if (IsMouseOverBar(aModelLocation))
+ {
+ const Point aLocalLocation (aModelLocation - mpDescriptor->GetBoundingBox().TopLeft());
+ ::std::vector<SharedButton>& rButtons (
+ mbIsExcluded ? maExcludedButtons : maRegularButtons);
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ {
+ if (rButtons[sal_uInt32(nIndex)]->GetBoundingBox().IsInside(aLocalLocation))
+ {
+ if (rButtons[sal_uInt32(nIndex)]->IsEnabled())
+ return rButtons[sal_uInt32(nIndex)];
+ else
+ return SharedButton();
+ }
+ }
+ }
+
+ return SharedButton();
+}
+
+
+
+
+bool ButtonBar::IsMouseOverBar (void) const
+{
+ return mbIsMouseOverBar;
+}
+
+
+
+
+bool ButtonBar::SetButtonUnderMouse (const SharedButton& rButton)
+{
+ if (mpButtonUnderMouse != rButton)
+ {
+ if (mpButtonUnderMouse)
+ mpButtonUnderMouse->SetState(Button::State_Normal);
+
+ mpButtonUnderMouse = rButton;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void ButtonBar::Paint (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+
+ const double nButtonBarAlpha (rpDescriptor->GetVisualState().GetButtonBarAlpha());
+ if (nButtonBarAlpha >= 1)
+ return;
+
+ LayoutButtons(rpDescriptor->GetBoundingBox().GetSize());
+
+ const Point aOffset (rpDescriptor->GetBoundingBox().TopLeft());
+
+ // Paint the background.
+ PaintButtonBackground(rDevice, rpDescriptor, aOffset);
+
+ // Paint the buttons.
+ const ::std::vector<SharedButton>& rButtons (
+ rpDescriptor->HasState(model::PageDescriptor::ST_Excluded)
+ ? maExcludedButtons
+ : maRegularButtons);
+
+
+ const double nButtonAlpha (rpDescriptor->GetVisualState().GetButtonAlpha());
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ rButtons[nIndex]->Paint(
+ rDevice,
+ aOffset,
+ nButtonAlpha,
+ mrSlideSorter.GetTheme());
+}
+
+
+
+
+bool ButtonBar::IsMouseOverButton (void) const
+{
+ return mpButtonUnderMouse;
+}
+
+
+
+
+void ButtonBar::PaintButtonBackground (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aOffset)
+{
+ BitmapEx* pBitmap = NULL;
+ if (maButtonDownBackground.IsEmpty() || maNormalBackground.IsEmpty())
+ {
+ if (mpBackgroundTheme)
+ {
+ maButtonDownBackground = mpBackgroundTheme->CreateBackground(rDevice, true);
+ maNormalBackground = mpBackgroundTheme->CreateBackground(rDevice, false);
+ }
+ }
+ if (mpButtonUnderMouse && mpButtonUnderMouse->IsDown())
+ pBitmap = &maButtonDownBackground;
+ else
+ pBitmap = &maNormalBackground;
+ if (pBitmap != NULL)
+ {
+ AlphaMask aMask (pBitmap->GetSizePixel());
+ AdaptTransparency(
+ aMask,
+ pBitmap->GetAlpha(),
+ rpDescriptor->GetVisualState().GetButtonBarAlpha());
+ rDevice.DrawBitmapEx(maBackgroundLocation+aOffset, BitmapEx(pBitmap->GetBitmap(), aMask));
+ }
+}
+
+
+
+
+bool ButtonBar::IsMouseOverBar (const Point aModelLocation) const
+{
+ if ( ! mpDescriptor || ! mpDescriptor->GetBoundingBox().IsInside(aModelLocation))
+ return false;
+
+ if ( ! maButtonBoundingBox.IsInside(aModelLocation - mpDescriptor->GetBoundingBox().TopLeft()))
+ return false;
+
+ return true;
+}
+
+
+
+
+void ButtonBar::RequestLayout (void)
+{
+ maPageObjectSize = Size(0,0);
+}
+
+
+
+
+void ButtonBar::LayoutButtons (const Size aPageObjectSize)
+{
+ if (maPageObjectSize != aPageObjectSize)
+ {
+ maPageObjectSize = aPageObjectSize;
+
+ if (mpBackgroundTheme)
+ {
+ mpBackgroundTheme->SetPreviewBoundingBox(
+ mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
+ Point(0,0),
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+ LayoutButtons();
+ }
+
+ // Release the background bitmaps so that on the next paint
+ // they are created anew in the right size.
+ maNormalBackground.SetEmpty();
+ maButtonDownBackground.SetEmpty();
+ }
+}
+
+
+
+
+bool ButtonBar::LayoutButtons (void)
+{
+ const sal_Int32 nGap (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonGap));
+ const sal_Int32 nBorder (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonBorder));
+
+ const Button::IconSize eIconSize (mpBackgroundTheme->GetIconSize());
+
+ // Tell buttons which size they are.
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ maExcludedButtons[nIndex]->SetIconSize(eIconSize);
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ maRegularButtons[nIndex]->SetIconSize(eIconSize);
+
+ // Determine maximal height and total width of the buttons.
+ // Start with the buttons used for the excluded state.
+ sal_Int32 nMaximumHeight (0);
+ sal_Int32 nExcludedTotalWidth ((maExcludedButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ {
+ const Size aSize (maExcludedButtons[nIndex]->GetSize());
+ if (aSize.Height() > nMaximumHeight)
+ nMaximumHeight = aSize.Height();
+ nExcludedTotalWidth += aSize.Width();
+ }
+
+ // Do the same for the regular buttons.
+ sal_Int32 nRegularTotalWidth ((maRegularButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ {
+ const Size aSize (maRegularButtons[nIndex]->GetSize());
+ if (aSize.Height() > nMaximumHeight)
+ nMaximumHeight = aSize.Height();
+ nRegularTotalWidth += aSize.Width();
+ }
+ nMaximumHeight += 2*nBorder;
+
+ // Set up the bounding box of the button bar.
+ maButtonBoundingBox = mpBackgroundTheme->GetButtonArea();
+ maBackgroundLocation = mpBackgroundTheme->GetBackgroundLocation();
+ if (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonPaintType) == 1)
+ {
+ // Center the buttons.
+ maButtonBoundingBox.Left() += (maButtonBoundingBox.GetWidth() - nRegularTotalWidth)/2;
+ maButtonBoundingBox.Right() = maButtonBoundingBox.Left() + nRegularTotalWidth - 1;
+ }
+
+ // Place the buttons.
+ Rectangle aBox (maButtonBoundingBox);
+ aBox.Right() -= nBorder;
+ for (sal_Int32 nIndex=maRegularButtons.size()-1; nIndex>=0; --nIndex)
+ {
+ maRegularButtons[nIndex]->Place(aBox);
+ aBox.Right() = maRegularButtons[nIndex]->GetBoundingBox().Left() - nGap;
+ }
+
+ // For slides excluded from the show there is only one icon placed
+ // exactly like the second of the regular icons.
+ if (maRegularButtons.size()>=2 && maExcludedButtons.size()>=1)
+ {
+ aBox = maRegularButtons[1]->GetBoundingBox();
+ maExcludedButtons[0]->Place(aBox);
+ }
+
+ // We return true only when there is no inactive button.
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ if ( ! maExcludedButtons[nIndex]->IsActive())
+ return false;
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ if ( ! maRegularButtons[nIndex]->IsActive())
+ return false;
+
+ return true;
+}
+
+
+
+
+void ButtonBar::RequestFadeIn (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if ( ! rpDescriptor)
+ return;
+ if (mnLockCount > 0)
+ return;
+
+ const double nMinAlpha (0);
+ if ( ! bAnimate)
+ {
+ rpDescriptor->GetVisualState().SetButtonAlpha(nMinAlpha);
+ rpDescriptor->GetVisualState().SetButtonBarAlpha(nMinAlpha);
+ }
+ else
+ StartFadeAnimation(rpDescriptor, nMinAlpha, true);
+}
+
+
+
+
+void ButtonBar::RequestFadeOut (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if ( ! rpDescriptor)
+ return;
+ if (mnLockCount > 0)
+ return;
+
+ const double nMaxAlpha (1);
+ if ( ! bAnimate)
+ {
+ rpDescriptor->GetVisualState().SetButtonAlpha(nMaxAlpha);
+ rpDescriptor->GetVisualState().SetButtonBarAlpha(nMaxAlpha);
+ }
+ else
+ StartFadeAnimation(rpDescriptor, nMaxAlpha, false);
+}
+
+
+
+
+bool ButtonBar::IsVisible (const model::SharedPageDescriptor& rpDescriptor)
+{
+ const double nMaxAlpha (1);
+ return rpDescriptor && rpDescriptor->GetVisualState().GetButtonBarAlpha() < nMaxAlpha;
+}
+
+
+
+
+void ButtonBar::HandleDataChangeEvent (void)
+{
+ maExcludedButtons.clear();
+ maExcludedButtons.push_back(::boost::shared_ptr<Button>(new UnhideButton(mrSlideSorter)));
+
+ maRegularButtons.clear();
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new StartShowButton(mrSlideSorter)));
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new HideButton(mrSlideSorter)));
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new DuplicateButton(mrSlideSorter)));
+
+ mpBackgroundTheme.reset(
+ new BitmapBackgroundTheme(
+ mrSlideSorter.GetTheme(),
+ maRegularButtons));
+
+ // Force layout on next Paint().
+ maPageObjectSize = Size(0,0);
+}
+
+
+
+
+void ButtonBar::StartFadeAnimation (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const double nTargetAlpha,
+ const bool bFadeIn)
+{
+ model::SharedPageDescriptor pDescriptor (rpDescriptor);
+
+ const double nCurrentButtonAlpha (pDescriptor->GetVisualState().GetButtonAlpha());
+ const double nCurrentButtonBarAlpha (pDescriptor->GetVisualState().GetButtonBarAlpha());
+
+ // Stop a running animation.
+ const controller::Animator::AnimationId nId (
+ pDescriptor->GetVisualState().GetButtonAlphaAnimationId());
+ if (nId != controller::Animator::NotAnAnimationId)
+ mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(nId);
+
+ // Prepare the blending functors that translate [0,1] animation
+ // times into alpha values of buttons and button bar.
+ const ::boost::function<double(double)> aButtonBlendFunctor (
+ ::boost::bind(
+ controller::AnimationFunction::Blend,
+ nCurrentButtonAlpha,
+ nTargetAlpha,
+ ::boost::bind(controller::AnimationFunction::Linear, _1)));
+ const ::boost::function<double(double)> aButtonBarBlendFunctor (
+ ::boost::bind(
+ controller::AnimationFunction::Blend,
+ nCurrentButtonBarAlpha,
+ nTargetAlpha,
+ ::boost::bind(controller::AnimationFunction::Linear, _1)));
+
+ // Delay the fade in a little bit when the buttons are not visible at
+ // all so that we do not leave a trail of half-visible buttons when the
+ // mouse is moved across the screen. No delay on fade out or when the
+ // buttons are already showing. Fade out is faster than fade in.
+ const double nDelay (nCurrentButtonBarAlpha>0 && nCurrentButtonBarAlpha<1
+ ? 0
+ : (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
+ ? Theme::Integer_ButtonFadeInDelay
+ : Theme::Integer_ButtonFadeOutDelay)));
+ const double nDuration (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
+ ? Theme::Integer_ButtonFadeInDuration
+ : Theme::Integer_ButtonFadeOutDuration));
+ pDescriptor->GetVisualState().SetButtonAlphaAnimationId(
+ mrSlideSorter.GetController().GetAnimator()->AddAnimation(
+ ::boost::bind(
+ controller::AnimationFunction::ApplyButtonAlphaChange,
+ pDescriptor,
+ ::boost::ref(mrSlideSorter.GetView()),
+ ::boost::bind(aButtonBlendFunctor, _1),
+ ::boost::bind(aButtonBarBlendFunctor, _1)),
+ nDelay,
+ nDuration,
+ ::boost::bind(
+ &model::VisualState::SetButtonAlphaAnimationId,
+ ::boost::ref(pDescriptor->GetVisualState()),
+ controller::Animator::NotAnAnimationId)
+ ));
+}
+
+
+
+
+void ButtonBar::AcquireLock (void)
+{
+ if (mnLockCount == 0 && mpDescriptor)
+ RequestFadeOut(mpDescriptor, true);
+
+ ++mnLockCount;
+}
+
+
+
+
+void ButtonBar::ReleaseLock (void)
+{
+ --mnLockCount;
+
+ if (mnLockCount == 0 && mpDescriptor)
+ RequestFadeIn(mpDescriptor, true);
+}
+
+
+
+
+//===== BackgroundTheme =====================================================
+
+ButtonBar::BackgroundTheme::BackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : mpTheme(rpTheme)
+{
+ UpdateMinimumIconSizes(rButtons);
+}
+
+
+
+
+void ButtonBar::BackgroundTheme::SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox)
+{
+ maPreviewBoundingBox = rPreviewBoundingBox;
+ Layout();
+}
+
+
+
+
+void ButtonBar::BackgroundTheme::UpdateMinimumIconSizes (
+ const ::std::vector<SharedButton>& rButtons)
+{
+ OSL_ASSERT(mpTheme);
+
+ sal_Int32 nMaximumHeightLarge (0);
+ sal_Int32 nMaximumHeightMedium (0);
+ sal_Int32 nMaximumHeightSmall (0);
+ const sal_Int32 nGap (mpTheme->GetIntegerValue(Theme::Integer_ButtonGap));
+ const sal_Int32 nBorder (mpTheme->GetIntegerValue(Theme::Integer_ButtonBorder));
+ sal_Int32 nTotalWidthLarge ((rButtons.size()-1) * nGap + 2*nBorder);
+ sal_Int32 nTotalWidthMedium ((rButtons.size()-1) * nGap + 2*nBorder);
+ sal_Int32 nTotalWidthSmall ((rButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ {
+ // Update large size.
+ Size aSize = rButtons[nIndex]->GetSize(Button::IconSize_Large);
+ if (aSize.Height() > nMaximumHeightLarge)
+ nMaximumHeightLarge = aSize.Height();
+ nTotalWidthLarge += aSize.Width();
+
+ // Update medium size.
+ aSize = rButtons[nIndex]->GetSize(Button::IconSize_Medium);
+ if (aSize.Height() > nMaximumHeightMedium)
+ nMaximumHeightMedium = aSize.Height();
+ nTotalWidthMedium += aSize.Width();
+
+ // Update small size.
+ aSize = rButtons[nIndex]->GetSize(Button::IconSize_Small);
+ if (aSize.Height() > nMaximumHeightSmall)
+ nMaximumHeightSmall = aSize.Height();
+ nTotalWidthSmall += aSize.Width();
+ }
+ maMinimumLargeButtonAreaSize = Size(nTotalWidthLarge, nMaximumHeightLarge+2*nBorder);
+ maMinimumMediumButtonAreaSize = Size(nTotalWidthMedium, nMaximumHeightMedium+2*nBorder);
+ maMinimumSmallButtonAreaSize = Size(nTotalWidthSmall, nMaximumHeightSmall+2*nBorder);
+}
+
+
+
+
+Button::IconSize ButtonBar::BackgroundTheme::GetIconSize (void) const
+{
+ return meIconSize;
+}
+
+
+
+
+//===== RectangleBackgroundTheme ============================================
+
+RectangleBackgroundTheme::RectangleBackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : BackgroundTheme(rpTheme, rButtons),
+ mnBarHeight(0)
+{
+}
+
+
+
+
+BitmapEx RectangleBackgroundTheme::CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const
+{
+ OSL_ASSERT(mpTheme);
+
+ // Setup background color.
+ Color aTopFillColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Fill1));
+ Color aTopBorderColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Border1));
+ Color aBottomFillColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Fill2));
+ Color aBottomBorderColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Border2));
+ if (bIsButtonDown)
+ {
+ aTopFillColor.DecreaseLuminance(50);
+ aTopBorderColor.DecreaseLuminance(50);
+ aBottomFillColor.DecreaseLuminance(50);
+ aBottomBorderColor.DecreaseLuminance(50);
+ }
+
+ const int nWidth (maPreviewBoundingBox.GetWidth()+2);
+ const int nHeight (mnBarHeight);
+ const int nCenter (nHeight / 2);
+
+ VirtualDevice aDevice (rTemplateDevice, 0, 8);
+ aDevice.SetOutputSizePixel(Size(nWidth,nHeight));
+
+ // Fill upper and lower half.
+ aDevice.SetLineColor();
+ aDevice.SetFillColor(aTopFillColor);
+ aDevice.DrawRect(Rectangle(0,0,nWidth-1,nCenter));
+ aDevice.SetFillColor(aBottomFillColor);
+ aDevice.DrawRect(Rectangle(0,nCenter,nWidth-1,nHeight-1));
+
+ // Draw border.
+ aDevice.SetFillColor();
+ aDevice.SetLineColor(aTopBorderColor);
+ aDevice.DrawLine(Point(0,nCenter),Point(0,0));
+ aDevice.DrawLine(Point(0,0), Point(nWidth-1,0));
+ aDevice.DrawLine(Point(nWidth-1,0),Point(nWidth-1,nCenter));
+ aDevice.SetLineColor(aBottomBorderColor);
+ aDevice.DrawLine(Point(0,nCenter),Point(0,nHeight-1));
+ aDevice.DrawLine(Point(0,nHeight-1), Point(nWidth-1,nHeight-1));
+ aDevice.DrawLine(Point(nWidth-1,nHeight-1),Point(nWidth-1,nCenter));
+
+ return aDevice.GetBitmapEx(Point(0,0), Size(nWidth,nHeight));
+}
+
+
+
+
+Point RectangleBackgroundTheme::GetBackgroundLocation (void)
+{
+ return Point(
+ maPreviewBoundingBox.Left()-1,
+ maPreviewBoundingBox.Bottom() - mnBarHeight + 2);
+}
+
+
+
+
+Rectangle RectangleBackgroundTheme::GetButtonArea (void)
+{
+ return Rectangle(
+ maPreviewBoundingBox.Left(),
+ maPreviewBoundingBox.Bottom() - mnBarHeight + 2,
+ maPreviewBoundingBox.Right(),
+ maPreviewBoundingBox.Bottom());
+}
+
+
+
+
+void RectangleBackgroundTheme::Layout (void)
+{
+ if (maPreviewBoundingBox.GetWidth() < maMinimumLargeButtonAreaSize.Width())
+ if (maPreviewBoundingBox.GetWidth() < maMinimumMediumButtonAreaSize.Width())
+ {
+ meIconSize = Button::IconSize_Small;
+ mnBarHeight = maMinimumSmallButtonAreaSize.Height();
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Medium;
+ mnBarHeight = maMinimumMediumButtonAreaSize.Height();
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Large;
+ mnBarHeight = maMinimumLargeButtonAreaSize.Height();
+ }
+}
+
+
+
+
+//===== BitmapBackgroundTheme =================================================
+
+BitmapBackgroundTheme::BitmapBackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : BackgroundTheme(rpTheme, rButtons),
+ maButtonArea(),
+ maBackgroundLocation()
+{
+}
+
+
+
+
+BitmapEx BitmapBackgroundTheme::CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const
+{
+ (void)rTemplateDevice;
+ (void)bIsButtonDown;
+
+ OSL_ASSERT(mpTheme);
+
+ // Get images.
+ switch (meIconSize)
+ {
+ case Button::IconSize_Large:
+ default:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarLarge);
+
+ case Button::IconSize_Medium:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarMedium);
+
+ case Button::IconSize_Small:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarSmall);
+ }
+}
+
+
+
+
+Point BitmapBackgroundTheme::GetBackgroundLocation (void)
+{
+ return maBackgroundLocation;
+}
+
+
+
+
+Rectangle BitmapBackgroundTheme::GetButtonArea (void)
+{
+ return maButtonArea;
+}
+
+
+
+
+void BitmapBackgroundTheme::Layout (void)
+{
+ Size aImageSize (mpTheme->GetIcon(Theme::Icon_ButtonBarLarge).GetSizePixel());
+ if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
+ {
+ aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarMedium).GetSizePixel();
+ if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
+ {
+ meIconSize = Button::IconSize_Small;
+ aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarSmall).GetSizePixel();
+ }
+ else
+ meIconSize = Button::IconSize_Medium;
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Large;
+ }
+
+ maBackgroundLocation = Point(
+ maPreviewBoundingBox.Left()
+ + (maPreviewBoundingBox.GetWidth()-aImageSize.Width())/2,
+ maPreviewBoundingBox.Bottom() - aImageSize.Height());
+ maButtonArea = Rectangle(maBackgroundLocation, aImageSize);
+}
+
+
+
+
+//===== Button ================================================================
+
+Button::Button (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsHelpText)
+ : mrSlideSorter(rSlideSorter),
+ meState(State_Normal),
+ maBoundingBox(),
+ msHelpText(rsHelpText),
+ mbIsActive(false),
+ meIconSize(IconSize_Large)
+{
+}
+
+
+
+
+Button::~Button (void)
+{
+}
+
+
+
+
+bool Button::SetState (const State eState)
+{
+ if (meState != eState)
+ {
+ meState = eState;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+Button::State Button::GetState (void) const
+{
+ return meState;
+}
+
+
+
+
+Rectangle Button::GetBoundingBox (void) const
+{
+ if (mbIsActive)
+ return maBoundingBox;
+ else
+ return Rectangle();
+}
+
+
+
+
+::rtl::OUString Button::GetHelpText (void) const
+{
+ if (mbIsActive)
+ return msHelpText;
+ else
+ return ::rtl::OUString();
+}
+
+
+
+
+bool Button::IsDown (void) const
+{
+ return mbIsActive && meState==State_Down;
+}
+
+
+
+
+void Button::SetActiveState (const bool bIsActive)
+{
+ mbIsActive = bIsActive;
+}
+
+
+
+
+bool Button::IsActive (void) const
+{
+ return mbIsActive;
+}
+
+
+
+
+void Button::SetIconSize (const IconSize eIconSize)
+{
+ meIconSize = eIconSize;
+}
+
+
+
+
+Button::IconSize Button::GetIconSize (void) const
+{
+ return meIconSize;
+}
+
+
+
+
+bool Button::IsEnabled (void) const
+{
+ return true;
+}
+
+
+
+
+//===== TextButton ============================================================
+
+TextButton::TextButton (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsText,
+ const ::rtl::OUString& rsHelpText)
+ : Button(rSlideSorter, rsHelpText),
+ msText(rsText)
+{
+}
+
+
+
+
+void TextButton::Place (const Rectangle aButtonBarBox)
+{
+ maBoundingBox = aButtonBarBox;
+ SetActiveState(true);
+}
+
+
+
+
+void TextButton::Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const
+{
+ (void)nAlpha;
+
+ if (mbIsActive)
+ {
+ // Paint text over the button background.
+ if (meState == State_Normal)
+ rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonText));
+ else
+ rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonTextHover));
+ Rectangle aBox (maBoundingBox);
+ aBox += aOffset;
+ rDevice.DrawText(aBox, msText, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER);
+ }
+}
+
+
+
+
+Size TextButton::GetSize (void) const
+{
+ return Size();
+}
+
+
+
+
+Size TextButton::GetSize (const Button::IconSize) const
+{
+ return Size();
+}
+
+
+
+
+//===== ImageButon ============================================================
+
+ImageButton::ImageButton (
+ SlideSorter& rSlideSorter,
+ const BitmapEx& rLargeIcon,
+ const BitmapEx& rLargeHoverIcon,
+ const BitmapEx& rMediumIcon,
+ const BitmapEx& rMediumHoverIcon,
+ const BitmapEx& rSmallIcon,
+ const BitmapEx& rSmallHoverIcon,
+ const ::rtl::OUString& rsHelpText)
+ : Button(rSlideSorter, rsHelpText),
+ maLargeIcon(rLargeIcon),
+ maLargeHoverIcon(rLargeHoverIcon.IsEmpty() ? rLargeIcon : rLargeHoverIcon),
+ maMediumIcon(rMediumIcon),
+ maMediumHoverIcon(rMediumHoverIcon.IsEmpty() ? rMediumIcon : rMediumHoverIcon),
+ maSmallIcon(rSmallIcon),
+ maSmallHoverIcon(rSmallHoverIcon.IsEmpty() ? rSmallIcon : rSmallHoverIcon)
+{
+}
+
+
+
+
+void ImageButton::Place (const Rectangle aButtonBarBox)
+{
+ const sal_Int32 nWidth (GetSize().Width());
+ maBoundingBox = Rectangle(
+ aButtonBarBox.Right() - nWidth,
+ aButtonBarBox.Top(),
+ aButtonBarBox.Right(),
+ aButtonBarBox.Bottom());
+ SetActiveState(aButtonBarBox.IsInside(maBoundingBox));
+}
+
+
+
+
+void ImageButton::Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const
+{
+ (void)rpTheme;
+
+ if ( ! mbIsActive)
+ return;
+
+ const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing());
+ rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW);
+
+ rDevice.SetLineColor();
+
+ // Choose icon.
+ BitmapEx aIcon;
+ switch (meIconSize)
+ {
+ case IconSize_Large:
+ default:
+ if (meState == State_Normal)
+ aIcon = maLargeIcon;
+ else
+ aIcon = maLargeHoverIcon;
+ break;
+
+ case IconSize_Medium:
+ if (meState == State_Normal)
+ aIcon = maMediumIcon;
+ else
+ aIcon = maMediumHoverIcon;
+ break;
+
+ case IconSize_Small:
+ if (meState == State_Normal)
+ aIcon = maSmallIcon;
+ else
+ aIcon = maSmallHoverIcon;
+ break;
+ }
+
+ // Paint icon.
+ if ( ! aIcon.IsEmpty())
+ {
+ AlphaMask aMask (aIcon.GetSizePixel());
+ AdaptTransparency(aMask, aIcon.GetAlpha(), nAlpha);
+ rDevice.DrawBitmapEx(
+ Point(
+ maBoundingBox.Left()
+ + aOffset.X()
+ + (maBoundingBox.GetWidth()-aIcon.GetSizePixel().Width())/2,
+ maBoundingBox.Top()
+ + aOffset.Y()
+ + (maBoundingBox.GetHeight()-aIcon.GetSizePixel().Height())/2),
+ BitmapEx(aIcon.GetBitmap(), aMask));
+ }
+
+ rDevice.SetAntialiasing(nSavedAntialiasingMode);
+}
+
+
+
+
+Size ImageButton::GetSize (void) const
+{
+ return GetSize(meIconSize);
+}
+
+
+
+
+Size ImageButton::GetSize (const Button::IconSize eIconSize) const
+{
+ switch (eIconSize)
+ {
+ case IconSize_Large:
+ default:
+ return maLargeIcon.GetSizePixel();
+
+ case IconSize_Medium:
+ return maMediumIcon.GetSizePixel();
+
+ case IconSize_Small:
+ return maSmallIcon.GetSizePixel();
+ }
+}
+
+
+
+
+//===== UnhideButton ==========================================================
+
+UnhideButton::UnhideButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLarge),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMedium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmall),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command2B))
+{
+}
+
+
+
+
+void UnhideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+ mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
+ (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
+ ? model::SharedPageDescriptor()
+ : rpDescriptor),
+ false);
+}
+
+
+
+
+//===== StartSlideShowButton ==================================================
+
+StartShowButton::StartShowButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command1))
+{
+}
+
+
+
+
+bool StartShowButton::IsEnabled (void) const
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == NULL)
+ return false;
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher == NULL)
+ return false;
+
+ const SfxPoolItem* pState = NULL;
+ const SfxItemState eState (pDispatcher->QueryState(SID_PRESENTATION, pState));
+ return (eState & SFX_ITEM_DISABLED) == 0;
+}
+
+
+
+
+void StartShowButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ // Hide the tool tip early, while the slide show still intializes.
+ mrSlideSorter.GetView().GetToolTip().SetPage(model::SharedPageDescriptor());
+
+ Reference< XPresentation2 > xPresentation(
+ mrSlideSorter.GetModel().GetDocument()->getPresentation());
+ if (xPresentation.is())
+ {
+ Sequence<PropertyValue> aProperties (1);
+ aProperties[0].Name = ::rtl::OUString::createFromAscii("FirstPage");
+ const ::rtl::OUString sName (rpDescriptor->GetPage()->GetName());
+ aProperties[0].Value = Any(sName);
+ xPresentation->startWithArguments(aProperties);
+ }
+}
+
+
+
+
+//===== HideButton ============================================================
+
+HideButton::HideButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command2))
+{
+}
+
+
+
+
+void HideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+ mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
+ (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
+ ? model::SharedPageDescriptor()
+ : rpDescriptor),
+ true);
+}
+
+
+
+
+//===== DuplicateButton =======================================================
+
+DuplicateButton::DuplicateButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command3))
+{
+}
+
+
+
+
+bool DuplicateButton::IsEnabled (void) const
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == NULL)
+ return false;
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher == NULL)
+ return false;
+
+ const SfxPoolItem* pState = NULL;
+ const SfxItemState eState (pDispatcher->QueryState(
+ SID_DUPLICATE_PAGE,
+ pState));
+ return (eState & SFX_ITEM_DISABLED) == 0;
+}
+
+
+
+
+void DuplicateButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor(),false);
+
+ // When the page under the button is not selected then set the
+ // selection to just this page.
+ if ( ! rpDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ {
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+ }
+ // Duplicate the selected pages. Insert the new pages right
+ // after the current selection and select them
+ if (mrSlideSorter.GetViewShell() != NULL
+ && mrSlideSorter.GetViewShell()->GetDispatcher() != NULL)
+ {
+ mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
+ SID_DUPLICATE_PAGE,
+ SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsFontProvider.cxx b/sd/source/ui/slidesorter/view/SlsFontProvider.cxx
new file mode 100644
index 000000000000..f81035e50be1
--- /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(sal_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/SlsFramePainter.cxx b/sd/source/ui/slidesorter/view/SlsFramePainter.cxx
new file mode 100644
index 000000000000..c62c32e7d841
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsFramePainter.cxx
@@ -0,0 +1,265 @@
+/*************************************************************************
+ *
+ * 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 "SlsFramePainter.hxx"
+#include <vcl/outdev.hxx>
+#include <vcl/bmpacc.hxx>
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+FramePainter::FramePainter (const BitmapEx& rShadowBitmap)
+ : maTopLeft(rShadowBitmap,-1,-1),
+ maTop(rShadowBitmap,0,-1),
+ maTopRight(rShadowBitmap,+1,-1),
+ maLeft(rShadowBitmap,-1,0),
+ maRight(rShadowBitmap,+1,0),
+ maBottomLeft(rShadowBitmap,-1,+1),
+ maBottom(rShadowBitmap,0,+1),
+ maBottomRight(rShadowBitmap,+1,+1),
+ maCenter(rShadowBitmap,0,0),
+ mbIsValid(false)
+{
+ if (rShadowBitmap.GetSizePixel().Width() == rShadowBitmap.GetSizePixel().Height()
+ && (rShadowBitmap.GetSizePixel().Width()-1)%2 == 0
+ && ((rShadowBitmap.GetSizePixel().Width()-1)/2)%2 == 1)
+ {
+ mbIsValid = true;
+ }
+ else
+ {
+ OSL_ASSERT(rShadowBitmap.GetSizePixel().Width() == rShadowBitmap.GetSizePixel().Height());
+ OSL_ASSERT((rShadowBitmap.GetSizePixel().Width()-1)%2 == 0);
+ OSL_ASSERT(((rShadowBitmap.GetSizePixel().Width()-1)/2)%2 == 1);
+ }
+}
+
+
+
+
+FramePainter::~FramePainter (void)
+{
+}
+
+
+
+
+void FramePainter::PaintFrame (
+ OutputDevice& rDevice,
+ const Rectangle aBox) const
+{
+ if ( ! mbIsValid)
+ return;
+
+ // Paint the shadow.
+ maTopLeft.PaintCorner(rDevice, aBox.TopLeft());
+ maTopRight.PaintCorner(rDevice, aBox.TopRight());
+ maBottomLeft.PaintCorner(rDevice, aBox.BottomLeft());
+ maBottomRight.PaintCorner(rDevice, aBox.BottomRight());
+ maLeft.PaintSide(rDevice, aBox.TopLeft(), aBox.BottomLeft(), maTopLeft, maBottomLeft);
+ maRight.PaintSide(rDevice, aBox.TopRight(), aBox.BottomRight(), maTopRight, maBottomRight);
+ maTop.PaintSide(rDevice, aBox.TopLeft(), aBox.TopRight(), maTopLeft, maTopRight);
+ maBottom.PaintSide(rDevice, aBox.BottomLeft(), aBox.BottomRight(), maBottomLeft, maBottomRight);
+ maCenter.PaintCenter(rDevice,aBox);
+}
+
+
+
+
+void FramePainter::AdaptColor (
+ const Color aNewColor,
+ const bool bEraseCenter)
+{
+ // Get the source color.
+ if (maCenter.maBitmap.IsEmpty())
+ return;
+ BitmapReadAccess* pReadAccess = maCenter.maBitmap.GetBitmap().AcquireReadAccess();
+ if (pReadAccess == NULL)
+ return;
+ const Color aSourceColor = pReadAccess->GetColor(0,0);
+ maCenter.maBitmap.GetBitmap().ReleaseAccess(pReadAccess);
+
+ // Erase the center bitmap.
+ if (bEraseCenter)
+ maCenter.maBitmap.SetEmpty();
+
+ // Replace the color in all bitmaps.
+ maTopLeft.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maTop.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maTopRight.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maLeft.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maCenter.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maRight.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maBottomLeft.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maBottom.maBitmap.Replace(aSourceColor, aNewColor, 0);
+ maBottomRight.maBitmap.Replace(aSourceColor, aNewColor, 0);
+}
+
+
+
+
+//===== FramePainter::OffsetBitmap ============================================
+
+FramePainter::OffsetBitmap::OffsetBitmap (
+ const BitmapEx& rBitmap,
+ const sal_Int32 nHorizontalPosition,
+ const sal_Int32 nVerticalPosition)
+ : maBitmap(),
+ maOffset()
+{
+ OSL_ASSERT(nHorizontalPosition>=-1 && nHorizontalPosition<=+1);
+ OSL_ASSERT(nVerticalPosition>=-1 && nVerticalPosition<=+1);
+
+ const sal_Int32 nS (1);
+ const sal_Int32 nC (::std::max<sal_Int32>(0,(rBitmap.GetSizePixel().Width()-nS)/2));
+ const sal_Int32 nO (nC/2);
+
+ const Point aOrigin(
+ nHorizontalPosition<0 ? 0 : (nHorizontalPosition == 0 ? nC : nC+nS),
+ nVerticalPosition<0 ? 0 : (nVerticalPosition == 0 ? nC : nC+nS));
+ const Size aSize(
+ nHorizontalPosition==0 ? nS : nC,
+ nVerticalPosition==0 ? nS : nC);
+ maBitmap = BitmapEx(rBitmap, aOrigin, aSize);
+ if (maBitmap.IsEmpty())
+ return;
+ maOffset = Point(
+ nHorizontalPosition<0 ? -nO : nHorizontalPosition>0 ? -nO : 0,
+ nVerticalPosition<0 ? -nO : nVerticalPosition>0 ? -nO : 0);
+
+ // Enlarge the side bitmaps so that painting the frame requires less
+ // paint calls.
+ const sal_Int32 nSideBitmapSize (64);
+ if (nHorizontalPosition == 0 && nVerticalPosition == 0)
+ {
+ maBitmap.Scale(Size(nSideBitmapSize,nSideBitmapSize), BMP_SCALE_FAST);
+ }
+ else if (nHorizontalPosition == 0)
+ {
+ maBitmap.Scale(Size(nSideBitmapSize,aSize.Height()), BMP_SCALE_FAST);
+ }
+ else if (nVerticalPosition == 0)
+ {
+ maBitmap.Scale(Size(maBitmap.GetSizePixel().Width(), nSideBitmapSize), BMP_SCALE_FAST);
+ }
+}
+
+
+
+
+void FramePainter::OffsetBitmap::PaintCorner (
+ OutputDevice& rDevice,
+ const Point& rAnchor) const
+{
+ if ( ! maBitmap.IsEmpty())
+ rDevice.DrawBitmapEx(rAnchor+maOffset, maBitmap);
+}
+
+
+
+
+void FramePainter::OffsetBitmap::PaintSide (
+ OutputDevice& rDevice,
+ const Point& rAnchor1,
+ const Point& rAnchor2,
+ const OffsetBitmap& rCornerBitmap1,
+ const OffsetBitmap& rCornerBitmap2) const
+{
+ if (maBitmap.IsEmpty())
+ return;
+
+ const Size aBitmapSize (maBitmap.GetSizePixel());
+ if (rAnchor1.Y() == rAnchor2.Y())
+ {
+ // Side is horizontal.
+ const sal_Int32 nY (rAnchor1.Y() + maOffset.Y());
+ const sal_Int32 nLeft (
+ rAnchor1.X()
+ + rCornerBitmap1.maBitmap.GetSizePixel().Width()
+ + rCornerBitmap1.maOffset.X());
+ const sal_Int32 nRight (
+ rAnchor2.X()
+ + rCornerBitmap2.maOffset.X()\
+ - 1);
+ for (sal_Int32 nX=nLeft; nX<=nRight; nX+=aBitmapSize.Width())
+ {
+ rDevice.DrawBitmapEx(
+ Point(nX,nY),
+ Size(std::min(aBitmapSize.Width(),static_cast<long>(nRight-nX+1)),aBitmapSize.Height()),
+ maBitmap);
+ }
+ }
+ else if (rAnchor1.X() == rAnchor2.X())
+ {
+ // Side is vertical.
+ const sal_Int32 nX (rAnchor1.X() + maOffset.X());
+ const sal_Int32 nTop (
+ rAnchor1.Y()
+ + rCornerBitmap1.maBitmap.GetSizePixel().Height()
+ + rCornerBitmap1.maOffset.Y());
+ const sal_Int32 nBottom (
+ rAnchor2.Y()
+ + rCornerBitmap2.maOffset.Y()
+ - 1);
+ for (sal_Int32 nY=nTop; nY<=nBottom; nY+=aBitmapSize.Height())
+ {
+ rDevice.DrawBitmapEx(
+ Point(nX,nY),
+ Size(aBitmapSize.Width(), std::min(aBitmapSize.Height(), static_cast<long>(nBottom-nY+1))),
+ maBitmap);
+ }
+ }
+ else
+ {
+ // Diagonal sides indicatee an error.
+ OSL_ASSERT(false);
+ }
+}
+
+
+
+
+void FramePainter::OffsetBitmap::PaintCenter (
+ OutputDevice& rDevice,
+ const Rectangle& rBox) const
+{
+ const Size aBitmapSize (maBitmap.GetSizePixel());
+ for (sal_Int32 nY=rBox.Top(); nY<=rBox.Bottom(); nY+=aBitmapSize.Height())
+ for (sal_Int32 nX=rBox.Left(); nX<=rBox.Right(); nX+=aBitmapSize.Width())
+ rDevice.DrawBitmapEx(
+ Point(nX,nY),
+ Size(
+ ::std::min(aBitmapSize.Width(), rBox.Right()-nX+1),
+ std::min(aBitmapSize.Height(), rBox.Bottom()-nY+1)),
+ maBitmap);
+}
+
+
+
+} } } // end of namespace sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsFramePainter.hxx b/sd/source/ui/slidesorter/view/SlsFramePainter.hxx
new file mode 100644
index 000000000000..96ccf51c6323
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsFramePainter.hxx
@@ -0,0 +1,121 @@
+/*************************************************************************
+ *
+ * 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_FRAME_PAINTER_HXX
+#define SD_SLIDESORTER_VIEW_FRAME_PAINTER_HXX
+
+#include <vcl/bitmapex.hxx>
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+class FramePainter
+{
+public:
+ FramePainter (const BitmapEx& rBitmap);
+ ~FramePainter (void);
+
+ /** Paint a border around the given box by using a set of bitmaps for
+ the corners and sides.
+ */
+ void PaintFrame (OutputDevice&rDevice, const Rectangle aBox) const;
+
+ /** Special functionality that takes the color from the center
+ bitmap and replaces that color in all bitmaps by the given new
+ color. Alpha values are not modified.
+ @param bClearCenterBitmap
+ When <TRUE/> then the center bitmap is erased.
+ */
+ void AdaptColor (const Color aNewColor, const bool bClearCenterBitmap);
+
+private:
+ /** Bitmap with offset that is used when the bitmap is painted. The bitmap
+ */
+ class OffsetBitmap {
+ public:
+ BitmapEx maBitmap;
+ Point maOffset;
+
+ /** Create one of the eight shadow bitmaps from one that combines
+ them all. This larger bitmap is expected to have dimension NxN
+ with N=1+2*M. Of this larger bitmap there are created four
+ corner bitmaps of size 2*M x 2*M and four side bitmaps of sizes
+ 1xM (top and bottom) and Mx1 (left and right). The corner
+ bitmaps have each one quadrant of size MxM that is painted under
+ the interior of the frame.
+ @param rBitmap
+ The larger bitmap of which the eight shadow bitmaps are cut
+ out from.
+ @param nHorizontalPosition
+ Valid values are -1 (left), 0 (center), and +1 (right).
+ @param nVerticalPosition
+ Valid values are -1 (top), 0 (center), and +1 (bottom).
+ */
+ OffsetBitmap (
+ const BitmapEx& rBitmap,
+ const sal_Int32 nHorizontalPosition,
+ const sal_Int32 nVerticalPosition);
+
+ /** Use the given device to paint the bitmap at the location that is
+ the sum of the given anchor and the internal offset.
+ */
+ void PaintCorner (OutputDevice& rDevice, const Point& rAnchor) const;
+
+ /** Use the given device to paint the bitmap stretched between the
+ two given locations. Offsets of the adjacent corner bitmaps and
+ the offset of the side bitmap are used to determine the area
+ that is to be filled with the side bitmap.
+ */
+ void PaintSide (
+ OutputDevice& rDevice,
+ const Point& rAnchor1,
+ const Point& rAnchor2,
+ const OffsetBitmap& rCornerBitmap1,
+ const OffsetBitmap& rCornerBitmap2) const;
+
+ /** Fill the given rectangle with the bitmap.
+ */
+ void PaintCenter (
+ OutputDevice& rDevice,
+ const Rectangle& rBox) const;
+ };
+ OffsetBitmap maTopLeft;
+ OffsetBitmap maTop;
+ OffsetBitmap maTopRight;
+ OffsetBitmap maLeft;
+ OffsetBitmap maRight;
+ OffsetBitmap maBottomLeft;
+ OffsetBitmap maBottom;
+ OffsetBitmap maBottomRight;
+ OffsetBitmap maCenter;
+ bool mbIsValid;
+};
+
+
+} } } // end of namespace sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/view/SlsInsertAnimator.cxx b/sd/source/ui/slidesorter/view/SlsInsertAnimator.cxx
new file mode 100644
index 000000000000..3dd9af11194a
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsInsertAnimator.cxx
@@ -0,0 +1,537 @@
+/*************************************************************************
+ *
+ * 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/SlsInsertAnimator.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsAnimationFunction.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+
+#include <set>
+#include <boost/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+
+class PageObjectRun;
+
+class AnimatorAccess
+{
+public:
+ virtual void AddRun (const ::boost::shared_ptr<PageObjectRun> pRun) = 0;
+ virtual void RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun) = 0;
+ virtual model::SlideSorterModel& GetModel (void) const = 0;
+ virtual view::SlideSorterView& GetView (void) const = 0;
+ virtual ::boost::shared_ptr<controller::Animator> GetAnimator (void) = 0;
+ virtual SharedSdWindow GetContentWindow (void) = 0;
+};
+
+
+/** Controller of the position offsets of all page objects in one row or one
+ column.
+*/
+class PageObjectRun : public ::boost::enable_shared_from_this<PageObjectRun>
+{
+public:
+ PageObjectRun (
+ AnimatorAccess& rAnimatorAccess,
+ const sal_Int32 nRunIndex,
+ const sal_Int32 nStartIndex,
+ const sal_Int32 nEndIndex);
+ ~PageObjectRun (void);
+
+ void operator () (const double nTime);
+
+ void UpdateOffsets(
+ const InsertPosition& rInsertPosition,
+ const view::Layouter& GetLayouter);
+ void ResetOffsets (const controller::Animator::AnimationMode eMode);
+
+ /// Index of the row or column that this run represents.
+ sal_Int32 mnRunIndex;
+ /// The index at which to make place for the insertion indicator (-1 for
+ /// no indicator).
+ sal_Int32 mnLocalInsertIndex;
+ /// Index of the first page in the run.
+ sal_Int32 mnStartIndex;
+ /// Index of the last page in the run.
+ sal_Int32 mnEndIndex;
+ /// Offset of each item in the run at the start of the current animation.
+ ::std::vector<Point> maStartOffset;
+ /// Target offset of each item in the run at the end of the current animation.
+ ::std::vector<Point> maEndOffset;
+ /// Time at which the current animation started.
+ double mnStartTime;
+
+ class Comparator
+ {
+ public: bool operator() (
+ const ::boost::shared_ptr<PageObjectRun>& rpRunA,
+ const ::boost::shared_ptr<PageObjectRun>& rpRunB) const
+ {
+ return rpRunA->mnRunIndex < rpRunB->mnRunIndex;
+ }
+ };
+private:
+ controller::Animator::AnimationId mnAnimationId;
+ AnimatorAccess& mrAnimatorAccess;
+ ::boost::function<double(double)> maAccelerationFunction;
+
+ Rectangle GetInnerBoundingBox (
+ const view::Layouter& rLayouter,
+ const sal_Int32 nIndex) const;
+ void RestartAnimation (void);
+};
+typedef ::boost::shared_ptr<PageObjectRun> SharedPageObjectRun;
+
+
+Point Blend (const Point& rPointA, const Point& rPointB, const double nT)
+{
+ return Point(
+ sal_Int32(rPointA.X() * (1-nT) + rPointB.X() * nT),
+ sal_Int32(rPointA.Y() * (1-nT) + rPointB.Y() * nT));
+}
+
+} // end of anonymous namespace
+
+
+
+class InsertAnimator::Implementation : public AnimatorAccess
+{
+public:
+ Implementation (SlideSorter& rSlideSorter);
+ virtual ~Implementation (void);
+
+ void SetInsertPosition (
+ const InsertPosition& rInsertPosition,
+ const controller::Animator::AnimationMode eAnimationMode);
+
+ virtual void AddRun (const ::boost::shared_ptr<PageObjectRun> pRun);
+ virtual void RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun);
+
+ virtual model::SlideSorterModel& GetModel (void) const { return mrModel; }
+ virtual view::SlideSorterView& GetView (void) const { return mrView; }
+ virtual ::boost::shared_ptr<controller::Animator> GetAnimator (void) { return mpAnimator; }
+ virtual SharedSdWindow GetContentWindow (void) { return mrSlideSorter.GetContentWindow(); }
+
+private:
+ model::SlideSorterModel& mrModel;
+ view::SlideSorterView& mrView;
+ SlideSorter& mrSlideSorter;
+ ::boost::shared_ptr<controller::Animator> mpAnimator;
+ typedef ::std::set<SharedPageObjectRun, PageObjectRun::Comparator> RunContainer;
+ RunContainer maRuns;
+ InsertPosition maInsertPosition;
+
+ void StopAnimation (void);
+ SharedPageObjectRun GetRun (
+ view::Layouter& rLayouter,
+ const InsertPosition& rInsertPosition,
+ const bool bCreate = true);
+ RunContainer::const_iterator FindRun (const sal_Int32 nRunIndex) const;
+};
+
+
+
+
+
+//===== InsertAnimator ========================================================
+
+InsertAnimator::InsertAnimator (SlideSorter& rSlideSorter)
+ : mpImplementation(new Implementation(rSlideSorter))
+{
+}
+
+
+
+
+void InsertAnimator::SetInsertPosition (const InsertPosition& rInsertPosition)
+{
+ mpImplementation->SetInsertPosition(rInsertPosition, controller::Animator::AM_Animated);
+}
+
+
+
+
+void InsertAnimator::Reset (const controller::Animator::AnimationMode eMode)
+{
+ mpImplementation->SetInsertPosition(InsertPosition(), eMode);
+}
+
+
+
+
+//===== InsertAnimator::Implementation ========================================
+
+InsertAnimator::Implementation::Implementation (SlideSorter& rSlideSorter)
+ : mrModel(rSlideSorter.GetModel()),
+ mrView(rSlideSorter.GetView()),
+ mrSlideSorter(rSlideSorter),
+ mpAnimator(rSlideSorter.GetController().GetAnimator()),
+ maRuns(),
+ maInsertPosition()
+{
+}
+
+
+
+
+InsertAnimator::Implementation::~Implementation (void)
+{
+ SetInsertPosition(InsertPosition(), controller::Animator::AM_Immediate);
+}
+
+
+
+
+void InsertAnimator::Implementation::SetInsertPosition (
+ const InsertPosition& rInsertPosition,
+ const controller::Animator::AnimationMode eMode)
+{
+ if (maInsertPosition == rInsertPosition)
+ return;
+
+ SharedPageObjectRun pOldRun (GetRun(mrView.GetLayouter(), maInsertPosition));
+ SharedPageObjectRun pCurrentRun (GetRun(mrView.GetLayouter(), rInsertPosition));
+ maInsertPosition = rInsertPosition;
+
+ // When the new insert position is in a different run then move the page
+ // objects in the old run to their default positions.
+ if (pOldRun != pCurrentRun)
+ {
+ if (pOldRun)
+ pOldRun->ResetOffsets(eMode);
+ }
+
+ if (pCurrentRun)
+ {
+ pCurrentRun->UpdateOffsets(rInsertPosition, mrView.GetLayouter());
+ }
+}
+
+
+
+
+SharedPageObjectRun InsertAnimator::Implementation::GetRun (
+ view::Layouter& rLayouter,
+ const InsertPosition& rInsertPosition,
+ const bool bCreate)
+{
+ const sal_Int32 nRow (rInsertPosition.GetRow());
+ if (nRow < 0)
+ return SharedPageObjectRun();
+
+ RunContainer::const_iterator iRun (maRuns.end());
+ if (rLayouter.GetColumnCount() == 1)
+ {
+ // There is only one run that contains all slides.
+ if (maRuns.empty() && bCreate)
+ maRuns.insert(SharedPageObjectRun(new PageObjectRun(
+ *this,
+ 0,
+ 0,
+ mrModel.GetPageCount()-1)));
+ iRun = maRuns.begin();
+ }
+ else
+ {
+ iRun = FindRun(nRow);
+ if (iRun == maRuns.end() && bCreate)
+ {
+ // Create a new run.
+ const sal_Int32 nStartIndex (rLayouter.GetIndex(nRow, 0));
+ const sal_Int32 nEndIndex (rLayouter.GetIndex(nRow, rLayouter.GetColumnCount()-1));
+ if (nStartIndex <= nEndIndex)
+ {
+ iRun = maRuns.insert(SharedPageObjectRun(new PageObjectRun(
+ *this,
+ nRow,
+ nStartIndex,
+ nEndIndex))).first;
+ OSL_ASSERT(iRun != maRuns.end());
+ }
+ }
+ }
+
+ if (iRun != maRuns.end())
+ return *iRun;
+ else
+ return SharedPageObjectRun();
+}
+
+
+
+
+InsertAnimator::Implementation::RunContainer::const_iterator
+ InsertAnimator::Implementation::FindRun (const sal_Int32 nRunIndex) const
+{
+ return std::find_if(
+ maRuns.begin(),
+ maRuns.end(),
+ ::boost::bind(
+ ::std::equal_to<sal_Int32>(),
+ ::boost::bind(&PageObjectRun::mnRunIndex, _1),
+ nRunIndex));
+}
+
+
+
+
+void InsertAnimator::Implementation::AddRun (const ::boost::shared_ptr<PageObjectRun> pRun)
+{
+ if (pRun)
+ {
+ maRuns.insert(pRun);
+ }
+ else
+ {
+ OSL_ASSERT(pRun);
+ }
+}
+
+
+
+
+
+void InsertAnimator::Implementation::RemoveRun (const ::boost::shared_ptr<PageObjectRun> pRun)
+{
+ if (pRun)
+ {
+ // Do not remove runs that show the space for the insertion indicator.
+ if (pRun->mnLocalInsertIndex == -1)
+ {
+ InsertAnimator::Implementation::RunContainer::const_iterator iRun (FindRun(pRun->mnRunIndex));
+ if (iRun != maRuns.end())
+ {
+ OSL_ASSERT(*iRun == pRun);
+ maRuns.erase(iRun);
+ }
+ }
+ }
+ else
+ {
+ OSL_ASSERT(pRun);
+ }
+}
+
+
+
+
+
+//===== PageObjectRun =========================================================
+
+PageObjectRun::PageObjectRun (
+ AnimatorAccess& rAnimatorAccess,
+ const sal_Int32 nRunIndex,
+ const sal_Int32 nStartIndex,
+ const sal_Int32 nEndIndex)
+ : mnRunIndex(nRunIndex),
+ mnLocalInsertIndex(-1),
+ mnStartIndex(nStartIndex),
+ mnEndIndex(nEndIndex),
+ maStartOffset(),
+ maEndOffset(),
+ mnStartTime(-1),
+ mnAnimationId(controller::Animator::NotAnAnimationId),
+ mrAnimatorAccess(rAnimatorAccess),
+ maAccelerationFunction(
+ controller::AnimationParametricFunction(
+ controller::AnimationBezierFunction (0.1,0.7)))
+{
+ maStartOffset.resize(nEndIndex - nStartIndex + 1);
+ maEndOffset.resize(nEndIndex - nStartIndex + 1);
+}
+
+
+
+
+PageObjectRun::~PageObjectRun (void)
+{
+}
+
+
+
+
+Rectangle PageObjectRun::GetInnerBoundingBox (
+ const view::Layouter& rLayouter,
+ const sal_Int32 nIndex) const
+{
+ model::SharedPageDescriptor pDescriptor (
+ mrAnimatorAccess.GetModel().GetPageDescriptor(nIndex));
+ if (pDescriptor)
+ if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ return rLayouter.GetPageObjectLayouter()->GetBoundingBox(
+ pDescriptor,
+ PageObjectLayouter::PageObject,
+ PageObjectLayouter::ModelCoordinateSystem);
+ else
+ return rLayouter.GetPageObjectLayouter()->GetBoundingBox(
+ pDescriptor,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem);
+ else
+ return Rectangle();
+}
+
+
+
+
+void PageObjectRun::UpdateOffsets(
+ const InsertPosition& rInsertPosition,
+ const view::Layouter& rLayouter)
+{
+ const bool bIsVertical (rLayouter.GetColumnCount()==1);
+ const sal_Int32 nLocalInsertIndex(bIsVertical
+ ? rInsertPosition.GetRow()
+ : rInsertPosition.GetColumn());
+ if (nLocalInsertIndex != mnLocalInsertIndex)
+ {
+ mnLocalInsertIndex = nLocalInsertIndex;
+
+ model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
+ const sal_Int32 nRunLength (mnEndIndex - mnStartIndex + 1);
+ for (sal_Int32 nIndex=0; nIndex<nRunLength; ++nIndex)
+ {
+ model::SharedPageDescriptor pDescriptor(rModel.GetPageDescriptor(nIndex+mnStartIndex));
+ if (pDescriptor)
+ maStartOffset[nIndex] = pDescriptor->GetVisualState().GetLocationOffset();
+ maEndOffset[nIndex] = nIndex < mnLocalInsertIndex
+ ? rInsertPosition.GetLeadingOffset()
+ : rInsertPosition.GetTrailingOffset();
+ if (bIsVertical)
+ maEndOffset[nIndex].X() = 0;
+ else
+ maEndOffset[nIndex].Y() = 0;
+ }
+ RestartAnimation();
+ }
+}
+
+
+
+
+void PageObjectRun::ResetOffsets (const controller::Animator::AnimationMode eMode)
+{
+ mnLocalInsertIndex = -1;
+ const sal_Int32 nRunLength (mnEndIndex - mnStartIndex + 1);
+ model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
+ view::SlideSorterView& rView (mrAnimatorAccess.GetView());
+ for (sal_Int32 nIndex=0; nIndex<nRunLength; ++nIndex)
+ {
+ model::SharedPageDescriptor pDescriptor(rModel.GetPageDescriptor(nIndex+mnStartIndex));
+ if (pDescriptor)
+ {
+ if (eMode == controller::Animator::AM_Animated)
+ maStartOffset[nIndex] = pDescriptor->GetVisualState().GetLocationOffset();
+ else
+ {
+ const Rectangle aOldBoundingBox (pDescriptor->GetBoundingBox());
+ pDescriptor->GetVisualState().SetLocationOffset(Point(0,0));
+ rView.RequestRepaint(aOldBoundingBox);
+ rView.RequestRepaint(pDescriptor);
+ }
+ }
+ maEndOffset[nIndex] = Point(0,0);
+ }
+ if (eMode == controller::Animator::AM_Animated)
+ RestartAnimation();
+ else
+ mrAnimatorAccess.RemoveRun(shared_from_this());
+}
+
+
+
+
+void PageObjectRun::RestartAnimation (void)
+{
+ // Stop the current animation.
+ if (mnAnimationId != controller::Animator::NotAnAnimationId)
+ {
+ mrAnimatorAccess.GetAnimator()->RemoveAnimation(mnAnimationId);
+ }
+
+ // Restart the animation.
+ mrAnimatorAccess.AddRun(shared_from_this());
+ mnAnimationId = mrAnimatorAccess.GetAnimator()->AddAnimation(
+ ::boost::ref(*this),
+ 0,
+ 300,
+ ::boost::bind(
+ &AnimatorAccess::RemoveRun,
+ ::boost::ref(mrAnimatorAccess),
+ shared_from_this()));
+}
+
+
+
+
+void PageObjectRun::operator () (const double nGlobalTime)
+{
+ if (mnStartTime < 0)
+ mnStartTime = nGlobalTime;
+
+ double nLocalTime (nGlobalTime - mnStartTime);
+ if (nLocalTime > 1.0)
+ nLocalTime = 1.0;
+ nLocalTime = maAccelerationFunction(nLocalTime);
+
+ model::SlideSorterModel& rModel (mrAnimatorAccess.GetModel());
+ view::SlideSorterView& rView (mrAnimatorAccess.GetView());
+ for (sal_Int32 nIndex=mnStartIndex; nIndex<=mnEndIndex; ++nIndex)
+ {
+ model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
+ if ( ! pDescriptor)
+ continue;
+ const Rectangle aOldBoundingBox (pDescriptor->GetBoundingBox());
+ pDescriptor->GetVisualState().SetLocationOffset(
+ Blend(
+ maStartOffset[nIndex-mnStartIndex],
+ maEndOffset[nIndex-mnStartIndex],
+ nLocalTime));
+
+ // Request a repaint of the old and new bounding box (which largely overlap.)
+ rView.RequestRepaint(aOldBoundingBox);
+ rView.RequestRepaint(pDescriptor);
+ }
+
+ // Call Flush to make
+ // a) animations a bit more smooth and
+ // b) on Mac without the Flush a Reset of the page locations is not properly
+ // visualized when the mouse leaves the window during drag-and-drop.
+ mrAnimatorAccess.GetContentWindow()->Flush();
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx
new file mode 100644
index 000000000000..abaa5a43b215
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx
@@ -0,0 +1,448 @@
+/*************************************************************************
+ *
+ * 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/SlsInsertionIndicatorOverlay.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageEnumeration.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsTheme.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "SlsFramePainter.hxx"
+#include "SlsLayeredDevice.hxx"
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "sdmod.hxx"
+
+#include <vcl/virdev.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+
+namespace {
+
+
+static const double gnPreviewOffsetScale = 1.0 / 8.0;
+
+
+
+Rectangle GrowRectangle (const Rectangle& rBox, const sal_Int32 nOffset)
+{
+ return Rectangle (
+ rBox.Left() - nOffset,
+ rBox.Top() - nOffset,
+ rBox.Right() + nOffset,
+ rBox.Bottom() + nOffset);
+}
+
+sal_Int32 RoundToInt (const double nValue) { return sal_Int32(::rtl::math::round(nValue)); }
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+//===== InsertionIndicatorOverlay ===========================================
+
+const static sal_Int32 gnShadowBorder = 3;
+const static sal_Int32 gnSuperScaleFactor = 1;
+
+InsertionIndicatorOverlay::InsertionIndicatorOverlay (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mbIsVisible(false),
+ mnLayerIndex(2),
+ mpLayerInvalidator(),
+ maLocation(),
+ maIcon(),
+ maIconOffset(),
+ mpShadowPainter(
+ new FramePainter(mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_RawInsertShadow)))
+{
+}
+
+
+
+
+InsertionIndicatorOverlay::~InsertionIndicatorOverlay (void)
+{
+ Hide();
+}
+
+
+
+
+void InsertionIndicatorOverlay::Create (const controller::Transferable* pTransferable)
+{
+ if (pTransferable == NULL)
+ return;
+
+ sal_Int32 nSelectionCount (0);
+ if (pTransferable->HasPageBookmarks())
+ nSelectionCount = pTransferable->GetPageBookmarks().Count();
+ else
+ {
+ DrawDocShell* pDataDocShell = dynamic_cast<DrawDocShell*>(&pTransferable->GetDocShell());
+ if (pDataDocShell != NULL)
+ {
+ SdDrawDocument* pDataDocument = pDataDocShell->GetDoc();
+ if (pDataDocument != NULL)
+ nSelectionCount = pDataDocument->GetSdPageCount(PK_STANDARD);
+ }
+ }
+ Create(pTransferable->GetRepresentatives(), nSelectionCount);
+}
+
+
+
+
+void InsertionIndicatorOverlay::Create (
+ const ::std::vector<controller::Transferable::Representative>& rRepresentatives,
+ const sal_Int32 nSelectionCount)
+{
+ view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
+ ::boost::shared_ptr<view::PageObjectLayouter> pPageObjectLayouter (
+ rLayouter.GetPageObjectLayouter());
+ ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
+ const Size aOriginalPreviewSize (pPageObjectLayouter->GetSize(
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::WindowCoordinateSystem));
+
+ const double nPreviewScale (0.5);
+ const Size aPreviewSize (
+ RoundToInt(aOriginalPreviewSize.Width()*nPreviewScale),
+ RoundToInt(aOriginalPreviewSize.Height()*nPreviewScale));
+ const sal_Int32 nOffset (
+ RoundToInt(Min(aPreviewSize.Width(),aPreviewSize.Height()) * gnPreviewOffsetScale));
+
+ // Determine size and offset depending on the number of previews.
+ sal_Int32 nCount (rRepresentatives.size());
+ if (nCount > 0)
+ --nCount;
+ Size aIconSize(
+ aPreviewSize.Width() + 2 * gnShadowBorder + nCount*nOffset,
+ aPreviewSize.Height() + 2 * gnShadowBorder + nCount*nOffset);
+ maIconOffset = Point(gnShadowBorder, gnShadowBorder);
+
+ // Create virtual devices for bitmap and mask whose bitmaps later be
+ // combined to form the BitmapEx of the icon.
+ VirtualDevice aContent (
+ *mrSlideSorter.GetContentWindow(),
+ 0,
+ 0);
+ aContent.SetOutputSizePixel(aIconSize);
+
+ aContent.SetFillColor();
+ aContent.SetLineColor(pTheme->GetColor(Theme::Color_PreviewBorder));
+ const Point aOffset = PaintRepresentatives(aContent, aPreviewSize, nOffset, rRepresentatives);
+
+ PaintPageCount(aContent, nSelectionCount, aPreviewSize, aOffset);
+
+ maIcon = aContent.GetBitmapEx(Point(0,0), aIconSize);
+ maIcon.Scale(aIconSize);
+}
+
+
+
+
+void InsertionIndicatorOverlay::SelectRepresentatives (
+ model::PageEnumeration& rSelection,
+ ::std::vector<model::SharedPageDescriptor>& rDescriptors) const
+{
+ sal_Int32 nCount (0);
+ while (rSelection.HasMoreElements())
+ {
+ if (nCount++ >= 3)
+ break;
+ rDescriptors.push_back(rSelection.GetNextElement());
+ }
+}
+
+
+
+
+Point InsertionIndicatorOverlay::PaintRepresentatives (
+ OutputDevice& rContent,
+ const Size aPreviewSize,
+ const sal_Int32 nOffset,
+ const ::std::vector<controller::Transferable::Representative>& rRepresentatives) const
+{
+ const Point aOffset (0,rRepresentatives.size()==1 ? -nOffset : 0);
+
+ // Paint the pages.
+ Point aPageOffset (0,0);
+ double nTransparency (0);
+ const BitmapEx aExclusionOverlay (mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_HideSlideOverlay));
+ for (sal_Int32 nIndex=2; nIndex>=0; --nIndex)
+ {
+ if (rRepresentatives.size() <= sal_uInt32(nIndex))
+ continue;
+ switch(nIndex)
+ {
+ case 0 :
+ aPageOffset = Point(0, nOffset);
+ nTransparency = 0.85;
+ break;
+ case 1:
+ aPageOffset = Point(nOffset, 0);
+ nTransparency = 0.75;
+ break;
+ case 2:
+ aPageOffset = Point(2*nOffset, 2*nOffset);
+ nTransparency = 0.65;
+ break;
+ }
+ aPageOffset += aOffset;
+ aPageOffset.X() += gnShadowBorder;
+ aPageOffset.Y() += gnShadowBorder;
+
+ // Paint the preview.
+ Bitmap aPreview (rRepresentatives[nIndex].maBitmap);
+ const Size aSuperSampleSize(
+ aPreviewSize.Width()*gnSuperScaleFactor,
+ aPreviewSize.Height()*gnSuperScaleFactor);
+ aPreview.Scale(aPreviewSize, BMP_SCALE_INTERPOLATE);
+ rContent.DrawBitmapEx(aPageOffset, aPreview);
+
+ // When the page is marked as excluded from the slide show then
+ // paint an overlay that visualizes this.
+ if (rRepresentatives[nIndex].mbIsExcluded)
+ {
+ const Region aSavedClipRegion (rContent.GetClipRegion());
+ rContent.IntersectClipRegion(Rectangle(aPageOffset, aPreviewSize));
+ // Paint bitmap tiled over the preview to mark it as excluded.
+ const sal_Int32 nIconWidth (aExclusionOverlay.GetSizePixel().Width());
+ const sal_Int32 nIconHeight (aExclusionOverlay.GetSizePixel().Height());
+ if (nIconWidth>0 && nIconHeight>0)
+ {
+ for (sal_Int32 nX=0; nX<aPreviewSize.Width(); nX+=nIconWidth)
+ for (sal_Int32 nY=0; nY<aPreviewSize.Height(); nY+=nIconHeight)
+ rContent.DrawBitmapEx(Point(nX,nY)+aPageOffset, aExclusionOverlay);
+ }
+ rContent.SetClipRegion(aSavedClipRegion);
+ }
+
+ // Tone down the bitmap. The further back the darker it becomes.
+ Rectangle aBox (
+ aPageOffset.X(),
+ aPageOffset.Y(),
+ aPageOffset.X()+aPreviewSize.Width()-1,
+ aPageOffset.Y()+aPreviewSize.Height()-1);
+ rContent.SetFillColor(COL_BLACK);
+ rContent.SetLineColor();
+ rContent.DrawTransparent(
+ ::basegfx::B2DPolyPolygon(::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right()+1, aBox.Bottom()+1),
+ 0,
+ 0)),
+ nTransparency);
+
+ // Draw border around preview.
+ Rectangle aBorderBox (GrowRectangle(aBox, 1));
+ rContent.SetLineColor(COL_GRAY);
+ rContent.SetFillColor();
+ rContent.DrawRect(aBorderBox);
+
+ // Draw shadow around preview.
+ mpShadowPainter->PaintFrame(rContent, aBorderBox);
+ }
+
+ return aPageOffset;
+}
+
+
+
+
+void InsertionIndicatorOverlay::PaintPageCount (
+ OutputDevice& rDevice,
+ const sal_Int32 nSelectionCount,
+ const Size aPreviewSize,
+ const Point aFirstPageOffset) const
+{
+ // Paint the number of slides.
+ ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
+ ::boost::shared_ptr<Font> pFont(Theme::GetFont(Theme::Font_PageCount, rDevice));
+ if (pFont)
+ {
+ ::rtl::OUString sNumber (::rtl::OUString::valueOf(nSelectionCount));
+
+ // Determine the size of the (painted) text and create a bounding
+ // box that centers the text on the first preview.
+ rDevice.SetFont(*pFont);
+ Rectangle aTextBox;
+ rDevice.GetTextBoundRect(aTextBox, sNumber);
+ Point aTextOffset (aTextBox.TopLeft());
+ Size aTextSize (aTextBox.GetSize());
+ // Place text inside the first page preview.
+ Point aTextLocation(aFirstPageOffset);
+ // Center the text.
+ aTextLocation += Point(
+ (aPreviewSize.Width()-aTextBox.GetWidth())/2,
+ (aPreviewSize.Height()-aTextBox.GetHeight())/2);
+ aTextBox = Rectangle(aTextLocation, aTextSize);
+
+ // Paint background, border and text.
+ static const sal_Int32 nBorder = 5;
+ rDevice.SetFillColor(pTheme->GetColor(Theme::Color_Selection));
+ rDevice.SetLineColor(pTheme->GetColor(Theme::Color_Selection));
+ rDevice.DrawRect(GrowRectangle(aTextBox, nBorder));
+
+ rDevice.SetFillColor();
+ rDevice.SetLineColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
+ rDevice.DrawRect(GrowRectangle(aTextBox, nBorder-1));
+
+ rDevice.SetTextColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
+ rDevice.DrawText(aTextBox.TopLeft()-aTextOffset, sNumber);
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetLocation (const Point& rLocation)
+{
+ const Point aTopLeft (
+ rLocation - Point(
+ maIcon.GetSizePixel().Width()/2,
+ maIcon.GetSizePixel().Height()/2));
+ if (maLocation != aTopLeft)
+ {
+ const Rectangle aOldBoundingBox (GetBoundingBox());
+
+ maLocation = aTopLeft;
+
+ if (mpLayerInvalidator && IsVisible())
+ {
+ mpLayerInvalidator->Invalidate(aOldBoundingBox);
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ }
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea)
+{
+ (void)rRepaintArea;
+
+ if ( ! IsVisible())
+ return;
+
+ rDevice.DrawImage(maLocation, maIcon);
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetLayerInvalidator (const SharedILayerInvalidator& rpInvalidator)
+{
+ mpLayerInvalidator = rpInvalidator;
+
+ if (mbIsVisible && mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+}
+
+
+
+
+bool InsertionIndicatorOverlay::IsVisible (void) const
+{
+ return mbIsVisible;
+}
+
+
+
+
+void InsertionIndicatorOverlay::Show (void)
+{
+ if ( ! mbIsVisible)
+ {
+ mbIsVisible = true;
+
+ ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
+ mrSlideSorter.GetView().GetLayeredDevice());
+ if (pLayeredDevice)
+ {
+ pLayeredDevice->RegisterPainter(shared_from_this(), mnLayerIndex);
+ if (mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ }
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::Hide (void)
+{
+ if (mbIsVisible)
+ {
+ mbIsVisible = false;
+
+ ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
+ mrSlideSorter.GetView().GetLayeredDevice());
+ if (pLayeredDevice)
+ {
+ if (mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ pLayeredDevice->RemovePainter(shared_from_this(), mnLayerIndex);
+ }
+ }
+}
+
+
+
+
+Rectangle InsertionIndicatorOverlay::GetBoundingBox (void) const
+{
+ return Rectangle(maLocation, maIcon.GetSizePixel());
+}
+
+
+
+
+Size InsertionIndicatorOverlay::GetSize (void) const
+{
+ return Size(
+ maIcon.GetSizePixel().Width() + 10,
+ maIcon.GetSizePixel().Height() + 10);
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
diff --git a/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx
new file mode 100644
index 000000000000..e3303278111f
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx
@@ -0,0 +1,565 @@
+/*************************************************************************
+ *
+ * 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 "SlsLayeredDevice.hxx"
+
+#include <vcl/window.hxx>
+#include <vcl/virdev.hxx>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+static const sal_Int32 gnMaximumLayerCount = 8;
+
+class LayerInvalidator : public ILayerInvalidator
+{
+public:
+ LayerInvalidator (
+ const ::boost::shared_ptr<LayeredDevice>& rpLayeredDevice,
+ const SharedSdWindow& rpTargetWindow,
+ const int nLayer)
+ : mpLayeredDevice(rpLayeredDevice),
+ mpTargetWindow(rpTargetWindow),
+ mnLayer(nLayer)
+ {
+ }
+
+ virtual void Invalidate (const Rectangle& rInvalidationBox)
+ {
+ mpLayeredDevice->Invalidate(rInvalidationBox, mnLayer);
+ mpTargetWindow->Invalidate(rInvalidationBox);
+ }
+
+private:
+ const ::boost::shared_ptr<LayeredDevice> mpLayeredDevice;
+ SharedSdWindow mpTargetWindow;
+ const int mnLayer;
+};
+
+void DeviceCopy (
+ OutputDevice& rTargetDevice,
+ OutputDevice& rSourceDevice,
+ const Rectangle& rBox)
+{
+ rTargetDevice.DrawOutDev(
+ rBox.TopLeft(),
+ rBox.GetSize(),
+ rBox.TopLeft(),
+ rBox.GetSize(),
+ rSourceDevice);
+}
+
+
+void ForAllRectangles (const Region& rRegion, ::boost::function<void(const Rectangle&)> aFunction)
+{
+ OSL_ASSERT(aFunction);
+
+ if (rRegion.GetRectCount() <= 1)
+ {
+ aFunction(rRegion.GetBoundRect());
+ }
+ else
+ {
+ Region aMutableRegionCopy (rRegion);
+ RegionHandle aHandle(aMutableRegionCopy.BeginEnumRects());
+ Rectangle aBox;
+ while (aMutableRegionCopy.GetNextEnumRect(aHandle, aBox))
+ aFunction(aBox);
+ aMutableRegionCopy.EndEnumRects(aHandle);
+ }
+}
+
+class Layer : private ::boost::noncopyable
+{
+public:
+ Layer (void);
+ ~Layer (void);
+
+ void Initialize (const SharedSdWindow& rpTargetWindow);
+ void InvalidateRectangle (const Rectangle& rInvalidationBox);
+ void InvalidateRegion (const Region& rInvalidationRegion);
+ void Validate (const MapMode& rMapMode);
+ void Repaint (
+ OutputDevice& rTargetDevice,
+ const Rectangle& rRepaintRectangle);
+ void Resize (const Size& rSize);
+ void AddPainter (const SharedILayerPainter& rpPainter);
+ void RemovePainter (const SharedILayerPainter& rpPainter);
+ bool HasPainter (void) const;
+ void Dispose (void);
+
+private:
+ ::boost::shared_ptr<VirtualDevice> mpLayerDevice;
+ ::std::vector<SharedILayerPainter> maPainters;
+ Region maInvalidationRegion;
+
+ void ValidateRectangle (const Rectangle& rBox);
+};
+typedef ::boost::shared_ptr<Layer> SharedLayer;
+
+
+} // end of anonymous namespace
+
+
+class LayeredDevice::LayerContainer : public ::std::vector<SharedLayer>
+{
+public:
+ LayerContainer (void) {}
+ ~LayerContainer (void) {}
+};
+
+
+
+
+//===== LayeredDevice =========================================================
+
+LayeredDevice::LayeredDevice (const SharedSdWindow& rpTargetWindow)
+ : mpTargetWindow(rpTargetWindow),
+ mpLayers(new LayerContainer()),
+ mpBackBuffer(new VirtualDevice(*mpTargetWindow)),
+ maSavedMapMode(rpTargetWindow->GetMapMode())
+{
+ mpBackBuffer->SetOutputSizePixel(mpTargetWindow->GetSizePixel());
+}
+
+
+
+
+LayeredDevice::~LayeredDevice (void)
+{
+}
+
+
+
+
+void LayeredDevice::Invalidate (
+ const Rectangle& rInvalidationArea,
+ const sal_Int32 nLayer)
+{
+ if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
+ {
+ OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
+ return;
+ }
+
+ (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
+}
+
+
+
+
+void LayeredDevice::InvalidateAllLayers (const Rectangle& rInvalidationArea)
+{
+ for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
+ (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
+}
+
+
+
+
+void LayeredDevice::InvalidateAllLayers (const Region& rInvalidationRegion)
+{
+ for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
+ (*mpLayers)[nLayer]->InvalidateRegion(rInvalidationRegion);
+}
+
+
+
+
+void LayeredDevice::RegisterPainter (
+ const SharedILayerPainter& rpPainter,
+ const sal_Int32 nLayer)
+{
+ OSL_ASSERT(mpLayers);
+ if ( ! rpPainter)
+ {
+ OSL_ASSERT(rpPainter);
+ return;
+ }
+ if (nLayer<0 || nLayer>=gnMaximumLayerCount)
+ {
+ OSL_ASSERT(nLayer>=0 && nLayer<gnMaximumLayerCount);
+ return;
+ }
+
+ // Provide the layers.
+ if (sal_uInt32(nLayer) >= mpLayers->size())
+ {
+ const sal_Int32 nOldLayerCount (mpLayers->size());
+ mpLayers->resize(nLayer+1);
+
+ for (size_t nIndex=nOldLayerCount; nIndex<mpLayers->size(); ++nIndex)
+ (*mpLayers)[nIndex].reset(new Layer());
+ }
+
+ (*mpLayers)[nLayer]->AddPainter(rpPainter);
+ if (nLayer == 0)
+ (*mpLayers)[nLayer]->Initialize(mpTargetWindow);
+
+ rpPainter->SetLayerInvalidator(
+ SharedILayerInvalidator(new LayerInvalidator(shared_from_this(),mpTargetWindow,nLayer)));
+}
+
+
+
+
+void LayeredDevice::RemovePainter (
+ const SharedILayerPainter& rpPainter,
+ const sal_Int32 nLayer)
+{
+ if ( ! rpPainter)
+ {
+ OSL_ASSERT(rpPainter);
+ return;
+ }
+ if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
+ {
+ OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
+ return;
+ }
+
+ rpPainter->SetLayerInvalidator(SharedILayerInvalidator());
+
+ (*mpLayers)[nLayer]->RemovePainter(rpPainter);
+
+ // Remove top most layers that do not contain any painters.
+ while ( ! mpLayers->empty() && ! mpLayers->back()->HasPainter())
+ mpLayers->erase(mpLayers->end()-1);
+}
+
+
+
+
+bool LayeredDevice::HasPainter (const sal_Int32 nLayer)
+{
+ return nLayer>=0
+ && sal_uInt32(nLayer)<mpLayers->size()
+ && (*mpLayers)[nLayer]->HasPainter();
+}
+
+
+
+
+void LayeredDevice::Repaint (const Region& rRepaintRegion)
+{
+ // Validate the contents of all layers (that have their own devices.)
+ ::std::for_each(
+ mpLayers->begin(),
+ mpLayers->end(),
+ ::boost::bind(&Layer::Validate, _1, mpTargetWindow->GetMapMode()));
+
+ ForAllRectangles(rRepaintRegion, ::boost::bind(&LayeredDevice::RepaintRectangle, this, _1));
+}
+
+
+
+
+void LayeredDevice::RepaintRectangle (const Rectangle& rRepaintRectangle)
+{
+ if (mpLayers->size() == 0)
+ return;
+ else if (mpLayers->size() == 1)
+ {
+ // Just copy the main layer into the target device.
+ (*mpLayers)[0]->Repaint(*mpTargetWindow, rRepaintRectangle);
+ }
+ else
+ {
+ // Paint all layers first into the back buffer (to avoid flickering
+ // due to synchronous paints) and then copy that into the target
+ // device.
+ mpBackBuffer->SetMapMode(mpTargetWindow->GetMapMode());
+ ::std::for_each(
+ mpLayers->begin(),
+ mpLayers->end(),
+ ::boost::bind(&Layer::Repaint, _1, ::boost::ref(*mpBackBuffer), rRepaintRectangle));
+
+ DeviceCopy(*mpTargetWindow, *mpBackBuffer, rRepaintRectangle);
+ }
+}
+
+
+
+
+void LayeredDevice::Resize (void)
+{
+ const Size aSize (mpTargetWindow->GetSizePixel());
+ mpBackBuffer->SetOutputSizePixel(aSize);
+ ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Resize, _1, aSize));
+}
+
+
+
+
+void LayeredDevice::Dispose (void)
+{
+ ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Dispose, _1));
+ mpLayers->clear();
+}
+
+
+
+
+bool LayeredDevice::HandleMapModeChange (void)
+{
+ const MapMode& rMapMode (mpTargetWindow->GetMapMode());
+ if (maSavedMapMode == rMapMode)
+ return false;
+
+ const Rectangle aLogicWindowBox (
+ mpTargetWindow->PixelToLogic(Rectangle(Point(0,0), mpTargetWindow->GetSizePixel())));
+ if (maSavedMapMode.GetScaleX() != rMapMode.GetScaleX()
+ || maSavedMapMode.GetScaleY() != rMapMode.GetScaleY()
+ || maSavedMapMode.GetMapUnit() != rMapMode.GetMapUnit())
+ {
+ // When the scale has changed then we have to paint everything.
+ InvalidateAllLayers(aLogicWindowBox);
+ }
+ else if (maSavedMapMode.GetOrigin() != rMapMode.GetOrigin())
+ {
+ // Window has been scrolled. Adapt contents of backbuffers and
+ // layer devices.
+ const Point aDelta (rMapMode.GetOrigin() - maSavedMapMode.GetOrigin());
+ mpBackBuffer->CopyArea(
+ aLogicWindowBox.TopLeft(),
+ mpTargetWindow->PixelToLogic(Point(0,0), maSavedMapMode),
+ aLogicWindowBox.GetSize());
+
+ // Invalidate the area(s) that have been exposed.
+ const Rectangle aWindowBox (Point(0,0), mpTargetWindow->GetSizePixel());
+ if (aDelta.Y() < 0)
+ InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
+ aWindowBox.Left(),
+ aWindowBox.Bottom()+aDelta.Y(),
+ aWindowBox.Right(),
+ aWindowBox.Bottom())));
+ else if (aDelta.Y() > 0)
+ InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
+ aWindowBox.Left(),
+ aWindowBox.Top(),
+ aWindowBox.Right(),
+ aWindowBox.Top()+aDelta.Y())));
+ if (aDelta.X() < 0)
+ InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
+ aWindowBox.Right()+aDelta.X(),
+ aWindowBox.Top(),
+ aWindowBox.Right(),
+ aWindowBox.Bottom())));
+ else if (aDelta.X() > 0)
+ InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
+ aWindowBox.Left(),
+ aWindowBox.Top(),
+ aWindowBox.Left()+aDelta.X(),
+ aWindowBox.Bottom())));
+ }
+ else
+ {
+ // Can this happen? Lets trigger a warning when it does.
+ OSL_ASSERT(false);
+ }
+
+ maSavedMapMode = rMapMode;
+
+ return true;
+}
+
+
+
+
+//===== Layer =================================================================
+
+Layer::Layer (void)
+ : mpLayerDevice(),
+ maPainters(),
+ maInvalidationRegion()
+{
+}
+
+
+
+
+Layer::~Layer (void)
+{
+}
+
+
+
+
+void Layer::Initialize (const SharedSdWindow& rpTargetWindow)
+{
+#if 0
+ (void)rpTargetWindow;
+#else
+ if ( ! mpLayerDevice)
+ {
+ mpLayerDevice.reset(new VirtualDevice(*rpTargetWindow));
+ mpLayerDevice->SetOutputSizePixel(rpTargetWindow->GetSizePixel());
+ }
+#endif
+}
+
+
+
+
+void Layer::InvalidateRectangle (const Rectangle& rInvalidationBox)
+{
+ maInvalidationRegion.Union(rInvalidationBox);
+}
+
+
+
+
+void Layer::InvalidateRegion (const Region& rInvalidationRegion)
+{
+ maInvalidationRegion.Union(rInvalidationRegion);
+}
+
+
+
+
+void Layer::Validate (const MapMode& rMapMode)
+{
+ if (mpLayerDevice && ! maInvalidationRegion.IsEmpty())
+ {
+ Region aRegion (maInvalidationRegion);
+ maInvalidationRegion.SetEmpty();
+
+ mpLayerDevice->SetMapMode(rMapMode);
+ ForAllRectangles(
+ aRegion,
+ ::boost::bind(&Layer::ValidateRectangle, this, _1));
+ }
+}
+
+
+
+
+void Layer::ValidateRectangle (const Rectangle& rBox)
+{
+ if ( ! mpLayerDevice)
+ return;
+ const Region aSavedClipRegion (mpLayerDevice->GetClipRegion());
+ mpLayerDevice->IntersectClipRegion(rBox);
+
+ for (::std::vector<SharedILayerPainter>::const_iterator
+ iPainter(maPainters.begin()),
+ iEnd(maPainters.end());
+ iPainter!=iEnd;
+ ++iPainter)
+ {
+ (*iPainter)->Paint(*mpLayerDevice, rBox);
+ }
+
+ mpLayerDevice->SetClipRegion(aSavedClipRegion);
+}
+
+
+
+
+void Layer::Repaint (
+ OutputDevice& rTargetDevice,
+ const Rectangle& rRepaintRectangle)
+{
+ if (mpLayerDevice)
+ {
+ DeviceCopy(rTargetDevice, *mpLayerDevice, rRepaintRectangle);
+ }
+ else
+ {
+ ::std::for_each(
+ maPainters.begin(),
+ maPainters.end(),
+ ::boost::bind(&ILayerPainter::Paint,
+ _1,
+ ::boost::ref(rTargetDevice),
+ rRepaintRectangle));
+ }
+}
+
+
+
+
+void Layer::Resize (const Size& rSize)
+{
+ if (mpLayerDevice)
+ {
+ mpLayerDevice->SetOutputSizePixel(rSize);
+ maInvalidationRegion = Rectangle(Point(0,0), rSize);
+ }
+}
+
+
+
+
+void Layer::AddPainter (const SharedILayerPainter& rpPainter)
+{
+ OSL_ASSERT(::std::find(maPainters.begin(), maPainters.end(), rpPainter) == maPainters.end());
+
+ maPainters.push_back(rpPainter);
+}
+
+
+
+
+void Layer::RemovePainter (const SharedILayerPainter& rpPainter)
+{
+ const ::std::vector<SharedILayerPainter>::iterator iPainter (
+ ::std::find(maPainters.begin(), maPainters.end(), rpPainter));
+ if (iPainter != maPainters.end())
+ {
+ maPainters.erase(iPainter);
+ }
+ else
+ {
+ DBG_ASSERT(false,"LayeredDevice::RemovePainter called for painter that is not registered");
+ }
+}
+
+
+
+
+bool Layer::HasPainter (void) const
+{
+ return !maPainters.empty();
+}
+
+
+
+
+void Layer::Dispose (void)
+{
+ maPainters.clear();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx b/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx
new file mode 100644
index 000000000000..8b2398221548
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * 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_LAYERED_DEVICE_HXX
+#define SD_SLIDESORTER_VIEW_LAYERED_DEVICE_HXX
+
+#include "view/SlsILayerPainter.hxx"
+#include "SlideSorter.hxx"
+
+#include <tools/gen.hxx>
+#include <vcl/region.hxx>
+#include <vcl/virdev.hxx>
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <vector>
+
+class Window;
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** A simple wrapper around an OutputDevice that provides support for
+ independent layers and buffering.
+ Each layer may contain any number of painters.
+*/
+class LayeredDevice
+ : public ::boost::enable_shared_from_this<LayeredDevice>
+
+{
+public:
+ LayeredDevice (const SharedSdWindow& rpTargetWindow);
+ ~LayeredDevice (void);
+
+ void Invalidate (
+ const Rectangle& rInvalidationBox,
+ const sal_Int32 nLayer);
+ void InvalidateAllLayers (
+ const Rectangle& rInvalidationBox);
+ void InvalidateAllLayers (
+ const Region& rInvalidationRegion);
+
+ void RegisterPainter (
+ const SharedILayerPainter& rPainter,
+ const sal_Int32 nLayer);
+
+ void RemovePainter (
+ const SharedILayerPainter& rPainter,
+ const sal_Int32 nLayer);
+
+ bool HasPainter (const sal_Int32 nLayer);
+
+ bool HandleMapModeChange (void);
+ void Repaint (const Region& rRepaintRegion);
+
+ void Resize (void);
+
+ void Dispose (void);
+
+private:
+ SharedSdWindow mpTargetWindow;
+ class LayerContainer;
+ ::boost::scoped_ptr<LayerContainer> mpLayers;
+ ::boost::scoped_ptr<VirtualDevice> mpBackBuffer;
+ MapMode maSavedMapMode;
+
+ void RepaintRectangle (const Rectangle& rRepaintRectangle);
+};
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
diff --git a/sd/source/ui/slidesorter/view/SlsLayouter.cxx b/sd/source/ui/slidesorter/view/SlsLayouter.cxx
new file mode 100644
index 000000000000..66f22097993a
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsLayouter.cxx
@@ -0,0 +1,1555 @@
+/* -*- 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 "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "Window.hxx"
+#include <rtl/math.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+namespace {
+ sal_Int32 RoundToInt (const double nValue)
+ {
+ return sal_Int32(::rtl::math::round(nValue));
+ }
+}
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+class Layouter::Implementation
+{
+public:
+ SharedSdWindow mpWindow;
+ sal_Int32 mnRequestedLeftBorder;
+ sal_Int32 mnRequestedRightBorder;
+ sal_Int32 mnRequestedTopBorder;
+ sal_Int32 mnRequestedBottomBorder;
+ sal_Int32 mnLeftBorder;
+ sal_Int32 mnRightBorder;
+ sal_Int32 mnTopBorder;
+ sal_Int32 mnBottomBorder;
+ sal_Int32 mnVerticalGap;
+ sal_Int32 mnHorizontalGap;
+ Size maMinimalSize;
+ Size maPreferredSize;
+ Size maMaximalSize;
+ sal_Int32 mnMinimalColumnCount;
+ sal_Int32 mnMaximalColumnCount;
+ sal_Int32 mnPageCount;
+ sal_Int32 mnColumnCount;
+ sal_Int32 mnRowCount;
+ /// The maximum number of columns. Can only be larger than the current
+ /// number of columns when there are not enough pages to fill all
+ /// available columns.
+ sal_Int32 mnMaxColumnCount;
+ /// The maximum number of rows. Can only be larger than the current
+ /// number of rows when there are not enough pages to fill all available
+ /// rows.
+ sal_Int32 mnMaxRowCount;
+ Size maPageObjectSize;
+ ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
+ ::boost::shared_ptr<view::Theme> mpTheme;
+
+ /** Specify how the gap between two page objects is associated with the
+ page objects.
+ */
+ enum GapMembership {
+ GM_NONE, // Gap is not associated with any page object.
+ GM_PREVIOUS, // The whole gap is associated with the previous page
+ // object (left or above the gap.)
+ GM_BOTH, // Half of the gap is associated with previous, half
+ // with the next page object.
+ GM_NEXT, // The whole gap is associated with the next page
+ // object (right or below the gap.)
+ GM_PAGE_BORDER
+ };
+
+ static Implementation* Create (
+ const Implementation& rImplementation,
+ const Layouter::Orientation eOrientation);
+
+ virtual Layouter::Orientation GetOrientation (void) const = 0;
+
+ bool Rearrange (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize,
+ const sal_uInt32 nPageCount);
+
+ /** 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.
+ */
+ 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 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 nGap) const;
+
+ /** Calculate the logical part of the insert position, i.e. the page
+ after whicht to insert.
+ */
+ virtual void CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const = 0;
+
+ /** Calculate the geometrical part of the insert position, i.e. the
+ location of where to display the insertion indicator and the
+ distances about which the leading and trailing pages have to be
+ moved to make room for the indicator.
+ */
+ void CalculateGeometricPosition (
+ InsertPosition& rPosition,
+ const Size& rIndicatorSize,
+ const bool bIsVertical,
+ model::SlideSorterModel& rModel) const;
+
+ /** Return the bounding box of the preview or, when selected, of the page
+ object. Thus, it returns something like a visual bounding box.
+ */
+ Rectangle GetInnerBoundingBox (
+ model::SlideSorterModel& rModel,
+ const sal_Int32 nIndex) const;
+
+ Range GetValidHorizontalSizeRange (void) const;
+ Range GetValidVerticalSizeRange (void) const;
+
+ Range GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const;
+ sal_Int32 GetIndex (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn,
+ const bool bClampToValidRange) const;
+
+ Rectangle GetPageObjectBox (
+ const sal_Int32 nIndex,
+ const bool bIncludeBorderAndGap = false) const;
+
+ Rectangle GetPageObjectBox (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn) const;
+
+ Rectangle AddBorderAndGap (
+ const Rectangle& rBoundingBox,
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn) const;
+
+ Rectangle GetTotalBoundingBox (void) const;
+
+ virtual ~Implementation (void);
+
+protected:
+ Implementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme);
+ Implementation (const Implementation& rImplementation);
+
+ virtual void CalculateRowAndColumnCount (const Size& rWindowSize) = 0;
+ virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) = 0;
+ virtual Size CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const = 0;
+ Size GetTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize,
+ const bool bCalculateWidth,
+ const bool bCalculateHeight) const;
+ void CalculateVerticalLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const;
+};
+
+
+/** The vertical layouter has one column and as many rows as there are
+ pages.
+*/
+class VerticalImplementation : public Layouter::Implementation
+{
+public:
+ VerticalImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme);
+ VerticalImplementation (const Implementation& rImplementation);
+
+ virtual Layouter::Orientation GetOrientation (void) const;
+
+ void CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const;
+
+protected:
+ virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
+ virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
+ virtual Size CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const;
+};
+
+
+/** The horizontal layouter has one row and as many columns as there are
+ pages.
+*/
+class HorizontalImplementation : public Layouter::Implementation
+{
+public:
+ HorizontalImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme);
+ HorizontalImplementation (const Implementation& rImplementation);
+
+ virtual Layouter::Orientation GetOrientation (void) const;
+
+ void CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const;
+
+protected:
+ virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
+ virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
+ virtual Size CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const;
+};
+
+
+/** The number of columns of the grid layouter is defined via a control in
+ the slide sorter tool bar. The number of rows is calculated from the
+ number of columns and the number of pages.
+*/
+class GridImplementation : public Layouter::Implementation
+{
+public:
+ GridImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme);
+ GridImplementation (const Implementation& rImplementation);
+
+ virtual Layouter::Orientation GetOrientation (void) const;
+
+ void CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const;
+
+protected:
+ virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
+ virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
+ virtual Size CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const;
+};
+
+
+
+
+//===== Layouter ==============================================================
+
+Layouter::Layouter (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<Theme>& rpTheme)
+ : mpImplementation(new GridImplementation(rpWindow, rpTheme)),
+ mpWindow(rpWindow)
+{
+}
+
+
+
+
+Layouter::~Layouter (void)
+{
+}
+
+
+
+
+::boost::shared_ptr<PageObjectLayouter> Layouter::GetPageObjectLayouter (void) const
+{
+ return mpImplementation->mpPageObjectLayouter;
+}
+
+
+
+
+void Layouter::SetBorders (
+ sal_Int32 nLeftBorder,
+ sal_Int32 nRightBorder,
+ sal_Int32 nTopBorder,
+ sal_Int32 nBottomBorder)
+{
+ if (nLeftBorder >= 0)
+ mpImplementation->mnRequestedLeftBorder = nLeftBorder;
+ if (nRightBorder >= 0)
+ mpImplementation->mnRequestedRightBorder = nRightBorder;
+ if (nTopBorder >= 0)
+ mpImplementation->mnRequestedTopBorder = nTopBorder;
+ if (nBottomBorder >= 0)
+ mpImplementation->mnRequestedBottomBorder = nBottomBorder;
+}
+
+
+
+
+void Layouter::SetColumnCount (
+ sal_Int32 nMinimalColumnCount,
+ sal_Int32 nMaximalColumnCount)
+{
+ if (nMinimalColumnCount <= nMaximalColumnCount)
+ {
+ mpImplementation->mnMinimalColumnCount = nMinimalColumnCount;
+ mpImplementation->mnMaximalColumnCount = nMaximalColumnCount;
+ }
+}
+
+
+
+
+bool Layouter::Rearrange (
+ const Orientation eOrientation,
+ const Size& rWindowSize,
+ const Size& rPageSize,
+ const sal_uInt32 nPageCount)
+{
+ OSL_ASSERT(mpWindow);
+
+ if (eOrientation != mpImplementation->GetOrientation())
+ mpImplementation.reset(Implementation::Create(*mpImplementation, eOrientation));
+
+ return mpImplementation->Rearrange(rWindowSize, rPageSize, nPageCount);
+}
+
+
+
+
+void Layouter::_SetZoom (double nZoomFactor)
+{
+ _SetZoom(Fraction(nZoomFactor));
+}
+
+
+
+
+void Layouter::_SetZoom (Fraction nZoomFactor)
+{
+ OSL_ASSERT(mpWindow);
+
+ MapMode aMapMode (mpWindow->GetMapMode());
+ aMapMode.SetScaleX (nZoomFactor);
+ aMapMode.SetScaleY (nZoomFactor);
+ mpWindow->SetMapMode (aMapMode);
+}
+
+
+
+
+sal_Int32 Layouter::GetColumnCount (void) const
+{
+ return mpImplementation->mnColumnCount;
+}
+
+
+
+
+sal_Int32 Layouter::GetRowCount (void) const
+{
+ return mpImplementation->mnRowCount;
+}
+
+
+
+
+sal_Int32 Layouter::GetRow (const sal_Int32 nIndex) const
+{
+ return nIndex / mpImplementation->mnColumnCount;
+}
+
+
+
+
+sal_Int32 Layouter::GetColumn (const sal_Int32 nIndex) const
+{
+ return nIndex % mpImplementation->mnColumnCount;
+}
+
+
+
+
+sal_Int32 Layouter::GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const
+{
+ return mpImplementation->GetIndex(nRow,nColumn,true);
+}
+
+
+
+
+Size Layouter::GetPageObjectSize (void) const
+{
+ return mpImplementation->maPageObjectSize;
+}
+
+
+
+
+Rectangle Layouter::GetPageObjectBox (
+ const sal_Int32 nIndex,
+ const bool bIncludeBorderAndGap) const
+{
+ return mpImplementation->GetPageObjectBox(nIndex, bIncludeBorderAndGap);
+}
+
+
+
+
+Rectangle Layouter::GetTotalBoundingBox (void) const
+{
+ return mpImplementation->GetTotalBoundingBox();
+}
+
+
+
+
+InsertPosition Layouter::GetInsertPosition (
+ const Point& rModelPosition,
+ const Size& rIndicatorSize,
+ model::SlideSorterModel& rModel) const
+{
+ InsertPosition aPosition;
+ mpImplementation->CalculateLogicalInsertPosition(
+ rModelPosition,
+ aPosition);
+ mpImplementation->CalculateGeometricPosition(
+ aPosition,
+ rIndicatorSize,
+ GetColumnCount()==1,
+ rModel);
+ return aPosition;
+}
+
+
+
+
+Range Layouter::GetValidHorizontalSizeRange (void) const
+{
+ return mpImplementation->GetValidHorizontalSizeRange();
+}
+
+
+
+
+Range Layouter::GetValidVerticalSizeRange (void) const
+{
+ return mpImplementation->GetValidVerticalSizeRange();
+}
+
+
+
+
+Range Layouter::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
+{
+ return mpImplementation->GetRangeOfVisiblePageObjects(aVisibleArea);
+}
+
+
+
+
+sal_Int32 Layouter::GetIndexAtPoint (
+ const Point& rPosition,
+ const bool bIncludePageBorders,
+ const bool bClampToValidRange) const
+{
+ const sal_Int32 nRow (
+ mpImplementation->GetRowAtPosition (
+ rPosition.Y(),
+ bIncludePageBorders,
+ bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
+ const sal_Int32 nColumn (
+ mpImplementation->GetColumnAtPosition (
+ rPosition.X(),
+ bIncludePageBorders,
+ bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
+
+ return mpImplementation->GetIndex(nRow,nColumn,bClampToValidRange);
+}
+
+
+
+
+//===== Layouter::Implementation ==============================================
+
+Layouter::Implementation* Layouter::Implementation::Create (
+ const Implementation& rImplementation,
+ const Layouter::Orientation eOrientation)
+{
+ switch (eOrientation)
+ {
+ case HORIZONTAL: return new HorizontalImplementation(rImplementation);
+ case VERTICAL: return new VerticalImplementation(rImplementation);
+ case GRID:
+ default: return new GridImplementation(rImplementation);
+ }
+}
+
+
+
+
+Layouter::Implementation::Implementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme)
+ : mpWindow(rpWindow),
+ mnRequestedLeftBorder(5),
+ mnRequestedRightBorder(5),
+ mnRequestedTopBorder(5),
+ mnRequestedBottomBorder(5),
+ mnLeftBorder(5),
+ mnRightBorder(5),
+ mnTopBorder(5),
+ mnBottomBorder(5),
+ mnVerticalGap (10 - 2*rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth)),
+ mnHorizontalGap(10 - 2*rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth)),
+ maMinimalSize(132,98),
+ maPreferredSize(200,150),
+ maMaximalSize(300,200),
+ mnMinimalColumnCount(1),
+ mnMaximalColumnCount(15),
+ mnPageCount(0),
+ mnColumnCount(1),
+ mnRowCount(0),
+ mnMaxColumnCount(0),
+ mnMaxRowCount(0),
+ maPageObjectSize(1,1),
+ mpPageObjectLayouter(),
+ mpTheme(rpTheme)
+{
+}
+
+
+
+
+Layouter::Implementation::Implementation (const Implementation& rImplementation)
+ : mpWindow(rImplementation.mpWindow),
+ mnRequestedLeftBorder(rImplementation.mnRequestedLeftBorder),
+ mnRequestedRightBorder(rImplementation.mnRequestedRightBorder),
+ mnRequestedTopBorder(rImplementation.mnRequestedTopBorder),
+ mnRequestedBottomBorder(rImplementation.mnRequestedBottomBorder),
+ mnLeftBorder(rImplementation.mnLeftBorder),
+ mnRightBorder(rImplementation.mnRightBorder),
+ mnTopBorder(rImplementation.mnTopBorder),
+ mnBottomBorder(rImplementation.mnBottomBorder),
+ mnVerticalGap(rImplementation.mnVerticalGap),
+ mnHorizontalGap(rImplementation.mnHorizontalGap),
+ maMinimalSize(rImplementation.maMinimalSize),
+ maPreferredSize(rImplementation.maPreferredSize),
+ maMaximalSize(rImplementation.maMaximalSize),
+ mnMinimalColumnCount(rImplementation.mnMinimalColumnCount),
+ mnMaximalColumnCount(rImplementation.mnMaximalColumnCount),
+ mnPageCount(rImplementation.mnPageCount),
+ mnColumnCount(rImplementation.mnColumnCount),
+ mnRowCount(rImplementation.mnRowCount),
+ mnMaxColumnCount(rImplementation.mnMaxColumnCount),
+ mnMaxRowCount(rImplementation.mnMaxRowCount),
+ maPageObjectSize(rImplementation.maPageObjectSize),
+ mpPageObjectLayouter(),
+ mpTheme(rImplementation.mpTheme)
+{
+}
+
+
+
+
+Layouter::Implementation::~Implementation (void)
+{
+}
+
+
+
+
+bool Layouter::Implementation::Rearrange (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize,
+ const sal_uInt32 nPageCount)
+{
+ mnPageCount = nPageCount;
+
+ // Return early when the window or the model have not yet been initialized.
+ if (rWindowSize.Width()<=0 || rWindowSize.Height()<=0)
+ return false;
+ if (rPreviewModelSize.Width()<=0 || rPreviewModelSize.Height()<=0)
+ return false;
+
+ CalculateRowAndColumnCount(rWindowSize);
+
+ // Update the border values.
+ mnLeftBorder = mnRequestedLeftBorder;
+ mnTopBorder = mnRequestedTopBorder;
+ mnRightBorder = mnRequestedRightBorder;
+ mnBottomBorder = mnRequestedBottomBorder;
+ if (mnColumnCount > 1)
+ {
+ int nMinimumBorderWidth = mnHorizontalGap/2;
+ if (mnLeftBorder < nMinimumBorderWidth)
+ mnLeftBorder = nMinimumBorderWidth;
+ if (mnRightBorder < nMinimumBorderWidth)
+ mnRightBorder = nMinimumBorderWidth;
+ }
+ else
+ {
+ int nMinimumBorderHeight = mnVerticalGap/2;
+ if (mnTopBorder < nMinimumBorderHeight)
+ mnTopBorder = nMinimumBorderHeight;
+ if (mnBottomBorder < nMinimumBorderHeight)
+ mnBottomBorder = nMinimumBorderHeight;
+ }
+
+ mpPageObjectLayouter.reset(
+ new PageObjectLayouter(
+ mpTheme,
+ CalculateTargetSize(rWindowSize, rPreviewModelSize),
+ rPreviewModelSize,
+ mpWindow,
+ mnPageCount));
+ maPageObjectSize = mpPageObjectLayouter->GetSize(
+ PageObjectLayouter::FocusIndicator,
+ PageObjectLayouter::WindowCoordinateSystem);
+
+ CalculateMaxRowAndColumnCount(rWindowSize);
+
+ return true;
+}
+
+
+
+
+sal_Int32 Layouter::Implementation::GetRowAtPosition (
+ sal_Int32 nYPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership) const
+{
+ sal_Int32 nRow = -1;
+
+ const sal_Int32 nY = nYPosition - mnTopBorder;
+ if (nY >= 0)
+ {
+ // Vertical distance from one row to the next.
+ const sal_Int32 nRowOffset (maPageObjectSize.Height() + mnVerticalGap);
+
+ // Calculate row consisting of page objects and gap below.
+ nRow = nY / nRowOffset;
+
+ const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height());
+ // When inside the gap below then nYPosition is not over a page
+ // object.
+ if (nDistanceIntoGap > 0)
+ nRow = ResolvePositionInGap (
+ nDistanceIntoGap,
+ eGapMembership,
+ nRow,
+ mnVerticalGap);
+ }
+ 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::Implementation::GetColumnAtPosition (
+ sal_Int32 nXPosition,
+ bool bIncludeBordersAndGaps,
+ GapMembership eGapMembership) const
+{
+ sal_Int32 nColumn = -1;
+
+ sal_Int32 nX = nXPosition - mnLeftBorder;
+ if (nX >= 0)
+ {
+ // Horizontal distance from one column to the next.
+ const sal_Int32 nColumnOffset (maPageObjectSize.Width() + mnHorizontalGap);
+
+ // 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) - maPageObjectSize.Width());
+ // When inside the gap at the right then nXPosition is not over a
+ // page object.
+ if (nDistanceIntoGap > 0)
+ nColumn = ResolvePositionInGap (
+ nDistanceIntoGap,
+ eGapMembership,
+ nColumn,
+ mnHorizontalGap);
+ }
+ 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::Implementation::ResolvePositionInGap (
+ sal_Int32 nDistanceIntoGap,
+ GapMembership eGapMembership,
+ sal_Int32 nIndex,
+ 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 = 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 > 0)
+ {
+ if (nDistanceIntoGap > 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;
+}
+
+
+
+
+void Layouter::Implementation::CalculateGeometricPosition (
+ InsertPosition& rPosition,
+ const Size& rIndicatorSize,
+ const bool bIsVertical,
+ model::SlideSorterModel& rModel) const
+{
+ // 1. Determine right/bottom of the leading page and the left/top of the
+ // trailing page object and how to distribute the missing space.
+ sal_Int32 nLeadingLocation (0);
+ sal_Int32 nTrailingLocation (0);
+ bool bIsLeadingFixed (false);
+ bool bIsTrailingFixed (false);
+ sal_Int32 nSecondaryLocation (0);
+ const sal_Int32 nIndex (rPosition.GetIndex());
+
+ if (rPosition.IsAtRunStart())
+ {
+ // Place indicator at the top of the column.
+ const Rectangle aOuterBox (GetPageObjectBox(nIndex));
+ const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex));
+ if (bIsVertical)
+ {
+ nLeadingLocation = aOuterBox.Top();
+ nTrailingLocation = aInnerBox.Top();
+ nSecondaryLocation = aInnerBox.Center().X();
+ }
+ else
+ {
+ nLeadingLocation = aOuterBox.Left();
+ nTrailingLocation = aInnerBox.Left();
+ nSecondaryLocation = aInnerBox.Center().Y();
+ }
+ bIsLeadingFixed = true;
+ }
+ else if (rPosition.IsAtRunEnd())
+ {
+ // Place indicator at the bottom/right of the column/row.
+
+ const Rectangle aOuterBox (GetPageObjectBox(nIndex-1));
+ const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex-1));
+ if (bIsVertical)
+ {
+ nLeadingLocation = aInnerBox.Bottom();
+ nTrailingLocation = aOuterBox.Bottom();
+ nSecondaryLocation = aInnerBox.Center().X();
+ }
+ else
+ {
+ nLeadingLocation = aInnerBox.Right();
+ nTrailingLocation = aOuterBox.Right();
+ nSecondaryLocation = aInnerBox.Center().Y();
+ }
+ bIsTrailingFixed = true;
+ if ( ! rPosition.IsExtraSpaceNeeded())
+ bIsLeadingFixed = true;
+ }
+ else
+ {
+ // Place indicator between two rows/columns.
+ const Rectangle aBox1 (GetInnerBoundingBox(rModel, nIndex-1));
+ const Rectangle aBox2 (GetInnerBoundingBox(rModel, nIndex));
+ if (bIsVertical)
+ {
+ nLeadingLocation = aBox1.Bottom();
+ nTrailingLocation = aBox2.Top();
+ nSecondaryLocation = (aBox1.Center().X() + aBox2.Center().X()) / 2;
+ }
+ else
+ {
+ nLeadingLocation = aBox1.Right();
+ nTrailingLocation = aBox2.Left();
+ nSecondaryLocation = (aBox1.Center().Y() + aBox2.Center().Y()) / 2;
+ }
+ }
+
+ // 2. Calculate the location of the insert indicator and the offsets of
+ // leading and trailing pages.
+ const sal_Int32 nAvailableSpace (nTrailingLocation - nLeadingLocation);
+ const sal_Int32 nRequiredSpace (bIsVertical ? rIndicatorSize.Height():rIndicatorSize.Width());
+ const sal_Int32 nMissingSpace (::std::max(sal_Int32(0), nRequiredSpace - nAvailableSpace));
+ sal_Int32 nPrimaryLocation (0);
+ sal_Int32 nLeadingOffset (0);
+ sal_Int32 nTrailingOffset (0);
+ if (bIsLeadingFixed)
+ {
+ nPrimaryLocation = nLeadingLocation + nRequiredSpace/2;
+ if ( ! bIsTrailingFixed)
+ nTrailingOffset = nMissingSpace;
+ }
+ else if (bIsTrailingFixed)
+ {
+ nPrimaryLocation = nTrailingLocation - nRequiredSpace/2;
+ nLeadingOffset = -nMissingSpace;
+ }
+ else
+ {
+ nPrimaryLocation = (nLeadingLocation + nTrailingLocation) /2;
+ nLeadingOffset = -nMissingSpace/2;
+ nTrailingOffset = nMissingSpace + nLeadingOffset;
+ }
+
+ if (bIsVertical)
+ {
+ rPosition.SetGeometricalPosition(
+ Point(nSecondaryLocation, nPrimaryLocation),
+ Point(0, nLeadingOffset),
+ Point(0, nTrailingOffset));
+ }
+ else
+ {
+ rPosition.SetGeometricalPosition(
+ Point(nPrimaryLocation, nSecondaryLocation),
+ Point(nLeadingOffset, 0),
+ Point(nTrailingOffset, 0));
+ }
+}
+
+
+
+
+Rectangle Layouter::Implementation::GetInnerBoundingBox (
+ model::SlideSorterModel& rModel,
+ const sal_Int32 nIndex) const
+{
+ model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
+ if ( ! pDescriptor)
+ return Rectangle();
+
+ const Point aLocation (pDescriptor->GetLocation(true));
+ if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ return mpPageObjectLayouter->GetBoundingBox(
+ aLocation,
+ PageObjectLayouter::PageObject,
+ PageObjectLayouter::ModelCoordinateSystem);
+ else
+ return mpPageObjectLayouter->GetBoundingBox(
+ aLocation,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem);
+}
+
+
+
+
+Range Layouter::Implementation::GetValidHorizontalSizeRange (void) const
+{
+ return Range(
+ mnLeftBorder + maMinimalSize.Width() + mnRightBorder,
+ mnLeftBorder + maMaximalSize.Width() + mnRightBorder);
+}
+
+
+
+
+Range Layouter::Implementation::GetValidVerticalSizeRange (void) const
+{
+ return Range(
+ mnTopBorder + maMinimalSize.Height() + mnBottomBorder,
+ mnTopBorder + maMaximalSize.Height() + mnBottomBorder);
+}
+
+
+
+
+Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
+{
+ const sal_Int32 nRow0 (GetRowAtPosition(aVisibleArea.Top(), true, GM_NEXT));
+ const sal_Int32 nCol0 (GetColumnAtPosition(aVisibleArea.Left(),true, GM_NEXT));
+ const sal_Int32 nRow1 (GetRowAtPosition(aVisibleArea.Bottom(), true, GM_PREVIOUS));
+ const sal_Int32 nCol1 (GetColumnAtPosition(aVisibleArea.Right(), true, GM_PREVIOUS));
+
+ // When start and end lie in different rows then the range may include
+ // slides outside (left or right of) the given area.
+ return Range(GetIndex(nRow0,nCol0,true), GetIndex(nRow1,nCol1,true));
+}
+
+
+
+
+Size Layouter::Implementation::GetTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize,
+ const bool bCalculateWidth,
+ const bool bCalculateHeight) const
+{
+ (void)rPreviewModelSize;
+
+ if (mnColumnCount<=0 || mnRowCount<=0)
+ return maPreferredSize;
+ if ( ! (bCalculateWidth || bCalculateHeight))
+ {
+ OSL_ASSERT(bCalculateWidth || bCalculateHeight);
+ return maPreferredSize;
+ }
+
+ // Calculate the width of each page object.
+ Size aTargetSize (0,0);
+ if (bCalculateWidth)
+ aTargetSize.setWidth(
+ (rWindowSize.Width() - mnLeftBorder - mnRightBorder
+ - (mnColumnCount-1) * mnHorizontalGap)
+ / mnColumnCount);
+ else if (bCalculateHeight)
+ aTargetSize.setHeight(
+ (rWindowSize.Height() - mnTopBorder - mnBottomBorder
+ - (mnRowCount-1) * mnVerticalGap)
+ / mnRowCount);
+
+ if (bCalculateWidth)
+ {
+ if (aTargetSize.Width() < maMinimalSize.Width())
+ aTargetSize.setWidth(maMinimalSize.Width());
+ else if (aTargetSize.Width() > maMaximalSize.Width())
+ aTargetSize.setWidth(maMaximalSize.Width());
+ }
+ else if (bCalculateHeight)
+ {
+ if (aTargetSize.Height() < maMinimalSize.Height())
+ aTargetSize.setHeight(maMinimalSize.Height());
+ else if (aTargetSize.Height() > maMaximalSize.Height())
+ aTargetSize.setHeight(maMaximalSize.Height());
+ }
+
+ return aTargetSize;
+}
+
+
+
+
+sal_Int32 Layouter::Implementation::GetIndex (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn,
+ const bool bClampToValidRange) const
+{
+ if (nRow >= 0 && nColumn >= 0)
+ {
+ const sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
+ if (nIndex >= mnPageCount)
+ if (bClampToValidRange)
+ return mnPageCount-1;
+ else
+ return -1;
+ else
+ return nIndex;
+ }
+ else if (bClampToValidRange)
+ return 0;
+ else
+ return -1;
+}
+
+
+
+
+Rectangle Layouter::Implementation::GetPageObjectBox (
+ const sal_Int32 nIndex,
+ const bool bIncludeBorderAndGap) const
+{
+ const sal_Int32 nRow (nIndex / mnColumnCount);
+ const sal_Int32 nColumn (nIndex % mnColumnCount);
+
+ const Rectangle aBoundingBox (GetPageObjectBox(nRow,nColumn));
+ if (bIncludeBorderAndGap)
+ return AddBorderAndGap(aBoundingBox, nRow, nColumn);
+ else
+ return aBoundingBox;
+}
+
+
+
+
+Rectangle Layouter::Implementation::GetPageObjectBox (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn) const
+{
+ return Rectangle(
+ Point (mnLeftBorder
+ + nColumn * maPageObjectSize.Width()
+ + (nColumn>0 ? nColumn : 0) * mnHorizontalGap,
+ mnTopBorder
+ + nRow * maPageObjectSize.Height()
+ + (nRow>0 ? nRow : 0) * mnVerticalGap),
+ maPageObjectSize);
+}
+
+
+
+
+
+Rectangle Layouter::Implementation::AddBorderAndGap (
+ const Rectangle& rBoundingBox,
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn) const
+{
+ Rectangle aBoundingBox (rBoundingBox);
+
+ if (nColumn == 0)
+ aBoundingBox.Left() = 0;
+ else
+ aBoundingBox.Left() -= mnHorizontalGap/2;
+ if (nColumn == mnColumnCount-1)
+ aBoundingBox.Right() += mnRightBorder;
+ else
+ aBoundingBox.Right() += mnHorizontalGap/2;
+ if (nRow == 0)
+ aBoundingBox.Top() = 0;
+ else
+ aBoundingBox.Top() -= mnVerticalGap/2;
+ if (nRow == mnRowCount-1)
+ aBoundingBox.Bottom() += mnBottomBorder;
+ else
+ aBoundingBox.Bottom() += mnVerticalGap/2;
+ return aBoundingBox;
+}
+
+
+
+
+Rectangle Layouter::Implementation::GetTotalBoundingBox (void) const
+{
+ sal_Int32 nHorizontalSize = 0;
+ sal_Int32 nVerticalSize = 0;
+ if (mnColumnCount > 0)
+ {
+ sal_Int32 nRowCount = (mnPageCount+mnColumnCount-1) / mnColumnCount;
+ nHorizontalSize =
+ mnLeftBorder
+ + mnRightBorder
+ + mnColumnCount * maPageObjectSize.Width();
+ if (mnColumnCount > 1)
+ nHorizontalSize += (mnColumnCount-1) * mnHorizontalGap;
+ nVerticalSize =
+ mnTopBorder
+ + mnBottomBorder
+ + nRowCount * maPageObjectSize.Height();
+ if (nRowCount > 1)
+ nVerticalSize += (nRowCount-1) * mnVerticalGap;
+ }
+
+ return Rectangle (
+ Point(0,0),
+ Size (nHorizontalSize, nVerticalSize)
+ );
+}
+
+
+
+
+void Layouter::Implementation::CalculateVerticalLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const
+{
+ const sal_Int32 nY = rModelPosition.Y() - mnTopBorder + maPageObjectSize.Height()/2;
+ const sal_Int32 nRowHeight (maPageObjectSize.Height() + mnVerticalGap);
+ const sal_Int32 nRow (::std::min(mnPageCount, nY / nRowHeight));
+ rPosition.SetLogicalPosition (
+ nRow,
+ 0,
+ nRow,
+ (nRow == 0),
+ (nRow == mnRowCount),
+ (nRow >= mnMaxRowCount));
+}
+
+
+
+
+//===== HorizontalImplementation ================================================
+
+HorizontalImplementation::HorizontalImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme)
+ : Implementation(rpWindow, rpTheme)
+{
+}
+
+
+
+
+HorizontalImplementation::HorizontalImplementation (const Implementation& rImplementation)
+ : Implementation(rImplementation)
+{
+}
+
+
+
+
+Layouter::Orientation HorizontalImplementation::GetOrientation (void) const
+{
+ return Layouter::HORIZONTAL;
+}
+
+
+
+
+void HorizontalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
+{
+ (void)rWindowSize;
+
+ // Row and column count are fixed (for a given page count.)
+ mnColumnCount = mnPageCount;
+ mnRowCount = 1;
+}
+
+
+
+
+void HorizontalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
+{
+ mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
+ / (maPageObjectSize.Width() + mnHorizontalGap);
+ mnMaxRowCount = 1;
+}
+
+
+
+
+Size HorizontalImplementation::CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const
+{
+ return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, false, true);
+}
+
+
+
+
+void HorizontalImplementation::CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const
+{
+ const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
+ const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
+ const sal_Int32 nColumn (::std::min(mnPageCount, nX / nColumnWidth));
+ rPosition.SetLogicalPosition (
+ 0,
+ nColumn,
+ nColumn,
+ (nColumn == 0),
+ (nColumn == mnColumnCount),
+ (nColumn >= mnMaxColumnCount));
+}
+
+
+
+
+//===== VerticalImplementation ================================================
+
+VerticalImplementation::VerticalImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme)
+ : Implementation(rpWindow, rpTheme)
+{
+}
+
+
+
+
+VerticalImplementation::VerticalImplementation (const Implementation& rImplementation)
+ : Implementation(rImplementation)
+{
+}
+
+
+
+
+Layouter::Orientation VerticalImplementation::GetOrientation (void) const
+{
+ return Layouter::VERTICAL;
+}
+
+
+
+
+void VerticalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
+{
+ (void)rWindowSize;
+
+ // Row and column count are fixed (for a given page count.)
+ mnRowCount = mnPageCount;
+ mnColumnCount = 1;
+
+}
+
+
+
+
+void VerticalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
+{
+ mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
+ / (maPageObjectSize.Height() + mnVerticalGap);
+ mnMaxColumnCount = 1;
+}
+
+
+
+
+Size VerticalImplementation::CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const
+{
+ return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, false);
+}
+
+
+
+
+void VerticalImplementation::CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const
+{
+ return CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
+}
+
+
+
+
+//===== GridImplementation ================================================
+
+GridImplementation::GridImplementation (
+ const SharedSdWindow& rpWindow,
+ const ::boost::shared_ptr<view::Theme>& rpTheme)
+ : Implementation(rpWindow, rpTheme)
+{
+}
+
+
+
+
+GridImplementation::GridImplementation (const Implementation& rImplementation)
+ : Implementation(rImplementation)
+{
+}
+
+
+
+
+Layouter::Orientation GridImplementation::GetOrientation (void) const
+{
+ return Layouter::GRID;
+}
+
+
+
+
+void GridImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
+{
+ // Calculate the column count.
+ mnColumnCount
+ = (rWindowSize.Width() - mnRequestedLeftBorder - mnRequestedRightBorder)
+ / (maPreferredSize.Width() + mnHorizontalGap);
+ if (mnColumnCount < mnMinimalColumnCount)
+ mnColumnCount = mnMinimalColumnCount;
+ if (mnColumnCount > mnMaximalColumnCount)
+ mnColumnCount = mnMaximalColumnCount;
+ mnRowCount = (mnPageCount + mnColumnCount-1)/mnColumnCount;
+}
+
+
+
+
+void GridImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
+{
+ mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
+ / (maPageObjectSize.Width() + mnHorizontalGap);
+ mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
+ / (maPageObjectSize.Height() + mnVerticalGap);
+}
+
+
+
+
+
+Size GridImplementation::CalculateTargetSize (
+ const Size& rWindowSize,
+ const Size& rPreviewModelSize) const
+{
+ return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, true);
+}
+
+
+
+
+void GridImplementation::CalculateLogicalInsertPosition (
+ const Point& rModelPosition,
+ InsertPosition& rPosition) const
+{
+ if (mnColumnCount == 1)
+ {
+ CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
+ }
+ else
+ {
+ // Handle the general case of more than one column.
+ sal_Int32 nRow (::std::min(
+ mnRowCount-1,
+ GetRowAtPosition (rModelPosition.Y(), true, GM_BOTH)));
+ const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
+ const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
+ sal_Int32 nColumn (::std::min(mnColumnCount, nX / nColumnWidth));
+ sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
+ bool bIsAtRunEnd (nColumn == mnColumnCount);
+
+ if (nIndex >= mnPageCount)
+ {
+ nIndex = mnPageCount;
+ nRow = mnRowCount-1;
+ nColumn = ::std::min(::std::min(mnPageCount, mnColumnCount), nColumn);
+ bIsAtRunEnd = true;
+ }
+
+ rPosition.SetLogicalPosition (
+ nRow,
+ nColumn,
+ nIndex,
+ (nColumn == 0),
+ bIsAtRunEnd,
+ (nColumn >= mnMaxColumnCount));
+ }
+}
+
+
+
+
+//===== InsertPosition ========================================================
+
+InsertPosition::InsertPosition (void)
+ : mnRow(-1),
+ mnColumn(-1),
+ mnIndex(-1),
+ mbIsAtRunStart(false),
+ mbIsAtRunEnd(false),
+ mbIsExtraSpaceNeeded(false),
+ maLocation(0,0),
+ maLeadingOffset(0,0),
+ maTrailingOffset(0,0)
+{
+}
+
+
+
+
+InsertPosition& InsertPosition::operator= (const InsertPosition& rInsertPosition)
+{
+ if (this != &rInsertPosition)
+ {
+ mnRow = rInsertPosition.mnRow;
+ mnColumn = rInsertPosition.mnColumn;
+ mnIndex = rInsertPosition.mnIndex;
+ mbIsAtRunStart = rInsertPosition.mbIsAtRunStart;
+ mbIsAtRunEnd = rInsertPosition.mbIsAtRunEnd;
+ mbIsExtraSpaceNeeded = rInsertPosition.mbIsExtraSpaceNeeded;
+ maLocation = rInsertPosition.maLocation;
+ maLeadingOffset = rInsertPosition.maLeadingOffset;
+ maTrailingOffset = rInsertPosition.maTrailingOffset;
+ }
+ return *this;
+}
+
+
+
+
+bool InsertPosition::operator== (const InsertPosition& rInsertPosition) const
+{
+ // Do not compare the geometrical information (maLocation).
+ return mnRow==rInsertPosition.mnRow
+ && mnColumn==rInsertPosition.mnColumn
+ && mnIndex==rInsertPosition.mnIndex
+ && mbIsAtRunStart==rInsertPosition.mbIsAtRunStart
+ && mbIsAtRunEnd==rInsertPosition.mbIsAtRunEnd
+ && mbIsExtraSpaceNeeded==rInsertPosition.mbIsExtraSpaceNeeded;
+}
+
+
+
+
+bool InsertPosition::operator!= (const InsertPosition& rInsertPosition) const
+{
+ return !operator==(rInsertPosition);
+}
+
+
+
+
+void InsertPosition::SetLogicalPosition (
+ const sal_Int32 nRow,
+ const sal_Int32 nColumn,
+ const sal_Int32 nIndex,
+ const bool bIsAtRunStart,
+ const bool bIsAtRunEnd,
+ const bool bIsExtraSpaceNeeded)
+{
+ mnRow = nRow;
+ mnColumn = nColumn;
+ mnIndex = nIndex;
+ mbIsAtRunStart = bIsAtRunStart;
+ mbIsAtRunEnd = bIsAtRunEnd;
+ mbIsExtraSpaceNeeded = bIsExtraSpaceNeeded;
+}
+
+
+
+
+void InsertPosition::SetGeometricalPosition(
+ const Point aLocation,
+ const Point aLeadingOffset,
+ const Point aTrailingOffset)
+{
+ maLocation = aLocation;
+ maLeadingOffset = aLeadingOffset;
+ maTrailingOffset = aTrailingOffset;
+}
+
+
+
+} } } // 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..3e9b0aa94b35
--- /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/SlsPageObjectLayouter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx
new file mode 100644
index 000000000000..d798fa27accb
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx
@@ -0,0 +1,287 @@
+/*************************************************************************
+ *
+ * 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/SlsPageObjectLayouter.hxx"
+
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlsFontProvider.hxx"
+#include "view/SlsTheme.hxx"
+#include "tools/IconCache.hxx"
+#include "Window.hxx"
+#include "res_bmp.hrc"
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+const static sal_Int32 gnLeftPageNumberOffset = 2;
+const static sal_Int32 gnRightPageNumberOffset = 5;
+const static sal_Int32 gnOuterBorderWidth = 5;
+const static sal_Int32 gnInfoAreaMinWidth = 26;
+}
+
+PageObjectLayouter::PageObjectLayouter (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const Size& rPageObjectWindowSize,
+ const Size& rPageSize,
+ const SharedSdWindow& rpWindow,
+ const sal_Int32 nPageCount)
+ : mpWindow(rpWindow),
+ maPageObjectSize(rPageObjectWindowSize.Width(), rPageObjectWindowSize.Height()),
+ mnModelToWindowScale(1),
+ maPageObjectBoundingBox(),
+ maPageNumberAreaBoundingBox(),
+ maPreviewBoundingBox(),
+ maTransitionEffectBoundingBox(),
+ maTransitionEffectIcon(IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR)),
+ mpPageNumberFont(Theme::GetFont(Theme::Font_PageNumber, *rpWindow))
+{
+ const Size aPageNumberAreaSize (GetPageNumberAreaSize(nPageCount));
+
+ const int nMaximumBorderWidth (gnOuterBorderWidth);
+ const int nFocusIndicatorWidth (rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth));
+
+ maPreviewBoundingBox = CalculatePreviewBoundingBox(
+ maPageObjectSize,
+ Size(rPageSize.Width(), rPageSize.Height()),
+ aPageNumberAreaSize.Width(),
+ nFocusIndicatorWidth);
+ maFocusIndicatorBoundingBox = Rectangle(Point(0,0), maPageObjectSize);
+ maPageObjectBoundingBox = Rectangle(
+ Point(
+ nFocusIndicatorWidth,
+ nFocusIndicatorWidth),
+ Size(
+ maPageObjectSize.Width()-2*nFocusIndicatorWidth,
+ maPageObjectSize.Height()-2*nFocusIndicatorWidth));
+
+ maPageNumberAreaBoundingBox = Rectangle(
+ Point(
+ std::max(gnLeftPageNumberOffset,
+ sal_Int32(maPreviewBoundingBox.Left()
+ - gnRightPageNumberOffset
+ - aPageNumberAreaSize.Width())),
+ nMaximumBorderWidth),
+ aPageNumberAreaSize);
+
+ const Size aIconSize (maTransitionEffectIcon.GetSizePixel());
+ maTransitionEffectBoundingBox = Rectangle(
+ Point(
+ (maPreviewBoundingBox.Left() - aIconSize.Width()) / 2,
+ maPreviewBoundingBox.Bottom() - aIconSize.Height()),
+ aIconSize);
+}
+
+
+
+
+PageObjectLayouter::~PageObjectLayouter(void)
+{
+}
+
+
+
+
+Rectangle PageObjectLayouter::CalculatePreviewBoundingBox (
+ Size& rPageObjectSize,
+ const Size& rPageSize,
+ const sal_Int32 nPageNumberAreaWidth,
+ const sal_Int32 nFocusIndicatorWidth)
+{
+ const sal_Int32 nIconWidth (maTransitionEffectIcon.GetSizePixel().Width());
+ const sal_Int32 nLeftAreaWidth (
+ ::std::max(
+ gnInfoAreaMinWidth,
+ gnRightPageNumberOffset
+ + ::std::max(
+ nPageNumberAreaWidth,
+ nIconWidth)));
+ sal_Int32 nPreviewWidth;
+ sal_Int32 nPreviewHeight;
+ const double nPageAspectRatio (double(rPageSize.Width()) / double(rPageSize.Height()));
+ if (rPageObjectSize.Height() == 0)
+ {
+ // Calculate height so that the preview fills the available
+ // horizontal space completely while observing the aspect ratio of
+ // the preview.
+ nPreviewWidth = rPageObjectSize.Width()
+ - nLeftAreaWidth - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
+ nPreviewHeight = ::basegfx::fround(nPreviewWidth / nPageAspectRatio);
+ rPageObjectSize.setHeight(nPreviewHeight + 2*gnOuterBorderWidth + 2*nFocusIndicatorWidth + 1);
+ }
+ else if (rPageObjectSize.Width() == 0)
+ {
+ // Calculate the width of the page object so that the preview fills
+ // the available vertical space completely while observing the
+ // aspect ratio of the preview.
+ nPreviewHeight = rPageObjectSize.Height() - 2*gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
+ nPreviewWidth = ::basegfx::fround(nPreviewHeight * nPageAspectRatio);
+ rPageObjectSize.setWidth(nPreviewWidth
+ + nLeftAreaWidth + gnOuterBorderWidth + 2*nFocusIndicatorWidth + 1);
+
+ }
+ else
+ {
+ // The size of the page object is given. Calculate the size of the
+ // preview.
+ nPreviewWidth = rPageObjectSize.Width()
+ - nLeftAreaWidth - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
+ nPreviewHeight = rPageObjectSize.Height()
+ - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
+ if (double(nPreviewWidth)/double(nPreviewHeight) > nPageAspectRatio)
+ nPreviewWidth = ::basegfx::fround(nPreviewHeight * nPageAspectRatio);
+ else
+ nPreviewHeight = ::basegfx::fround(nPreviewWidth / nPageAspectRatio);
+ }
+ // When the preview does not fill the available space completely then
+ // place it flush right and vertically centered.
+ const int nLeft (rPageObjectSize.Width()
+ - gnOuterBorderWidth - nPreviewWidth - nFocusIndicatorWidth - 1);
+ const int nTop ((rPageObjectSize.Height() - nPreviewHeight)/2);
+ return Rectangle(
+ nLeft,
+ nTop,
+ nLeft + nPreviewWidth,
+ nTop + nPreviewHeight);
+}
+
+
+
+
+Rectangle PageObjectLayouter::GetBoundingBox (
+ const model::SharedPageDescriptor& rpPageDescriptor,
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem)
+{
+ OSL_ASSERT(rpPageDescriptor);
+ Point aLocation (rpPageDescriptor ? rpPageDescriptor->GetLocation() : Point(0,0));
+ return GetBoundingBox(aLocation, ePart, eCoordinateSystem);
+}
+
+
+
+
+Rectangle PageObjectLayouter::GetBoundingBox (
+ const Point& rPageObjectLocation,
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem)
+{
+ Rectangle aBoundingBox;
+ switch (ePart)
+ {
+ case FocusIndicator:
+ aBoundingBox = maFocusIndicatorBoundingBox;
+ break;
+
+ case PageObject:
+ case MouseOverIndicator:
+ aBoundingBox = maPageObjectBoundingBox;
+ break;
+
+ case Preview:
+ aBoundingBox = maPreviewBoundingBox;
+ break;
+
+ case PageNumber:
+ aBoundingBox = maPageNumberAreaBoundingBox;
+ break;
+
+ case Name:
+ aBoundingBox = maPageNumberAreaBoundingBox;
+ break;
+
+ case TransitionEffectIndicator:
+ aBoundingBox = maTransitionEffectBoundingBox;
+ break;
+ }
+
+ // Adapt coordinates to the requested coordinate system.
+ Point aLocation (rPageObjectLocation);
+ if (eCoordinateSystem == WindowCoordinateSystem)
+ aLocation += mpWindow->GetMapMode().GetOrigin();
+
+ return Rectangle(
+ aBoundingBox.TopLeft() + aLocation,
+ aBoundingBox.BottomRight() + aLocation);
+}
+
+
+
+
+Size PageObjectLayouter::GetSize (
+ const Part ePart,
+ const CoordinateSystem eCoordinateSystem)
+{
+ return GetBoundingBox(Point(0,0), ePart, eCoordinateSystem).GetSize();
+}
+
+
+
+
+Size PageObjectLayouter::GetPageNumberAreaSize (const int nPageCount)
+{
+ OSL_ASSERT(mpWindow);
+
+ // Set the correct font.
+ Font aOriginalFont (mpWindow->GetFont());
+ if (mpPageNumberFont)
+ mpWindow->SetFont(*mpPageNumberFont);
+
+ 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.
+
+ const Size aSize (
+ mpWindow->GetTextWidth(sPageNumberTemplate),
+ mpWindow->GetTextHeight());
+
+ mpWindow->SetFont(aOriginalFont);
+
+ return aSize;
+}
+
+
+
+
+Image PageObjectLayouter::GetTransitionEffectIcon (void) const
+{
+ return maTransitionEffectIcon;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx
new file mode 100644
index 000000000000..cb78c1a12f71
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx
@@ -0,0 +1,584 @@
+/*************************************************************************
+ *
+ * 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/SlsPageObjectPainter.hxx"
+
+#include "model/SlsPageDescriptor.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsTheme.hxx"
+#include "view/SlsButtonBar.hxx"
+#include "SlsFramePainter.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "controller/SlsProperties.hxx"
+#include "Window.hxx"
+#include "sdpage.hxx"
+#include "sdresid.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/virdev.hxx>
+#include <boost/scoped_ptr.hpp>
+
+using namespace ::drawinglayer::primitive2d;
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+
+sal_uInt8 Blend (
+ const sal_uInt8 nValue1,
+ const sal_uInt8 nValue2,
+ const double nWeight)
+{
+ const double nValue (nValue1*(1-nWeight) + nValue2 * nWeight);
+ if (nValue < 0)
+ return 0;
+ else if (nValue > 255)
+ return 255;
+ else
+ return (sal_uInt8)nValue;
+}
+
+sal_uInt8 ClampColorChannel (const double nValue)
+{
+ if (nValue <= 0)
+ return 0;
+ else if (nValue >= 255)
+ return 255;
+ else
+ return sal_uInt8(nValue);
+}
+
+sal_uInt8 CalculateColorChannel(
+ const double nColor1,
+ const double nColor2,
+ const double nAlpha1,
+ const double nAlpha2,
+ const double nAlpha0)
+{
+ if (nAlpha0 == 0)
+ return 0;
+
+ const double nColor0 ((nAlpha1*nColor1 + nAlpha1*nAlpha2*nColor1 + nAlpha2*nColor2) / nAlpha0);
+ return ClampColorChannel(255 * nColor0);
+}
+
+} // end of anonymous namespace
+
+
+
+
+//===== PageObjectPainter =====================================================
+
+PageObjectPainter::PageObjectPainter (
+ const SlideSorter& rSlideSorter)
+ : mrLayouter(rSlideSorter.GetView().GetLayouter()),
+ mpPageObjectLayouter(),
+ mpCache(rSlideSorter.GetView().GetPreviewCache()),
+ mpProperties(rSlideSorter.GetProperties()),
+ mpTheme(rSlideSorter.GetTheme()),
+ mpPageNumberFont(Theme::GetFont(Theme::Font_PageNumber, *rSlideSorter.GetContentWindow())),
+ mpShadowPainter(new FramePainter(mpTheme->GetIcon(Theme::Icon_RawShadow))),
+ mpFocusBorderPainter(new FramePainter(mpTheme->GetIcon(Theme::Icon_FocusBorder))),
+ maNormalBackground(),
+ maSelectionBackground(),
+ maFocusedSelectionBackground(),
+ maMouseOverBackground(),
+ maMouseOverFocusedBackground(),
+ msUnhideString(mpTheme->GetString(Theme::String_Unhide)),
+ mrButtonBar(rSlideSorter.GetView().GetButtonBar())
+{
+ // Replace the color (not the alpha values) in the focus border with a
+ // color derived from the current selection color.
+ Color aColor (mpTheme->GetColor(Theme::Color_Selection));
+ sal_uInt16 nHue, nSat, nBri;
+ aColor.RGBtoHSB(nHue, nSat, nBri);
+ aColor = Color::HSBtoRGB(nHue, 28, 65);
+ mpFocusBorderPainter->AdaptColor(aColor, true);
+}
+
+
+
+
+PageObjectPainter::~PageObjectPainter (void)
+{
+}
+
+
+
+
+void PageObjectPainter::PaintPageObject (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ // The page object layouter is quite volatile. It may have been replaced
+ // since the last call. Update it now.
+ mpPageObjectLayouter = mrLayouter.GetPageObjectLayouter();
+ if ( ! mpPageObjectLayouter)
+ {
+ OSL_ASSERT(mpPageObjectLayouter);
+ return;
+ }
+
+ // Turn off antialiasing to avoid the bitmaps from being shifted by
+ // fractions of a pixel and thus show blurry edges.
+ const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing());
+ rDevice.SetAntialiasing(nSavedAntialiasingMode & ~ANTIALIASING_ENABLE_B2DDRAW);
+
+ PaintBackground(rDevice, rpDescriptor);
+ PaintPreview(rDevice, rpDescriptor);
+ PaintPageNumber(rDevice, rpDescriptor);
+ PaintTransitionEffect(rDevice, rpDescriptor);
+ mrButtonBar.Paint(rDevice, rpDescriptor);
+
+ rDevice.SetAntialiasing(nSavedAntialiasingMode);
+}
+
+
+
+
+void PageObjectPainter::NotifyResize (const bool bForce)
+{
+ (void)bForce;
+ maNormalBackground.SetEmpty();
+ maSelectionBackground.SetEmpty();
+ maFocusedSelectionBackground.SetEmpty();
+ maFocusedBackground.SetEmpty();
+ maMouseOverBackground.SetEmpty();
+ maMouseOverFocusedBackground.SetEmpty();
+ maMouseOverSelectedAndFocusedBackground.SetEmpty();
+}
+
+
+
+
+void PageObjectPainter::SetTheme (const ::boost::shared_ptr<view::Theme>& rpTheme)
+{
+ mpTheme = rpTheme;
+ NotifyResize(true);
+}
+
+
+
+
+void PageObjectPainter::PaintBackground (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::FocusIndicator,
+ PageObjectLayouter::ModelCoordinateSystem));
+
+ const Bitmap& rBackground (GetBackgroundForState(rpDescriptor, rDevice));
+ rDevice.DrawBitmap(aBox.TopLeft(), rBackground);
+
+ // Fill the interior of the preview area with the default background
+ // color of the page.
+ SdPage* pPage = rpDescriptor->GetPage();
+ if (pPage != NULL)
+ {
+ rDevice.SetFillColor(pPage->GetPageBackgroundColor(NULL));
+ rDevice.SetLineColor(pPage->GetPageBackgroundColor(NULL));
+ const Rectangle aPreviewBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+ rDevice.DrawRect(aPreviewBox);
+ }
+}
+
+
+
+
+void PageObjectPainter::PaintPreview (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const
+{
+ const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+
+ if (mpCache != NULL)
+ {
+ const SdrPage* pPage = rpDescriptor->GetPage();
+ mpCache->SetPreciousFlag(pPage, true);
+
+ const Bitmap aPreview (GetPreviewBitmap(rpDescriptor, &rDevice));
+ if ( ! aPreview.IsEmpty())
+ {
+ if (aPreview.GetSizePixel() != aBox.GetSize())
+ rDevice.DrawBitmap(aBox.TopLeft(), aBox.GetSize(), aPreview);
+ else
+ rDevice.DrawBitmap(aBox.TopLeft(), aPreview);
+ }
+ }
+}
+
+
+
+
+Bitmap PageObjectPainter::CreateMarkedPreview (
+ const Size& rSize,
+ const Bitmap& rPreview,
+ const BitmapEx& rOverlay,
+ const OutputDevice* pReferenceDevice) const
+{
+ ::boost::scoped_ptr<VirtualDevice> pDevice;
+ if (pReferenceDevice != NULL)
+ pDevice.reset(new VirtualDevice(*pReferenceDevice));
+ else
+ pDevice.reset(new VirtualDevice());
+ pDevice->SetOutputSizePixel(rSize);
+
+ pDevice->DrawBitmap(Point(0,0), rSize, rPreview);
+
+ // Paint bitmap tiled over the preview to mark it as excluded.
+ const sal_Int32 nIconWidth (rOverlay.GetSizePixel().Width());
+ const sal_Int32 nIconHeight (rOverlay.GetSizePixel().Height());
+ if (nIconWidth>0 && nIconHeight>0)
+ {
+ for (sal_Int32 nX=0; nX<rSize.Width(); nX+=nIconWidth)
+ for (sal_Int32 nY=0; nY<rSize.Height(); nY+=nIconHeight)
+ pDevice->DrawBitmapEx(Point(nX,nY), rOverlay);
+ }
+ return pDevice->GetBitmap(Point(0,0), rSize);
+}
+
+
+
+
+Bitmap PageObjectPainter::GetPreviewBitmap (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const OutputDevice* pReferenceDevice) const
+{
+ const SdrPage* pPage = rpDescriptor->GetPage();
+ const bool bIsExcluded (rpDescriptor->HasState(model::PageDescriptor::ST_Excluded));
+
+ if (bIsExcluded)
+ {
+ Bitmap aMarkedPreview (mpCache->GetMarkedPreviewBitmap(pPage,false));
+ const Rectangle aPreviewBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+ if (aMarkedPreview.IsEmpty() || aMarkedPreview.GetSizePixel()!=aPreviewBox.GetSize())
+ {
+ aMarkedPreview = CreateMarkedPreview(
+ aPreviewBox.GetSize(),
+ mpCache->GetPreviewBitmap(pPage,true),
+ mpTheme->GetIcon(Theme::Icon_HideSlideOverlay),
+ pReferenceDevice);
+ mpCache->SetMarkedPreviewBitmap(pPage, aMarkedPreview);
+ }
+ return aMarkedPreview;
+ }
+ else
+ {
+ return mpCache->GetPreviewBitmap(pPage,false);
+ }
+}
+
+
+
+
+void PageObjectPainter::PaintPageNumber (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const
+{
+ const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::PageNumber,
+ PageObjectLayouter::ModelCoordinateSystem));
+
+ // Determine the color of the page number.
+ Color aPageNumberColor (mpTheme->GetColor(Theme::Color_PageNumberDefault));
+ if (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) ||
+ rpDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ {
+ // Page number is painted on background for hover or selection or
+ // both. Each of these background colors has a predefined luminance
+ // which is compatible with the PageNumberHover color.
+ aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberHover));
+ }
+ else
+ {
+ const Color aBackgroundColor (mpTheme->GetColor(Theme::Color_Background));
+ const sal_Int32 nBackgroundLuminance (aBackgroundColor.GetLuminance());
+ // When the background color is black then this is interpreted as
+ // high contrast mode and the font color is set to white.
+ if (nBackgroundLuminance == 0)
+ aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberHighContrast));
+ else
+ {
+ // Compare luminance of default page number color and background
+ // color. When the two are similar then use a darker
+ // (preferred) or brighter font color.
+ const sal_Int32 nFontLuminance (aPageNumberColor.GetLuminance());
+ if (abs(nBackgroundLuminance - nFontLuminance) < 60)
+ {
+ if (nBackgroundLuminance > nFontLuminance-30)
+ aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberBrightBackground));
+ else
+ aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberDarkBackground));
+ }
+ }
+ }
+
+ // Paint the page number.
+ OSL_ASSERT(rpDescriptor->GetPage()!=NULL);
+ const sal_Int32 nPageNumber ((rpDescriptor->GetPage()->GetPageNum() - 1) / 2 + 1);
+ const String sPageNumber (String::CreateFromInt32(nPageNumber));
+ rDevice.SetFont(*mpPageNumberFont);
+ rDevice.SetTextColor(aPageNumberColor);
+ rDevice.DrawText(aBox, sPageNumber, TEXT_DRAW_RIGHT | TEXT_DRAW_VCENTER);
+}
+
+
+
+
+void PageObjectPainter::PaintTransitionEffect (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor) const
+{
+ const SdPage* pPage = rpDescriptor->GetPage();
+ if (pPage!=NULL && pPage->getTransitionType() > 0)
+ {
+ const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
+ rpDescriptor,
+ PageObjectLayouter::TransitionEffectIndicator,
+ PageObjectLayouter::ModelCoordinateSystem));
+
+ rDevice.DrawBitmapEx(
+ aBox.TopLeft(),
+ mpPageObjectLayouter->GetTransitionEffectIcon().GetBitmapEx());
+ }
+}
+
+
+
+
+Bitmap& PageObjectPainter::GetBackgroundForState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const OutputDevice& rReferenceDevice)
+{
+ enum State { None = 0x00, Selected = 0x01, MouseOver = 0x02, Focused = 0x04 };
+ const int eState =
+ (rpDescriptor->HasState(model::PageDescriptor::ST_Selected) ? Selected : None)
+ | (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) ? MouseOver : None)
+ | (rpDescriptor->HasState(model::PageDescriptor::ST_Focused) ? Focused : None);
+
+ switch (eState)
+ {
+ case MouseOver | Selected | Focused:
+ return GetBackground(
+ maMouseOverSelectedAndFocusedBackground,
+ Theme::Gradient_MouseOverSelectedAndFocusedPage,
+ rReferenceDevice,
+ true);
+
+ case MouseOver | Selected:
+ case MouseOver:
+ return GetBackground(
+ maMouseOverBackground,
+ Theme::Gradient_MouseOverPage,
+ rReferenceDevice,
+ false);
+
+ case MouseOver | Focused:
+ return GetBackground(
+ maMouseOverFocusedBackground,
+ Theme::Gradient_MouseOverPage,
+ rReferenceDevice,
+ true);
+
+ case Selected | Focused:
+ return GetBackground(
+ maFocusedSelectionBackground,
+ Theme::Gradient_SelectedAndFocusedPage,
+ rReferenceDevice,
+ true);
+
+ case Selected:
+ return GetBackground(
+ maSelectionBackground,
+ Theme::Gradient_SelectedPage,
+ rReferenceDevice,
+ false);
+
+ case Focused:
+ return GetBackground(
+ maFocusedBackground,
+ Theme::Gradient_FocusedPage,
+ rReferenceDevice,
+ true);
+
+ case None:
+ default:
+ return GetBackground(
+ maNormalBackground,
+ Theme::Gradient_NormalPage,
+ rReferenceDevice,
+ false);
+ }
+}
+
+
+
+
+Bitmap& PageObjectPainter::GetBackground(
+ Bitmap& rBackground,
+ Theme::GradientColorType eType,
+ const OutputDevice& rReferenceDevice,
+ const bool bHasFocusBorder)
+{
+ if (rBackground.IsEmpty())
+ rBackground = CreateBackgroundBitmap(rReferenceDevice, eType, bHasFocusBorder);
+ return rBackground;
+}
+
+
+
+
+Bitmap PageObjectPainter::CreateBackgroundBitmap(
+ const OutputDevice& rReferenceDevice,
+ const Theme::GradientColorType eColorType,
+ const bool bHasFocusBorder) const
+{
+ const Size aSize (mpPageObjectLayouter->GetSize(
+ PageObjectLayouter::FocusIndicator,
+ PageObjectLayouter::WindowCoordinateSystem));
+ const Rectangle aPageObjectBox (mpPageObjectLayouter->GetBoundingBox(
+ Point(0,0),
+ PageObjectLayouter::PageObject,
+ PageObjectLayouter::ModelCoordinateSystem));
+ VirtualDevice aBitmapDevice (rReferenceDevice);
+ aBitmapDevice.SetOutputSizePixel(aSize);
+
+ // Fill the background with the background color of the slide sorter.
+ const Color aBackgroundColor (mpTheme->GetColor(Theme::Color_Background));
+ OSL_TRACE("filling background of page object bitmap with color %x", aBackgroundColor.GetColor());
+ aBitmapDevice.SetFillColor(aBackgroundColor);
+ aBitmapDevice.SetLineColor(aBackgroundColor);
+ aBitmapDevice.DrawRect(Rectangle(Point(0,0), aSize));
+
+ // Paint the slide area with a linear gradient that starts some pixels
+ // below the top and ends some pixels above the bottom.
+ const Color aTopColor(mpTheme->GetGradientColor(eColorType, Theme::Fill1));
+ const Color aBottomColor(mpTheme->GetGradientColor(eColorType, Theme::Fill2));
+ if (aTopColor != aBottomColor)
+ {
+ const sal_Int32 nHeight (aPageObjectBox.GetHeight());
+ const sal_Int32 nDefaultConstantSize(nHeight/4);
+ const sal_Int32 nMinimalGradientSize(40);
+ const sal_Int32 nY1 (
+ ::std::max<sal_Int32>(
+ 0,
+ ::std::min<sal_Int32>(
+ nDefaultConstantSize,
+ (nHeight - nMinimalGradientSize)/2)));
+ const sal_Int32 nY2 (nHeight-nY1);
+ const sal_Int32 nTop (aPageObjectBox.Top());
+ for (sal_Int32 nY=0; nY<nHeight; ++nY)
+ {
+ if (nY<=nY1)
+ aBitmapDevice.SetLineColor(aTopColor);
+ else if (nY>=nY2)
+ aBitmapDevice.SetLineColor(aBottomColor);
+ else
+ {
+ Color aColor (aTopColor);
+ aColor.Merge(aBottomColor, 255 * (nY2-nY) / (nY2-nY1));
+ aBitmapDevice.SetLineColor(aColor);
+ }
+ aBitmapDevice.DrawLine(
+ Point(aPageObjectBox.Left(), nY+nTop),
+ Point(aPageObjectBox.Right(), nY+nTop));
+ }
+ }
+ else
+ {
+ aBitmapDevice.SetFillColor(aTopColor);
+ aBitmapDevice.DrawRect(aPageObjectBox);
+ }
+
+ // Paint the simple border and, for some backgrounds, the focus border.
+ if (bHasFocusBorder)
+ mpFocusBorderPainter->PaintFrame(aBitmapDevice, aPageObjectBox);
+ else
+ PaintBorder(aBitmapDevice, eColorType, aPageObjectBox);
+
+ // Get bounding box of the preview around which a shadow is painted.
+ // Compensate for the border around the preview.
+ const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
+ Point(0,0),
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+ Rectangle aFrameBox (aBox.Left()-1,aBox.Top()-1,aBox.Right()+1,aBox.Bottom()+1);
+ mpShadowPainter->PaintFrame(aBitmapDevice, aFrameBox);
+
+ return aBitmapDevice.GetBitmap (Point(0,0),aSize);
+}
+
+
+
+
+void PageObjectPainter::PaintBorder (
+ OutputDevice& rDevice,
+ const Theme::GradientColorType eColorType,
+ const Rectangle& rBox) const
+{
+ rDevice.SetFillColor();
+ const sal_Int32 nBorderWidth (1);
+ for (int nIndex=0; nIndex<nBorderWidth; ++nIndex)
+ {
+ const int nDelta (nIndex);
+ rDevice.SetLineColor(mpTheme->GetGradientColor(eColorType, Theme::Border2));
+ rDevice.DrawLine(
+ Point(rBox.Left()-nDelta, rBox.Top()-nDelta),
+ Point(rBox.Left()-nDelta, rBox.Bottom()+nDelta));
+ rDevice.DrawLine(
+ Point(rBox.Left()-nDelta, rBox.Bottom()+nDelta),
+ Point(rBox.Right()+nDelta, rBox.Bottom()+nDelta));
+ rDevice.DrawLine(
+ Point(rBox.Right()+nDelta, rBox.Bottom()+nDelta),
+ Point(rBox.Right()+nDelta, rBox.Top()-nDelta));
+
+ rDevice.SetLineColor(mpTheme->GetGradientColor(eColorType, Theme::Border1));
+ rDevice.DrawLine(
+ Point(rBox.Left()-nDelta, rBox.Top()-nDelta),
+ Point(rBox.Right()+nDelta, rBox.Top()-nDelta));
+ }
+}
+
+
+
+} } } // end of namespace sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsResource.hxx b/sd/source/ui/slidesorter/view/SlsResource.hxx
new file mode 100644
index 000000000000..9ba3e33b2422
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsResource.hxx
@@ -0,0 +1,50 @@
+/* -*- 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_RESOURCE_HXX
+#define SD_SLIDESORTER_RESOURCE_HXX
+
+#include "view/SlsResource.hrc"
+#include "sdresid.hxx"
+#include <tools/rc.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+class LocalResource : public Resource
+{
+public:
+ LocalResource (const sal_uInt16 nResourceId) : Resource(SdResId(nResourceId)){}
+ ~LocalResource (void) { FreeResource(); }
+};
+
+
+} } } // end of namespace ::sd::slidesorter::view
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/view/SlsResource.src b/sd/source/ui/slidesorter/view/SlsResource.src
new file mode 100644
index 000000000000..13f6cd08c775
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsResource.src
@@ -0,0 +1,314 @@
+/*************************************************************************
+ *
+ * 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 "view/SlsResource.hrc"
+
+Resource RID_SLIDESORTER_ICONS
+{
+ Image IMAGE_COMMAND1_LARGE
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_large.png" ; };
+ };
+ Image IMAGE_COMMAND1_LARGE_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_large_hover.png" ; };
+ };
+ Image IMAGE_COMMAND1_MEDIUM
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_medium.png" ; };
+ };
+ Image IMAGE_COMMAND1_MEDIUM_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_medium_hover.png" ; };
+ };
+ Image IMAGE_COMMAND1_SMALL
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_small.png" ; };
+ };
+ Image IMAGE_COMMAND1_SMALL_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_small_hover.png" ; };
+ };
+
+ Image IMAGE_COMMAND1_LARGE_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_large_hc.png" ; };
+ };
+ Image IMAGE_COMMAND1_LARGE_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_large_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND1_MEDIUM_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_medium_hc.png" ; };
+ };
+ Image IMAGE_COMMAND1_MEDIUM_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_medium_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND1_SMALL_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_small_hc.png" ; };
+ };
+ Image IMAGE_COMMAND1_SMALL_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command1_small_hover_hc.png" ; };
+ };
+
+
+ Image IMAGE_COMMAND2_LARGE
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_large.png" ; };
+ };
+ Image IMAGE_COMMAND2_LARGE_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_large_hover.png" ; };
+ };
+ Image IMAGE_COMMAND2_MEDIUM
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_medium.png" ; };
+ };
+ Image IMAGE_COMMAND2_MEDIUM_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_medium_hover.png" ; };
+ };
+ Image IMAGE_COMMAND2_SMALL
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_small.png" ; };
+ };
+ Image IMAGE_COMMAND2_SMALL_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_small_hover.png" ; };
+ };
+
+ Image IMAGE_COMMAND2_LARGE_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_large_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2_LARGE_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_large_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2_MEDIUM_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_medium_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2_MEDIUM_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_medium_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2_SMALL_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_small_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2_SMALL_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2_small_hover_hc.png" ; };
+ };
+
+
+ Image IMAGE_COMMAND2B_LARGE
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_large.png" ; };
+ };
+ Image IMAGE_COMMAND2B_LARGE_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_large_hover.png" ; };
+ };
+ Image IMAGE_COMMAND2B_MEDIUM
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_medium.png" ; };
+ };
+ Image IMAGE_COMMAND2B_MEDIUM_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_medium_hover.png" ; };
+ };
+ Image IMAGE_COMMAND2B_SMALL
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_small.png" ; };
+ };
+ Image IMAGE_COMMAND2B_SMALL_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_small_hover.png" ; };
+ };
+
+ Image IMAGE_COMMAND2B_LARGE_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_large_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2B_LARGE_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_large_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2B_MEDIUM_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_medium_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2B_MEDIUM_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_medium_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2B_SMALL_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_small_hc.png" ; };
+ };
+ Image IMAGE_COMMAND2B_SMALL_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command2b_small_hover_hc.png" ; };
+ };
+
+
+ Image IMAGE_COMMAND3_LARGE
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_large.png" ; };
+ };
+ Image IMAGE_COMMAND3_LARGE_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_large_hover.png" ; };
+ };
+ Image IMAGE_COMMAND3_MEDIUM
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_medium.png" ; };
+ };
+ Image IMAGE_COMMAND3_MEDIUM_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_medium_hover.png" ; };
+ };
+ Image IMAGE_COMMAND3_SMALL
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_small.png" ; };
+ };
+ Image IMAGE_COMMAND3_SMALL_HOVER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_small_hover.png" ; };
+ };
+
+ Image IMAGE_COMMAND3_LARGE_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_large_hc.png" ; };
+ };
+ Image IMAGE_COMMAND3_LARGE_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_large_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND3_MEDIUM_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_medium_hc.png" ; };
+ };
+ Image IMAGE_COMMAND3_MEDIUM_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_medium_hover_hc.png" ; };
+ };
+ Image IMAGE_COMMAND3_SMALL_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_small_hc.png" ; };
+ };
+ Image IMAGE_COMMAND3_SMALL_HOVER_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command3_small_hover_hc.png" ; };
+ };
+
+
+ Image IMAGE_BUTTONBAR_LARGE
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_large.png" ; };
+ };
+ Image IMAGE_BUTTONBAR_MEDIUM
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_medium.png" ; };
+ };
+ Image IMAGE_BUTTONBAR_SMALL
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_small.png" ; };
+ };
+
+ Image IMAGE_BUTTONBAR_LARGE_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_large_hc.png" ; };
+ };
+ Image IMAGE_BUTTONBAR_MEDIUM_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_medium_hc.png" ; };
+ };
+ Image IMAGE_BUTTONBAR_SMALL_HC
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_command_background_small_hc.png" ; };
+ };
+
+
+
+ Image IMAGE_SHADOW
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_shadow.png" ; };
+ };
+
+ Image IMAGE_INSERT_SHADOW
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_insert_shadow.png" ; };
+ };
+
+ Image IMAGE_HIDE_SLIDE_OVERLAY
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_hide_slide_overlay.png" ; };
+ };
+
+ Image IMAGE_FOCUS_BORDER
+ {
+ ImageBitmap = Bitmap { File = "slide_sorter_focus_border.png" ; };
+ };
+
+
+ String STRING_DRAG_AND_DROP_PAGES
+ {
+ Text [ en-US ] = "Drag and Drop Pages" ;
+ };
+
+ String STRING_DRAG_AND_DROP_SLIDES
+ {
+ Text [ en-US ] = "Drag and Drop Slides" ;
+ };
+
+ String STRING_COMMAND1
+ {
+ Text [ en-US ] = "Start Slide Show" ;
+ };
+
+ String STRING_COMMAND2_A
+ {
+ Text [ en-US ] = "Hide Slide" ;
+ };
+
+ String STRING_COMMAND2_B
+ {
+ Text [ en-US ] = "Show Slide" ;
+ };
+
+ String STRING_COMMAND3
+ {
+ Text [ en-US ] = "Duplicate Slide" ;
+ };
+};
diff --git a/sd/source/ui/slidesorter/view/SlsTheme.cxx b/sd/source/ui/slidesorter/view/SlsTheme.cxx
new file mode 100644
index 000000000000..5cc06eadae04
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsTheme.cxx
@@ -0,0 +1,536 @@
+/*************************************************************************
+ *
+ * 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/SlsTheme.hxx"
+#include "SlsResource.hxx"
+#include "controller/SlsProperties.hxx"
+#include "sdresid.hxx"
+#include <tools/color.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/colorcfg.hxx>
+
+namespace sd { namespace slidesorter { namespace view {
+
+const static ColorData Black = 0x000000;
+const static ColorData White = 0xffffff;
+
+
+
+ColorData ChangeLuminance (const ColorData aColorData, const int nValue)
+{
+ Color aColor (aColorData);
+ if (nValue > 0)
+ aColor.IncreaseLuminance(nValue);
+ else
+ aColor.DecreaseLuminance(-nValue);
+ return aColor.GetColor();
+}
+
+ColorData HGBAdapt (
+ const ColorData aColorData,
+ const sal_Int32 nNewSaturation,
+ const sal_Int32 nNewBrightness)
+{
+ sal_uInt16 nHue (0);
+ sal_uInt16 nSaturation (0);
+ sal_uInt16 nBrightness (0);
+ Color(aColorData).RGBtoHSB(nHue, nSaturation, nBrightness);
+ return Color::HSBtoRGB(
+ nHue,
+ nNewSaturation>=0 ? nNewSaturation : nSaturation,
+ nNewBrightness>=0 ? nNewBrightness : nBrightness);
+}
+
+
+
+
+Theme::Theme (const ::boost::shared_ptr<controller::Properties>& rpProperties)
+ : mbIsHighContrastMode(false),
+ maBackgroundColor(rpProperties->GetBackgroundColor().GetColor()),
+ maPageBackgroundColor(COL_WHITE),
+ maGradients(),
+ maIcons(),
+ maColor(),
+ maIntegerValues()
+{
+ {
+ LocalResource aResource (RID_SLIDESORTER_ICONS);
+
+ maStrings.resize(_StringType_Size_);
+ maStrings[String_DragAndDropPages] = String(SdResId(STRING_DRAG_AND_DROP_PAGES));
+ maStrings[String_DragAndDropSlides] = String(SdResId(STRING_DRAG_AND_DROP_SLIDES));
+ maStrings[String_Command1] = String(SdResId(STRING_COMMAND1));
+ maStrings[String_Command2] = String(SdResId(STRING_COMMAND2_A));
+ maStrings[String_Command2B] = String(SdResId(STRING_COMMAND2_B));
+ maStrings[String_Command3] = String(SdResId(STRING_COMMAND3));
+
+ maColor.resize(_ColorType_Size_);
+ maColor[Color_Background] = maBackgroundColor;
+ maColor[Color_ButtonBackground] = Black;
+ maColor[Color_ButtonText] = 0xc0c0c0;
+ maColor[Color_ButtonTextHover] = White;
+ maColor[Color_PageNumberDefault] = 0x0808080;
+ maColor[Color_PageNumberHover] = 0x4c4c4c;
+ maColor[Color_PageNumberHighContrast] = White;
+ maColor[Color_PageNumberBrightBackground] = 0x333333;
+ maColor[Color_PageNumberDarkBackground] = 0xcccccc;
+ maColor[Color_PreviewBorder] = 0x949599;
+
+ maIntegerValues.resize(_IntegerValueType_Size_);
+ maIntegerValues[Integer_ButtonCornerRadius] = 3;
+ maIntegerValues[Integer_ButtonMaxAlpha] = 0;
+ maIntegerValues[Integer_ButtonBarMaxAlpha] = 0;
+ maIntegerValues[Integer_ButtonPaintType] = 1;
+ maIntegerValues[Integer_ButtonBorder] = 4;
+ maIntegerValues[Integer_ButtonGap] = 0;
+ maIntegerValues[Integer_ButtonFadeInDelay] = 800;
+ maIntegerValues[Integer_ButtonFadeInDuration] = 100;
+ maIntegerValues[Integer_ButtonFadeOutDelay] = 0;
+ maIntegerValues[Integer_ButtonFadeOutDuration] = 100;
+ maIntegerValues[Integer_ToolTipDelay] = 1000;
+ maIntegerValues[Integer_FocusIndicatorWidth] = 3;
+ }
+
+ Update(rpProperties);
+}
+
+
+
+
+void Theme::Update (const ::boost::shared_ptr<controller::Properties>& rpProperties)
+{
+ const bool bSavedHighContrastMode (mbIsHighContrastMode);
+ mbIsHighContrastMode = rpProperties->IsHighContrastModeActive();
+
+ // Set up colors.
+ maBackgroundColor = rpProperties->GetBackgroundColor().GetColor();
+ maPageBackgroundColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
+
+ maColor[Color_Background] = maBackgroundColor;
+
+ maGradients.resize(_GradientColorType_Size_);
+
+ maColor[Color_Background] = maBackgroundColor;
+ const ColorData aSelectionColor (rpProperties->GetSelectionColor().GetColor());
+ maColor[Color_Selection] = aSelectionColor;
+ if (Color(aSelectionColor).IsBright())
+ maColor[Color_PageCountFontColor] = Black;
+ else
+ maColor[Color_PageCountFontColor] = White;
+
+ // Set up gradients.
+ SetGradient(Gradient_SelectedPage, aSelectionColor, 50, 50, +100,+100, +50,+25);
+ SetGradient(Gradient_MouseOverPage, aSelectionColor, 75, 75, +100,+100, +50,+25);
+ SetGradient(Gradient_SelectedAndFocusedPage, aSelectionColor, 50, 50, +100,+100, -50,-75);
+ SetGradient(Gradient_MouseOverSelectedAndFocusedPage, aSelectionColor, 75, 75, +100,+100, -50,-75);
+ SetGradient(Gradient_FocusedPage, aSelectionColor, -1,-1, 0,0, -50,-75);
+
+ SetGradient(Gradient_ButtonBackground, Black, -1,-1, 0,0, 0,0);
+ SetGradient(Gradient_NormalPage, maBackgroundColor, -1,-1, 0,0, 0,0);
+
+ // The focused gradient needs special handling because its fill color is
+ // like that of the NormalPage gradient.
+ GetGradient(Gradient_FocusedPage).maFillColor1 = GetGradient(Gradient_NormalPage).maFillColor1;
+ GetGradient(Gradient_FocusedPage).maFillColor2 = GetGradient(Gradient_NormalPage).maFillColor2;
+
+ // Set up icons.
+ if (bSavedHighContrastMode != mbIsHighContrastMode || maIcons.empty())
+ {
+ LocalResource aResource (RID_SLIDESORTER_ICONS);
+
+ maIcons.resize(_IconType_Size_);
+ if (mbIsHighContrastMode)
+ {
+ InitializeIcon(Icon_RawShadow, IMAGE_SHADOW);
+ InitializeIcon(Icon_RawInsertShadow, IMAGE_INSERT_SHADOW);
+ InitializeIcon(Icon_HideSlideOverlay, IMAGE_HIDE_SLIDE_OVERLAY);
+
+ InitializeIcon(Icon_ButtonBarLarge, IMAGE_BUTTONBAR_LARGE_HC);
+ InitializeIcon(Icon_ButtonBarMedium, IMAGE_BUTTONBAR_MEDIUM_HC);
+ InitializeIcon(Icon_ButtonBarSmall, IMAGE_BUTTONBAR_SMALL_HC);
+
+ InitializeIcon(Icon_Command1Large, IMAGE_COMMAND1_LARGE_HC);
+ InitializeIcon(Icon_Command1LargeHover, IMAGE_COMMAND1_LARGE_HOVER_HC);
+ InitializeIcon(Icon_Command1Medium, IMAGE_COMMAND1_MEDIUM_HC);
+ InitializeIcon(Icon_Command1MediumHover, IMAGE_COMMAND1_MEDIUM_HOVER_HC);
+ InitializeIcon(Icon_Command1Small, IMAGE_COMMAND1_SMALL_HC);
+ InitializeIcon(Icon_Command1SmallHover, IMAGE_COMMAND1_SMALL_HOVER_HC);
+
+ InitializeIcon(Icon_Command2Large, IMAGE_COMMAND2_LARGE_HC);
+ InitializeIcon(Icon_Command2LargeHover, IMAGE_COMMAND2_LARGE_HOVER_HC);
+ InitializeIcon(Icon_Command2Medium, IMAGE_COMMAND2_MEDIUM_HC);
+ InitializeIcon(Icon_Command2MediumHover, IMAGE_COMMAND2_MEDIUM_HOVER_HC);
+ InitializeIcon(Icon_Command2Small, IMAGE_COMMAND2_SMALL_HC);
+ InitializeIcon(Icon_Command2SmallHover, IMAGE_COMMAND2_SMALL_HOVER_HC);
+
+ InitializeIcon(Icon_Command2BLarge, IMAGE_COMMAND2B_LARGE_HC);
+ InitializeIcon(Icon_Command2BLargeHover, IMAGE_COMMAND2B_LARGE_HOVER_HC);
+ InitializeIcon(Icon_Command2BMedium, IMAGE_COMMAND2B_MEDIUM_HC);
+ InitializeIcon(Icon_Command2BMediumHover, IMAGE_COMMAND2B_MEDIUM_HOVER_HC);
+ InitializeIcon(Icon_Command2BSmall, IMAGE_COMMAND2B_SMALL_HC);
+ InitializeIcon(Icon_Command2BSmallHover, IMAGE_COMMAND2B_SMALL_HOVER_HC);
+
+ InitializeIcon(Icon_Command3Large, IMAGE_COMMAND3_LARGE_HC);
+ InitializeIcon(Icon_Command3LargeHover, IMAGE_COMMAND3_LARGE_HOVER_HC);
+ InitializeIcon(Icon_Command3Medium, IMAGE_COMMAND3_SMALL_HC);
+ InitializeIcon(Icon_Command3MediumHover, IMAGE_COMMAND3_SMALL_HOVER_HC);
+ InitializeIcon(Icon_Command3Small, IMAGE_COMMAND3_SMALL_HC);
+ InitializeIcon(Icon_Command3SmallHover, IMAGE_COMMAND3_SMALL_HOVER_HC);
+ }
+ else
+ {
+ InitializeIcon(Icon_RawShadow, IMAGE_SHADOW);
+ InitializeIcon(Icon_RawInsertShadow, IMAGE_INSERT_SHADOW);
+ InitializeIcon(Icon_HideSlideOverlay, IMAGE_HIDE_SLIDE_OVERLAY);
+
+ InitializeIcon(Icon_ButtonBarLarge, IMAGE_BUTTONBAR_LARGE);
+ InitializeIcon(Icon_ButtonBarMedium, IMAGE_BUTTONBAR_MEDIUM);
+ InitializeIcon(Icon_ButtonBarSmall, IMAGE_BUTTONBAR_SMALL);
+
+ InitializeIcon(Icon_Command1Large, IMAGE_COMMAND1_LARGE);
+ InitializeIcon(Icon_Command1LargeHover, IMAGE_COMMAND1_LARGE_HOVER);
+ InitializeIcon(Icon_Command1Medium, IMAGE_COMMAND1_MEDIUM);
+ InitializeIcon(Icon_Command1MediumHover, IMAGE_COMMAND1_MEDIUM_HOVER);
+ InitializeIcon(Icon_Command1Small, IMAGE_COMMAND1_SMALL);
+ InitializeIcon(Icon_Command1SmallHover, IMAGE_COMMAND1_SMALL_HOVER);
+
+ InitializeIcon(Icon_Command2Large, IMAGE_COMMAND2_LARGE);
+ InitializeIcon(Icon_Command2LargeHover, IMAGE_COMMAND2_LARGE_HOVER);
+ InitializeIcon(Icon_Command2Medium, IMAGE_COMMAND2_MEDIUM);
+ InitializeIcon(Icon_Command2MediumHover, IMAGE_COMMAND2_MEDIUM_HOVER);
+ InitializeIcon(Icon_Command2Small, IMAGE_COMMAND2_SMALL);
+ InitializeIcon(Icon_Command2SmallHover, IMAGE_COMMAND2_SMALL_HOVER);
+
+ InitializeIcon(Icon_Command2BLarge, IMAGE_COMMAND2B_LARGE);
+ InitializeIcon(Icon_Command2BLargeHover, IMAGE_COMMAND2B_LARGE_HOVER);
+ InitializeIcon(Icon_Command2BMedium, IMAGE_COMMAND2B_MEDIUM);
+ InitializeIcon(Icon_Command2BMediumHover, IMAGE_COMMAND2B_MEDIUM_HOVER);
+ InitializeIcon(Icon_Command2BSmall, IMAGE_COMMAND2B_SMALL);
+ InitializeIcon(Icon_Command2BSmallHover, IMAGE_COMMAND2B_SMALL_HOVER);
+
+ InitializeIcon(Icon_Command3Large, IMAGE_COMMAND3_LARGE);
+ InitializeIcon(Icon_Command3LargeHover, IMAGE_COMMAND3_LARGE_HOVER);
+ InitializeIcon(Icon_Command3Medium, IMAGE_COMMAND3_MEDIUM);
+ InitializeIcon(Icon_Command3MediumHover, IMAGE_COMMAND3_MEDIUM_HOVER);
+ InitializeIcon(Icon_Command3Small, IMAGE_COMMAND3_SMALL);
+ InitializeIcon(Icon_Command3SmallHover, IMAGE_COMMAND3_SMALL_HOVER);
+ }
+ InitializeIcon(Icon_FocusBorder, IMAGE_FOCUS_BORDER);
+ }
+}
+
+
+
+
+::boost::shared_ptr<Font> Theme::GetFont (
+ const FontType eType,
+ const OutputDevice& rDevice)
+{
+ ::boost::shared_ptr<Font> pFont;
+
+ switch (eType)
+ {
+ case Font_PageNumber:
+ pFont.reset(new Font(Application::GetSettings().GetStyleSettings().GetAppFont()));
+ pFont->SetTransparent(sal_True);
+ pFont->SetWeight(WEIGHT_BOLD);
+ break;
+
+ case Font_PageCount:
+ pFont.reset(new Font(Application::GetSettings().GetStyleSettings().GetAppFont()));
+ pFont->SetTransparent(sal_True);
+ pFont->SetWeight(WEIGHT_NORMAL);
+ {
+ const Size aSize (pFont->GetSize());
+ pFont->SetSize(Size(aSize.Width()*5/3, aSize.Height()*5/3));
+ }
+ break;
+
+ case Font_Button:
+ pFont.reset(new Font(Application::GetSettings().GetStyleSettings().GetAppFont()));
+ pFont->SetTransparent(sal_True);
+ pFont->SetWeight(WEIGHT_BOLD);
+ {
+ const Size aSize (pFont->GetSize());
+ pFont->SetSize(Size(aSize.Width()*4/3, aSize.Height()*4/3));
+ }
+ break;
+ }
+
+ if (pFont)
+ {
+ // Transform the point size to pixel size.
+ const MapMode aFontMapMode (MAP_POINT);
+ const Size aFontSize (rDevice.LogicToPixel(pFont->GetSize(), aFontMapMode));
+
+ // Transform the font size to the logical coordinates of the device.
+ pFont->SetSize(rDevice.PixelToLogic(aFontSize));
+ }
+
+ return pFont;
+}
+
+
+
+
+ColorData Theme::GetColor (const ColorType eType)
+{
+ if (eType>=0 && sal_uInt32(eType)<maColor.size())
+ return maColor[eType];
+ else
+ return 0;
+}
+
+
+
+
+void Theme::SetColor (
+ const ColorType eType,
+ const ColorData aData)
+{
+ if (eType>=0 && sal_uInt32(eType)<maColor.size())
+ maColor[eType] = aData;
+}
+
+
+
+
+ColorData Theme::GetGradientColor (
+ const GradientColorType eType,
+ const GradientColorClass eClass)
+{
+ GradientDescriptor& rDescriptor (GetGradient(eType));
+
+ switch (eClass)
+ {
+ case Border1: return rDescriptor.maBorderColor1;
+ case Border2: return rDescriptor.maBorderColor2;
+ case Fill1: return rDescriptor.maFillColor1;
+ case Fill2: return rDescriptor.maFillColor2;
+ default: OSL_ASSERT(false); // fall through
+ case Base: return rDescriptor.maBaseColor;
+ }
+}
+
+
+
+
+sal_Int32 Theme::GetGradientOffset (
+ const GradientColorType eType,
+ const GradientColorClass eClass)
+{
+ GradientDescriptor& rDescriptor (GetGradient(eType));
+
+ switch (eClass)
+ {
+ case Border1: return rDescriptor.mnBorderOffset1;
+ case Border2: return rDescriptor.mnBorderOffset2;
+ case Fill1: return rDescriptor.mnFillOffset1;
+ case Fill2: return rDescriptor.mnFillOffset2;
+ default: OSL_ASSERT(false); // fall through
+ case Base: return 0;
+ }
+}
+
+
+
+
+void Theme::SetGradient (
+ const GradientColorType eType,
+ const ColorData aBaseColor,
+ const sal_Int32 nSaturationOverride,
+ const sal_Int32 nBrightnessOverride,
+ const sal_Int32 nFillStartOffset,
+ const sal_Int32 nFillEndOffset,
+ const sal_Int32 nBorderStartOffset,
+ const sal_Int32 nBorderEndOffset)
+{
+ GradientDescriptor& rGradient (GetGradient(eType));
+
+ rGradient.maBaseColor = aBaseColor;
+
+ rGradient.mnSaturationOverride = nSaturationOverride;
+ rGradient.mnBrightnessOverride = nBrightnessOverride;
+ const ColorData aColor (nSaturationOverride>=0 || nBrightnessOverride>=0
+ ? HGBAdapt(aBaseColor, nSaturationOverride, nBrightnessOverride)
+ : aBaseColor);
+
+ rGradient.maFillColor1 = ChangeLuminance(aColor, nFillStartOffset);
+ rGradient.maFillColor2 = ChangeLuminance(aColor, nFillEndOffset);
+ rGradient.maBorderColor1 = ChangeLuminance(aColor, nBorderStartOffset);
+ rGradient.maBorderColor2 = ChangeLuminance(aColor, nBorderEndOffset);
+
+ rGradient.mnFillOffset1 = nFillStartOffset;
+ rGradient.mnFillOffset2 = nFillEndOffset;
+ rGradient.mnBorderOffset1 = nBorderStartOffset;
+ rGradient.mnBorderOffset2 = nBorderEndOffset;
+}
+
+
+
+
+sal_Int32 Theme::GetGradientSaturationOverride (const GradientColorType eType)
+{
+ GradientDescriptor& rGradient (GetGradient(eType));
+ return rGradient.mnSaturationOverride;
+}
+
+
+
+
+sal_Int32 Theme::GetGradientBrightnessOverride (const GradientColorType eType)
+{
+ GradientDescriptor& rGradient (GetGradient(eType));
+ return rGradient.mnBrightnessOverride;
+}
+
+
+
+
+void Theme::SetGradientSaturationOverride (const GradientColorType eType, const sal_Int32 nValue)
+{
+ GradientDescriptor& rGradient (GetGradient(eType));
+ SetGradient(
+ eType,
+ rGradient.maBaseColor,
+ nValue,
+ rGradient.mnBrightnessOverride,
+ rGradient.mnFillOffset1,
+ rGradient.mnFillOffset2,
+ rGradient.mnBorderOffset1,
+ rGradient.mnBorderOffset2);
+}
+
+
+
+
+void Theme::SetGradientBrightnessOverride (const GradientColorType eType, const sal_Int32 nValue)
+{
+ GradientDescriptor& rGradient (GetGradient(eType));
+ SetGradient(eType,
+ rGradient.maBaseColor,
+ rGradient.mnSaturationOverride,
+ nValue,
+ rGradient.mnFillOffset1,
+ rGradient.mnFillOffset2,
+ rGradient.mnBorderOffset1,
+ rGradient.mnBorderOffset2);
+}
+
+
+
+
+const BitmapEx& Theme::GetIcon (const IconType eType)
+{
+ if (eType>=0 && size_t(eType)<maIcons.size())
+ return maIcons[eType];
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maIcons.size());
+ return maIcons[0];
+ }
+}
+
+
+
+
+sal_Int32 Theme::GetIntegerValue (const IntegerValueType eType) const
+{
+ if (eType>=0 && size_t(eType)<maIntegerValues.size())
+ return maIntegerValues[eType];
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maIntegerValues.size());
+ return 0;
+ }
+}
+
+
+
+
+void Theme::SetIntegerValue (const IntegerValueType eType, const sal_Int32 nValue)
+{
+ if (eType>=0 && size_t(eType)<maIntegerValues.size())
+ maIntegerValues[eType] = nValue;
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maIntegerValues.size());
+ }
+}
+
+
+
+
+::rtl::OUString Theme::GetString (const StringType eType) const
+{
+ if (eType>=0 && size_t(eType)<maStrings.size())
+ return maStrings[eType];
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maStrings.size());
+ return ::rtl::OUString();
+ }
+}
+
+
+
+
+Theme::GradientDescriptor& Theme::GetGradient (const GradientColorType eType)
+{
+ if (eType>=0 && size_t(eType)<maGradients.size())
+ return maGradients[eType];
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maGradients.size());
+ return maGradients[0];
+ }
+}
+
+
+
+
+void Theme::InitializeIcon (const IconType eType, sal_uInt16 nResourceId)
+{
+ if (eType>=0 && size_t(eType)<maIcons.size())
+ {
+ const BitmapEx aIcon (Image(SdResId(nResourceId)).GetBitmapEx());
+ maIcons[eType] = aIcon;
+ }
+ else
+ {
+ OSL_ASSERT(eType>=0 && size_t(eType)<maIcons.size());
+ }
+}
+
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsToolTip.cxx b/sd/source/ui/slidesorter/view/SlsToolTip.cxx
new file mode 100644
index 000000000000..211760ef2002
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsToolTip.cxx
@@ -0,0 +1,230 @@
+/*************************************************************************
+ *
+ * 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/SlsToolTip.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsTheme.hxx"
+#include "sdpage.hxx"
+#include "sdresid.hxx"
+#include "glob.hrc"
+#include <vcl/help.hxx>
+
+using ::rtl::OUString;
+
+namespace sd { namespace slidesorter { namespace view {
+
+ToolTip::ToolTip (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ msDefaultHelpText(),
+ msCurrentHelpText(),
+ mnHelpWindowHandle(0),
+ maTimer()
+{
+ maTimer.SetTimeout(rSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ToolTipDelay));
+ maTimer.SetTimeoutHdl(LINK(this, ToolTip, DelayTrigger));
+}
+
+
+
+
+ToolTip::~ToolTip (void)
+{
+ maTimer.Stop();
+ Hide();
+}
+
+
+
+
+void ToolTip::SetPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (mpDescriptor != rpDescriptor)
+ {
+ maTimer.Stop();
+ Hide();
+
+ mpDescriptor = rpDescriptor;
+
+ if (mpDescriptor)
+ {
+ SdPage* pPage = mpDescriptor->GetPage();
+ OUString sHelpText;
+ if (pPage != NULL)
+ sHelpText = pPage->GetName();
+ else
+ {
+ OSL_ASSERT(mpDescriptor->GetPage() != NULL);
+ }
+ if (sHelpText.getLength() == 0)
+ {
+ sHelpText = String(SdResId(STR_PAGE));
+ sHelpText += String::CreateFromInt32(mpDescriptor->GetPageIndex()+1);
+ }
+
+ msDefaultHelpText = sHelpText;
+ msCurrentHelpText = sHelpText;
+ Show(false);
+ }
+ else
+ {
+ msDefaultHelpText = OUString();
+ msCurrentHelpText = OUString();
+ }
+ }
+}
+
+
+
+
+void ToolTip::ShowDefaultHelpText (const ::rtl::OUString& rsHelpText)
+{
+ if (msDefaultHelpText != rsHelpText)
+ {
+ const bool bIsVisible (Hide());
+
+ msDefaultHelpText = rsHelpText;
+ msCurrentHelpText = rsHelpText;
+
+ Show(bIsVisible);
+ }
+}
+
+
+
+
+void ToolTip::ShowDefaultHelpText (void)
+{
+ if (msCurrentHelpText != msDefaultHelpText)
+ {
+ const bool bIsVisible (Hide());
+
+ msCurrentHelpText = msDefaultHelpText;
+
+ Show(bIsVisible);
+ }
+}
+
+
+
+
+void ToolTip::ShowHelpText (const ::rtl::OUString& rsHelpText)
+{
+ if (msCurrentHelpText != rsHelpText)
+ {
+ const bool bIsVisible (Hide());
+
+ msCurrentHelpText = rsHelpText;
+
+ Show(bIsVisible);
+ }
+}
+
+
+
+
+void ToolTip::Show (const bool bNoDelay)
+{
+ if (bNoDelay)
+ DoShow();
+ else
+ maTimer.Start();
+}
+
+
+
+
+void ToolTip::DoShow (void)
+{
+ if (maTimer.IsActive())
+ {
+ // The delay timer is active. Wait for it to trigger the showing of
+ // the tool tip.
+ return;
+ }
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (msCurrentHelpText.getLength()>0 && pWindow)
+ {
+ Rectangle aBox (
+ mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
+ mpDescriptor,
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::WindowCoordinateSystem));
+
+ // Do not show the help text when the (lower edge of the ) preview
+ // is not visible. The tool tip itself may still be outside the
+ // window.
+ if (aBox.Bottom() >= pWindow->GetSizePixel().Height())
+ return;
+
+ ::Window* pParent (pWindow.get());
+ while (pParent!=NULL && pParent->GetParent()!=NULL)
+ pParent = pParent->GetParent();
+ const Point aOffset (pWindow->GetWindowExtentsRelative(pParent).TopLeft());
+
+ // We do not know how high the tool tip will be but want its top
+ // edge not its bottom to be at a specific position (a little below
+ // the preview). Therefore we use a little trick and place the tool
+ // tip at the top of a rectangle that is placed below the preview.
+ aBox.Move(aOffset.X(), aOffset.Y() + aBox.GetHeight() + 3);
+ mnHelpWindowHandle = Help::ShowTip(
+ pWindow.get(),
+ aBox,
+ msCurrentHelpText,
+ QUICKHELP_CENTER | QUICKHELP_TOP);
+ }
+}
+
+
+
+
+bool ToolTip::Hide (void)
+{
+ if (mnHelpWindowHandle>0)
+ {
+ Help::HideTip(mnHelpWindowHandle);
+ mnHelpWindowHandle = 0;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+IMPL_LINK(ToolTip, DelayTrigger, void*, EMPTYARG)
+{
+ DoShow();
+
+ return 0;
+}
+
+} } } // end of namespace ::sd::slidesorter::view
diff --git a/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx b/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx
new file mode 100644
index 000000000000..76da9c1a4f15
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsViewCacheContext.cxx
@@ -0,0 +1,162 @@
+/* -*- 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 "SlsViewCacheContext.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "view/SlideSorterView.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 (SlideSorter& rSlideSorter)
+ : mrModel(rSlideSorter.GetModel()),
+ mrSlideSorter(rSlideSorter)
+{
+}
+
+
+
+
+ViewCacheContext::~ViewCacheContext (void)
+{
+}
+
+
+
+
+void ViewCacheContext::NotifyPreviewCreation (
+ cache::CacheKey aKey,
+ const Bitmap&)
+{
+ const model::SharedPageDescriptor pDescriptor (GetDescriptor(aKey));
+ if (pDescriptor.get() != NULL)
+ {
+ // Force a repaint that will trigger their re-creation.
+ mrSlideSorter.GetView().RequestRepaint(pDescriptor);
+ }
+ else
+ {
+ OSL_ASSERT(pDescriptor);
+ }
+}
+
+
+
+
+bool ViewCacheContext::IsIdle (void)
+{
+ sal_Int32 nIdleState (tools::IdleDetection::GetIdleState(mrSlideSorter.GetContentWindow().get()));
+ if (nIdleState == tools::IdleDetection::IDET_IDLE)
+ return true;
+ else
+ return false;
+}
+
+
+
+
+bool ViewCacheContext::IsVisible (cache::CacheKey aKey)
+{
+ const model::SharedPageDescriptor pDescriptor (GetDescriptor(aKey));
+ return pDescriptor && pDescriptor->HasState(model::PageDescriptor::ST_Visible);
+}
+
+
+
+
+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..886e36c82210
--- /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 {
+class SlideSorter;
+} }
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** 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 (SlideSorter& rSlideSorter);
+ virtual ~ViewCacheContext (void);
+ virtual void NotifyPreviewCreation (cache::CacheKey aKey, const Bitmap& 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;
+ SlideSorter& mrSlideSorter;
+
+ 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/makefile.mk b/sd/source/ui/slidesorter/view/makefile.mk
new file mode 100755
index 000000000000..3c5fc39c3ede
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/makefile.mk
@@ -0,0 +1,69 @@
+#*************************************************************************
+#
+# 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=..$/..
+
+IMGLST_SRS=$(SRS)$/$(TARGET).srs
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SRS1NAME=$(TARGET)
+SRC1FILES = \
+ SlsResource.src
+
+SLOFILES = \
+ $(SLO)$/SlideSorterView.obj \
+ $(SLO)$/SlsButtonBar.obj \
+ $(SLO)$/SlsFontProvider.obj \
+ $(SLO)$/SlsFramePainter.obj \
+ $(SLO)$/SlsInsertAnimator.obj \
+ $(SLO)$/SlsInsertionIndicatorOverlay.obj\
+ $(SLO)$/SlsLayeredDevice.obj \
+ $(SLO)$/SlsLayouter.obj \
+ $(SLO)$/SlsPageObjectLayouter.obj \
+ $(SLO)$/SlsPageObjectPainter.obj \
+ $(SLO)$/SlsTheme.obj \
+ $(SLO)$/SlsToolTip.obj \
+ $(SLO)$/SlsViewCacheContext.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+