diff options
author | Andre Fischer <af@openoffice.org> | 2010-02-12 13:58:24 +0100 |
---|---|---|
committer | Andre Fischer <af@openoffice.org> | 2010-02-12 13:58:24 +0100 |
commit | ab518ae9111d251a4e6267ae9f40836b8a7a3913 (patch) | |
tree | a283642af55ae4f76dbb28ab09fba62627257b01 /sd/source/ui | |
parent | 2336af0eb45bee98f98b0ac9a6988bfd0e6193e5 (diff) |
renaissance1: #i107215# Adaption to latest changes of the spec.
Diffstat (limited to 'sd/source/ui')
40 files changed, 1824 insertions, 639 deletions
diff --git a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx index 1169795139db..5b00b7da303b 100644 --- a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx +++ b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx @@ -809,10 +809,9 @@ AccessibleSlideSorterView::Implementation::~Implementation (void) void AccessibleSlideSorterView::Implementation::UpdateVisibility (void) { - ::sd::slidesorter::view::SlideSorterView::PageRange aRange ( - mrSlideSorter.GetView().GetVisiblePageRange()); - mnFirstVisibleChild = aRange.first; - mnLastVisibleChild = aRange.second; + Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange()); + mnFirstVisibleChild = aRange.A(); + mnLastVisibleChild = aRange.B(); } @@ -850,7 +849,7 @@ void AccessibleSlideSorterView::Implementation::Clear (void) sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount (void) const { - if (mnFirstVisibleChild <= mnLastVisibleChild) + if (mnFirstVisibleChild <= mnLastVisibleChild && mnFirstVisibleChild>=0) return mnLastVisibleChild - mnFirstVisibleChild + 1; else return 0; diff --git a/sd/source/ui/inc/SlideSorter.hxx b/sd/source/ui/inc/SlideSorter.hxx index 3e2c69232fe3..49869d807848 100644 --- a/sd/source/ui/inc/SlideSorter.hxx +++ b/sd/source/ui/inc/SlideSorter.hxx @@ -33,12 +33,15 @@ #define SD_SLIDESORTER_SLIDE_SORTER_HXX #include "fupoor.hxx" +#include "Window.hxx" #include <com/sun/star/frame/XController.hpp> #include <cppuhelper/weakref.hxx> #include <sfx2/viewfrm.hxx> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> #include <boost/scoped_ptr.hpp> +#include <boost/current_function.hpp> + class ScrollBar; class ScrollBarBox; @@ -57,6 +60,7 @@ class SlideSorterModel; namespace sd { namespace slidesorter { namespace view { class SlideSorterView; +class Theme; } } } namespace sd { namespace slidesorter { namespace controller { @@ -67,6 +71,9 @@ class Properties; } } } +typedef ::boost::shared_ptr<sd::Window> SharedSdWindow; + + namespace sd { namespace slidesorter { /** Show previews for all the slides in a document and allow the user to @@ -144,7 +151,7 @@ public: /** Return the content window. This is a sibling and is geometrically enclosed by the scroll bars. */ - ::boost::shared_ptr<sd::Window> GetContentWindow (void) const; + SharedSdWindow GetContentWindow (void) const; model::SlideSorterModel& GetModel (void) const; @@ -193,6 +200,8 @@ public: */ ::boost::shared_ptr<controller::Properties> GetProperties (void) const; + ::boost::shared_ptr<view::Theme> GetTheme (void) const; + protected: /** This virtual method makes it possible to create a specialization of the slide sorter view shell that works with its own implementation @@ -229,7 +238,8 @@ private: ::com::sun::star::uno::WeakReference<com::sun::star::frame::XController> mxControllerWeak; ViewShell* mpViewShell; ViewShellBase* mpViewShellBase; - ::boost::shared_ptr<sd::Window> mpContentWindow; + SharedSdWindow mpContentWindow; + bool mbOwnesContentWindow; ::boost::shared_ptr<ScrollBar> mpHorizontalScrollBar; ::boost::shared_ptr<ScrollBar> mpVerticalScrollBar; ::boost::shared_ptr<ScrollBarBox> mpScrollBarBox; @@ -242,6 +252,7 @@ private: classes. */ ::boost::shared_ptr<controller::Properties> mpProperties; + ::boost::shared_ptr<view::Theme> mpTheme; SlideSorter ( ViewShell& rViewShell, diff --git a/sd/source/ui/inc/SlideSorterViewShell.hxx b/sd/source/ui/inc/SlideSorterViewShell.hxx index 42eacb552e9e..c861af9dfa21 100644 --- a/sd/source/ui/inc/SlideSorterViewShell.hxx +++ b/sd/source/ui/inc/SlideSorterViewShell.hxx @@ -129,6 +129,8 @@ public: */ virtual void ArrangeGUIElements (void); + virtual bool HandleScrollCommand (const CommandEvent& rEvent, ::sd::Window* pWindow); + //===== Drag and Drop ===================================================== virtual void StartDrag ( diff --git a/sd/source/ui/inc/ViewShell.hxx b/sd/source/ui/inc/ViewShell.hxx index 395566f0cded..84587e6464a3 100644 --- a/sd/source/ui/inc/ViewShell.hxx +++ b/sd/source/ui/inc/ViewShell.hxx @@ -216,7 +216,7 @@ public: virtual BOOL RequestHelp( const HelpEvent& rEvt, ::sd::Window* pWin ); virtual long Notify( NotifyEvent& rNEvt, ::sd::Window* pWin ); - BOOL HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin); + virtual bool HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin); virtual void Draw(OutputDevice &rDev, const Region &rReg); diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx index 82575d0bce11..519acebe1526 100644 --- a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx +++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.cxx @@ -42,6 +42,10 @@ #include <svx/svdtypes.hxx> #include <svx/svdpage.hxx> #include <vcl/bitmapex.hxx> +#include <vcl/bmpacc.hxx> + + +const static sal_Int32 gnSuperSampleFactor (2); namespace sd { namespace slidesorter { namespace view { class SlideSorterView; @@ -51,7 +55,8 @@ class PageObjectViewObjectContact; namespace sd { namespace slidesorter { namespace cache { BitmapFactory::BitmapFactory (void) - : maRenderer(NULL, false) + : maRenderer(NULL, false), + mbRemoveBorder(true) { } @@ -71,17 +76,57 @@ BitmapFactory::~BitmapFactory (void) const bool bDoSuperSampling) { Size aSize (rPixelSize); - if (bDoSuperSampling) + bool bDo (true); + if (bDo) + { + aSize.Width() *= gnSuperSampleFactor; + aSize.Height() *= gnSuperSampleFactor; + } + if (mbRemoveBorder) { - aSize.Width() *= 2; - aSize.Height() *= 2; + aSize.Width() += 2; + aSize.Height() += 2; } const Image aPreview (maRenderer.RenderPage (&rPage, aSize, String())); ::boost::shared_ptr<BitmapEx> pPreview (new BitmapEx(aPreview.GetBitmapEx())); - if (bDoSuperSampling) + if (mbRemoveBorder) + pPreview->Crop(Rectangle(1,1,aSize.Width()-2,aSize.Height()-2)); + if (bDo) + { +#if 1 + const sal_Int32 nSuperSampleCount (gnSuperSampleFactor * gnSuperSampleFactor); + BitmapReadAccess* pRA = pPreview->GetBitmap().AcquireReadAccess(); + Bitmap aBitmap (rPixelSize, pPreview->GetBitCount()); + BitmapWriteAccess* pWA = aBitmap.AcquireWriteAccess(); + const sal_Int32 nWidth (pRA->Width()); + const sal_Int32 nHeight (pRA->Height()); + for (sal_Int32 nY=0; nY<nHeight; nY+=gnSuperSampleFactor) + for (sal_Int32 nX=0; nX<nWidth; nX+=gnSuperSampleFactor) + { + sal_Int32 nRed (0); + sal_Int32 nGreen (0); + sal_Int32 nBlue (0); + for (sal_Int32 nV=0; nV<gnSuperSampleFactor; ++nV) + for (sal_Int32 nU=0; nU<gnSuperSampleFactor; ++nU) + { + const BitmapColor aColor (pRA->GetColor(nY+nV, nX+nU)); + nRed += aColor.GetRed(); + nGreen += aColor.GetGreen(); + nBlue += aColor.GetBlue(); + } + pWA->SetPixel(nY/gnSuperSampleFactor, nX/gnSuperSampleFactor, + BitmapColor( + nRed/nSuperSampleCount, + nGreen/nSuperSampleCount, + nBlue/nSuperSampleCount)); + } + pPreview.reset(new BitmapEx(aBitmap)); +#else pPreview->Scale(rPixelSize, BMP_SCALE_INTERPOLATE); +#endif + } return pPreview; } diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx index 51d7d1c60f1b..6da0aabfe3d2 100644 --- a/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx +++ b/sd/source/ui/slidesorter/cache/SlsBitmapFactory.hxx @@ -61,6 +61,7 @@ public: private: PreviewRenderer maRenderer; + const bool mbRemoveBorder; }; diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx index e47e934a47b9..8ee0f748fcd3 100644 --- a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx +++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx @@ -131,7 +131,7 @@ SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter) mnPaintEntranceCount(0), mbIsContextMenuOpen(false) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); OSL_ASSERT(pWindow); if (pWindow) { @@ -156,8 +156,6 @@ SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter) void SlideSorterController::Init (void) { - mrView.HandleModelChange(); - mpCurrentSlideManager.reset(new CurrentSlideManager(mrSlideSorter)); mpPageSelector.reset(new PageSelector(mrSlideSorter)); mpFocusManager.reset(new FocusManager(mrSlideSorter)); @@ -208,6 +206,7 @@ SlideSorterController::~SlideSorterController (void) void SlideSorterController::Dispose (void) { + mpInsertionIndicatorHandler->End(); mpAnimator->Dispose(); } @@ -554,7 +553,7 @@ void SlideSorterController::PostModelChange (void) mbPostModelChangePending = false; mrModel.Resync(); - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { GetCurrentSlideManager()->HandleModelChange(); @@ -601,7 +600,7 @@ IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent*, pEvent) if (pEvent != NULL) { ::Window* pWindow = pEvent->GetWindow(); - ::boost::shared_ptr<sd::Window> pActiveWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pActiveWindow (mrSlideSorter.GetContentWindow()); switch (pEvent->GetId()) { case VCLEVENT_WINDOW_ACTIVATE: @@ -777,7 +776,7 @@ Rectangle SlideSorterController::Rearrange (bool bForce) { Rectangle aNewContentArea (maTotalWindowArea); - const ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { // Place the scroll bars. @@ -813,7 +812,7 @@ Rectangle SlideSorterController::Rearrange (bool bForce) void SlideSorterController::SetZoom (long int nZoom) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); long int nCurrentZoom ((long int)( pWindow->GetMapMode().GetScaleX().operator double() * 100)); @@ -960,7 +959,7 @@ void SlideSorterController::PageNameHasChanged (int nPageIndex, const String& rs // that of the name change. do { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if ( ! pWindow) break; diff --git a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx index dff12bda7f3e..69be776179d3 100644 --- a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx +++ b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx @@ -53,7 +53,14 @@ public: 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 (void); + /** 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); @@ -99,6 +106,12 @@ Animator::~Animator (void) 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(); mpDrawLock.reset(); } @@ -111,7 +124,11 @@ Animator::AnimationId Animator::AddAnimation ( 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; const double nDelta = double(gnResolution) / double(nDuration); boost::shared_ptr<Animation> pAnimation ( @@ -134,7 +151,11 @@ Animator::AnimationId Animator::AddInfiniteAnimation ( const AnimationFunctor& rAnimation, const double 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, nDelta, -1.0, mnNextAnimationId++, FinishFunctor())); @@ -180,9 +201,12 @@ void Animator::RemoveAnimation (const Animator::AnimationId nId) bool Animator::ProcessAnimations (void) { + bool bExpired (false); + OSL_ASSERT( ! mbIsDisposed); + if (mbIsDisposed) + return bExpired; - bool bExpired (false); AnimationList aCopy (maAnimations); AnimationList::const_iterator iAnimation; @@ -200,6 +224,8 @@ bool Animator::ProcessAnimations (void) void Animator::CleanUpAnimationList (void) { OSL_ASSERT( ! mbIsDisposed); + if (mbIsDisposed) + return; AnimationList aActiveAnimations; @@ -221,6 +247,8 @@ IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG) if (mbIsDisposed) return 0; + OSL_TRACE("Animator timeout start"); + if (ProcessAnimations()) CleanUpAnimationList(); @@ -233,6 +261,8 @@ IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG) maTimer.Start(); } + OSL_TRACE("Animator timeout end"); + return 0; } diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx index ca272b405b8b..0c0213e9e702 100644 --- a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx @@ -49,7 +49,8 @@ namespace sd { namespace slidesorter { namespace controller { FocusManager::FocusManager (SlideSorter& rSlideSorter) : mrSlideSorter(rSlideSorter), mnPageIndex(0), - mbPageIsFocused(false) + mbPageIsFocused(false), + mbIsVerticalWrapActive(false) { if (mrSlideSorter.GetModel().GetPageCount() > 0) mnPageIndex = 0; @@ -71,67 +72,97 @@ void FocusManager::MoveFocus (FocusMoveDirection eDirection) { HideFocusIndicator (GetFocusedPageDescriptor()); - int nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount()); + const sal_Int32 nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount()); + const sal_Int32 nPageCount (mrSlideSorter.GetModel().GetPageCount()); switch (eDirection) { case FMD_NONE: - if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) - mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1; + // Nothing to be done. break; case FMD_LEFT: - mnPageIndex -= 1; - if (mnPageIndex < 0) - { - mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1; - SetFocusToToolBox(); - } + if (mnPageIndex > 0) + mnPageIndex -= 1; + else if (mbIsVerticalWrapActive) + mnPageIndex = nPageCount-1; break; case FMD_RIGHT: - mnPageIndex += 1; - if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) - { + if (mnPageIndex < nPageCount-1) + mnPageIndex += 1; + else if (mbIsVerticalWrapActive) mnPageIndex = 0; - SetFocusToToolBox(); - } break; case FMD_UP: { - int nColumn = mnPageIndex % nColumnCount; - mnPageIndex -= nColumnCount; - if (mnPageIndex < 0) + const sal_Int32 nCandidate (mnPageIndex - nColumnCount); + if (nCandidate < 0) { - // Wrap arround to the bottom row or the one above and - // go to the correct column. - int nCandidate = mrSlideSorter.GetModel().GetPageCount()-1; - int nCandidateColumn = nCandidate % nColumnCount; - if (nCandidateColumn > nColumn) - mnPageIndex = nCandidate - (nCandidateColumn-nColumn); - else if (nCandidateColumn < nColumn) - mnPageIndex = nCandidate - - nColumnCount - + (nColumn - nCandidateColumn); - else - mnPageIndex = nCandidate; + 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: { - int nColumn = mnPageIndex % nColumnCount; - mnPageIndex += nColumnCount; - if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) + const sal_Int32 nCandidate (mnPageIndex + nColumnCount); + if (nCandidate >= nPageCount) { - // Wrap arround to the correct column. - mnPageIndex = nColumn; + 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); } diff --git a/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx index 8b9cc659fd54..04c505d72b5c 100644 --- a/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx +++ b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx @@ -51,7 +51,8 @@ InsertionIndicatorHandler::InsertionIndicatorHandler (SlideSorter& rSlideSorter) mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay()), mnInsertionIndex(-1), mbIsBeforePage(false), - mbIsActive(false) + mbIsActive(false), + mbIsReadOnly(mrSlideSorter.GetModel().IsReadOnly()) { } @@ -72,7 +73,8 @@ void InsertionIndicatorHandler::Start (const Point& rMouseModelPosition) OSL_ASSERT(!mbIsActive); } - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) + mbIsReadOnly = mrSlideSorter.GetModel().IsReadOnly(); + if (mbIsReadOnly) return; SetPosition(rMouseModelPosition); @@ -85,9 +87,10 @@ void InsertionIndicatorHandler::Start (const Point& rMouseModelPosition) void InsertionIndicatorHandler::UpdatePosition (const Point& rMouseModelPosition) { - OSL_ASSERT(mbIsActive); + if ( ! mbIsActive) + return; - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) + if (mbIsReadOnly) return; SetPosition(rMouseModelPosition); @@ -98,7 +101,12 @@ void InsertionIndicatorHandler::UpdatePosition (const Point& rMouseModelPosition void InsertionIndicatorHandler::End (void) { - OSL_ASSERT(mbIsActive); + if ( ! mbIsActive) + return; + + if (mbIsReadOnly) + return; + GetInsertAnimator()->SetInsertPosition(-1, false); mbIsActive = false; @@ -119,7 +127,10 @@ bool InsertionIndicatorHandler::IsActive (void) const sal_Int32 InsertionIndicatorHandler::GetInsertionPageIndex (void) const { - return mnInsertionIndex; + if (mbIsReadOnly) + return -1; + else + return mnInsertionIndex; } diff --git a/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx index 0a8bebc1bdbf..5f4e2b3c1fb5 100644 --- a/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx @@ -244,7 +244,7 @@ void ScrollBarManager::AdaptWindowSize (const Rectangle& rArea) void ScrollBarManager::UpdateScrollBars (bool bResetThumbPosition, bool bUseScrolling) { Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea()); - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); Size aWindowModelSize (pWindow->PixelToLogic(pWindow->GetSizePixel())); // The horizontal scroll bar is only shown when the window is @@ -336,6 +336,11 @@ IMPL_LINK(ScrollBarManager, VerticalScrollBarHandler, ScrollBar*, pScrollBar) mrSlideSorter.GetContentWindow()->SetVisibleXY ( -1, nRelativePosition); + /* + mrSlideSorter.GetView().UpdatePageUnderMouse( + aMousePosition, + (rEvent.GetButtons() & MOUSE_LEFT)!=0); + */ } return TRUE; } @@ -368,7 +373,7 @@ void ScrollBarManager::SetWindowOrigin ( mnHorizontalPosition = nHorizontalPosition; mnVerticalPosition = nVerticalPosition; - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); Size aViewSize (pWindow->GetViewSize()); Point aOrigin ( (long int) (mnHorizontalPosition * aViewSize.Width()), @@ -569,7 +574,7 @@ int ScrollBarManager::GetHorizontalScrollBarHeight (void) const void ScrollBarManager::CalcAutoScrollOffset (const Point& rMouseWindowPosition) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); int nDx = 0; int nDy = 0; diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx index e0566bb3818b..d12fbe3bbfc0 100644 --- a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx @@ -108,18 +108,28 @@ static const sal_uInt32 MODIFIER_MASK (SHIFT_MODIFIER | CONTROL_MODIF namespace sd { namespace slidesorter { namespace controller { +/** A SubstitutionHandler object handles the display of a number of selected + slides at the mouse position and the insertion or (with or without + removing the pages at their original position) when the object is + destoyed. +*/ class SelectionFunction::SubstitutionHandler { public: - SubstitutionHandler (SlideSorter& rSlideSorter); - ~SubstitutionHandler (void); - - void SetHitDescriptor (const model::SharedPageDescriptor& rpHitDescriptor); - /** Create a substitution display of the currently selected pages and use the given position as the anchor point. */ - void Start (const Point& rMouseModelPosition); + SubstitutionHandler ( + SlideSorter& rSlideSorter, + const model::SharedPageDescriptor& rpHitDescriptor, + const Point& rMouseModelPosition); + ~SubstitutionHandler (void); + + /** Call this method (for example as reaction to ESC key press) to avoid + processing (ie moving or inserting) the substition when the called + SubstitutionHandler 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 @@ -129,31 +139,26 @@ public: const Point& rMousePosition, const bool bAllowAutoScroll = true); - /** Move the substitution display of the currently selected pages. - */ - void Process (void); - - void End (void); - - bool IsActive (void) const; - private: SlideSorter& mrSlideSorter; model::SharedPageDescriptor mpHitDescriptor; - bool mbIsActive; sal_Int32 mnInsertionIndex; + + /** Move the substitution display of the currently selected pages. + */ + void Process (void); }; -class SelectionFunction::RectangleSelector + + +class SelectionFunction::MouseMultiSelector { public: - /** Start a rectangle selection at the given position. - */ - RectangleSelector ( + MouseMultiSelector ( SlideSorter& rSlideSorter, const Point& rMouseModelPosition); - ~RectangleSelector (void); + virtual ~MouseMultiSelector (void); void RestoreInitialSelection (void); @@ -163,21 +168,75 @@ public: void UpdatePosition ( const Point& rMousePosition, const bool bAllowAutoScroll = true); - enum SelectionMode { SM_Normal, SM_Add, SM_Toggle }; + void SetSelectionMode (const SelectionMode eSelectionMode); void SetSelectionModeFromModifier (const sal_uInt32 nEventCode); -private: +protected: SlideSorter& mrSlideSorter; SelectionMode meSelectionMode; ::std::set<sal_Int32> maInitialSelection; - /** Select all pages that lie completly in the selection rectangle. - */ - void ProcessRectangleSelection (void); + virtual void UpdateModelPosition (const Point& rMouseModelPosition) = 0; + virtual void UpdateSelection (void) = 0; + + void UpdateSelectionState ( + const model::SharedPageDescriptor& rpDescriptor, + const bool bIsInSelection) const; }; +namespace { + + class RectangleSelector + : public SelectionFunction::MouseMultiSelector + { + public: + /** Start a rectangle selection at the given position. + */ + RectangleSelector ( + SlideSorter& rSlideSorter, + const Point& rMouseModelPosition); + virtual ~RectangleSelector (void); + + protected: + virtual void UpdateModelPosition (const Point& rMouseModelPosition); + + /** Select all pages that lie completly in the selection rectangle. + */ + virtual void UpdateSelection (void); + }; + + class RangeSelector + : public SelectionFunction::MouseMultiSelector + { + public: + /** Start a rectangle selection at the given position. + */ + RangeSelector ( + SlideSorter& rSlideSorter, + const Point& rMouseModelPosition); + virtual ~RangeSelector (void); + + protected: + virtual void UpdateModelPosition (const Point& rMouseModelPosition); + + /** Select all pages that lie completly in the selection rectangle. + */ + virtual void UpdateSelection (void); + + private: + Point maAnchor; + Point maSecondCorner; + Pointer maSavedPointer; + sal_Int32 mnAnchorIndex; + sal_Int32 mnSecondIndex; + + Rectangle GetBoundingBox (void) const; + }; + +} // end of anonymous namespace + class SelectionFunction::EventDescriptor { @@ -221,15 +280,14 @@ SelectionFunction::SelectionFunction ( mbDragSelection(false), maInsertionMarkerBox(), mbProcessingMouseButtonDown(false), - mpSubstitutionHandler(new SubstitutionHandler(mrSlideSorter)), - mpRectangleSelector(), + mpSubstitutionHandler(), + mpMouseMultiSelector(), mnButtonDownPageIndex(-1), mnButtonDownButtonIndex(-1), mbIsDeselectionPending(false), mnShiftKeySelectionAnchor(-1) { - //af aDelayToScrollTimer.SetTimeout(50); - aDragTimer.SetTimeoutHdl( LINK( this, SelectionFunction, DragSlideHdl ) ); + aDragTimer.SetTimeoutHdl(LINK(this, SelectionFunction, DragSlideHdl)); } SelectionFunction::~SelectionFunction (void) @@ -284,23 +342,28 @@ BOOL SelectionFunction::MouseMove (const MouseEvent& rEvent) // In some modes (dragging, moving) the mouse over indicator is only // annoying. Turn it off in these cases. - if (mrSlideSorter.GetView().GetOverlay().GetSubstitutionOverlay()->IsVisible() - || mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay()->IsVisible()) + if (mpSubstitutionHandler || mpMouseMultiSelector) { mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); } else { - UpdatePageUnderMouse(aMousePosition, (rEvent.GetButtons() & MOUSE_LEFT)!=0); + mrSlideSorter.GetView().UpdatePageUnderMouse( + aMousePosition, + (rEvent.GetButtons() & MOUSE_LEFT)!=0); } view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); Rectangle aRectangle (Point(0,0),mpWindow->GetOutputSizePixel()); if ( ! aRectangle.IsInside(aMousePosition) - && rOverlay.GetSubstitutionOverlay()->IsVisible()) + && mpSubstitutionHandler) { // Mouse left the window with pressed left button. Make it a drag. StartDrag(aMousePosition); + // Mouse motion events are not sent to us while the mouse is outside + // the window and drag&drop is active. Therefore hide the + // substitution. + // mpSubstitutionHandler->Hide(); } else { @@ -350,7 +413,7 @@ void SelectionFunction::MouseDragged (const AcceptDropEvent& rEvent) view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); if (rOverlay.GetSubstitutionOverlay()->IsVisible()) pEventDescriptor->mnEventCode |= SUBSTITUTION_VISIBLE; - if (mpRectangleSelector) + if (mpMouseMultiSelector) pEventDescriptor->mnEventCode |= RECTANGLE_VISIBLE; // 3. Process the event. @@ -398,12 +461,15 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent) case KEY_ESCAPE: rFocusManager.SetFocusToToolBox(); - if (mpSubstitutionHandler->IsActive()) - mpSubstitutionHandler->End(); - if (mpRectangleSelector) + if (mpSubstitutionHandler) + { + mpSubstitutionHandler->Dispose(); + mpSubstitutionHandler.reset(); + } + if (mpMouseMultiSelector) { - mpRectangleSelector->RestoreInitialSelection(); - mpRectangleSelector.reset(); + mpMouseMultiSelector->RestoreInitialSelection(); + mpMouseMultiSelector.reset(); } bResult = TRUE; break; @@ -653,7 +719,14 @@ void SelectionFunction::StartDrag (const Point& rMousePosition) if (mbPageHit && ! mrSlideSorter.GetProperties()->IsUIReadOnly()) { - mpSubstitutionHandler->Start(rMousePosition); + if ( ! mpSubstitutionHandler) + mpSubstitutionHandler.reset( + new SubstitutionHandler( + mrSlideSorter, + mrSlideSorter.GetController().GetPageAt(rMousePosition), + rMousePosition)); + else + mpSubstitutionHandler->UpdatePosition(rMousePosition); mbPageHit = false; mpWindow->ReleaseMouse(); @@ -880,9 +953,9 @@ sal_uInt32 SelectionFunction::EncodeState ( // Detect whether we are dragging pages or dragging a selection rectangle. view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - if (rOverlay.GetSubstitutionOverlay()->IsVisible()) + if (mpSubstitutionHandler) nEventCode |= SUBSTITUTION_VISIBLE; - if (mpRectangleSelector) + if (mpMouseMultiSelector) nEventCode |= RECTANGLE_VISIBLE; return nEventCode; @@ -928,11 +1001,9 @@ void SelectionFunction::EventPreprocessing (const EventDescriptor& rDescriptor) bool Match ( const sal_uInt32 nEventCode, - const sal_uInt32 nPositivePattern, - const sal_uInt32 nNegativePattern = 0) + const sal_uInt32 nPositivePattern) { - return (nEventCode & nPositivePattern)==nPositivePattern - && (nEventCode & nNegativePattern)==0; + return (nEventCode & nPositivePattern)==nPositivePattern; } @@ -974,8 +1045,6 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) // The substitution is visible. Handle events accordingly. if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK)) { - // Move substitution. - mpSubstitutionHandler->SetHitDescriptor(pHitDescriptor); if ((rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0) StartDrag(rDescriptor.maMousePosition); mpSubstitutionHandler->UpdatePosition(rDescriptor.maMousePosition); @@ -989,32 +1058,31 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) // The following Process() call may lead to the desctruction // of pHitDescriptor so release our reference to it. pHitDescriptor.reset(); - mpSubstitutionHandler->End(); - mpSubstitutionHandler->Process(); + mpSubstitutionHandler.reset(); } break; case RECTANGLE_VISIBLE: - OSL_ASSERT(mpRectangleSelector); + OSL_ASSERT(mpMouseMultiSelector); // The selection rectangle is visible. Handle events accordingly. if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK)) { - if (mpRectangleSelector) + if (mpMouseMultiSelector) { - mpRectangleSelector->SetSelectionModeFromModifier(rDescriptor.mnEventCode); - mpRectangleSelector->UpdatePosition(rDescriptor.maMousePosition); + mpMouseMultiSelector->SetSelectionModeFromModifier(rDescriptor.mnEventCode); + mpMouseMultiSelector->UpdatePosition(rDescriptor.maMousePosition); } bMakeSelectionVisible = false; } else if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK)) { - mpRectangleSelector.reset(); + mpMouseMultiSelector.reset(); } // Anything else stops the rectangle selection and the event is // processed again. else { - mpRectangleSelector.reset(); + mpMouseMultiSelector.reset(); EventDescriptor aModifiedDescriptor (rDescriptor); aModifiedDescriptor.mnEventCode &= ~RECTANGLE_VISIBLE; EventProcessing(aModifiedDescriptor); @@ -1022,7 +1090,7 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) break; default: - OSL_ASSERT(!mpRectangleSelector); + OSL_ASSERT(!mpMouseMultiSelector); switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION)) { case BUTTON_DOWN: @@ -1086,7 +1154,7 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) // Rectangle selection. case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): mbIsDeselectionPending = true; - OSL_ASSERT(!mpRectangleSelector); + OSL_ASSERT(!mpMouseMultiSelector); break; } break; @@ -1126,16 +1194,18 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) { // A mouse motion without visible substitution starts that. case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE): - mpSubstitutionHandler->SetHitDescriptor(pHitDescriptor); - mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition); + mpSubstitutionHandler.reset(new SubstitutionHandler( + mrSlideSorter, + pHitDescriptor, + rDescriptor.maMouseModelPosition)); break; // A mouse motion not over a page starts a rectangle selection. case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): - OSL_ASSERT(!mpRectangleSelector); - mpRectangleSelector.reset( - new RectangleSelector(mrSlideSorter, rDescriptor.maMouseModelPosition)); - mpRectangleSelector->SetSelectionModeFromModifier(rDescriptor.mnEventCode); + OSL_ASSERT(!mpMouseMultiSelector); + mpMouseMultiSelector.reset( + new RangeSelector(mrSlideSorter, rDescriptor.maMouseModelPosition)); + mpMouseMultiSelector->SetSelectionModeFromModifier(rDescriptor.mnEventCode); break; } break; @@ -1224,37 +1294,6 @@ void SelectionFunction::SwitchView (const model::SharedPageDescriptor& rpDescrip -void SelectionFunction::UpdatePageUnderMouse ( - const Point& rMousePosition, - const bool bIsMouseButtonDown) -{ - // Determine page under mouse and show the mouse over effect. - model::SharedPageDescriptor pHitDescriptor ( - mrController.GetPageAt(rMousePosition)); - mrSlideSorter.GetView().SetPageUnderMouse(pHitDescriptor); - - // Handle the mouse being over any buttons. - if (pHitDescriptor) - { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); - const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); - const sal_Int32 nButtonIndex ( - mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetButtonIndexAt ( - pHitDescriptor, - aMouseModelPosition)); - mrSlideSorter.GetView().SetButtonUnderMouse(nButtonIndex); - if (bIsMouseButtonDown) - { - pHitDescriptor->GetVisualState().SetActiveButtonState( - nButtonIndex, - model::VisualState::BS_Pressed); - } - } -} - - - - void SelectionFunction::ProcessButtonClick ( const model::SharedPageDescriptor& rpDescriptor, const sal_Int32 nButtonIndex) @@ -1314,7 +1353,7 @@ SelectionFunction::EventDescriptor::EventDescriptor ( mnEventCode(nEventType), mnButtonIndex(-1) { - ::boost::shared_ptr<sd::Window> pWindow (rSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (rSlideSorter.GetContentWindow()); maMousePosition = rEvent.GetPosPixel(); maMouseModelPosition = pWindow->PixelToLogic(maMousePosition); @@ -1369,7 +1408,7 @@ SelectionFunction::EventDescriptor::EventDescriptor ( mnEventCode(MOUSE_DRAG), mnButtonIndex(-1) { - ::boost::shared_ptr<sd::Window> pWindow (rSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (rSlideSorter.GetContentWindow()); maMouseModelPosition = pWindow->PixelToLogic(maMousePosition); model::SharedPageDescriptor pHitDescriptor ( @@ -1399,44 +1438,14 @@ SelectionFunction::EventDescriptor::EventDescriptor (const EventDescriptor& rDes //===== SubstitutionHandler =================================================== -SelectionFunction::SubstitutionHandler::SubstitutionHandler (SlideSorter& rSlideSorter) +SelectionFunction::SubstitutionHandler::SubstitutionHandler ( + SlideSorter& rSlideSorter, + const model::SharedPageDescriptor& rpHitDescriptor, + const Point& rMouseModelPosition) : mrSlideSorter(rSlideSorter), - mpHitDescriptor(), - mbIsActive(false), + mpHitDescriptor(rpHitDescriptor), mnInsertionIndex(-1) { -} - - - - -SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void) -{ - OSL_ASSERT(!mbIsActive); - if (mrSlideSorter.IsValid()) - { - view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); - rOverlay.GetSubstitutionOverlay()->Clear(); - } -} - - - - -void SelectionFunction::SubstitutionHandler::SetHitDescriptor ( - const model::SharedPageDescriptor& rpHitDescriptor) -{ - mpHitDescriptor = rpHitDescriptor; -} - - - - -void SelectionFunction::SubstitutionHandler::Start (const Point& rMouseModelPosition) -{ - OSL_ASSERT(!mbIsActive); - mbIsActive = true; mnInsertionIndex = -1; // No Drag-and-Drop for master pages. @@ -1466,19 +1475,39 @@ void SelectionFunction::SubstitutionHandler::Start (const Point& rMouseModelPosi +SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void) +{ + Process(); + + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); + rOverlay.GetSubstitutionOverlay()->Clear(); + mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(); + mpHitDescriptor.reset(); +} + + + + +void SelectionFunction::SubstitutionHandler::Dispose (void) +{ + mnInsertionIndex = -1; +} + + + + void SelectionFunction::SubstitutionHandler::UpdatePosition ( const Point& rMousePosition, const bool bAllowAutoScroll) { - OSL_ASSERT(mbIsActive); - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) return; // Convert window coordinates into model coordinates (we need the // window coordinates for auto-scrolling because that remains // constant while scrolling.) - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll( @@ -1531,44 +1560,15 @@ void SelectionFunction::SubstitutionHandler::Process (void) -void SelectionFunction::SubstitutionHandler::End (void) -{ - OSL_ASSERT(mbIsActive); - mbIsActive = false; - - view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); - rOverlay.GetSubstitutionOverlay()->Clear(); - mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(); - mpHitDescriptor.reset(); -} - - - - -bool SelectionFunction::SubstitutionHandler::IsActive (void) const -{ - return mbIsActive; -} - - - +//===== SelectionFunction::MouseMultiSelector ====================================== -//===== SelectionFunction::RectangleSelector ================================== - -SelectionFunction::RectangleSelector::RectangleSelector ( +SelectionFunction::MouseMultiSelector::MouseMultiSelector ( SlideSorter& rSlideSorter, const Point& rMouseModelPosition) : mrSlideSorter(rSlideSorter), meSelectionMode(SM_Normal), maInitialSelection() { - if (mrSlideSorter.GetProperties()->IsShowSelection()) - { - mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay() - ->Start(rMouseModelPosition); - } - // Remember the current selection. model::PageEnumeration aPages ( model::PageEnumerationProvider::CreateAllPagesEnumeration( @@ -1585,18 +1585,14 @@ SelectionFunction::RectangleSelector::RectangleSelector ( -SelectionFunction::RectangleSelector::~RectangleSelector (void) +SelectionFunction::MouseMultiSelector::~MouseMultiSelector (void) { - if (mrSlideSorter.GetProperties()->IsShowSelection()) - { - mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay()->SetIsVisible(false); - } } -void SelectionFunction::RectangleSelector::RestoreInitialSelection (void) +void SelectionFunction::MouseMultiSelector::RestoreInitialSelection (void) { // Remember the current selection. model::PageEnumeration aPages ( @@ -1616,37 +1612,32 @@ void SelectionFunction::RectangleSelector::RestoreInitialSelection (void) -void SelectionFunction::RectangleSelector::UpdatePosition ( +void SelectionFunction::MouseMultiSelector::UpdatePosition ( const Point& rMousePosition, const bool bAllowAutoScroll) { // Convert window coordinates into model coordinates (we need the // window coordinates for auto-scrolling because that remains // constant while scrolling.) - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll( rMousePosition, ::boost::bind( - &SelectionFunction::RectangleSelector::UpdatePosition, + &SelectionFunction::MouseMultiSelector::UpdatePosition, this, rMousePosition, false)))) { - if (mrSlideSorter.GetProperties()->IsShowSelection()) - { - mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay() - ->Update(aMouseModelPosition); - ProcessRectangleSelection(); - } + UpdateModelPosition(aMouseModelPosition); } } -void SelectionFunction::RectangleSelector::SetSelectionModeFromModifier ( +void SelectionFunction::MouseMultiSelector::SetSelectionModeFromModifier ( const sal_uInt32 nEventCode) { switch (nEventCode & MODIFIER_MASK) @@ -1668,19 +1659,100 @@ void SelectionFunction::RectangleSelector::SetSelectionModeFromModifier ( -void SelectionFunction::RectangleSelector::SetSelectionMode (const SelectionMode eSelectionMode) +void SelectionFunction::MouseMultiSelector::SetSelectionMode (const SelectionMode eSelectionMode) { if (meSelectionMode != eSelectionMode) { meSelectionMode = eSelectionMode; - ProcessRectangleSelection(); + UpdateSelection(); } } -void SelectionFunction::RectangleSelector::ProcessRectangleSelection (void) +void SelectionFunction::MouseMultiSelector::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); +} + + + + +//===== RectangleSelector ===================================================== + +namespace { + +RectangleSelector::RectangleSelector ( + SlideSorter& rSlideSorter, + const Point& rMouseModelPosition) + : MouseMultiSelector(rSlideSorter,rMouseModelPosition) +{ + if (mrSlideSorter.GetProperties()->IsShowSelection()) + { + mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay() + ->Start(rMouseModelPosition); + } +} + + + + +RectangleSelector::~RectangleSelector (void) +{ + if (mrSlideSorter.GetProperties()->IsShowSelection()) + { + mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay()->SetIsVisible(false); + } +} + + + + +void RectangleSelector::UpdateModelPosition (const Point& rMouseModelPosition) +{ + if (mrSlideSorter.GetProperties()->IsShowSelection()) + { + mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay() + ->Update(rMouseModelPosition); + UpdateSelection(); + } +} + + + + +void RectangleSelector::UpdateSelection (void) { if ( ! mrSlideSorter.GetProperties()->IsShowSelection()) return; @@ -1690,8 +1762,6 @@ void SelectionFunction::RectangleSelector::ProcessRectangleSelection (void) { view::SlideSorterView::DrawLock aLock (mrSlideSorter); - PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector()); - // Select all pages whose page object lies completly or partially // inside the selection rectangle. const Rectangle& rSelectionRectangle ( @@ -1711,35 +1781,85 @@ void SelectionFunction::RectangleSelector::ProcessRectangleSelection (void) view::PageObjectLayouter::WindowCoordinateSystem)); const bool bIsPageInSelectionRectangle (rSelectionRectangle.IsOver(aPageBox)); - // Determine whether the page was selected before the rectangle - // selection was started. - const bool bWasSelected (pDescriptor->HasState(model::PageDescriptor::ST_WasSelected)); + UpdateSelectionState(pDescriptor, bIsPageInSelectionRectangle); + } - // Combine the two selection states depending on the selection mode. - bool bSelect (false); - switch(meSelectionMode) - { - case SM_Normal: - bSelect = bIsPageInSelectionRectangle; - break; + // Rely on auto scrolling to make page objects visible. + mrSlideSorter.GetController().GetSelectionManager()->ResetMakeSelectionVisiblePending(); + } +} - case SM_Add: - bSelect = bIsPageInSelectionRectangle || bWasSelected; - break; +} // end of anonymous namespace - case SM_Toggle: - if (bIsPageInSelectionRectangle) - bSelect = !bWasSelected; - else - bSelect = bWasSelected; - break; - } - // Set the new selection state. - if (bSelect) - rSelector.SelectPage(pDescriptor); - else - rSelector.DeselectPage(pDescriptor); + + +//===== RangeSelector ========================================================= + +namespace { + +RangeSelector::RangeSelector ( + SlideSorter& rSlideSorter, + const Point& rMouseModelPosition) + : MouseMultiSelector(rSlideSorter,rMouseModelPosition), + maAnchor(rMouseModelPosition), + maSecondCorner(rMouseModelPosition), + maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()), + mnAnchorIndex(-1) +{ + const Pointer aSelectionPointer (POINTER_TEXT); + mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer); +} + + + + +RangeSelector::~RangeSelector (void) +{ + mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer); +} + + + + +void RangeSelector::UpdateModelPosition (const Point& rMouseModelPosition) +{ + maSecondCorner = rMouseModelPosition; + UpdateSelection(); +} + + + + +void RangeSelector::UpdateSelection (void) +{ + view::SlideSorterView::DrawLock aLock (mrSlideSorter); + + PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector()); + + const sal_Int32 nIndexUnderMouse ( + mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint ( + maSecondCorner, + false)); + if (nIndexUnderMouse >= 0) + { + if (mnAnchorIndex < 0) + mnAnchorIndex = nIndexUnderMouse; + mnSecondIndex = nIndexUnderMouse; + + Range aRange (mnAnchorIndex, mnSecondIndex); + aRange.Justify(); + + model::SlideSorterModel& rModel (mrSlideSorter.GetModel()); + for (sal_Int32 nIndex=0,nCount(rModel.GetPageCount()); nIndex<nCount; ++nIndex) + { + model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex)); + + // Determine whether the page was selected before the rectangle + // selection was started. + const bool bWasSelected (pDescriptor->HasState(model::PageDescriptor::ST_WasSelected)); + + UpdateSelectionState(pDescriptor, aRange.IsInside(nIndex)); } // Rely on auto scrolling to make page objects visible. @@ -1750,4 +1870,17 @@ void SelectionFunction::RectangleSelector::ProcessRectangleSelection (void) +Rectangle RangeSelector::GetBoundingBox (void) const +{ + return Rectangle( + ::std::min(maAnchor.X(), maSecondCorner.X()), + ::std::min(maAnchor.Y(), maSecondCorner.Y()), + ::std::max(maAnchor.X(), maSecondCorner.X()), + ::std::max(maAnchor.Y(), maSecondCorner.Y())); +} + + +} // end of anonymous namespace + + } } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx index 2ce5b11e302a..ff511b60625e 100644 --- a/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx @@ -356,7 +356,7 @@ void SelectionManager::ResetMakeSelectionVisiblePending (void) */ Size SelectionManager::MakeSelectionVisible (const SelectionHint eSelectionHint) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow == NULL) return Size(0,0); @@ -403,7 +403,7 @@ Size SelectionManager::MakeSelectionVisible (const SelectionHint eSelectionHint) Size SelectionManager::MakeRectangleVisible (const Rectangle& rBox) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow == NULL) return Size(0,0); @@ -519,7 +519,7 @@ void SelectionManager::RemoveSelectionChangeListener(const Link&rListener) bool SelectionManager::DoesSelectionExceedVisibleArea (const Rectangle& rSelectionBox) const { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow == NULL) return true; diff --git a/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx index 4384e1a66d9d..2529915b2fea 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx @@ -206,6 +206,12 @@ private: ::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 diff --git a/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx index 514b0ca056a5..006cf0083ed9 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx @@ -88,6 +88,7 @@ private: bool mbIsBeforePage; bool mbIsInsertionTrivial; bool mbIsActive; + bool mbIsReadOnly; void SetPosition (const Point& rPoint); ::boost::shared_ptr<view::InsertAnimator> GetInsertAnimator (void); diff --git a/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx index 0e1edb0576d7..7c1f76bf1407 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx @@ -31,6 +31,8 @@ #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> @@ -216,7 +218,7 @@ private: /** The content window is the one whose view port is controlled by the scroll bars. */ - ::boost::shared_ptr<sd::Window> mpContentWindow; + SharedSdWindow mpContentWindow; ::boost::function<void(void)> maAutoScrollFunctor; diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx index bc5f49b12c8b..d1b8fedd1143 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx @@ -35,7 +35,6 @@ #include "controller/SlsFocusManager.hxx" #include "fupoor.hxx" #include <svtools/transfer.hxx> -//#include <memory> #include <boost/noncopyable.hpp> #include <boost/scoped_ptr.hpp> @@ -94,6 +93,8 @@ public: void MouseDragged (const AcceptDropEvent& rEvent); + class MouseMultiSelector; + protected: SlideSorter& mrSlideSorter; SlideSorterController& mrController; @@ -106,7 +107,6 @@ protected: private: class SubstitutionHandler; - class RectangleSelector; class EventDescriptor; /// Set in MouseButtonDown this flag indicates that a page has been hit. @@ -128,7 +128,7 @@ private: bool mbProcessingMouseButtonDown; ::boost::scoped_ptr<SubstitutionHandler> mpSubstitutionHandler; - ::boost::scoped_ptr<RectangleSelector> mpRectangleSelector; + ::boost::scoped_ptr<MouseMultiSelector> mpMouseMultiSelector; /** Remember where the left mouse button was pressed. */ diff --git a/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx index e9c76e68fd35..e8fed3b423ce 100644 --- a/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx +++ b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx @@ -69,6 +69,7 @@ class SlideSorterModel { public: SlideSorterModel (SlideSorter& rSlideSorter); + void Init (void); virtual ~SlideSorterModel (void); void Dispose (void); @@ -193,6 +194,8 @@ public: */ void UpdatePageList (void); + bool IsReadOnly (void) const; + private: mutable ::osl::Mutex maMutex; SlideSorter& mrSlideSorter; diff --git a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx index 6c7c5f735045..4abdfdc328b1 100644 --- a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx @@ -70,9 +70,9 @@ namespace sd { namespace slidesorter { namespace view { class LayeredDevice; class Layouter; class PageObjectPainter; +class SelectionPainter; class ViewOverlay; - class SlideSorterView : public sd::View, public ::boost::noncopyable @@ -87,6 +87,7 @@ public: */ SlideSorterView (SlideSorter& rSlideSorter); + void Init (void); virtual ~SlideSorterView (void); void Dispose (void); @@ -179,20 +180,22 @@ public: */ void SetSelectionRectangleVisibility (bool bVisible); - typedef ::std::pair<sal_Int32,sal_Int32> PageRange; /** Return the range of currently visible page objects including the first and last one in that range. @return The returned pair of page object indices is empty when the second index is lower than the first. */ - PageRange GetVisiblePageRange (void); + Pair GetVisiblePageRange (void); /** Add a shape to the page. Typically used from inside PostModelChange(). */ void AddSdrObject (SdrObject& rObject); + void UpdatePageUnderMouse ( + const Point& rMousePosition, + const bool bIsMouseButtonDown); void SetPageUnderMouse (const model::SharedPageDescriptor& rpDescriptor); void SetButtonUnderMouse (const sal_Int32 nButtonIndex); @@ -220,13 +223,13 @@ protected: 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; ::boost::shared_ptr<ViewOverlay> mpViewOverlay; - int mnFirstVisiblePageIndex; - int mnLastVisiblePageIndex; + Range maVisiblePageRange; bool mbModelChangedWhileModifyEnabled; Size maPreviewSize; bool mbPreciousFlagUpdatePending; @@ -235,6 +238,7 @@ private: model::SharedPageDescriptor mpPageUnderMouse; sal_Int32 mnButtonUnderMouse; ::boost::shared_ptr<PageObjectPainter> mpPageObjectPainter; + ::boost::shared_ptr<SelectionPainter> mpSelectionPainter; /** Determine the visibility of all page objects. */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx index b697b157017d..e90fb968ff7e 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx @@ -71,7 +71,7 @@ namespace sd { namespace slidesorter { namespace view { class Layouter { public: - Layouter (const ::boost::shared_ptr< ::Window>& rpWindow); + Layouter (const SharedSdWindow& rpWindow); ~Layouter (void); ::boost::shared_ptr<PageObjectLayouter> GetPageObjectLayouter (void) const; @@ -216,16 +216,30 @@ public: /** Return the index of the first fully or partially visible page object. This takes into account only the vertical dimension. - */ - sal_Int32 GetIndexOfFirstVisiblePageObject (const Rectangle& rVisibleArea) const; - - /** Return the index of the last fully or partially visible page - object. This takes into account only the vertical dimension. @return - The returned index may be larger than the number of existing + The second index may be larger than the number of existing page objects. */ - sal_Int32 GetIndexOfLastVisiblePageObject (const Rectangle& rVisibleArea) const; + Range GetRangeOfVisiblePageObjects (const Rectangle& rVisibleArea) const; + + /** Return a pair of indices that point to the first and last slide in + the selection delimited by the two given points. The second point + may be located above and/or left of the anchor. + @param rAnchor + Location where the mouse button was pressed and the range + selection started. + @param rOther + Current location of the mouse. + @param rCurrentSelectionRange + Current range of the selection. + @return + The indices are sorted. When the first index is -1 then the + range is empty. + */ + Range GetSelectionRange ( + const Point& rAnchor, + const Point& rOther, + const Range& rCurrentSelectionRange) const; /** Return the index of the page object that is rendered at the given point. @@ -272,8 +286,13 @@ public: const Point& rModelPosition, bool bAllowVerticalPosition) const; + /** Return whether the main orientation of the slides in the slide + sorter is vertical, i.e. all slides are arranged in one column. + */ + bool IsVertical (void) const; + private: - ::boost::shared_ptr< ::Window> mpWindow; + SharedSdWindow mpWindow; sal_Int32 mnRequestedLeftBorder; sal_Int32 mnRequestedRightBorder; sal_Int32 mnRequestedTopBorder; @@ -293,6 +312,7 @@ private: sal_Int32 mnColumnCount; sal_Int32 mnRowCount; Size maPageObjectSize; + bool mbIsVertical; ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter; diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx index fcd398377b01..65f67efaeb22 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx @@ -56,11 +56,12 @@ public: 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 ( + PageObjectLayouter( const Size& rPageObjectWindowSize, const Size& rPreviewModelSize, - const ::boost::shared_ptr< ::Window>& rpWindow, - const int nPageCount); + const SharedSdWindow& rpWindow, + const sal_Int32 nPageCount); + ~PageObjectLayouter(void); enum Part { // This is the outer bounding box that includes the preview, page @@ -70,10 +71,6 @@ public: Preview, // Bounding box of the mouse indicator indicator frame. MouseOverIndicator, - // Bounding box of the focus indicator frame. - FocusIndicator, - // Bounding box of the selection indicator frame. - SelectionIndicator, // Bounding box of the page number. PageNumber, // Bounding box of the pane name. @@ -107,7 +104,9 @@ public: This device is used to translate between model and window coordinates. @param rpPageDescriptor - The page for which to calculate the bounding box. + 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. @@ -141,26 +140,19 @@ public: const Point& rWindowLocation); 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; /// Minimal border around the page number area. static const sal_Int32 mnPageNumberOffset; static const sal_Int32 mnOuterBorderWidth; + static const sal_Int32 mnInfoAreaMinWidth; static const Size maButtonSize; static const sal_Int32 mnButtonGap; - const ::boost::shared_ptr< ::Window> mpWindow; + SharedSdWindow mpWindow; Size maPageObjectSize; double mnModelToWindowScale; Rectangle maPageObjectBoundingBox; Rectangle maPageNumberAreaBoundingBox; Rectangle maPreviewBoundingBox; - Rectangle maFocusIndicatorBoundingBox; - Rectangle maSelectionIndicatorBoundingBox; Rectangle maTransitionEffectBoundingBox; Rectangle maButtonAreaBoundingBox; const Image maTransitionEffectIcon; @@ -169,7 +161,7 @@ private: Rectangle CalculatePreviewBoundingBox ( Size& rPageObjectSize, const Size& rPreviewModelSize, - const Size& rPageNumberAreaSize); + const sal_Int32 nInfoAreaWidth); }; diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx index b67e6cb3969f..36a7dde48eae 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx @@ -39,6 +39,8 @@ #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; } } } @@ -47,24 +49,35 @@ namespace sd { namespace slidesorter { namespace view { class Layouter; class PageObjectLayouter; +namespace { class FramePainter; } + + class PageObjectPainter { public: PageObjectPainter (const SlideSorter& rSlideSorter); + ~PageObjectPainter (void); void PaintPageObject ( OutputDevice& rDevice, const model::SharedPageDescriptor& rpDescriptor); + void NotifyResize (void); + private: const Layouter& mrLayouter; ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter; ::boost::shared_ptr<cache::PageCache> mpCache; ::boost::shared_ptr<controller::Properties> mpProperties; - ::boost::scoped_ptr<Font> mpFont; + ::boost::shared_ptr<view::Theme> mpTheme; + ::boost::shared_ptr<Font> mpPageNumberFont; BitmapEx maStartPresentationIcon; BitmapEx maShowSlideIcon; BitmapEx maNewSlideIcon; + ::boost::scoped_ptr<FramePainter> mpShadowPainter; + Bitmap maNormalBackground; + Bitmap maSelectionBackground; + Bitmap maMouseOverBackground; void PaintBackground ( OutputDevice& rDevice, @@ -81,8 +94,10 @@ private: void PaintButtons ( OutputDevice& rDevice, const model::SharedPageDescriptor& rpDescriptor) const; - - ColorData GetColorForVisualState (const model::SharedPageDescriptor& rpDescriptor) const; + void PrepareBackgrounds (OutputDevice& rDevice); + Bitmap CreateBackgroundBitmap( + const OutputDevice& rReferenceDevice, + const Theme::ColorType eType) const; }; } } } // end of namespace sd::slidesorter::view 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..6eed762a0c44 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SlsViewCacheContext.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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> + + +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 { PageNumberFont }; + ::boost::shared_ptr<Font> CreateFont ( + const FontType eType, + OutputDevice& rDevice) const; + + ColorData GetColorForVisualState (const model::VisualState::State eState) const; + + enum ColorType { + Background, + ButtonBackground, + MouseOverColor, + PageNumberBorder, + Selection, + NormalPage, + SelectedPage, + MouseOverPage + }; + enum ColorClass { Border1, Border2, Fill1, Fill2, Other }; + ColorData GetColor (const ColorType eType, const ColorClass eClass = Other); + + enum IconType { + InsertionIndicator, + RawShadow + }; + BitmapEx GetIcon (const IconType eType); + +private: + ColorData maBackgroundColor; + BitmapEx maRawShadow; + BitmapEx maInsertionIndicator; +}; + + +} } } // end of namespace ::sd::slidesorter::view + +#endif diff --git a/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx index 2e141ad6b9be..911160501935 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx @@ -235,10 +235,7 @@ private: index. */ bool mbIsBeforePage; - ImageList maIcons; - Image maIconWithBorder; - Image maIcon; - Image maMask; + BitmapEx maIcon; void SetPositionAndSize (const Rectangle& rBoundingBox); }; diff --git a/sd/source/ui/slidesorter/model/SlideSorterModel.cxx b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx index 553737d1493d..f60b8494edfd 100644 --- a/sd/source/ui/slidesorter/model/SlideSorterModel.cxx +++ b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx @@ -48,6 +48,7 @@ #include "ViewShellBase.hxx" #include "DrawViewShell.hxx" +#include "DrawDocShell.hxx" #include "drawdoc.hxx" #include "sdpage.hxx" #include "FrameView.hxx" @@ -93,6 +94,13 @@ SlideSorterModel::~SlideSorterModel (void) +void SlideSorterModel::Init (void) +{ +} + + + + void SlideSorterModel::Dispose (void) { ClearDescriptorList (); @@ -493,4 +501,18 @@ void SlideSorterModel::AdaptSize (void) maPageDescriptors.resize(0); } + + + +bool SlideSorterModel::IsReadOnly (void) const +{ + if (mrSlideSorter.GetViewShellBase() != NULL + && mrSlideSorter.GetViewShellBase()->GetDocShell()) + return mrSlideSorter.GetViewShellBase()->GetDocShell()->IsReadOnly(); + else + return true; +} + + + } } } // end of namespace ::sd::slidesorter::model diff --git a/sd/source/ui/slidesorter/model/SlsVisualState.cxx b/sd/source/ui/slidesorter/model/SlsVisualState.cxx index d6b3deecea5b..c900403eed84 100644 --- a/sd/source/ui/slidesorter/model/SlsVisualState.cxx +++ b/sd/source/ui/slidesorter/model/SlsVisualState.cxx @@ -52,8 +52,12 @@ VisualState::VisualState (const sal_Int32 nPageId) VisualState::~VisualState (void) { - OSL_ASSERT(mnStateAnimationId == controller::Animator::NotAnAnimationId); - OSL_ASSERT(mnLocationAnimationId == controller::Animator::NotAnAnimationId); + if (mnStateAnimationId != controller::Animator::NotAnAnimationId + || mnLocationAnimationId != controller::Animator::NotAnAnimationId) + { + OSL_ASSERT(mnStateAnimationId == controller::Animator::NotAnAnimationId); + OSL_ASSERT(mnLocationAnimationId == controller::Animator::NotAnAnimationId); + } } diff --git a/sd/source/ui/slidesorter/shell/SlideSorter.cxx b/sd/source/ui/slidesorter/shell/SlideSorter.cxx index 2e42f5672d6a..8fe45e5e0cf7 100644 --- a/sd/source/ui/slidesorter/shell/SlideSorter.cxx +++ b/sd/source/ui/slidesorter/shell/SlideSorter.cxx @@ -38,6 +38,7 @@ #include "controller/SlsScrollBarManager.hxx" #include "controller/SlsProperties.hxx" #include "view/SlideSorterView.hxx" +#include "view/SlsTheme.hxx" #include "model/SlideSorterModel.hxx" #include "glob.hrc" @@ -136,11 +137,13 @@ SlideSorter::SlideSorter ( mpViewShell(&rViewShell), mpViewShellBase(&rViewShell.GetViewShellBase()), mpContentWindow(rpContentWindow), + mbOwnesContentWindow(false), mpHorizontalScrollBar(rpHorizontalScrollBar), mpVerticalScrollBar(rpVerticalScrollBar), mpScrollBarBox(rpScrollBarBox), mbLayoutPending(true), - mpProperties(new controller::Properties()) + mpProperties(new controller::Properties()), + mpTheme(new view::Theme(mpProperties)) { } @@ -159,11 +162,13 @@ SlideSorter::SlideSorter ( 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()) + mpProperties(new controller::Properties()), + mpTheme(new view::Theme(mpProperties)) { } @@ -194,7 +199,7 @@ void SlideSorter::Init (void) SetupListeners (); // Initialize the window. - ::boost::shared_ptr<sd::Window> pWindow (GetContentWindow()); + SharedSdWindow pWindow (GetContentWindow()); if (pWindow != NULL) { ::Window* pParentWindow = pWindow->GetParent(); @@ -213,6 +218,7 @@ void SlideSorter::Init (void) mbIsValid = true; } + } @@ -238,8 +244,17 @@ SlideSorter::~SlideSorter (void) mpHorizontalScrollBar.reset(); mpVerticalScrollBar.reset(); mpScrollBarBox.reset(); - OSL_ASSERT(mpContentWindow.unique()); - OSL_ASSERT(mpContentWindow.use_count()==1); + + 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(); } @@ -325,7 +340,7 @@ void SlideSorter::Paint (const Rectangle& rRepaintArea) -::boost::shared_ptr<sd::Window> SlideSorter::GetContentWindow (void) const +::SharedSdWindow SlideSorter::GetContentWindow (void) const { return mpContentWindow; } @@ -360,7 +375,7 @@ void SlideSorter::SetupControls (::Window* ) void SlideSorter::SetupListeners (void) { - ::boost::shared_ptr<sd::Window> pWindow (GetContentWindow()); + SharedSdWindow pWindow (GetContentWindow()); if (pWindow) { ::Window* pParentWindow = pWindow->GetParent(); @@ -392,7 +407,7 @@ void SlideSorter::ReleaseListeners (void) { mpSlideSorterController->GetScrollBarManager().Disconnect(); - ::boost::shared_ptr<sd::Window> pWindow (GetContentWindow()); + SharedSdWindow pWindow (GetContentWindow()); if (pWindow) { @@ -430,7 +445,12 @@ void SlideSorter::CreateModelViewController (void) 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(); } @@ -551,9 +571,8 @@ void SlideSorter::SetCurrentFunction (const FunctionReference& rpFunction) } else { - ::boost::shared_ptr<ContentWindow> pWindow - = ::boost::dynamic_pointer_cast<ContentWindow>(GetContentWindow()); - if (pWindow.get() != NULL) + ContentWindow* pWindow = dynamic_cast<ContentWindow*>(GetContentWindow().get()); + if (pWindow != NULL) pWindow->SetCurrentFunction(rpFunction); } } @@ -563,12 +582,22 @@ void SlideSorter::SetCurrentFunction (const FunctionReference& 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 { @@ -667,4 +696,7 @@ long ContentWindow::Notify (NotifyEvent& rEvent) } // end of anonymous namespace + + + } } // end of namespace ::sd::slidesorter diff --git a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx index 194cf0f0ab83..97d2b563906d 100644 --- a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx +++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx @@ -191,7 +191,7 @@ void SlideSorterViewShell::Initialize (void) // 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.) - ::boost::shared_ptr<sd::Window> pWindow (mpSlideSorter->GetContentWindow()); + SharedSdWindow pWindow (mpSlideSorter->GetContentWindow()); if (pWindow) { pWindow->Hide(); @@ -549,6 +549,23 @@ void SlideSorterViewShell::ArrangeGUIElements (void) +bool SlideSorterViewShell::HandleScrollCommand (const CommandEvent& rEvent, ::sd::Window* pWindow) +{ + bool bDone = ViewShell::HandleScrollCommand(rEvent, pWindow); + + if (bDone) + { + OSL_ASSERT(mpSlideSorter.get()!=NULL); + if (rEvent.GetCommand() == COMMAND_WHEEL) + mpSlideSorter->GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel(), false); + } + + return bDone; +} + + + + SvBorder SlideSorterViewShell::GetBorder (bool ) { OSL_ASSERT(mpSlideSorter.get()!=NULL); diff --git a/sd/source/ui/slidesorter/view/SlideSorterView.cxx b/sd/source/ui/slidesorter/view/SlideSorterView.cxx index 410971abf664..ec3a83202e56 100644 --- a/sd/source/ui/slidesorter/view/SlideSorterView.cxx +++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx @@ -38,6 +38,7 @@ #include "ViewShell.hxx" #include "SlsViewCacheContext.hxx" #include "SlsLayeredDevice.hxx" +#include "SlsSelectionPainter.hxx" #include "view/SlsLayouter.hxx" #include "view/SlsPageObjectLayouter.hxx" #include "view/SlsPageObjectPainter.hxx" @@ -82,6 +83,7 @@ #include <drawinglayer/geometry/viewinformation2d.hxx> #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx> +#include <canvas/elapsedtime.hxx> #include <boost/bind.hpp> @@ -131,22 +133,24 @@ public: maColor(GetColor()), mnLocalTime(-nStartTime), mnValue(0), - mnStartTime(nStartTime) + mnStartTime(nStartTime), + mbIsValid(rWindowSize.Width()>10 && rWindowSize.Height()>10), + mnSpeedUp(0.5 + rand() * 1.0 / RAND_MAX) { } void SetTime (const double nTime) { - mnLocalTime = nTime - mnStartTime; - if (mnLocalTime >= 0 && mnLocalTime <= 1) - mnValue = controller::AnimationFunction::SlowInSlowOut_0to0_Sine(mnLocalTime); + mnLocalTime = (nTime - mnStartTime) * mnSpeedUp; + if (mnLocalTime >= 0 && mnLocalTime <= mnSpeedUp) + mnValue = controller::AnimationFunction::SlowInSlowOut_0to0_Sine(mnLocalTime/mnSpeedUp); else mnValue = 0; } bool IsExpired (void) { - return mnLocalTime >= 1.0; + return mnLocalTime >= mnSpeedUp || ! mbIsValid; } Rectangle GetBoundingBox (void) @@ -165,7 +169,7 @@ public: void Paint (OutputDevice& rDevice) { - if (mnLocalTime < 0) + if (mnLocalTime < 0 || ! mbIsValid) return; rDevice.SetFillColor(maColor); @@ -191,6 +195,8 @@ private: double mnLocalTime; double mnValue; const double mnStartTime; + const bool mbIsValid; + const double mnSpeedUp; static Color GetColor (void) { @@ -213,7 +219,7 @@ class BackgroundPainter public: BackgroundPainter ( const ::boost::shared_ptr<controller::Animator>& rpAnimator, - const ::boost::shared_ptr< ::Window>& rpWindow, + const SharedSdWindow& rpWindow, const Color aBackgroundColor, const bool bIsAnimated) : mpAnimator(rpAnimator), @@ -235,7 +241,8 @@ public: ~BackgroundPainter (void) { - mpAnimator->RemoveAnimation(mnAnimationId); + if (mnAnimationId >= 0) + mpAnimator->RemoveAnimation(mnAnimationId); } virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea) @@ -288,7 +295,7 @@ private: typedef ::std::vector< ::boost::shared_ptr<AnimatedSphere> > SphereVector; SphereVector maSpheres; SharedILayerInvalidator mpInvalidator; - ::boost::shared_ptr< ::Window> mpWindow; + SharedSdWindow mpWindow; controller::Animator::AnimationId mnAnimationId; void Invalidate (void) @@ -316,13 +323,13 @@ SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter) rSlideSorter.GetViewShell()), mrSlideSorter(rSlideSorter), mrModel(rSlideSorter.GetModel()), + mbIsDisposed(false), mpLayouter (new Layouter (rSlideSorter.GetContentWindow())), mbPageObjectVisibilitiesValid (false), mpPreviewCache(), mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())), mpViewOverlay (new ViewOverlay(rSlideSorter, mpLayeredDevice)), - mnFirstVisiblePageIndex(0), - mnLastVisiblePageIndex(-1), + maVisiblePageRange(-1,-1), mbModelChangedWhileModifyEnabled(true), maPreviewSize(0,0), mbPreciousFlagUpdatePending(true), @@ -330,8 +337,11 @@ SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter) mpProperties(rSlideSorter.GetProperties()), mpPageUnderMouse(), mnButtonUnderMouse(-1), - mpPageObjectPainter() + mpPageObjectPainter(), + mpSelectionPainter() { + OSL_TRACE("layered device at %x", mpLayeredDevice.get()); + // Hide the page that contains the page objects. SetPageVisible (FALSE); @@ -340,7 +350,8 @@ SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter) // the SlideSorterView destructor the layered device is destroyed and // with it the only reference to the wrapper which therefore is also // destroyed. - mpLayeredDevice->RegisterPainter(SharedILayerPainter(new Painter(*this)), 1); + OSL_TRACE("layered device at %x", mpLayeredDevice.get()); + mpLayeredDevice->RegisterPainter(SharedILayerPainter(new Painter(*this)), 2); } @@ -348,8 +359,32 @@ SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter) SlideSorterView::~SlideSorterView (void) { - mpLayeredDevice->Dispose(); + if ( ! mbIsDisposed) + { + OSL_ASSERT(mbIsDisposed); + Dispose(); + } +} + + + + +void SlideSorterView::Init (void) +{ + HandleModelChange(); + + // mpSelectionPainter.reset(new SelectionPainter(mrSlideSorter)); + // mpLayeredDevice->RegisterPainter(mpSelectionPainter, 1); +} + + + +void SlideSorterView::Dispose (void) +{ + mpSelectionPainter.reset(); + + mpLayeredDevice->Dispose(); mpPreviewCache.reset(); // hide the page to avoid problems in the view when deleting @@ -364,13 +399,8 @@ SlideSorterView::~SlideSorterView (void) OSL_ASSERT(mpLayeredDevice.unique()); mpLayeredDevice.reset(); -} - - - -void SlideSorterView::Dispose (void) -{ + mbIsDisposed = true; } @@ -380,7 +410,7 @@ sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rPosition) const { sal_Int32 nIndex (-1); - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { nIndex = mpLayouter->GetIndexAtPoint (pWindow->PixelToLogic (rPosition)); @@ -401,7 +431,7 @@ sal_Int32 SlideSorterView::GetFadePageIndexAtPoint ( { sal_Int32 nIndex (-1); - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { Point aModelPosition (pWindow->PixelToLogic (rPosition)); @@ -537,12 +567,12 @@ void SlideSorterView::Resize (void) SharedILayerPainter(new BackgroundPainter( mrSlideSorter.GetController().GetAnimator(), mrSlideSorter.GetContentWindow(), - Color(0xf9fafa),//mpProperties->GetBackgroundColor(), + mrSlideSorter.GetTheme()->GetColor(Theme::Background), false)), 0); mpLayeredDevice->Resize(); - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (mrModel.GetPageCount()>0 && pWindow) { bool bRearrangeSuccess (false); @@ -564,6 +594,7 @@ void SlideSorterView::Resize (void) if (bRearrangeSuccess) { Layout(); + RequestRepaint(); } } } @@ -573,7 +604,7 @@ void SlideSorterView::Resize (void) void SlideSorterView::Layout () { - const ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { // Set the model area, i.e. the smallest rectangle that includes all @@ -589,7 +620,7 @@ void SlideSorterView::Layout () const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetPreviewSize()); if (maPreviewSize != aNewPreviewSize && GetPreviewCache()) { - mpPreviewCache->ChangeSize(aNewPreviewSize, false); + mpPreviewCache->ChangeSize(aNewPreviewSize, true); maPreviewSize = aNewPreviewSize; } } @@ -603,6 +634,8 @@ void SlideSorterView::Layout () model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement()); pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex())); } + + GetPageObjectPainter()->NotifyResize(); } InvalidatePageObjectVisibilities (); @@ -621,7 +654,7 @@ void SlideSorterView::InvalidatePageObjectVisibilities (void) void SlideSorterView::DeterminePageObjectVisibilities (void) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { // Set this flag to true here so that an invalidate during the @@ -629,28 +662,27 @@ void SlideSorterView::DeterminePageObjectVisibilities (void) mbPageObjectVisibilitiesValid = true; Rectangle aViewArea (pWindow->PixelToLogic(Rectangle(Point(0,0),pWindow->GetSizePixel()))); - const int nFirstIndex (mpLayouter->GetIndexOfFirstVisiblePageObject(aViewArea)); - const int nLastIndex (mpLayouter->GetIndexOfLastVisiblePageObject(aViewArea)); - const int nMinIndex (::std::min (mnFirstVisiblePageIndex, nFirstIndex)); - const int nMaxIndex (::std::max (mnLastVisiblePageIndex, nLastIndex)); + 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 (mnFirstVisiblePageIndex!=nFirstIndex || mnLastVisiblePageIndex!=nLastIndex) + if (maVisiblePageRange != aRange) mbPreciousFlagUpdatePending |= true; model::SharedPageDescriptor pDescriptor; - for (int nIndex=nMinIndex; nIndex<=nMaxIndex; nIndex++) + for (int nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++) { pDescriptor = mrModel.GetPageDescriptor(nIndex); if (pDescriptor.get() != NULL) SetState( pDescriptor, PageDescriptor::ST_Visible, - nIndex>=nFirstIndex && nIndex<=nLastIndex); + aRange.IsInside(nIndex)); } - mnFirstVisiblePageIndex = nFirstIndex; - mnLastVisiblePageIndex = nLastIndex; + maVisiblePageRange = aRange; } } @@ -674,9 +706,9 @@ void SlideSorterView::UpdatePreciousFlags (void) { pCache->SetPreciousFlag( pDescriptor->GetPage(), - (nIndex>=mnFirstVisiblePageIndex && nIndex<=mnLastVisiblePageIndex)); + maVisiblePageRange.IsInside(nIndex)); SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex, - (nIndex>=mnFirstVisiblePageIndex && nIndex<=mnLastVisiblePageIndex)); + maVisiblePageRange.IsInside(nIndex)); } else { @@ -711,7 +743,7 @@ SlideSorterView::Orientation SlideSorterView::GetOrientation (void) const void SlideSorterView::RequestRepaint (void) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { pWindow->Invalidate(); @@ -735,7 +767,7 @@ void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescr void SlideSorterView::RequestRepaint (const Rectangle& rRepaintBox) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow) { pWindow->Invalidate(rRepaintBox); @@ -752,6 +784,7 @@ Rectangle SlideSorterView::GetModelArea (void) } +static ::canvas::tools::ElapsedTime gaTimer; void SlideSorterView::CompleteRedraw ( @@ -759,6 +792,11 @@ void SlideSorterView::CompleteRedraw ( const Region& rPaintArea, sdr::contact::ViewObjectContactRedirector* pRedirector) { + const double nStartTime (gaTimer.getElapsedTime()); + OSL_TRACE("SlideSorterView::CompleteRedraw start at %f, %d", + nStartTime, + mnLockRedrawSmph); + if (pDevice == NULL || pDevice!=mrSlideSorter.GetContentWindow().get()) return; @@ -778,6 +816,9 @@ void SlideSorterView::CompleteRedraw ( { View::CompleteRedraw(pDevice, rPaintArea, pRedirector); } + + const double nEndTime (gaTimer.getElapsedTime()); + OSL_TRACE("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000); } @@ -800,11 +841,8 @@ void SlideSorterView::Paint ( // Paint all page objects that are fully or partially inside the // repaint region. - sal_Int32 nFirst (mpLayouter->GetIndexOfFirstVisiblePageObject(rRepaintArea)); - sal_Int32 nLast (std::min( - mpLayouter->GetIndexOfLastVisiblePageObject(rRepaintArea), - mrModel.GetPageCount())); - for (sal_Int32 nIndex=nFirst; nIndex<=nLast; ++nIndex) + 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)) @@ -819,7 +857,7 @@ void SlideSorterView::Paint ( ::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache (void) { - ::boost::shared_ptr<sd::Window> pWindow (mrSlideSorter.GetContentWindow()); + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); if (pWindow && mpPreviewCache.get() == NULL) { mpPreviewCache.reset( @@ -843,14 +881,11 @@ ViewOverlay& SlideSorterView::GetOverlay (void) -SlideSorterView::PageRange SlideSorterView::GetVisiblePageRange (void) +Pair SlideSorterView::GetVisiblePageRange (void) { - const int nMaxPageIndex (mrModel.GetPageCount() - 1); if ( ! mbPageObjectVisibilitiesValid) DeterminePageObjectVisibilities(); - return PageRange( - ::std::min(mnFirstVisiblePageIndex,nMaxPageIndex), - ::std::min(mnLastVisiblePageIndex, nMaxPageIndex)); + return maVisiblePageRange; } @@ -868,6 +903,37 @@ void SlideSorterView::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint +void SlideSorterView::UpdatePageUnderMouse ( + const Point& rMousePosition, + const bool bIsMouseButtonDown) +{ + // Determine page under mouse and show the mouse over effect. + model::SharedPageDescriptor pHitDescriptor ( + mrSlideSorter.GetController().GetPageAt(rMousePosition)); + SetPageUnderMouse(pHitDescriptor); + + // Handle the mouse being over any buttons. + if (pHitDescriptor) + { + SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); + const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); + const sal_Int32 nButtonIndex ( + GetLayouter().GetPageObjectLayouter()->GetButtonIndexAt ( + pHitDescriptor, + aMouseModelPosition)); + SetButtonUnderMouse(nButtonIndex); + if (bIsMouseButtonDown) + { + pHitDescriptor->GetVisualState().SetActiveButtonState( + nButtonIndex, + model::VisualState::BS_Pressed); + } + } +} + + + + void SlideSorterView::SetPageUnderMouse (const model::SharedPageDescriptor& rpDescriptor) { if (mpPageUnderMouse != rpDescriptor) diff --git a/sd/source/ui/slidesorter/view/SlsIcons.hrc b/sd/source/ui/slidesorter/view/SlsIcons.hrc index c174252aa7ce..cb0fe634f501 100644 --- a/sd/source/ui/slidesorter/view/SlsIcons.hrc +++ b/sd/source/ui/slidesorter/view/SlsIcons.hrc @@ -42,4 +42,6 @@ #define IMAGE_SHOW_SLIDE 5 #define IMAGE_NEW_SLIDE 6 +#define IMAGE_SHADOW 10 + #endif diff --git a/sd/source/ui/slidesorter/view/SlsIcons.src b/sd/source/ui/slidesorter/view/SlsIcons.src index c3f68cde7436..facd4138b574 100644 --- a/sd/source/ui/slidesorter/view/SlsIcons.src +++ b/sd/source/ui/slidesorter/view/SlsIcons.src @@ -62,4 +62,8 @@ Resource IMG_ICONS ImageBitmap = Bitmap { File = "commandimagelist/lc_insertpage.png" ; }; }; + Image IMAGE_SHADOW + { + ImageBitmap = Bitmap { File = "slide_sorter_shadow.png" ; }; + }; }; diff --git a/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx index e76728e95c1c..aba967ebdeda 100644 --- a/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx +++ b/sd/source/ui/slidesorter/view/SlsLayeredDevice.cxx @@ -50,7 +50,7 @@ class LayerInvalidator : public ILayerInvalidator public: LayerInvalidator ( const ::boost::shared_ptr<LayeredDevice>& rpLayeredDevice, - const ::boost::shared_ptr< ::Window>& rpTargetWindow, + const SharedSdWindow& rpTargetWindow, const int nLayer) : mpLayeredDevice(rpLayeredDevice), mpTargetWindow(rpTargetWindow), @@ -66,7 +66,7 @@ public: private: const ::boost::shared_ptr<LayeredDevice> mpLayeredDevice; - const ::boost::shared_ptr< ::Window> mpTargetWindow; + SharedSdWindow mpTargetWindow; const int mnLayer; }; @@ -103,18 +103,56 @@ void ForAllRectangles (const Region& rRegion, ::boost::function<void(const Recta } } +class Layer : private ::boost::noncopyable +{ +public: + Layer (void); + ~Layer (void); + + void Initialize (const SharedSdWindow& rpTargetWindow); + void Invalidate (const Rectangle& rInvalidationBox); + 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) { OSL_TRACE("created layer container at %x", this); } + ~LayerContainer (void) { OSL_TRACE("destroyed layer container at %x", this); } +}; + + -LayeredDevice::LayeredDevice (const ::boost::shared_ptr< ::Window>& rpTargetWindow) +//===== LayeredDevice ========================================================= + +LayeredDevice::LayeredDevice (const SharedSdWindow& rpTargetWindow) : mpTargetWindow(rpTargetWindow), - maLayers(1), + mpLayers(new LayerContainer()), mpBackBuffer(new VirtualDevice(*mpTargetWindow)), maSavedMapMode(rpTargetWindow->GetMapMode()) { + OSL_TRACE("layered device created at %x", this); mpBackBuffer->SetOutputSizePixel(mpTargetWindow->GetSizePixel()); } @@ -123,6 +161,7 @@ LayeredDevice::LayeredDevice (const ::boost::shared_ptr< ::Window>& rpTargetWind LayeredDevice::~LayeredDevice (void) { + OSL_TRACE("layered device destroyed at %x", this); } @@ -132,13 +171,13 @@ void LayeredDevice::Invalidate ( const Rectangle& rInvalidationArea, const sal_Int32 nLayer) { - if (nLayer<0 || sal_uInt32(nLayer)>=maLayers.size()) + if (nLayer<0 || sal_uInt32(nLayer)>=mpLayers->size()) { - OSL_ASSERT(nLayer>=0 && nLayer<maLayers.size()); + OSL_ASSERT(nLayer>=0 && nLayer<mpLayers->size()); return; } - maLayers[nLayer].Invalidate(rInvalidationArea); + (*mpLayers)[nLayer]->Invalidate(rInvalidationArea); } @@ -146,8 +185,8 @@ void LayeredDevice::Invalidate ( void LayeredDevice::InvalidateAllLayers (const Rectangle& rInvalidationArea) { - for (sal_uInt32 nLayer=0; nLayer<maLayers.size(); ++nLayer) - maLayers[nLayer].Invalidate(rInvalidationArea); + for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer) + (*mpLayers)[nLayer]->Invalidate(rInvalidationArea); } @@ -157,6 +196,8 @@ void LayeredDevice::RegisterPainter ( const SharedILayerPainter& rpPainter, const sal_Int32 nLayer) { + OSL_TRACE("layered device registering painter at %x", this); + OSL_ASSERT(mpLayers); if ( ! rpPainter) { OSL_ASSERT(rpPainter); @@ -168,11 +209,19 @@ void LayeredDevice::RegisterPainter ( return; } - if (sal_uInt32(nLayer) >= maLayers.size()) - maLayers.resize(nLayer+1); - maLayers[nLayer].AddPainter(rpPainter); + // Provide the layers. + if (sal_uInt32(nLayer) >= mpLayers->size()) + { + const sal_Int32 nOldLayerCount (mpLayers->size()); + mpLayers->resize(nLayer+1); + + for (sal_Int32 nIndex=nOldLayerCount; nIndex<mpLayers->size(); ++nIndex) + (*mpLayers)[nIndex].reset(new Layer()); + } + + (*mpLayers)[nLayer]->AddPainter(rpPainter); if (nLayer == 0) - maLayers[nLayer].Initialize(mpTargetWindow); + (*mpLayers)[nLayer]->Initialize(mpTargetWindow); rpPainter->SetLayerInvalidator( SharedILayerInvalidator(new LayerInvalidator(shared_from_this(),mpTargetWindow,nLayer))); @@ -190,19 +239,19 @@ void LayeredDevice::RemovePainter ( OSL_ASSERT(rpPainter); return; } - if (nLayer<0 || sal_uInt32(nLayer)>=maLayers.size()) + if (nLayer<0 || sal_uInt32(nLayer)>=mpLayers->size()) { - OSL_ASSERT(nLayer>=0 && nLayer<maLayers.size()); + OSL_ASSERT(nLayer>=0 && nLayer<mpLayers->size()); return; } rpPainter->SetLayerInvalidator(SharedILayerInvalidator()); - maLayers[nLayer].RemovePainter(rpPainter); + (*mpLayers)[nLayer]->RemovePainter(rpPainter); // Remove top most layers that do not contain any painters. - while ( ! maLayers.empty() && ! maLayers.back().HasPainter()) - maLayers.erase(maLayers.end()-1); + while ( ! mpLayers->empty() && ! mpLayers->back()->HasPainter()) + mpLayers->erase(mpLayers->end()-1); } @@ -211,8 +260,8 @@ void LayeredDevice::RemovePainter ( bool LayeredDevice::HasPainter (const sal_Int32 nLayer) { return nLayer>=0 - && sal_uInt32(nLayer)<maLayers.size() - && maLayers[nLayer].HasPainter(); + && sal_uInt32(nLayer)<mpLayers->size() + && (*mpLayers)[nLayer]->HasPainter(); } @@ -224,8 +273,8 @@ void LayeredDevice::Repaint (const Region& rRepaintRegion) // Validate the contents of all layers (that have their own devices.) ::std::for_each( - maLayers.begin(), - maLayers.end(), + mpLayers->begin(), + mpLayers->end(), ::boost::bind(&Layer::Validate, _1, mpTargetWindow->GetMapMode())); ForAllRectangles(rRepaintRegion, ::boost::bind(&LayeredDevice::RepaintRectangle, this, _1)); @@ -236,10 +285,10 @@ void LayeredDevice::Repaint (const Region& rRepaintRegion) void LayeredDevice::RepaintRectangle (const Rectangle& rRepaintRectangle) { - if (maLayers.size() <= 1) + if (mpLayers->size() <= 1) { // Just copy the main layer into the target device. - maLayers[0].Repaint(*mpTargetWindow, rRepaintRectangle); + (*mpLayers)[0]->Repaint(*mpTargetWindow, rRepaintRectangle); } else { @@ -248,8 +297,8 @@ void LayeredDevice::RepaintRectangle (const Rectangle& rRepaintRectangle) // device. mpBackBuffer->SetMapMode(mpTargetWindow->GetMapMode()); ::std::for_each( - maLayers.begin(), - maLayers.end(), + mpLayers->begin(), + mpLayers->end(), ::boost::bind(&Layer::Repaint, _1, ::boost::ref(*mpBackBuffer), rRepaintRectangle)); DeviceCopy(*mpTargetWindow, *mpBackBuffer, rRepaintRectangle); @@ -263,7 +312,7 @@ void LayeredDevice::Resize (void) { const Size aSize (mpTargetWindow->GetSizePixel()); mpBackBuffer->SetOutputSizePixel(aSize); - ::std::for_each(maLayers.begin(), maLayers.end(), ::boost::bind(&Layer::Resize, _1, aSize)); + ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Resize, _1, aSize)); } @@ -271,8 +320,8 @@ void LayeredDevice::Resize (void) void LayeredDevice::Dispose (void) { - ::std::for_each(maLayers.begin(), maLayers.end(), ::boost::bind(&Layer::Dispose, _1)); - maLayers.clear(); + ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Dispose, _1)); + mpLayers->clear(); } @@ -292,8 +341,8 @@ void LayeredDevice::HandleMapModeChange (void) { // When the scale has changed then we have to paint everything. ::std::for_each( - maLayers.begin(), - maLayers.end(), + mpLayers->begin(), + mpLayers->end(), ::boost::bind(&Layer::Invalidate, _1, ::boost::cref(aLogicWindowBox))); } else if (maSavedMapMode.GetOrigin() != rMapMode.GetOrigin()) @@ -330,9 +379,9 @@ void LayeredDevice::HandleMapModeChange (void) -//===== LayeredDevice::Layer ================================================== +//===== Layer ================================================================= -LayeredDevice::Layer::Layer (void) +Layer::Layer (void) : mpLayerDevice(), maPainters(), maInvalidationRegion() @@ -342,7 +391,14 @@ LayeredDevice::Layer::Layer (void) -void LayeredDevice::Layer::Initialize (const ::boost::shared_ptr< ::Window>& rpTargetWindow) +Layer::~Layer (void) +{ +} + + + + +void Layer::Initialize (const SharedSdWindow& rpTargetWindow) { if ( ! mpLayerDevice) { @@ -354,7 +410,7 @@ void LayeredDevice::Layer::Initialize (const ::boost::shared_ptr< ::Window>& rpT -void LayeredDevice::Layer::Invalidate (const Rectangle& rInvalidationBox) +void Layer::Invalidate (const Rectangle& rInvalidationBox) { maInvalidationRegion.Union(rInvalidationBox); } @@ -362,7 +418,7 @@ void LayeredDevice::Layer::Invalidate (const Rectangle& rInvalidationBox) -void LayeredDevice::Layer::Validate (const MapMode& rMapMode) +void Layer::Validate (const MapMode& rMapMode) { if (mpLayerDevice && ! maInvalidationRegion.IsEmpty()) { @@ -370,7 +426,7 @@ void LayeredDevice::Layer::Validate (const MapMode& rMapMode) ForAllRectangles( maInvalidationRegion, - ::boost::bind(&LayeredDevice::Layer::ValidateRectangle, this, _1)); + ::boost::bind(&Layer::ValidateRectangle, this, _1)); } // else nothing to do now. The painting is done in Repaint() directly // into the back buffer. @@ -381,7 +437,7 @@ void LayeredDevice::Layer::Validate (const MapMode& rMapMode) -void LayeredDevice::Layer::ValidateRectangle (const Rectangle& rBox) +void Layer::ValidateRectangle (const Rectangle& rBox) { const Region aSavedClipRegion (mpLayerDevice->GetClipRegion()); mpLayerDevice->SetClipRegion(Region(rBox)); @@ -401,7 +457,7 @@ void LayeredDevice::Layer::ValidateRectangle (const Rectangle& rBox) -void LayeredDevice::Layer::Repaint ( +void Layer::Repaint ( OutputDevice& rTargetDevice, const Rectangle& rRepaintRectangle) { @@ -424,7 +480,7 @@ void LayeredDevice::Layer::Repaint ( -void LayeredDevice::Layer::Resize (const Size& rSize) +void Layer::Resize (const Size& rSize) { if (mpLayerDevice) { @@ -436,7 +492,7 @@ void LayeredDevice::Layer::Resize (const Size& rSize) -void LayeredDevice::Layer::AddPainter (const SharedILayerPainter& rpPainter) +void Layer::AddPainter (const SharedILayerPainter& rpPainter) { OSL_ASSERT(::std::find(maPainters.begin(), maPainters.end(), rpPainter) == maPainters.end()); @@ -446,7 +502,7 @@ void LayeredDevice::Layer::AddPainter (const SharedILayerPainter& rpPainter) -void LayeredDevice::Layer::RemovePainter (const SharedILayerPainter& rpPainter) +void Layer::RemovePainter (const SharedILayerPainter& rpPainter) { const ::std::vector<SharedILayerPainter>::iterator iPainter ( ::std::find(maPainters.begin(), maPainters.end(), rpPainter)); @@ -463,7 +519,7 @@ void LayeredDevice::Layer::RemovePainter (const SharedILayerPainter& rpPainter) -bool LayeredDevice::Layer::HasPainter (void) const +bool Layer::HasPainter (void) const { return !maPainters.empty(); } @@ -471,7 +527,7 @@ bool LayeredDevice::Layer::HasPainter (void) const -void LayeredDevice::Layer::Dispose (void) +void Layer::Dispose (void) { maPainters.clear(); } diff --git a/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx b/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx index 522355ca303e..3441b30d6739 100644 --- a/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx +++ b/sd/source/ui/slidesorter/view/SlsLayeredDevice.hxx @@ -33,6 +33,7 @@ #define SD_SLIDESORTER_VIEW_LAYERED_DEVICE_HXX #include "view/SlsILayerPainter.hxx" +#include "SlideSorter.hxx" #include <tools/gen.hxx> #include <vcl/region.hxx> @@ -53,7 +54,7 @@ class LayeredDevice { public: - LayeredDevice (const ::boost::shared_ptr< ::Window>& rpTargetWindow); + LayeredDevice (const SharedSdWindow& rpTargetWindow); ~LayeredDevice (void); void Invalidate ( @@ -78,33 +79,10 @@ public: void Dispose (void); - class Layer - { - public: - Layer (void); - - void Initialize (const ::boost::shared_ptr< ::Window>& rpTargetWindow); - void Invalidate (const Rectangle& rInvalidationBox); - 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); - }; - private: - const ::boost::shared_ptr< ::Window> mpTargetWindow; - ::std::vector<Layer> maLayers; + SharedSdWindow mpTargetWindow; + class LayerContainer; + ::boost::scoped_ptr<LayerContainer> mpLayers; ::boost::scoped_ptr<VirtualDevice> mpBackBuffer; MapMode maSavedMapMode; diff --git a/sd/source/ui/slidesorter/view/SlsLayouter.cxx b/sd/source/ui/slidesorter/view/SlsLayouter.cxx index 0c93c865dec8..9eee19b796c2 100644 --- a/sd/source/ui/slidesorter/view/SlsLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsLayouter.cxx @@ -38,7 +38,7 @@ namespace sd { namespace slidesorter { namespace view { -Layouter::Layouter (const ::boost::shared_ptr< ::Window>& rpWindow) +Layouter::Layouter (const SharedSdWindow& rpWindow) : mpWindow(rpWindow), mnRequestedLeftBorder(35), mnRequestedRightBorder(35), @@ -58,7 +58,8 @@ Layouter::Layouter (const ::boost::shared_ptr< ::Window>& rpWindow) mnPageCount(0), mnColumnCount(1), mnRowCount(0), - maPageObjectSize(1,1) + maPageObjectSize(1,1), + mbIsVertical(true) { } @@ -150,6 +151,7 @@ bool Layouter::RearrangeHorizontal ( { OSL_ASSERT(mpWindow); + mbIsVertical = false; mnPageCount = nPageCount; if (rWindowSize.Width() > 0 @@ -225,6 +227,7 @@ bool Layouter::RearrangeVertical ( { OSL_ASSERT(mpWindow); + mbIsVertical = true; mnPageCount = nPageCount; if (rWindowSize.Width() > 0 @@ -489,22 +492,69 @@ Point Layouter::GetInsertionMarkerLocation ( -sal_Int32 Layouter::GetIndexOfFirstVisiblePageObject ( - const Rectangle& aVisibleArea) const +Range Layouter::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const { - sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Top(), true, GM_BOTH); - return nRow * mnColumnCount; + sal_Int32 nRow0 = GetRowAtPosition (aVisibleArea.Top(), true, GM_BOTH); + sal_Int32 nRow1 = GetRowAtPosition (aVisibleArea.Bottom(), + true, GM_BOTH); + return Range( + ::std::min(nRow0 * mnColumnCount, mnPageCount-1), + ::std::min((nRow1+1) * mnColumnCount - 1, mnPageCount-1)); } -sal_Int32 Layouter::GetIndexOfLastVisiblePageObject ( - const Rectangle& aVisibleArea) const +Range Layouter::GetSelectionRange ( + const Point& rAnchor, + const Point& rOther, + const Range& rCurrentSelectionRange) const { - sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Bottom(), - true, GM_BOTH); - return (nRow+1) * mnColumnCount - 1; + sal_Int32 nIndexA (GetInsertionIndex(rAnchor, true)); + sal_Int32 nIndexB (GetInsertionIndex(rOther, true)); + + // When either of the locations does not lie over a page then we may + // have to adapt the start or end index. + Rectangle aBoxA (GetPageObjectBox(nIndexA)); + Rectangle aBoxB (GetPageObjectBox(nIndexB)); + if (nIndexA > nIndexB) + { + ::std::swap(nIndexA,nIndexB); + ::std::swap(aBoxA, aBoxB); + } + + if (mnColumnCount == 1) + { + // Vertical arrangement of pages. + if (nIndexA <= nIndexB) + { + if (rOther.Y() < aBoxB.Top()) + --nIndexB; + } + else + { + if (rOther.Y() > aBoxB.Bottom()) + --nIndexA; + } + } + else + { + // Horizontal arrangement of pages. + if (nIndexA <= nIndexB) + { + if (rOther.X() < aBoxB.Left()) + --nIndexB; + } + else + { + if (rOther.X() > aBoxB.Right()) + --nIndexA; + } + } + + return Range( + ::std::min(nIndexA, nIndexB), + ::std::min(mnPageCount-1, ::std::max(nIndexA, nIndexB))); } @@ -561,6 +611,14 @@ sal_Int32 Layouter::GetInsertionIndex ( +bool Layouter::IsVertical (void) const +{ + return mbIsVertical; +} + + + + sal_Int32 Layouter::GetRowAtPosition ( sal_Int32 nYPosition, bool bIncludeBordersAndGaps, diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx index 24cd3e0cdc86..be5c5066863a 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx @@ -39,11 +39,9 @@ namespace sd { namespace slidesorter { namespace view { -const sal_Int32 PageObjectLayouter::mnSelectionIndicatorOffset = 0; -const sal_Int32 PageObjectLayouter::mnSelectionIndicatorThickness = 3; -const sal_Int32 PageObjectLayouter::mnFocusIndicatorOffset = 3; const sal_Int32 PageObjectLayouter::mnPageNumberOffset = 9; -const sal_Int32 PageObjectLayouter::mnOuterBorderWidth = 5; +const sal_Int32 PageObjectLayouter::mnOuterBorderWidth = 6; +const sal_Int32 PageObjectLayouter::mnInfoAreaMinWidth = 26; const Size PageObjectLayouter::maButtonSize (32,32); const sal_Int32 PageObjectLayouter::mnButtonGap (5); @@ -51,23 +49,23 @@ const sal_Int32 PageObjectLayouter::mnButtonGap (5); PageObjectLayouter::PageObjectLayouter ( const Size& rPageObjectWindowSize, const Size& rPageSize, - const ::boost::shared_ptr< ::Window>& rpWindow, - const int nPageCount) + const SharedSdWindow& rpWindow, + const sal_Int32 nPageCount) : mpWindow(rpWindow), maPageObjectSize(rPageObjectWindowSize.Width(), rPageObjectWindowSize.Height()), mnModelToWindowScale(1), maPageObjectBoundingBox(), maPageNumberAreaBoundingBox(), maPreviewBoundingBox(), - maFocusIndicatorBoundingBox(), - maSelectionIndicatorBoundingBox(), maTransitionEffectBoundingBox(), maButtonAreaBoundingBox(), maTransitionEffectIcon(IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR)) { const Size aPageNumberAreaSize (GetPageNumberAreaSize(nPageCount)); - const int nMaximumBorderWidth (mnSelectionIndicatorOffset + mnOuterBorderWidth); + const int nMaximumBorderWidth (mnOuterBorderWidth); + + // Set up some bounding boxes relative to the page object origin. maPageNumberAreaBoundingBox = Rectangle( mnPageNumberOffset, @@ -78,21 +76,9 @@ PageObjectLayouter::PageObjectLayouter ( maPreviewBoundingBox = CalculatePreviewBoundingBox( maPageObjectSize, Size(rPageSize.Width(), rPageSize.Height()), - aPageNumberAreaSize); + ::std::min(aPageNumberAreaSize.Width(), mnInfoAreaMinWidth)); maPageObjectBoundingBox = Rectangle(Point(0,0), maPageObjectSize); - maFocusIndicatorBoundingBox = maPreviewBoundingBox; - maFocusIndicatorBoundingBox.Left() -= mnFocusIndicatorOffset; - maFocusIndicatorBoundingBox.Top() -= mnFocusIndicatorOffset; - maFocusIndicatorBoundingBox.Right() += mnFocusIndicatorOffset; - maFocusIndicatorBoundingBox.Bottom() += mnFocusIndicatorOffset; - - maSelectionIndicatorBoundingBox = maPreviewBoundingBox; - maSelectionIndicatorBoundingBox.Left() -= mnSelectionIndicatorOffset; - maSelectionIndicatorBoundingBox.Top() -= mnSelectionIndicatorOffset; - maSelectionIndicatorBoundingBox.Right() += mnSelectionIndicatorOffset; - maSelectionIndicatorBoundingBox.Bottom() += mnSelectionIndicatorOffset; - const Size aIconSize (maTransitionEffectIcon.GetSizePixel()); const int nLeft (maPreviewBoundingBox.Left() - mnPageNumberOffset - aIconSize.Width() - nMaximumBorderWidth); @@ -113,16 +99,23 @@ PageObjectLayouter::PageObjectLayouter ( +PageObjectLayouter::~PageObjectLayouter(void) +{ +} + + + + Rectangle PageObjectLayouter::CalculatePreviewBoundingBox ( Size& rPageObjectSize, const Size& rPageSize, - const Size& rPageNumberAreaSize) + const sal_Int32 nInfoAreaWidth) { - const int nMaximumBorderWidth (mnSelectionIndicatorOffset + mnOuterBorderWidth); + const int nMaximumBorderWidth (mnOuterBorderWidth); const int nLeftAreaWidth ( 2*mnPageNumberOffset + ::std::max( - rPageNumberAreaSize.Width(), + nInfoAreaWidth, maTransitionEffectIcon.GetSizePixel().Width())); int nPreviewWidth; int nPreviewHeight; @@ -178,12 +171,6 @@ Rectangle PageObjectLayouter::GetBoundingBox ( const CoordinateSystem eCoordinateSystem, const sal_Int32 nIndex) { - if ( ! rpPageDescriptor) - { - OSL_ASSERT(rpPageDescriptor); - return Rectangle(); - } - Rectangle aBoundingBox; switch (ePart) { @@ -196,14 +183,6 @@ Rectangle PageObjectLayouter::GetBoundingBox ( aBoundingBox = maPreviewBoundingBox; break; - case FocusIndicator: - aBoundingBox = maFocusIndicatorBoundingBox; - break; - - case SelectionIndicator: - aBoundingBox = maSelectionIndicatorBoundingBox; - break; - case PageNumber: aBoundingBox = maPageNumberAreaBoundingBox; break; @@ -230,7 +209,7 @@ Rectangle PageObjectLayouter::GetBoundingBox ( break; } - Point aLocation (rpPageDescriptor->GetLocation()); + Point aLocation (rpPageDescriptor ? rpPageDescriptor->GetLocation() : Point(0,0)); if (eCoordinateSystem == ScreenCoordinateSystem) aLocation += mpWindow->GetMapMode().GetOrigin(); diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx index 99674577e99c..41a9400c374c 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx @@ -39,6 +39,7 @@ #include "view/SlideSorterView.hxx" #include "view/SlsPageObjectLayouter.hxx" #include "view/SlsLayouter.hxx" +#include "view/SlsTheme.hxx" #include "SlsIcons.hxx" #include "cache/SlsPageCache.hxx" #include "controller/SlsProperties.hxx" @@ -54,6 +55,8 @@ #include <vcl/svapp.hxx> #include <vcl/vclenum.hxx> #include <vcl/bmpacc.hxx> +#include <vcl/virdev.hxx> +#include <canvas/elapsedtime.hxx> using namespace ::drawinglayer::primitive2d; using namespace ::basegfx; @@ -62,29 +65,6 @@ namespace sd { namespace slidesorter { namespace view { namespace { -// Reds -#define Amber 0xff7e00 - -// Greens -#define AndroidGreen 0xa4c639 -#define AppleGreen 0x8db600 -#define Asparagus 0x87a96b - -// Blues -#define Azure 0x000fff -#define DarkCerulean 0x08457e -#define StellaBlue 0x009ee1 -#define AirForceBlue 0x5d8aa8 - -// Off white -#define OldLace 0xfdf5e6 - -// Off grays -#define Arsenic 0x3b444b - -#define MouseOverColor (0x59000000 | StellaBlue) - -#define CornerRadius 4.0 UINT8 Blend ( const UINT8 nValue1, @@ -150,25 +130,126 @@ void AdaptTransparency (AlphaMask& rMask, const double nAlpha) } +/** Bitmap with offset that is used when the bitmap is painted. The bitmap +*/ +class OffsetBitmap +{ +public: + /** 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); + + /** Create bitmap and offset from the given values. Corner bitmaps are + constructed with the given width and height. Side bitmaps are + stretched along one axis to reduce the paint calls when the sides of + a frame are painted. + @param rBitmap + The larger bitmap that contains the four corner bitmaps and the + four side bitmaps. + */ + void SetBitmap ( + const BitmapEx& rBitmap, + const sal_Int32 nOriginX, + const sal_Int32 nOriginY, + const sal_Int32 nWidth, + const sal_Int32 nHeight, + const sal_Int32 nOffsetX, + const sal_Int32 nOffsetY); + + /** 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; + +private: + BitmapEx maBitmap; + Point maOffset; +}; + +class FramePainter +{ +public: + FramePainter (const BitmapEx& rBitmap); + ~FramePainter (void); + void PaintFrame (OutputDevice&rDevice, const Rectangle aBox) const; + +private: + OffsetBitmap maShadowTopLeft; + OffsetBitmap maShadowTop; + OffsetBitmap maShadowTopRight; + OffsetBitmap maShadowLeft; + OffsetBitmap maShadowRight; + OffsetBitmap maShadowBottomLeft; + OffsetBitmap maShadowBottom; + OffsetBitmap maShadowBottomRight; + bool mbIsValid; +}; + + } // end of anonymous namespace +//===== PageObjectPainter ===================================================== + PageObjectPainter::PageObjectPainter ( const SlideSorter& rSlideSorter) : mrLayouter(rSlideSorter.GetView().GetLayouter()), mpPageObjectLayouter(), mpCache(rSlideSorter.GetView().GetPreviewCache()), mpProperties(rSlideSorter.GetProperties()), - mpFont(), + mpTheme(rSlideSorter.GetTheme()), + mpPageNumberFont(), maStartPresentationIcon(), maShowSlideIcon(), - maNewSlideIcon() + maNewSlideIcon(), + mpShadowPainter(), + maNormalBackground(), + maSelectionBackground(), + maMouseOverBackground() { LocalResource aResource (IMG_ICONS); + maStartPresentationIcon = Image(SdResId(IMAGE_PRESENTATION)).GetBitmapEx(); maShowSlideIcon = Image(SdResId(IMAGE_SHOW_SLIDE)).GetBitmapEx(); maNewSlideIcon = Image(SdResId(IMAGE_NEW_SLIDE)).GetBitmapEx(); + + mpShadowPainter.reset(new FramePainter(mpTheme->GetIcon(Theme::RawShadow))); +} + + + + +PageObjectPainter::~PageObjectPainter (void) +{ } @@ -187,20 +268,32 @@ void PageObjectPainter::PaintPageObject ( return; } - if ( ! mpFont) - { - mpFont.reset(new Font(rDevice.GetFont())); - mpFont->SetWeight(WEIGHT_BOLD); - } - if (mpFont) - rDevice.SetFont(*mpFont); + if ( ! mpPageNumberFont) + mpPageNumberFont = mpTheme->CreateFont(Theme::PageNumberFont, rDevice); + PrepareBackgrounds(rDevice); + + // Turn off antialiasing to avoid the bitmaps from being shifted by + // fractions of a pixel and thus show blurry edges. + const USHORT nSavedAntialiasingMode (rDevice.GetAntialiasing()); + rDevice.SetAntialiasing(nSavedAntialiasingMode & ~ANTIALIASING_ENABLE_B2DDRAW); PaintBackground(rDevice, rpDescriptor); PaintPreview(rDevice, rpDescriptor); PaintPageNumber(rDevice, rpDescriptor); PaintTransitionEffect(rDevice, rpDescriptor); PaintButtons(rDevice, rpDescriptor); - // PaintBorder(rDevice, rpDescriptor); + + rDevice.SetAntialiasing(nSavedAntialiasingMode); +} + + + + +void PageObjectPainter::NotifyResize (void) +{ + maNormalBackground.SetEmpty(); + maSelectionBackground.SetEmpty(); + maMouseOverBackground.SetEmpty(); } @@ -215,36 +308,24 @@ void PageObjectPainter::PaintBackground ( PageObjectLayouter::PageObject, PageObjectLayouter::WindowCoordinateSystem)); - rDevice.SetLineColor(); - const USHORT nSavedAntialiasingMode (rDevice.GetAntialiasing()); - rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW); - - const ColorData nColor (GetColorForVisualState(rpDescriptor)); - rDevice.SetFillColor(Color(nColor & 0x00ffffff)); - double nTransparency (COLORDATA_TRANSPARENCY(nColor)/255.0); - rDevice.DrawTransparent( - ::basegfx::B2DPolyPolygon( - ::basegfx::tools::createPolygonFromRect( - ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right(), aBox.Bottom()), - CornerRadius/aBox.GetWidth(), - CornerRadius/aBox.GetHeight())), - nTransparency); - if (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver)) { - rDevice.SetFillColor(Color(MouseOverColor & 0x00ffffff)); - nTransparency = COLORDATA_TRANSPARENCY(MouseOverColor)/255.0; - nTransparency *= 1-rpDescriptor->GetVisualState().GetVisualStateBlend(); - rDevice.DrawTransparent( - ::basegfx::B2DPolyPolygon( - ::basegfx::tools::createPolygonFromRect( - ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right(), aBox.Bottom()), - CornerRadius/aBox.GetWidth(), - CornerRadius/aBox.GetHeight())), - nTransparency); + rDevice.DrawBitmap( + aBox.TopLeft(), + maMouseOverBackground); + } + else if (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)) + { + rDevice.DrawBitmap( + aBox.TopLeft(), + maSelectionBackground); + } + else + { + rDevice.DrawBitmap( + aBox.TopLeft(), + maNormalBackground); } - - rDevice.SetAntialiasing(nSavedAntialiasingMode); } @@ -254,7 +335,7 @@ void PageObjectPainter::PaintPreview ( OutputDevice& rDevice, const model::SharedPageDescriptor& rpDescriptor) const { - const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox( + Rectangle aBox (mpPageObjectLayouter->GetBoundingBox( rpDescriptor, PageObjectLayouter::Preview, PageObjectLayouter::WindowCoordinateSystem)); @@ -276,6 +357,11 @@ void PageObjectPainter::PaintPreview ( rDevice.DrawBitmapEx(aBox.TopLeft(), aBitmap); } + // Draw border around preview. + --aBox.Left(); + --aBox.Top(); + ++aBox.Right(); + ++aBox.Bottom(); rDevice.SetLineColor(Color(0,0,0)); rDevice.SetFillColor(); rDevice.DrawRect(aBox); @@ -297,6 +383,7 @@ void PageObjectPainter::PaintPageNumber ( 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(Color(0x0848a8f)); rDevice.DrawText(aBox.TopLeft(), sPageNumber); @@ -308,7 +395,7 @@ void PageObjectPainter::PaintPageNumber ( aBox.Top() -= 1; aBox.Right() += 2; aBox.Bottom() += 1; - rDevice.SetLineColor(Color(Azure)); + rDevice.SetLineColor(Color(mpTheme->GetColor(Theme::PageNumberBorder))); rDevice.SetFillColor(); rDevice.DrawRect(aBox); @@ -323,14 +410,18 @@ void PageObjectPainter::PaintTransitionEffect ( OutputDevice& rDevice, const model::SharedPageDescriptor& rpDescriptor) const { - const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox( - rpDescriptor, - PageObjectLayouter::TransitionEffectIndicator, - PageObjectLayouter::WindowCoordinateSystem)); - - rDevice.DrawBitmapEx( - aBox.TopLeft(), - mpPageObjectLayouter->GetTransitionEffectIcon().GetBitmapEx()); + const SdPage* pPage = rpDescriptor->GetPage(); + if (pPage!=NULL && pPage->getTransitionType() > 0) + { + const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox( + rpDescriptor, + PageObjectLayouter::TransitionEffectIndicator, + PageObjectLayouter::WindowCoordinateSystem)); + + rDevice.DrawBitmapEx( + aBox.TopLeft(), + mpPageObjectLayouter->GetTransitionEffectIcon().GetBitmapEx()); + } } @@ -351,12 +442,12 @@ void PageObjectPainter::PaintButtons ( const USHORT nSavedAntialiasingMode (rDevice.GetAntialiasing()); rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW); - rDevice.SetLineColor(Color(Arsenic)); + rDevice.SetLineColor(); const double nCornerRadius(3); for (int nButtonIndex=0; nButtonIndex<3; ++nButtonIndex) { - Color aButtonFillColor (AirForceBlue); + Color aButtonFillColor (mpTheme->GetColor(Theme::ButtonBackground)); const Rectangle aBox ( mpPageObjectLayouter->GetBoundingBox( rpDescriptor, @@ -421,36 +512,267 @@ void PageObjectPainter::PaintButtons ( -ColorData PageObjectPainter::GetColorForVisualState ( - const model::SharedPageDescriptor& rpDescriptor) const +void PageObjectPainter::PrepareBackgrounds (OutputDevice& rDevice) +{ + if (maNormalBackground.IsEmpty()) + { + maNormalBackground = CreateBackgroundBitmap(rDevice, Theme::NormalPage); + maSelectionBackground = CreateBackgroundBitmap(rDevice, Theme::SelectedPage); + maMouseOverBackground = CreateBackgroundBitmap(rDevice, Theme::MouseOverPage); + } +} + + + + +Bitmap PageObjectPainter::CreateBackgroundBitmap( + const OutputDevice& rReferenceDevice, + const Theme::ColorType eColorType) const +{ + ::canvas::tools::ElapsedTime aTimer; + const double nStartTime (aTimer.getElapsedTime()); + + const Size aSize (mpPageObjectLayouter->GetPageObjectSize()); + VirtualDevice aBitmapDevice (rReferenceDevice); + aBitmapDevice.SetOutputSizePixel(aSize); + + OSL_TRACE("created bitmap after %fms",(aTimer.getElapsedTime() - nStartTime)*1000); + + // Paint the background with a linear gradient that starts some pixels + // below the top and ends some pixels above the bottom. +#if 1 + const sal_Int32 nDefaultConstantSize(aSize.Height()/4); + const sal_Int32 nMinimalGradientSize(40); + const sal_Int32 nHeight (aSize.Height()); + const sal_Int32 nY1 ( + ::std::max<sal_Int32>( + 0, + ::std::min<sal_Int32>( + nDefaultConstantSize, + (nHeight - nMinimalGradientSize)/2))); + const sal_Int32 nY2 (nHeight-nY1); + const Color aTopColor(mpTheme->GetColor(eColorType, Theme::Fill1)); + const Color aBottomColor(mpTheme->GetColor(eColorType, Theme::Fill2)); + 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(0,nY), Point(aSize.Width(),nY)); + } +#else + const Color aTopColor(mpTheme->GetColor(eColorType, Theme::Fill1)); + const Color aBottomColor(mpTheme->GetColor(eColorType, Theme::Fill2)); + Color aColor (aTopColor); + aColor.Merge(aBottomColor, 128); + aBitmapDevice.SetFillColor(aColor); + aBitmapDevice.SetLineColor(aColor); + aBitmapDevice.DrawRect(Rectangle(Point(0,0), aSize)); +#endif + + OSL_TRACE("filled background after %fms",(aTimer.getElapsedTime() - nStartTime)*1000); + + // Paint the border. + aBitmapDevice.SetFillColor(); + aBitmapDevice.SetLineColor(mpTheme->GetColor(eColorType, Theme::Border2)); + aBitmapDevice.DrawRect(Rectangle(Point(0,0),aSize)); + aBitmapDevice.SetLineColor(mpTheme->GetColor(eColorType, Theme::Border1)); + aBitmapDevice.DrawLine(Point(0,0),Point(aSize.Width()-1,0)); + + OSL_TRACE("painted border after %fms",(aTimer.getElapsedTime() - nStartTime)*1000); + + // Get bounding box of the preview around which a shadow is painted. + // Compensate for the border around the preview. + Rectangle aBox (mpPageObjectLayouter->GetBoundingBox( + model::SharedPageDescriptor(), + PageObjectLayouter::Preview, + PageObjectLayouter::WindowCoordinateSystem)); + aBox.Left() -= 1; + aBox.Top() -= 1; + aBox.Right() += 1; + aBox.Bottom() += 1; + mpShadowPainter->PaintFrame(aBitmapDevice, aBox); + + OSL_TRACE("painted shadow border after %fms",(aTimer.getElapsedTime() - nStartTime)*1000); + + return aBitmapDevice.GetBitmap (Point(0,0),aSize); +} + + + + +//===== FramePainter ========================================================== + +FramePainter::FramePainter (const BitmapEx& rShadowBitmap) + : maShadowTopLeft(rShadowBitmap,-1,-1), + maShadowTop(rShadowBitmap,0,-1), + maShadowTopRight(rShadowBitmap,+1,-1), + maShadowLeft(rShadowBitmap,-1,0), + maShadowRight(rShadowBitmap,+1,0), + maShadowBottomLeft(rShadowBitmap,-1,+1), + maShadowBottom(rShadowBitmap,0,+1), + maShadowBottomRight(rShadowBitmap,+1,+1), + mbIsValid(false) +{ + if (rShadowBitmap.GetSizePixel().Width() == rShadowBitmap.GetSizePixel().Height() + && (rShadowBitmap.GetSizePixel().Width()-1)%2 == 0 + && ((rShadowBitmap.GetSizePixel().Width()-1)/2)%2 == 0) + { + 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 == 0); + } +} + + + + +FramePainter::~FramePainter (void) +{ +} + + + + +void FramePainter::PaintFrame ( + OutputDevice& rDevice, + const Rectangle aBox) const +{ + // Paint the shadow. + maShadowTopLeft.PaintCorner(rDevice, aBox.TopLeft()); + maShadowTopRight.PaintCorner(rDevice, aBox.TopRight()); + maShadowBottomLeft.PaintCorner(rDevice, aBox.BottomLeft()); + maShadowBottomRight.PaintCorner(rDevice, aBox.BottomRight()); + maShadowLeft.PaintSide(rDevice, + aBox.TopLeft(), aBox.BottomLeft(), + maShadowTopLeft, maShadowBottomLeft); + maShadowRight.PaintSide(rDevice, + aBox.TopRight(), aBox.BottomRight(), + maShadowTopRight, maShadowBottomRight); + maShadowTop.PaintSide(rDevice, + aBox.TopLeft(), aBox.TopRight(), + maShadowTopLeft, maShadowTopRight); + maShadowBottom.PaintSide(rDevice, + aBox.BottomLeft(), aBox.BottomRight(), + maShadowBottomLeft, maShadowBottomRight); +} + + + + +//===== OffsetBitmap ========================================================== + +OffsetBitmap::OffsetBitmap ( + const BitmapEx& rBitmap, + const sal_Int32 nHorizontalPosition, + const sal_Int32 nVerticalPosition) + : maBitmap(), + maOffset() { - ColorData nColor; - switch (rpDescriptor->GetVisualState().GetCurrentVisualState()) + 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); + maOffset = Point( + nHorizontalPosition<0 ? -nO : nHorizontalPosition>0 ? -nO+1 : 0, + nVerticalPosition<0 ? -nO : nVerticalPosition>0 ? -nO+1 : 0); + + // Enlarge the side bitmaps so that painting the frame requires less + // paint calls. + const sal_Int32 nSideBitmapSize (64); + if (nHorizontalPosition == 0) + { + maBitmap.Scale(Size(nSideBitmapSize,aSize.Height()), BMP_SCALE_FAST); + } + else if (nVerticalPosition == 0) { - case model::VisualState::VS_Selected: - nColor = 0x80000000 | StellaBlue; - break; - - case model::VisualState::VS_Focused: - nColor = AndroidGreen; - break; - - case model::VisualState::VS_Current: - nColor = 0x80000000 | StellaBlue; - // aColor = mpProperties->GetSelectionColor(); - break; - - case model::VisualState::VS_Excluded: - nColor = 0xcc929ca2; - break; - - case model::VisualState::VS_None: - default: - nColor = OldLace;//0x80000000 | OldLace; - break; + maBitmap.Scale(Size(aSize.Width(), nSideBitmapSize), BMP_SCALE_FAST); } +} + + + - return nColor; +void OffsetBitmap::PaintCorner ( + OutputDevice& rDevice, + const Point& rAnchor) const +{ + rDevice.DrawBitmapEx(rAnchor+maOffset, maBitmap); +} + + + + +void OffsetBitmap::PaintSide ( + OutputDevice& rDevice, + const Point& rAnchor1, + const Point& rAnchor2, + const OffsetBitmap& rCornerBitmap1, + const OffsetBitmap& rCornerBitmap2) const +{ + 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(), 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(), nBottom-nY+1)), + maBitmap); + } + else + { + // Diagonal sides indicatee an error. + OSL_ASSERT(false); + } } diff --git a/sd/source/ui/slidesorter/view/SlsTheme.cxx b/sd/source/ui/slidesorter/view/SlsTheme.cxx new file mode 100644 index 000000000000..c866a3bc6014 --- /dev/null +++ b/sd/source/ui/slidesorter/view/SlsTheme.cxx @@ -0,0 +1,242 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SlsViewCacheContext.hxx,v $ + * + * $Revision: 1.3 $ + * + * 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/SlsTheme.hxx" +#include "SlsIcons.hxx" +#include "controller/SlsProperties.hxx" +#include "sdresid.hxx" +#include <tools/color.hxx> +#include <vcl/outdev.hxx> +#include <vcl/image.hxx> + + +namespace sd { namespace slidesorter { namespace view { + +// Reds +#define Amber 0xff7e00 + +// Greens +#define AndroidGreen 0xa4c639 +#define AppleGreen 0x8db600 +#define Asparagus 0x87a96b + +// Blues +#define Azure 0x000fff +#define DarkCerulean 0x08457e +#define StellaBlue 0x009ee1 +#define AirForceBlue 0x5d8aa8 + +// Off white +#define OldLace 0xfdf5e6 +#define AntiqueWhite 0xfaebd7 + +// Off grays +#define Arsenic 0x3b444b + +const static ColorData SelectionFill1ColorData = 0xb7daf0; +const static ColorData SelectionFill2ColorData = 0x6db5e1; + +const static ColorData MouseOverFill1ColorData = 0x0e85cd; +const static ColorData MouseOverFill2ColorData = 0x044c99; + +const static ColorData Border1ColorData = 0x6db5e1; +const static ColorData Border2ColorData = 0x0e85cd; + +const static ColorData BackgroundColorData = 0xffffff; + +const static ColorData gnMouseOverColor = 0x59000000 | StellaBlue; + +const static double gnCornerRadius = 4.0; + +Theme::Theme (const ::boost::shared_ptr<controller::Properties>& rpProperties) + : maBackgroundColor(rpProperties->GetBackgroundColor().GetColor()), + maRawShadow(), + maInsertionIndicator() +{ + LocalResource aResource (IMG_ICONS); + + maRawShadow = Image(SdResId(IMAGE_SHADOW)).GetBitmapEx(); + maInsertionIndicator = Image(SdResId(IMAGE_INSERTION_INDICATOR_SELECT)).GetBitmapEx(); +} + + + + +void Theme::Update (const ::boost::shared_ptr<controller::Properties>& rpProperties) +{ + maBackgroundColor = rpProperties->GetBackgroundColor().GetColor(); +} + + +::boost::shared_ptr<Font> Theme::CreateFont ( + const FontType eType, + OutputDevice& rDevice) const +{ + ::boost::shared_ptr<Font> pFont; + + switch (eType) + { + case PageNumberFont: + pFont.reset(new Font(rDevice.GetFont())); + pFont->SetWeight(WEIGHT_BOLD); + break; + } + + return pFont; +} + + + + +ColorData Theme::GetColorForVisualState (const model::VisualState::State eState) const +{ + ColorData nColor; + switch (eState) + { + case model::VisualState::VS_Selected: + nColor = 0x80000000 | StellaBlue; + break; + + case model::VisualState::VS_Focused: + nColor = AndroidGreen; + break; + + case model::VisualState::VS_Current: + nColor = 0x80000000 | StellaBlue; + // aColor = mpProperties->GetSelectionColor(); + break; + + case model::VisualState::VS_Excluded: + nColor = 0xcc929ca2; + break; + + case model::VisualState::VS_None: + default: + nColor = 0x80000000 | AntiqueWhite; + break; + } + + return nColor; +} + + + + +ColorData Theme::GetColor ( + const ColorType eType, + const ColorClass eClass) +{ + switch(eType) + { + case Background: + return maBackgroundColor; + + case ButtonBackground: + return AirForceBlue; + + case MouseOverColor: + return gnMouseOverColor; + + case PageNumberBorder: + return Azure; + + case Selection: + return StellaBlue; + + case NormalPage: + switch (eClass) + { + case Border1: + case Border2: + return maBackgroundColor; + + case Fill1: + case Fill2: + return maBackgroundColor; + } + break; + + case SelectedPage: + switch (eClass) + { + case Border1: + return Border1ColorData; + + case Border2: + return Border2ColorData; + + case Fill1: + return SelectionFill1ColorData; + + case Fill2: + return SelectionFill2ColorData; + } + break; + + case MouseOverPage: + switch (eClass) + { + case Border1: + return Border1ColorData; + + case Border2: + return Border2ColorData; + + case Fill1: + return MouseOverFill1ColorData; + + case Fill2: + return MouseOverFill2ColorData; + } + break; + } + return 0; +} + + + + +BitmapEx Theme::GetIcon (const IconType eType) +{ + switch (eType) + { + case InsertionIndicator: + return maInsertionIndicator; + + case RawShadow: + return maRawShadow; + + default: + return BitmapEx(); + } +} + +} } } // end of namespace ::sd::slidesorter::view diff --git a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx index 3d997689dc45..d406a3c866b7 100644 --- a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx +++ b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx @@ -40,7 +40,7 @@ #include "model/SlsPageEnumeration.hxx" #include "view/SlideSorterView.hxx" #include "view/SlsLayouter.hxx" -#include "SlsIcons.hxx" +#include "view/SlsTheme.hxx" #include "cache/SlsPageCache.hxx" #include "ViewShell.hxx" #include "ViewShellBase.hxx" @@ -112,9 +112,9 @@ ViewOverlay::ViewOverlay ( const ::boost::shared_ptr<LayeredDevice>& rpLayeredDevice) : mrSlideSorter(rSlideSorter), mpLayeredDevice(rpLayeredDevice), - mpSelectionRectangleOverlay(new SelectionRectangleOverlay(*this, 2)), - mpInsertionIndicatorOverlay(new InsertionIndicatorOverlay(*this, 3)), - mpSubstitutionOverlay(new SubstitutionOverlay(*this, 2)) + mpSelectionRectangleOverlay(new SelectionRectangleOverlay(*this, 3)), + mpInsertionIndicatorOverlay(new InsertionIndicatorOverlay(*this, 4)), + mpSubstitutionOverlay(new SubstitutionOverlay(*this, 3)) { } @@ -551,14 +551,8 @@ InsertionIndicatorOverlay::InsertionIndicatorOverlay ( const sal_Int32 nLayerIndex) : OverlayBase (rViewOverlay, nLayerIndex), maLocation(), - maIconWithBorder(), - maIcon(), - maMask() + maIcon(rViewOverlay.GetSlideSorter().GetTheme()->GetIcon(Theme::InsertionIndicator)) { - LocalResource aResource (IMG_ICONS); - maIconWithBorder = Image(SdResId(IMAGE_INSERTION_INDICATOR_SELECT)); - maIcon = Image(SdResId(IMAGE_INSERTION_INDICATOR_NORMAL)); - maMask = Image(SdResId(IMAGE_INSERTION_INDICATOR_MASK)); } @@ -568,8 +562,8 @@ void InsertionIndicatorOverlay::SetLocation (const Point& rLocation) { const Point aTopLeft ( rLocation - Point( - maIconWithBorder.GetSizePixel().Width()/2, - maIconWithBorder.GetSizePixel().Height()/2)); + maIcon.GetSizePixel().Width()/2, + maIcon.GetSizePixel().Height()/2)); if (maLocation != aTopLeft) { Invalidator aInvalidator (*this); @@ -589,9 +583,7 @@ void InsertionIndicatorOverlay::Paint ( if ( ! IsVisible()) return; - rDevice.DrawImage( - maLocation, - maIconWithBorder); + rDevice.DrawImage(maLocation, maIcon); } @@ -599,7 +591,7 @@ void InsertionIndicatorOverlay::Paint ( Rectangle InsertionIndicatorOverlay::GetBoundingBox (void) const { - return Rectangle(maLocation, maIconWithBorder.GetSizePixel()); + return Rectangle(maLocation, maIcon.GetSizePixel()); } diff --git a/sd/source/ui/slidesorter/view/makefile.mk b/sd/source/ui/slidesorter/view/makefile.mk index 0741b9e9551f..50988f783531 100644 --- a/sd/source/ui/slidesorter/view/makefile.mk +++ b/sd/source/ui/slidesorter/view/makefile.mk @@ -52,15 +52,17 @@ SRS1NAME=$(TARGET) SRC1FILES = \ SlsIcons.src -SLOFILES = \ - $(SLO)$/SlideSorterView.obj \ - $(SLO)$/SlsFontProvider.obj \ - $(SLO)$/SlsInsertAnimator.obj \ - $(SLO)$/SlsLayeredDevice.obj \ - $(SLO)$/SlsLayouter.obj \ - $(SLO)$/SlsPageObjectLayouter.obj \ - $(SLO)$/SlsPageObjectPainter.obj \ - $(SLO)$/SlsViewCacheContext.obj \ +SLOFILES = \ + $(SLO)$/SlideSorterView.obj \ + $(SLO)$/SlsFontProvider.obj \ + $(SLO)$/SlsInsertAnimator.obj \ + $(SLO)$/SlsLayeredDevice.obj \ + $(SLO)$/SlsLayouter.obj \ + $(SLO)$/SlsPageObjectLayouter.obj \ + $(SLO)$/SlsPageObjectPainter.obj \ + $(SLO)$/SlsSelectionPainter.obj \ + $(SLO)$/SlsTheme.obj \ + $(SLO)$/SlsViewCacheContext.obj \ $(SLO)$/SlsViewOverlay.obj # --- Tagets ------------------------------------------------------- diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx index 7effb79a00b1..05907426621b 100644 --- a/sd/source/ui/view/viewshel.cxx +++ b/sd/source/ui/view/viewshel.cxx @@ -695,9 +695,9 @@ long ViewShell::Notify(NotifyEvent& rNEvt, ::sd::Window* pWin) } -BOOL ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin) +bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin) { - BOOL bDone = FALSE; + bool bDone = false; switch( rCEvt.GetCommand() ) { @@ -747,7 +747,7 @@ BOOL ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi Invalidate( SID_ATTR_ZOOM ); Invalidate( SID_ATTR_ZOOMSLIDER ); - bDone = TRUE; + bDone = true; } } else @@ -763,7 +763,7 @@ BOOL ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi rCEvt.IsMouseEvent(),(const void *) &aWheelData ); bDone = pWin->HandleScrollCommand( aReWrite, mpHorizontalScrollBar.get(), - mpVerticalScrollBar.get()); + mpVerticalScrollBar.get()) == TRUE; } } } |