summaryrefslogtreecommitdiffstats
path: root/sd/source/ui/slidesorter/inc/controller
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/inc/controller')
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx327
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx77
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx122
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx208
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx112
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx211
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx138
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx219
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx125
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx248
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx145
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx139
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx77
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx98
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsTransferableData.hxx78
-rw-r--r--sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx90
16 files changed, 2414 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
new file mode 100644
index 000000000..10c2aa13e
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+#include <pres.hxx>
+
+#include <tools/link.hxx>
+#include <tools/gen.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+
+#include <sddllapi.h>
+
+#include <memory>
+#include <vector>
+
+namespace com::sun::star::container
+{
+class XIndexAccess;
+}
+namespace com::sun::star::uno
+{
+template <typename> class Reference;
+}
+namespace sd
+{
+class FuPoor;
+}
+namespace sd
+{
+class Window;
+}
+namespace vcl
+{
+class Window;
+}
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+namespace sd::slidesorter::view
+{
+class SlideSorterView;
+}
+namespace sd::slidesorter::model
+{
+class SlideSorterModel;
+}
+
+class CommandEvent;
+class SdPage;
+class SfxItemSet;
+class SfxRequest;
+class VclSimpleEvent;
+class VclWindowEvent;
+
+namespace sd::slidesorter::controller
+{
+class Animator;
+class Clipboard;
+class CurrentSlideManager;
+class FocusManager;
+class InsertionIndicatorHandler;
+class Listener;
+class PageSelector;
+class ScrollBarManager;
+class SelectionFunction;
+class SelectionManager;
+class SlotManager;
+class VisibleAreaManager;
+
+class SlideSorterController final
+{
+public:
+ /** Create a new controller for the slide sorter.
+ @param pParentWindow
+ The window that contains the controls of the new
+ controller.
+ */
+ SlideSorterController(SlideSorter& rSlideSorter);
+
+ /** Late initialization. Call this method once a new object has been
+ created.
+ */
+ void Init();
+
+ ~SlideSorterController();
+
+ void Dispose();
+
+ /** Place and size the scroll bars and the browser window so that the
+ given rectangle is filled.
+ */
+ void Resize(const ::tools::Rectangle& rAvailableSpace);
+
+ /** Determine which of the UI elements--the scroll bars, the scroll bar
+ filler, the actual slide sorter view--are visible and place them in
+ the area last passed to Resize().
+ @param bForce
+ When <TRUE/> is given (<FALSE/> is the default) then the content
+ window and with it the SlideSorterView is resized event when its
+ size does not change (the size does change when the visibility
+ of scroll bars changes.)
+ */
+ void Rearrange(bool bForce);
+
+ /** Return the descriptor of the page that is rendered under the
+ given position. This takes the IsOnlyPreviewTriggersMouseOver
+ property into account.
+ @return
+ Returns a pointer to a page descriptor instead of a
+ reference because when no page is found at the position
+ then NULL is returned to indicate this.
+ */
+ model::SharedPageDescriptor GetPageAt(const Point& rPixelPosition);
+
+ // Exported for unit test
+ SD_DLLPUBLIC PageSelector& GetPageSelector();
+ FocusManager& GetFocusManager();
+ // Exported for unit test
+ SD_DLLPUBLIC controller::Clipboard& GetClipboard();
+
+ /** Return the object that manages the scroll bars.
+ */
+ ScrollBarManager& GetScrollBarManager();
+
+ std::shared_ptr<CurrentSlideManager> const& GetCurrentSlideManager() const;
+ std::shared_ptr<SlotManager> const& GetSlotManager() const;
+ std::shared_ptr<SelectionManager> const& GetSelectionManager() const;
+ std::shared_ptr<InsertionIndicatorHandler> const& GetInsertionIndicatorHandler() const;
+
+ /** This method forwards the call to the SlideSorterView and executes
+ pending operations like moving selected pages into the visible area.
+ */
+ void Paint(const ::tools::Rectangle& rRect, vcl::Window* pWin);
+
+ void FuTemporary(SfxRequest& rRequest);
+ void FuPermanent(SfxRequest& rRequest);
+ void FuSupport(SfxRequest& rRequest);
+ bool Command(const CommandEvent& rEvent, ::sd::Window* pWindow);
+
+ void GetCtrlState(SfxItemSet& rSet);
+ void GetStatusBarState(SfxItemSet& rSet);
+
+ void ExecCtrl(SfxRequest& rRequest);
+ void GetAttrState(SfxItemSet& rSet);
+
+ /** Create an object of this inner class to prevent updates due to model
+ changes.
+ */
+ class ModelChangeLock
+ {
+ public:
+ ModelChangeLock(SlideSorterController& rController);
+ ~ModelChangeLock() COVERITY_NOEXCEPT_FALSE;
+ void Release();
+
+ private:
+ SlideSorterController* mpController;
+ };
+ friend class ModelChangeLock;
+
+ /** Handle a change of the model, that is, handle the removal and
+ insertion of whole pages or a change of the edit mode.
+
+ This method is a convenience function that simply calls
+ PreModelChange() and then PostModelChange().
+ */
+ void HandleModelChange();
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent&, void);
+ DECL_LINK(ApplicationEventHandler, VclSimpleEvent&, void);
+
+ /** Update the display of all pages. This involves a redraw and
+ releasing previews and caches.
+ */
+ void UpdateAllPages();
+
+ /** This factory method creates a selection function.
+ */
+ rtl::Reference<FuPoor> CreateSelectionFunction(SfxRequest& rRequest);
+
+ /** When the current function of the view shell is the slide sorter
+ selection function then return a reference to it. Otherwise return
+ an empty reference.
+ */
+ ::rtl::Reference<SelectionFunction> GetCurrentSelectionFunction() const;
+
+ /** Prepare for a change of the edit mode. Depending on the current
+ edit mode we may save the selection so that it can be restored when
+ later changing back to the current edit mode.
+ */
+ void PrepareEditModeChange();
+
+ /** Set a new edit mode and return whether the edit mode really
+ has been changed. For proper saving and restoring of the selection
+ this method should be called between calls to
+ PrepareEditModeChange() and FinishEditModeChange().
+ */
+ void ChangeEditMode(EditMode eEditMode);
+
+ /** Finish the change of the edit mode. Here we may select a page or
+ restore a previously saved selection.
+ */
+ void FinishEditModeChange();
+
+ /** Call this method when the name of one of the pages has changed.
+ This is then notified to the accessibility object, when that exists.
+ @param nPageIndex
+ The index of the page whose name has been changed.
+ @param rsOldName
+ The old name of the page. The new name can be taken from the
+ page object.
+ */
+ void PageNameHasChanged(int nPageIndex, const OUString& rsOldName);
+
+ /** Provide the set of pages to be displayed in the slide sorter. The
+ GetDocumentSlides() method can be found only in the SlideSorterModel.
+ */
+ void SetDocumentSlides(const css::uno::Reference<css::container::XIndexAccess>& rxSlides);
+
+ /** Return an Animator object.
+ */
+ const std::shared_ptr<Animator>& GetAnimator() const { return mpAnimator; }
+
+ VisibleAreaManager& GetVisibleAreaManager() const;
+
+ void CheckForMasterPageAssignment();
+ void CheckForSlideTransitionAssignment();
+
+private:
+ SlideSorter& mrSlideSorter;
+ model::SlideSorterModel& mrModel;
+ view::SlideSorterView& mrView;
+ std::unique_ptr<PageSelector> mpPageSelector;
+ std::unique_ptr<FocusManager> mpFocusManager;
+ std::shared_ptr<SlotManager> mpSlotManager;
+ std::unique_ptr<ScrollBarManager> mpScrollBarManager;
+ mutable std::shared_ptr<CurrentSlideManager> mpCurrentSlideManager;
+ std::shared_ptr<SelectionManager> mpSelectionManager;
+ std::unique_ptr<controller::Clipboard> mpClipboard;
+ std::shared_ptr<InsertionIndicatorHandler> mpInsertionIndicatorHandler;
+ std::shared_ptr<Animator> mpAnimator;
+ std::unique_ptr<VisibleAreaManager> mpVisibleAreaManager;
+
+ // The listener listens to UNO events and thus is a UNO object.
+ ::rtl::Reference<controller::Listener> mpListener;
+
+ int mnModelChangeLockCount;
+ bool mbIsForcedRearrangePending;
+ bool mbContextMenuOpen;
+
+ bool mbPostModelChangePending;
+
+ /** This array stores the indices of the selected page descriptors at
+ the time when the edit mode is switched to EditMode::MasterPage. With this
+ we can restore the selection when switching back to EditMode::Page mode.
+ */
+ ::std::vector<SdPage*> maSelectionBeforeSwitch;
+ /// The current page before the edit mode is switched to EditMode::MasterPage.
+ int mnCurrentPageBeforeSwitch;
+
+ /** The master page to select after the edit mode is changed. This
+ member is used to pass the pointer from PrepareEditModeChange() to
+ FinishEditModeChange().
+ */
+ SdPage* mpEditModeChangeMasterPage;
+
+ /** This rectangle in the parent window encloses scroll bars and slide
+ sorter window. It is set when Resize() is called.
+ */
+ ::tools::Rectangle maTotalWindowArea;
+
+ /** This counter is used to avoid processing of reentrant calls to
+ Paint().
+ */
+ sal_Int32 mnPaintEntranceCount;
+
+ /** Prepare for several model changes, i.e. prevent time-consuming and
+ non-critical operations like repaints until UnlockModelChange() is
+ called. Critical operations like releasing references to pages that
+ do not exist anymore are executed.
+ */
+ void LockModelChange();
+
+ /** Further calls to HandleModelChange() will result in a full featured
+ update of model, view, and controller. When HandleModelChange() has
+ been called since the last LockModelChange() then this is done right
+ away to bring the view up-to-date.
+ */
+ void UnlockModelChange();
+
+ /** Prepare for a model change. This method does all the things that
+ need to be done _before_ the model changes, e.g. because they need
+ access to the model data before the change.
+ */
+ void PreModelChange();
+
+ /** Complete a model change. This includes the recreation of data
+ structures that depend on the model and the request for a repaint to
+ show the changes.
+ */
+ void PostModelChange();
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx
new file mode 100644
index 000000000..b4847de1a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsAnimationFunction.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <basegfx/point/b2dpoint.hxx>
+
+#include <functional>
+#include <vector>
+
+
+namespace sd::slidesorter::controller {
+
+class AnimationBezierFunction
+{
+public:
+ /** Create a cubic bezier curve whose start and end points are given
+ implicitly as P0=(0,0) and P3=(1,1). The second control point is
+ implicitly given as P2=(1-nY1,1-nX1).
+ */
+ AnimationBezierFunction (
+ const double nX1,
+ const double nY1);
+
+ ::basegfx::B2DPoint operator() (const double nT);
+
+private:
+ const double mnX1;
+ const double mnY1;
+ const double mnX2;
+ const double mnY2;
+
+ static double EvaluateComponent (
+ const double nT,
+ const double nV1,
+ const double nV2);
+};
+
+/** Turn a parametric function into one whose y-Values depend on its
+ x-Values. Note a lot of interpolation takes place. The resulting
+ accuracy should be good enough for the purpose of acceleration
+ function for animations.
+*/
+class AnimationParametricFunction
+{
+public:
+ typedef ::std::function<basegfx::B2DPoint (double)> ParametricFunction;
+ AnimationParametricFunction (const ParametricFunction& rFunction);
+
+ double operator() (const double nX);
+
+private:
+ /** y-Values of the parametric function given to the constructor
+ evaluated (and interpolated) for evenly spaced x-Values.
+ */
+ ::std::vector<double> maY;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx b/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx
new file mode 100644
index 000000000..8c9ec9e81
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsAnimator.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <view/SlideSorterView.hxx>
+#include <canvas/elapsedtime.hxx>
+#include <vcl/idle.hxx>
+#include <sal/types.h>
+#include <o3tl/deleter.hxx>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+namespace sd::slidesorter { class SlideSorter; }
+
+namespace sd::slidesorter::controller {
+
+/** Experimental class for simple eye candy animations.
+*/
+class Animator
+{
+public:
+ /** In some circumstances we have to avoid animation and jump to the
+ final animation state immediately. Use this enum instead of a bool
+ to be more expressive.
+ */
+ enum AnimationMode { AM_Animated, AM_Immediate };
+
+ explicit Animator (SlideSorter& rSlideSorter);
+ ~Animator();
+ Animator(const Animator&) = delete;
+ Animator& operator=(const Animator&) = delete;
+
+ /** When disposed the animator will stop its work immediately and not
+ process any timer events anymore.
+ */
+ void Dispose();
+
+ /** An animation object is called with values between 0 and 1 as single
+ argument to its operator() method.
+ */
+ typedef ::std::function<void (double)> AnimationFunctor;
+ typedef ::std::function<void ()> FinishFunctor;
+
+ typedef sal_Int32 AnimationId;
+ static const AnimationId NotAnAnimationId = -1;
+
+ /** Schedule a new animation for execution. The () operator of that
+ animation will be called with increasing values between 0 and 1 for
+ the specified duration.
+ @param rAnimation
+ The animation operation.
+ */
+ AnimationId AddAnimation (
+ const AnimationFunctor& rAnimation,
+ const FinishFunctor& rFinishFunctor);
+
+ /** Abort and remove an animation. In order to reduce the bookkeeping
+ on the caller side, it is OK to call this method with an animation
+ function that is not currently being animated. Such a call is
+ silently ignored.
+ */
+ void RemoveAnimation (const AnimationId nAnimationId);
+
+ /** A typical use case for this method is the temporary shutdown of the
+ slidesorter when the slide sorter bar is put into a cache due to a
+ change of the edit mode.
+ */
+ void RemoveAllAnimations();
+
+private:
+ SlideSorter& mrSlideSorter;
+ Idle maIdle;
+ bool mbIsDisposed;
+ class Animation;
+ typedef ::std::vector<std::shared_ptr<Animation> > AnimationList;
+ AnimationList maAnimations;
+ ::canvas::tools::ElapsedTime maElapsedTime;
+
+ std::unique_ptr<view::SlideSorterView::DrawLock, o3tl::default_delete<view::SlideSorterView::DrawLock>> mpDrawLock;
+
+ AnimationId mnNextAnimationId;
+
+ DECL_LINK(TimeoutHandler, Timer *, void);
+
+ /** Execute one step of every active animation.
+ @param nTime
+ Time measured in milliseconds with some arbitrary reference point.
+ @return
+ When one or more animation has finished then <TRUE/> is
+ returned. Call CleanUpAnimationList() in this case.
+ */
+ bool ProcessAnimations (const double nTime);
+
+ /** Remove animations that have expired.
+ */
+ void CleanUpAnimationList();
+
+ void RequestNextFrame();
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx
new file mode 100644
index 000000000..6ced17486
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <ViewClipboard.hxx>
+#include <controller/SlsSelectionObserver.hxx>
+#include <sdxfer.hxx>
+
+#include <sal/types.h>
+#include <o3tl/deleter.hxx>
+#include <svx/svdtypes.hxx>
+
+#include <sddllapi.h>
+
+class SfxRequest;
+struct AcceptDropEvent;
+class DropTargetHelper;
+struct ExecuteDropEvent;
+struct ImplSVEvent;
+class Point;
+class SdPage;
+namespace vcl { class Window; }
+
+namespace sd {
+class Window;
+}
+
+namespace sd::slidesorter { class SlideSorter; }
+
+namespace sd::slidesorter::controller {
+
+class SlideSorterController;
+
+class SAL_DLLPUBLIC_RTTI Clipboard final
+ : public ViewClipboard
+{
+public:
+ Clipboard (SlideSorter& rSlideSorter);
+ virtual ~Clipboard() override;
+
+ /** Create a slide sorter transferable from the given sd
+ transferable. The returned transferable is set up with all
+ information necessary so that it can be dropped on a slide sorter.
+ */
+ static std::shared_ptr<SdTransferable::UserData> CreateTransferableUserData (SdTransferable* pTransferable);
+
+ void HandleSlotCall (SfxRequest& rRequest);
+
+ void DoCut ();
+ // Exported for unit test
+ SD_DLLPUBLIC void DoCopy();
+ // Exported for unit test
+ SD_DLLPUBLIC void DoPaste();
+ void DoDelete ();
+
+ void StartDrag (
+ const Point& rDragPt,
+ vcl::Window* pWindow );
+
+ void DragFinished (
+ sal_Int8 nDropAction);
+
+ sal_Int8 AcceptDrop (
+ const AcceptDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ sal_uInt16 nPage,
+ SdrLayerID nLayer );
+
+ sal_Int8 ExecuteDrop (
+ const ExecuteDropEvent& rEvt,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ sal_uInt16 nPage,
+ SdrLayerID nLayer );
+
+ void Abort();
+
+private:
+ virtual sal_uInt16 DetermineInsertPosition () override;
+
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ typedef ::std::vector<SdPage*> PageList;
+ /** Remember the pages that are dragged to another document or to
+ another place in the same document so that they can be removed after
+ a move operation.
+ */
+ PageList maPagesToRemove;
+
+ /** Used when a drop is executed to combine all undo actions into one.
+ Typically created in ExecuteDrop() and released in DragFinish().
+ */
+ class UndoContext;
+ std::unique_ptr<UndoContext> mxUndoContext;
+
+ std::unique_ptr<SelectionObserver::Context, o3tl::default_delete<SelectionObserver::Context>> mxSelectionObserverContext;
+ ImplSVEvent * mnDragFinishedUserEventId;
+
+ void CreateSlideTransferable (
+ vcl::Window* pWindow,
+ bool bDrag);
+
+ /** Determine the position of where to insert the pages in the current
+ transferable of the sd module.
+ @return
+ The index in the range [0,n] (both inclusive) with n the number
+ of pages is returned.
+ */
+ sal_Int32 GetInsertionPosition ();
+
+ /** Paste the pages of the transferable of the sd module at the given
+ position.
+ @param nInsertPosition
+ The position at which to insert the pages. The valid range is
+ [0,n] (both inclusive) with n the number of pages in the
+ document.
+ @return
+ The number of inserted pages is returned.
+ */
+ sal_Int32 PasteTransferable (sal_Int32 nInsertPosition);
+
+ /** Select a range of pages of the model. Typically usage is the
+ selection of newly inserted pages.
+ @param nFirstIndex
+ The index of the first page to select.
+ @param nPageCount
+ The number of pages to select.
+ */
+ void SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount);
+
+ /** Return <TRUE/> when the current transferable in the current state of
+ the slidesorter is acceptable to be pasted. For this the
+ transferable has to
+ a) exist,
+ b) contain one or more regular draw pages, no master pages.
+ When master pages are involved, either in the transferable or in the
+ slide sorter (by it displaying master pages) the drop of the
+ transferable is not accepted. The reason is the missing
+ implementation of proper handling master pages copy-and-paste.
+ */
+ enum DropType { DT_PAGE, DT_PAGE_FROM_NAVIGATOR, DT_SHAPE, DT_NONE };
+ DropType IsDropAccepted() const;
+
+ /** This method contains the code for AcceptDrop() and ExecuteDrop() shapes.
+ There are only minor differences for the two cases at this level.
+ @param eCommand
+ This parameter specifies whether to do an AcceptDrop() or
+ ExecuteDrop().
+ @param rPosition
+ Since the event is given as void pointer we can not take the
+ mouse position from it. The caller has to supply it in this
+ parameter.
+ @param pDropEvent
+ Event though the AcceptDropEvent and ExecuteDropEvent are very
+ similar they do not have a common base class. Because of that
+ we have to use a void* to pass these structs.
+ @param nPage
+ When the page number is given as 0xffff then it is replaced by
+ the number of the page at the mouse position. If the mouse is
+ not over a page then neither AcceptDrop() nor ExecuteDrop() are
+ executed.
+ */
+ enum DropCommand { DC_ACCEPT, DC_EXECUTE };
+ sal_Int8 ExecuteOrAcceptShapeDrop (
+ DropCommand eCommand,
+ const Point& rPosition,
+ const void* pDropEvent ,
+ DropTargetHelper& rTargetHelper,
+ ::sd::Window* pTargetWindow,
+ sal_uInt16 nPage,
+ SdrLayerID nLayer);
+
+ /** Return whether the insertion defined by the transferable is
+ trivial, ie would not change either source nor target document.
+ */
+ bool IsInsertionTrivial (
+ SdTransferable const * pTransferable,
+ const sal_Int8 nDndAction) const;
+
+ /** Asynchronous part of DragFinished. The argument is the sal_Int8
+ nDropAction, disguised as void*.
+ */
+ DECL_DLLPRIVATE_LINK(ProcessDragFinished, void*, void);
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx
new file mode 100644
index 000000000..0c5b3b243
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsCurrentSlideManager.hxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+#include <vcl/timer.hxx>
+#include <tools/link.hxx>
+
+class SdPage;
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+namespace sd::slidesorter::controller
+{
+/** Manage the current slide. This includes setting the according flags at
+ the PageDescriptor objects and setting the current slide at the main
+ view shell.
+
+ Switching pages is triggered only after a little delay. This allows
+ fast travelling through a larger set of slides without having to wait
+ for the edit view to update its content after every slide change.
+*/
+class CurrentSlideManager
+{
+public:
+ /** Create a new CurrentSlideManager object that manages the current
+ slide for the given SlideSorter.
+ */
+ CurrentSlideManager(SlideSorter& rSlideSorter);
+
+ ~CurrentSlideManager();
+
+ /** Call this when the current page of the main view shell has been
+ switched. Use SwitchCurrentSlide() to initiate such a switch.
+ */
+ void NotifyCurrentSlideChange(const sal_Int32 nSlideIndex);
+ void NotifyCurrentSlideChange(const SdPage* pPage);
+
+ /** Call this method to switch the current page of the main view shell
+ to the given slide. Use CurrentSlideHasChanged() when the current
+ slide change has been initiated by someone else.
+ @param nSlideIndex
+ Zero based index in the range [0,number-of-slides).
+ The page selection is cleared and only the new
+ current slide is selected.
+ */
+ void SwitchCurrentSlide(const sal_Int32 nSlideIndex);
+ void SwitchCurrentSlide(const model::SharedPageDescriptor& rpSlide,
+ const bool bUpdateSelection = false);
+
+ /** Return the page descriptor for the current slide. Note, that when
+ there is no current slide then the returned pointer is empty.
+ */
+ const model::SharedPageDescriptor& GetCurrentSlide() const { return mpCurrentSlide; }
+
+ /** Release all references to model data.
+ */
+ void PrepareModelChange();
+
+ /** Modify inner state in reaction to a change of the SlideSorterModel.
+ */
+ void HandleModelChange();
+
+private:
+ SlideSorter& mrSlideSorter;
+ sal_Int32 mnCurrentSlideIndex;
+ model::SharedPageDescriptor mpCurrentSlide;
+ /** Timer to control the delay after which to ask
+ XController/ViewShellBase to switch to another slide.
+ */
+ Timer maSwitchPageDelayTimer;
+
+ void SetCurrentSlideAtViewShellBase(const model::SharedPageDescriptor& rpSlide);
+ void SetCurrentSlideAtTabControl(const model::SharedPageDescriptor& rpSlide);
+ void SetCurrentSlideAtXController(const model::SharedPageDescriptor& rpSlide);
+
+ /** When switching from one slide to a new current slide then this
+ method releases all ties to the old slide.
+ */
+ void ReleaseCurrentSlide();
+
+ /** When switching from one slide to a new current slide then this
+ method connects to the new current slide.
+ */
+ void AcquireCurrentSlide(const sal_Int32 nSlideIndex);
+
+ DECL_LINK(SwitchPageCallback, Timer*, void);
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx
new file mode 100644
index 000000000..180b7143f
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsFocusManager.hxx
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+
+#include <sal/types.h>
+#include <tools/link.hxx>
+#include <vector>
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+namespace sd::slidesorter::controller
+{
+/** This class manages the focus of the slide sorter. There is the focus
+ page which is or is not focused. Initialized to point to the first page
+ it can be set to other pages by using the MoveFocus() method. The
+ focused state of the focus page can be toggled with the ToggleFocus()
+ method.
+*/
+class FocusManager
+{
+public:
+ /** Create a new focus manager that operates on the pages of the model
+ associated with the given controller. The focus page is set to the
+ first page. Focused state is off.
+ */
+ FocusManager(SlideSorter& rSlideSorter);
+
+ ~FocusManager();
+
+ enum class FocusMoveDirection
+ {
+ Left,
+ Right,
+ Up,
+ Down
+ };
+
+ /** Move the focus from the currently focused page to one that is
+ displayed adjacent to it, either vertically or horizontally.
+ @param eDirection
+ Direction in which to move the focus. Wrap around is done
+ differently when moving vertically or horizontally. Vertical
+ wrap around takes place in the same column, i.e. when you are
+ in the top row and move up you come out in the bottom row in the
+ same column. Horizontal wrap around moves to the next
+ (FocusMoveDirection::Right) or previous (FocusMoveDirection::Left) page. Moving to the right
+ from the last page goes to the first page and vice versa.
+ The current page index is set to the nearest valid
+ page index.
+ */
+ void MoveFocus(FocusMoveDirection eDirection);
+
+ /** Show the focus indicator of the current slide.
+ @param bScrollToFocus
+ When <TRUE/> (the default) then the view is scrolled so that the
+ focus rectangle lies inside its visible area.
+ */
+ void ShowFocus(const bool bScrollToFocus = true);
+
+ /** Hide the focus indicator.
+ */
+ void HideFocus();
+
+ /** Toggle the focused state of the current slide.
+ @return
+ Returns the focused state of the focus page after the call.
+ */
+ bool ToggleFocus();
+
+ /** Return whether the window managed by the called focus manager has
+ the input focus of the application.
+ */
+ bool HasFocus() const;
+
+ /** Return the descriptor of the page that currently has the focus.
+ @return
+ When there is no page that currently has the focus then NULL is
+ returned.
+ */
+ model::SharedPageDescriptor GetFocusedPageDescriptor() const;
+
+ /** Return the index of the page that currently has the focus as it is
+ accepted by the slide sorter model.
+ @return
+ When there is no page that currently has the focus then -1 is
+ returned.
+ */
+ sal_Int32 GetFocusedPageIndex() const { return mnPageIndex; }
+
+ /** Set the focused page to the one described by the given page
+ descriptor. The visibility of the focus indicator is not modified.
+ @param rDescriptor
+ One of the page descriptors that are currently managed by the
+ SlideSorterModel.
+ */
+ bool SetFocusedPage(const model::SharedPageDescriptor& rDescriptor);
+
+ /** Set the focused page to the one described by the given page
+ index. The visibility of the focus indicator is not modified.
+ @param nPageIndex
+ A valid page index that is understood by the SlideSorterModel.
+ */
+ void SetFocusedPage(sal_Int32 nPageIndex);
+
+ bool SetFocusedPageToCurrentPage();
+
+ /** Return <TRUE/> when the focus indicator is currently shown. A
+ prerequisite is that the window managed by this focus manager has
+ the input focus as indicated by a <TRUE/> return value of
+ HasFocus(). It is not necessary that the focus indicator is
+ visible. It may have been scrolled outside the visible area.
+ */
+ bool IsFocusShowing() const;
+
+ /** Add a listener that is called when the focus is shown or hidden or
+ set to another page object.
+ @param rListener
+ When this method is called multiple times for the same listener
+ the second and all following calls are ignored. Each listener
+ is added only once.
+ */
+ void AddFocusChangeListener(const Link<LinkParamNone*, void>& rListener);
+
+ /** Remove a focus change listener.
+ @param rListener
+ It is safe to pass a listener that was not added are has been
+ removed previously. Such calls are ignored.
+ */
+ void RemoveFocusChangeListener(const Link<LinkParamNone*, void>& rListener);
+
+ /** Create an instance of this class to temporarily hide the focus
+ indicator. It is restored to its former visibility state when the
+ FocusHider is destroyed.
+ */
+ class FocusHider
+ {
+ public:
+ FocusHider(FocusManager&);
+ ~FocusHider() COVERITY_NOEXCEPT_FALSE;
+
+ private:
+ bool mbFocusVisible;
+ FocusManager& mrManager;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** Index of the page that may be focused. It is -1 when the model
+ contains no page.
+ */
+ sal_Int32 mnPageIndex;
+
+ /** This flag indicates whether the page pointed to by mpFocusDescriptor
+ has the focus.
+ */
+ bool mbPageIsFocused;
+
+ ::std::vector<Link<LinkParamNone*, void>> maFocusChangeListeners;
+
+ /** Reset the focus state of the given descriptor and request a repaint
+ so that the focus indicator is hidden.
+ @param pDescriptor
+ When NULL is given then the call is ignored.
+ */
+ void HideFocusIndicator(const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Set the focus state of the given descriptor, scroll it into the
+ visible area and request a repaint so that the focus indicator is
+ made visible.
+ @param pDescriptor
+ When NULL is given then the call is ignored.
+ @param bScrollToFocus
+ When <TRUE/> (the default) then the view is scrolled so that the
+ focus rectangle lies inside its visible area.
+ */
+ void ShowFocusIndicator(const model::SharedPageDescriptor& rpDescriptor,
+ const bool bScrollToFocus);
+
+ /** Call all currently registered listeners that a focus change has
+ happened. The focus may be hidden or shown or moved from one page
+ object to another.
+ */
+ void NotifyFocusChangeListeners() const;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx
new file mode 100644
index 000000000..43f2d2f6a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <controller/SlsAnimator.hxx>
+
+#include <view/SlsLayouter.hxx>
+
+namespace sd::slidesorter { class SlideSorter; }
+namespace sd::slidesorter::view {
+class InsertAnimator;
+class InsertionIndicatorOverlay;
+}
+
+class SdTransferable;
+
+namespace sd::slidesorter::controller {
+
+/** Manage the visibility and location of the insertion indicator. Its
+ actual display is controlled by the InsertionIndicatorOverlay.
+*/
+class InsertionIndicatorHandler
+{
+public:
+ InsertionIndicatorHandler (SlideSorter& rSlideSorter);
+ ~InsertionIndicatorHandler() COVERITY_NOEXCEPT_FALSE;
+
+ enum Mode { CopyMode, MoveMode, UnknownMode };
+ static Mode GetModeFromDndAction (const sal_Int8 nDndAction);
+
+ /** Activate the insertion marker at the given coordinates.
+ */
+ void Start (const bool bIsOverSourceView);
+
+ /** Deactivate the insertion marker.
+ */
+ void End (const controller::Animator::AnimationMode eMode);
+
+ /** This context make sure that the insertion indicator is shown
+ (provided that the clipboard is not empty) while the context is
+ alive. Typically used while a context menu is displayed.
+ */
+ class ForceShowContext
+ {
+ public:
+ ForceShowContext (const std::shared_ptr<InsertionIndicatorHandler>& rpHandler);
+ ~ForceShowContext() COVERITY_NOEXCEPT_FALSE;
+ private:
+ const std::shared_ptr<InsertionIndicatorHandler> mpHandler;
+ };
+
+ /** Update the indicator icon from the current transferable (from the
+ clipboard or an active drag and drop operation.)
+ */
+ void UpdateIndicatorIcon (const SdTransferable* pTransferable);
+
+ /** Set the position of the insertion marker to the given coordinates.
+ */
+ void UpdatePosition (
+ const Point& rMouseModelPosition,
+ const Mode eMode);
+ void UpdatePosition (
+ const Point& rMouseModelPosition,
+ const sal_Int8 nDndAction);
+
+ /** Return whether the insertion marker is active.
+ */
+ bool IsActive() const { return mbIsActive;}
+
+ /** Return the insertion index that corresponds with the current
+ graphical location of the insertion indicator.
+ */
+ sal_Int32 GetInsertionPageIndex() const;
+
+ /** Determine whether moving the current selection to the current
+ position of the insertion marker would alter the document. This
+ would be the case when the selection is not consecutive or would be
+ moved to a position outside and not adjacent to the selection.
+ */
+ bool IsInsertionTrivial (
+ const sal_Int32 nInsertionIndex,
+ const Mode eMode) const;
+ /** This method is like the other variant. It operates implicitly
+ on the current insertion index as would be returned by
+ GetInsertionPageIndex().
+ */
+ bool IsInsertionTrivial (const sal_Int8 nDndAction);
+
+private:
+ SlideSorter& mrSlideSorter;
+ std::shared_ptr<view::InsertAnimator> mpInsertAnimator;
+ std::shared_ptr<view::InsertionIndicatorOverlay> mpInsertionIndicatorOverlay;
+ view::InsertPosition maInsertPosition;
+ Mode meMode;
+ bool mbIsInsertionTrivial;
+ bool mbIsActive;
+ bool mbIsReadOnly;
+ bool mbIsOverSourceView;
+ Size maIconSize;
+ bool mbIsForcedShow;
+
+ void SetPosition (
+ const Point& rPoint,
+ const Mode eMode);
+ std::shared_ptr<view::InsertAnimator> const & GetInsertAnimator();
+
+ /** Make the insertion indicator visible (that is the show part) and
+ keep it visible, even when the mouse leaves the window (that is the
+ force part). We need this when a context menu is displayed (mouse
+ over the popup menu triggers a mouse leave event) while the
+ insertion indicator remains visible in the background.
+
+ In effect all calls to End() are ignored until ForceEnd() is called.
+ */
+ void ForceShow();
+ void ForceEnd();
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
new file mode 100644
index 000000000..6a4b75004
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+
+#include <vector>
+#include <memory>
+
+#include <sddllapi.h>
+
+class SdPage;
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+namespace sd::slidesorter::model
+{
+class SlideSorterModel;
+}
+
+namespace sd::slidesorter::controller
+{
+class SlideSorterController;
+
+/** A sub-controller that handles page selection of the slide browser.
+ Selecting a page does not make it the current page (of the main view)
+ automatically as this would not be desired in a multi selection. This
+ has to be done explicitly by calling the
+ CurrentSlideManager::SetCurrentSlide() method.
+
+ Indices of pages relate always to the number of all pages in the model
+ (as returned by GetPageCount()) not just the selected pages.
+*/
+class PageSelector
+{
+public:
+ explicit PageSelector(SlideSorter& rSlideSorter);
+ PageSelector(const PageSelector&) = delete;
+ PageSelector& operator=(const PageSelector&) = delete;
+
+ // Exported for unit test
+ SD_DLLPUBLIC void SelectAllPages();
+ SD_DLLPUBLIC void DeselectAllPages();
+
+ /** Update the selection state of all page descriptors to be the same as
+ that of the corresponding pages of the SdPage objects and issue
+ redraw requests where necessary.
+ */
+ void GetCoreSelection();
+
+ /** Update the selection state of the SdPage objects to be the same as
+ that of the corresponding page descriptors.
+ */
+ void SetCoreSelection();
+
+ /** Select the specified descriptor. The selection state of the other
+ descriptors is not affected.
+ */
+ void SelectPage(int nPageIndex);
+ /** Select the descriptor that is associated with the given page. The
+ selection state of the other descriptors is not affected.
+ */
+ void SelectPage(const SdPage* pPage);
+ /** Select the specified descriptor. The selection state of the other
+ descriptors is not affected.
+ */
+ void SelectPage(const model::SharedPageDescriptor& rpDescriptor);
+
+ /** Return whether the specified page is selected. This convenience
+ method is a substitute for
+ SlideSorterModel::GetPageDescriptor(i)->HasState(ST_Selected) is
+ included here to make this class more self contained.
+ */
+ SD_DLLPUBLIC bool IsPageSelected(int nPageIndex);
+
+ /** Return whether the specified page is visible. This convenience
+ method is a substitute for
+ SlideSorterModel::GetPageDescriptor(i)->HasState(ST_Visible) is
+ included here to make this class more self contained.
+ */
+ bool IsPageVisible(int nPageIndex);
+
+ /** Deselect the descriptor that is associated with the given page.
+ The current page is updated to the first slide
+ of the remaining selection.
+ */
+ void DeselectPage(int nPageIndex);
+ void DeselectPage(const model::SharedPageDescriptor& rpDescriptor,
+ const bool bUpdateCurrentPage = true);
+
+ /** This convenience method returns the same number of pages that
+ SlideSorterModel.GetPageCount() returns. It is included here so
+ that it is self contained for iterating over all pages to select or
+ deselect them.
+ */
+ int GetPageCount() const;
+ int GetSelectedPageCount() const { return mnSelectedPageCount; }
+
+ /** Return the anchor for a range selection. This usually is the first
+ selected page after all pages have been deselected.
+ @return
+ The returned anchor may be NULL.
+ */
+ const model::SharedPageDescriptor& GetSelectionAnchor() const { return mpSelectionAnchor; }
+
+ typedef ::std::vector<SdPage*> PageSelection;
+
+ /** Return an object that describes the current selection. The caller
+ can use that object to later restore the selection.
+ @return
+ The object returned describes the selection via indices. So
+ even if pages are exchanged a later call to SetPageSelection()
+ is valid.
+ */
+ std::shared_ptr<PageSelection> GetPageSelection() const;
+
+ /** Restore a page selection according to the given selection object.
+ @param rSelection
+ Typically obtained by calling GetPageSelection() this object
+ is used to restore the selection. If pages were exchanged since
+ the last call to GetPageSelection() it is still valid to call
+ this method with the selection. When pages have been inserted
+ or removed the result may be unexpected.
+ @param bUpdateCurrentPage
+ When <TRUE/> (the default value) then after setting the
+ selection update the current page to the first page of the
+ selection.
+ When called from within UpdateCurrentPage() then this flag is
+ used to prevent a recursion loop.
+ */
+ void SetPageSelection(const std::shared_ptr<PageSelection>& rSelection,
+ const bool bUpdateCurrentPage);
+
+ /** Call this method after the model has changed to set the number
+ of selected pages.
+ */
+ void CountSelectedPages();
+
+ /** Use the UpdateLock whenever you do a complex selection, i.e. call
+ more than one method in a row. An active lock prevents intermediate
+ changes of the current slide.
+ */
+ class UpdateLock
+ {
+ public:
+ UpdateLock(SlideSorter const& rSlideSorter);
+ UpdateLock(PageSelector& rPageSelector);
+ ~UpdateLock();
+ void Release();
+
+ private:
+ PageSelector* mpSelector;
+ };
+
+ class BroadcastLock
+ {
+ public:
+ BroadcastLock(SlideSorter const& rSlideSorter);
+ BroadcastLock(PageSelector& rPageSelector);
+ ~BroadcastLock();
+
+ private:
+ PageSelector& mrSelector;
+ };
+
+private:
+ model::SlideSorterModel& mrModel;
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+ int mnSelectedPageCount;
+ int mnBroadcastDisableLevel;
+ bool mbSelectionChangeBroadcastPending;
+ model::SharedPageDescriptor mpMostRecentlySelectedPage;
+ /// Anchor for a range selection.
+ model::SharedPageDescriptor mpSelectionAnchor;
+ sal_Int32 mnUpdateLockCount;
+ bool mbIsUpdateCurrentPagePending;
+
+ /** Enable the broadcasting of selection change events. This calls the
+ SlideSorterController::SelectionHasChanged() method to do the actual
+ work. When EnableBroadcasting has been called as many times as
+ DisableBroadcasting() was called before and the selection has been
+ changed in the meantime, this change will be broadcasted.
+ */
+ void EnableBroadcasting();
+
+ /** Disable the broadcasting of selection change events. Subsequent
+ changes of the selection will set a flag that triggers the sending
+ of events when EnableBroadcasting() is called.
+ */
+ void DisableBroadcasting();
+
+ void UpdateCurrentPage(const bool bUpdateOnlyWhenPending = false);
+
+ void CheckConsistency() const;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
new file mode 100644
index 000000000..344ac67f3
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsProperties.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/color.hxx>
+
+namespace sd::slidesorter::controller
+{
+/** An extensible set of properties used throughout the slide sorter.
+*/
+class Properties
+{
+public:
+ Properties();
+
+ /** Call this method after receiving a VclEventId::ApplicationDataChanged
+ event.
+ */
+ void HandleDataChangeEvent();
+
+ /** When this method returns <TRUE/> then the current slide is
+ highlighted in the view. The default value is <FALSE/>.
+ */
+ bool IsHighlightCurrentSlide() const { return mbIsHighlightCurrentSlide; }
+ void SetHighlightCurrentSlide(const bool bIsHighlightCurrentSlide);
+
+ /** When this method returns <TRUE/> then the selection is indicated in
+ the view (typically by drawing rectangles around the selected
+ slides.) The default value is <TRUE/>.
+ */
+ bool IsShowSelection() const { return mbIsShowSelection; }
+ void SetShowSelection(const bool bIsShowSelection);
+
+ /** When this method returns <TRUE/> then the focusdselection is indicated in
+ the view (typically by drawing dotted rectangles around the selected
+ slides.) The default value is <TRUE/>.
+ */
+ bool IsShowFocus() const { return mbIsShowFocus; }
+ void SetShowFocus(const bool bIsShowFocus);
+
+ /** When this method returns <TRUE/> then on a selection change the
+ visible area is adapted so that the selected slides are shown
+ centered in the view. This can be used to center the current slide
+ by selecting only the current slide. The default value is <FALSE/>.
+ */
+ bool IsCenterSelection() const { return mbIsCenterSelection; }
+ void SetCenterSelection(const bool bIsCenterSelection);
+
+ /** When this method returns <TRUE/> then the view may try to change the
+ visible area by scrolling it smoothly on the screen. Experimental.
+ Default value is <FALSE/>.
+ */
+ bool IsSmoothSelectionScrolling() const { return mbIsSmoothSelectionScrolling; }
+ void SetSmoothSelectionScrolling(const bool bIsSmoothSelectionScrolling);
+
+ /** When this method returns <TRUE/> then during a full screen
+ presentation the previews in a slide sorter are not updated.
+ Default value is <TRUE/>.
+ */
+ bool IsSuspendPreviewUpdatesDuringFullScreenPresentation() const
+ {
+ return mbIsSuspendPreviewUpdatesDuringFullScreenPresentation;
+ }
+ void SetSuspendPreviewUpdatesDuringFullScreenPresentation(const bool bFlag);
+
+ /** Return the background color.
+ */
+ const Color& GetBackgroundColor() const { return maBackgroundColor; }
+ void SetBackgroundColor(const Color& rColor);
+
+ /** Return the text color.
+ */
+ const Color& GetTextColor() const { return maTextColor; }
+ void SetTextColor(const Color& rColor);
+
+ /** Return the color in which selections are to be painted.
+ */
+ const Color& GetSelectionColor() const { return maSelectionColor; }
+ void SetSelectionColor(const Color& rColor);
+
+ /** Return the color used for highlighting e.g. the current slide.
+ */
+ const Color& GetHighlightColor() const { return maHighlightColor; }
+ void SetHighlightColor(const Color& rColor);
+
+ /** The UI can be set to be read only independently from the model status.
+ Used for instance in the presenter view.
+ */
+ bool IsUIReadOnly() const { return mbIsUIReadOnly; }
+ void SetUIReadOnly(const bool bIsUIReadOnly);
+
+private:
+ bool mbIsHighlightCurrentSlide;
+ bool mbIsShowSelection;
+ bool mbIsShowFocus;
+ bool mbIsCenterSelection;
+ bool mbIsSmoothSelectionScrolling;
+ bool mbIsSuspendPreviewUpdatesDuringFullScreenPresentation;
+ Color maBackgroundColor;
+ Color maTextColor;
+ Color maSelectionColor;
+ Color maHighlightColor;
+ bool mbIsUIReadOnly;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx
new file mode 100644
index 000000000..853d98f4a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsScrollBarManager.hxx
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/link.hxx>
+#include <tools/gen.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/scrbar.hxx>
+#include <vcl/vclptr.hxx>
+
+#include <functional>
+
+namespace sd { class Window; }
+
+namespace sd::slidesorter { class SlideSorter; }
+
+namespace sd::slidesorter::controller {
+
+/** Manage the horizontal and vertical scroll bars. Listen for events, set
+ their sizes, place them in the window, determine their visibilities.
+
+ <p>Handle auto scrolling, i.e. the scrolling of the window when the
+ mouse comes near the window border while dragging a selection.</p>
+
+ <p>In order to make the slide sorter be used in the task pane with its
+ own vertical scrollbars the vertical scrollbar of the use of the slide
+ sorter is optional. When using it the available area in a window is
+ used and the vertical scrollbar is displayed when that area is not large
+ enough. When the vertical scrollbar is not used then the available area
+ is assumed to be modifiable. In that case the PlaceScrollBars() method
+ may return an area larger than the one given.<p>
+*/
+class ScrollBarManager
+{
+public:
+ /** Create a new scroll bar manager that manages three controls: the
+ horizontal scroll bar, the vertical scroll bar, and the little
+ window that fills the gap at the bottom right corner that is left
+ between the two scroll bars. Call LateInitialization() after
+ constructing a new object.
+ */
+ ScrollBarManager (SlideSorter& rSlideSorter);
+
+ ~ScrollBarManager();
+
+ /** Register listeners at the scroll bars. This method is called after
+ startup of a new slide sorter object or after a reactivation of a
+ slide sorter that for example is taken from a cache.
+ */
+ void Connect();
+
+ /** Remove listeners from the scroll bars. This method is called when
+ the slide sorter is destroyed or when it is suspended, e.g. put
+ into a cache for later reuse.
+ */
+ void Disconnect();
+
+ /** Set up the scroll bar, i.e. thumb size and position. Call this
+ method when the content of the browser window changed, i.e. pages
+ were inserted or deleted, the layout or the zoom factor has
+ changed.
+ @param bScrollToCurrentPosition
+ When <TRUE/> then scroll the window to the new offset that is
+ defined by the scroll bars. Otherwise the new offset is simply
+ set and the whole window is repainted.
+ */
+ void UpdateScrollBars (
+ bool bScrollToCurrentPosition);
+
+ /** Place the scroll bars inside the given area. When the available
+ area is not large enough for the content to display the horizontal
+ and/or vertical scroll bar is enabled.
+ @param rAvailableArea
+ The scroll bars will be placed inside this rectangle. It is
+ expected to be given in pixel relative to its parent.
+ @param bIsHorizontalScrollBarAllowed
+ Only when this flag is <TRUE/> the horizontal scroll may be
+ displayed.
+ @param bIsVerticalScrollBarAllowed
+ Only when this flag is <TRUE/> the horizontal scroll may be
+ displayed.
+ @return
+ Returns the space that remains after the scroll bars are
+ placed.
+ */
+ ::tools::Rectangle PlaceScrollBars (
+ const ::tools::Rectangle& rAvailableArea,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed);
+
+ /** Update the vertical and horizontal scroll bars so that the visible
+ area has the given top and left values.
+ */
+ void SetTopLeft (const Point& rNewTopLeft);
+
+ /** Return the width of the vertical scroll bar, which--when
+ shown--should be fixed in contrast to its height.
+ @return
+ Returns 0 when the vertical scroll bar is not shown or does not
+ exist, otherwise its width in pixel is returned.
+ */
+ int GetVerticalScrollBarWidth() const;
+
+ /** Return the height of the horizontal scroll bar, which--when
+ shown--should be fixed in contrast to its width.
+ @return
+ Returns 0 when the vertical scroll bar is not shown or does not
+ exist, otherwise its height in pixel is returned.
+ */
+ int GetHorizontalScrollBarHeight() const;
+
+ /** Call this method to scroll a window while the mouse is in dragging a
+ selection. If the mouse is near the window border or is outside the
+ window then scroll the window accordingly.
+ @param rMouseWindowPosition
+ The mouse position for which the scroll amount is calculated.
+ @param rAutoScrollFunctor
+ Every time when the window is scrolled then this functor is executed.
+ @return
+ When the window is scrolled then this method returns <TRUE/>.
+ When the window is not changed then <FALSE/> is returned.
+ */
+ bool AutoScroll (
+ const Point& rMouseWindowPosition,
+ const ::std::function<void ()>& rAutoScrollFunctor);
+
+ void StopAutoScroll();
+
+ void clearAutoScrollFunctor();
+
+ enum Orientation { Orientation_Horizontal, Orientation_Vertical };
+ /** Scroll the slide sorter by setting the thumbs of the scroll bars and
+ by moving the content of the content window.
+ @param eOrientation
+ Defines whether to scroll horizontally or vertically.
+ @param nDistance
+ distance in slides.
+ */
+ void Scroll(
+ const Orientation eOrientation,
+ const sal_Int32 nDistance);
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** The horizontal scroll bar. Note that is used but not owned by
+ objects of this class. It is given to the constructor.
+ */
+ VclPtr<ScrollBar> mpHorizontalScrollBar;
+
+ /** The vertical scroll bar. Note that is used but not owned by
+ objects of this class. It is given to the constructor.
+ */
+ VclPtr<ScrollBar> mpVerticalScrollBar;
+
+ /// Relative horizontal position of the visible area in the view.
+ double mnHorizontalPosition;
+ /// Relative vertical position of the visible area in the view.
+ double mnVerticalPosition;
+ /** The width and height of the border at the inside of the window which
+ when entered while in drag mode leads to a scrolling of the window.
+ */
+ Size maScrollBorder;
+ /** The only task of this little window is to paint the little square at
+ the bottom right corner left by the two scroll bars (when both are
+ visible).
+ */
+ VclPtr<ScrollBarBox> mpScrollBarFiller;
+
+ /** The auto scroll timer is used for keep scrolling the window when the
+ mouse reaches its border while dragging a selection. When the mouse
+ is not moved the timer issues events to keep scrolling.
+ */
+ Timer maAutoScrollTimer;
+ Size maAutoScrollOffset;
+ bool mbIsAutoScrollActive;
+
+ /** The content window is the one whose view port is controlled by the
+ scroll bars.
+ */
+ VclPtr<sd::Window> mpContentWindow;
+
+ ::std::function<void ()> maAutoScrollFunctor;
+
+ void SetWindowOrigin (
+ double nHorizontalPosition,
+ double nVerticalPosition);
+
+ /** Determine the visibility of the scroll bars so that the window
+ content is not clipped in any dimension without showing a scroll
+ bar.
+ @param rAvailableArea
+ The area in which the scroll bars, the scroll bar filler, and
+ the SlideSorterView will be placed.
+ @return
+ The area that is enclosed by the scroll bars is returned. It
+ will be filled with the SlideSorterView.
+ */
+ ::tools::Rectangle DetermineScrollBarVisibilities(
+ const ::tools::Rectangle& rAvailableArea,
+ const bool bIsHorizontalScrollBarAllowed,
+ const bool bIsVerticalScrollBarAllowed);
+
+ /** Typically called by DetermineScrollBarVisibilities() this method
+ tests a specific configuration of the two scroll bars being visible
+ or hidden.
+ @return
+ When the window content can be shown with only being clipped in
+ an orientation where the scroll bar would be shown then <TRUE/>
+ is returned.
+ */
+ bool TestScrollBarVisibilities (
+ bool bHorizontalScrollBarVisible,
+ bool bVerticalScrollBarVisible,
+ const ::tools::Rectangle& rAvailableArea);
+
+ void CalcAutoScrollOffset (const Point& rMouseWindowPosition);
+ bool RepeatAutoScroll();
+
+ DECL_LINK(HorizontalScrollBarHandler, ScrollBar*, void);
+ DECL_LINK(VerticalScrollBarHandler, ScrollBar*, void);
+ DECL_LINK(AutoScrollTimeoutHandler, Timer *, void);
+
+ void PlaceHorizontalScrollBar (const ::tools::Rectangle& aArea);
+ void PlaceVerticalScrollBar (const ::tools::Rectangle& aArea);
+ void PlaceFiller (const ::tools::Rectangle& aArea);
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx
new file mode 100644
index 000000000..7d80fbd26
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <controller/SlsFocusManager.hxx>
+#include <fupoor.hxx>
+#include <memory>
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+struct AcceptDropEvent;
+
+namespace sd::slidesorter::controller
+{
+class SlideSorterController;
+
+class SelectionFunction final : public FuPoor
+{
+public:
+ SelectionFunction(const SelectionFunction&) = delete;
+ SelectionFunction& operator=(const SelectionFunction&) = delete;
+
+ static rtl::Reference<FuPoor> Create(SlideSorter& rSlideSorter, SfxRequest& rRequest);
+
+ // Mouse- & Key-Events
+ virtual bool KeyInput(const KeyEvent& rKEvt) override;
+ virtual bool MouseMove(const MouseEvent& rMEvt) override;
+ virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
+ virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
+
+ /// Forward to the clipboard manager.
+ virtual void DoCut() override;
+
+ /// Forward to the clipboard manager.
+ virtual void DoCopy() override;
+
+ /// Forward to the clipboard manager.
+ virtual void DoPaste() override;
+
+ /** is called when the current function should be aborted. <p>
+ This is used when a function gets a KEY_ESCAPE but can also
+ be called directly.
+
+ @returns
+ true if an active function was aborted
+ */
+ virtual bool cancel() override;
+
+ void MouseDragged(const AcceptDropEvent& rEvent, const sal_Int8 nDragAction);
+
+ /** Turn of substitution display and insertion indicator.
+ */
+ void NotifyDragFinished();
+
+ class EventDescriptor;
+ class ModeHandler;
+ friend class ModeHandler;
+ enum Mode
+ {
+ NormalMode,
+ MultiSelectionMode,
+ DragAndDropMode
+ };
+ void SwitchToNormalMode();
+ void SwitchToDragAndDropMode(const Point& rMousePosition);
+ void SwitchToMultiSelectionMode(const Point& rMousePosition, const sal_uInt32 nEventCode);
+
+ void ResetShiftKeySelectionAnchor();
+ /** Special case handling for when the context menu is hidden. This
+ method will reinitialize the current mouse position to prevent the
+ mouse motion during the time the context menu is displayed from
+ being interpreted as drag-and-drop start.
+ */
+ void ResetMouseAnchor();
+
+private:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ SelectionFunction(SlideSorter& rSlideSorter, SfxRequest& rRequest);
+
+ virtual ~SelectionFunction() override;
+
+ /** Remember the slide where the shift key was pressed and started a
+ multiselection via keyboard.
+ */
+ sal_Int32 mnShiftKeySelectionAnchor;
+
+ /** The selection function can be in one of several mutually
+ exclusive modes.
+ */
+ std::shared_ptr<ModeHandler> mpModeHandler;
+
+ /** Make the slide nOffset slides away of the current one the new
+ current slide. When the new index is outside the range of valid
+ page numbers it is clipped to that range.
+ @param nOffset
+ When nOffset is negative then go back. When nOffset if positive go
+ forward. When it is zero then ignore the call.
+ */
+ void GotoNextPage(int nOffset);
+
+ /** Make the slide with the given index the new current slide.
+ @param nIndex
+ Index of the new current slide. When the new index is outside
+ the range of valid page numbers it is clipped to that range.
+ */
+ void GotoPage(int nIndex);
+
+ void ProcessMouseEvent(sal_uInt32 nEventType, const MouseEvent& rEvent);
+
+ // What follows are a couple of helper methods that are used by
+ // ProcessMouseEvent().
+
+ void ProcessEvent(EventDescriptor& rEvent);
+
+ void MoveFocus(const FocusManager::FocusMoveDirection eDirection, const bool bIsShiftDown,
+ const bool bIsControlDown);
+
+ void SwitchMode(const std::shared_ptr<ModeHandler>& rpHandler);
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx
new file mode 100644
index 000000000..4f52d49e6
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionManager.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <tools/link.hxx>
+#include <vector>
+#include <memory>
+
+class SdPage;
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+namespace sd::slidesorter::controller
+{
+class SlideSorterController;
+class SelectionObserver;
+
+/** This class is a part of the controller and handles the selection of
+ slides.
+ <p>It has methods to modify the selected slides (delete them or
+ move them to other places in the document), change the visible area so
+ to make the selected slides visible, tell listeners when the selection
+ changes.</p>
+*/
+class SelectionManager
+{
+public:
+ /** Create a new SelectionManager for the given slide sorter.
+ */
+ SelectionManager(SlideSorter& rSlideSorter);
+
+ ~SelectionManager();
+
+ /** Delete the currently selected slides. When this method returns the
+ selection is empty.
+ @param bSelectFollowingPage
+ When <TRUE/> then after deleting the selected pages make the
+ slide after the last selected page the new current page.
+ When <FALSE/> then make the first slide before the selected
+ pages the new current slide.
+ */
+ void DeleteSelectedPages(const bool bSelectFollowingPage = true);
+
+ /** Call this method after the selection has changed (possible several
+ calls to the PageSelector) to invalidate the relevant slots and send
+ appropriate events.
+ */
+ void SelectionHasChanged();
+
+ /** Add a listener that is called when the selection of the slide sorter
+ changes.
+ @param rListener
+ When this method is called multiple times for the same listener
+ the second and all following calls are ignored. Each listener
+ is added only once.
+ */
+ void AddSelectionChangeListener(const Link<LinkParamNone*, void>& rListener);
+
+ /** Remove a listener that was called when the selection of the slide
+ sorter changes.
+ @param rListener
+ It is safe to pass a listener that was not added are has been
+ removed previously. Such calls are ignored.
+ */
+ void RemoveSelectionChangeListener(const Link<LinkParamNone*, void>& rListener);
+
+ /** Return the position where to insert pasted slides based on the
+ current selection. When there is a selection then the insert
+ position is behind the last slide. When the selection is empty then
+ most of the time the insert position is at the end of the document.
+ There is an exception right after the display of a popup-menu. The
+ position of the associated insertion marker is stored here and reset
+ the next time the selection changes.
+ */
+ sal_Int32 GetInsertionPosition() const;
+
+ /** Store an insertion position temporarily. It is reset when the
+ selection changes the next time.
+ */
+ void SetInsertionPosition(const sal_Int32 nInsertionPosition);
+
+ const std::shared_ptr<SelectionObserver>& GetSelectionObserver() const
+ {
+ return mpSelectionObserver;
+ }
+
+private:
+ SlideSorter& mrSlideSorter;
+ SlideSorterController& mrController;
+
+ ::std::vector<Link<LinkParamNone*, void>> maSelectionChangeListeners;
+
+ /** The insertion position is only temporarily valid. Negative values
+ indicate that the explicit insertion position is not valid. In this
+ case GetInsertionPosition() calculates it from the current selection.
+ */
+ sal_Int32 mnInsertionPosition;
+
+ std::shared_ptr<SelectionObserver> mpSelectionObserver;
+
+ /** Delete the given list of normal pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedNormalPages
+ A list of normal pages. Supplying master pages is an error.
+ */
+ void DeleteSelectedNormalPages(const ::std::vector<SdPage*>& rSelectedNormalPages);
+
+ /** Delete the given list of master pages. This method is a helper
+ function for DeleteSelectedPages().
+ @param rSelectedMasterPages
+ A list of master pages. Supplying normal pages is an error.
+ */
+ void DeleteSelectedMasterPages(const ::std::vector<SdPage*>& rSelectedMasterPages);
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx
new file mode 100644
index 000000000..11742b890
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionObserver.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+class SdrPage;
+class SdPage;
+
+namespace sd::slidesorter::controller
+{
+/** Observe insertions and deletions of pages between calls to
+ StartObservation() and EndObservation(). When the later is called
+ the selection is set to just the newly inserted pages.
+*/
+class SelectionObserver final
+{
+public:
+ SelectionObserver(SlideSorter& rSlideSorter);
+ ~SelectionObserver();
+
+ void NotifyPageEvent(const SdrPage* pPage);
+ void StartObservation();
+ void AbortObservation();
+ void EndObservation();
+
+ /** Use this little class instead of calling StartObservation and
+ EndObservation directly so that EndObservation is not forgotten or
+ omitted due to an exception or some break or return in the middle of
+ code.
+ */
+ class Context
+ {
+ public:
+ Context(SlideSorter const& rSlideSorter);
+ ~Context() COVERITY_NOEXCEPT_FALSE;
+ void Abort();
+
+ private:
+ std::shared_ptr<SelectionObserver> mpSelectionObserver;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+ bool mbIsObservationActive;
+ bool mbPageEventOccurred;
+
+ ::std::vector<const SdPage*> maInsertedPages;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx
new file mode 100644
index 000000000..57de8422a
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsSlotManager.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+#include <tools/link.hxx>
+#include <rtl/ustring.hxx>
+
+class AbstractSvxNameDialog;
+class SfxItemSet;
+class SfxRequest;
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+namespace sd::slidesorter::controller
+{
+/** This manager takes over the work of handling slot calls from the
+ controller of the slide sorter.
+*/
+class SlotManager
+{
+public:
+ /** Create a new slot manager that handles slot calls for the controller
+ of a slide sorter.
+ @param rController
+ The controller for which to handle the slot calls.
+ */
+ SlotManager(SlideSorter& rSlideSorter);
+
+ void FuTemporary(SfxRequest& rRequest);
+ void FuPermanent(SfxRequest& rRequest);
+ void FuSupport(SfxRequest& rRequest);
+ void GetMenuState(SfxItemSet& rSet);
+ void GetClipboardState(SfxItemSet& rSet);
+ void GetStatusBarState(SfxItemSet& rSet);
+ void ExecCtrl(SfxRequest& rRequest);
+ void GetAttrState(SfxItemSet& rSet);
+
+ /** Exclude or include one slide or all selected slides.
+ @param rpDescriptor
+ When the pointer is empty then apply the new state to all
+ selected pages. Otherwise apply the new state to just the
+ specified state.
+ */
+ void ChangeSlideExclusionState(const model::SharedPageDescriptor& rpDescriptor,
+ const bool bExcludeSlide);
+
+ /** Call this after a change from normal mode to master mode or back.
+ The affected slots are invalidated.
+ */
+ void NotifyEditModeChange();
+
+private:
+ /// The controller for which we manage the slot calls.
+ SlideSorter& mrSlideSorter;
+
+ /** The implementation is a copy of the code for SID_RENAMEPAGE in
+ drviews2.cxx.
+ */
+ void RenameSlide(const SfxRequest& rRequest);
+ DECL_LINK(RenameSlideHdl, AbstractSvxNameDialog&, bool);
+ DECL_STATIC_LINK(SlotManager, RenameSlideTooltipHdl, AbstractSvxNameDialog&, OUString);
+ bool RenameSlideFromDrawViewShell(sal_uInt16 nPageId, const OUString& rName);
+
+ /** Handle SID_INSERTPAGE slot calls.
+ */
+ void InsertSlide(SfxRequest& rRequest);
+
+ void DuplicateSelectedSlides(SfxRequest& rRequest);
+
+ /** Use one of several ways to determine where to insert a new page.
+ This can be the current selection or the insertion indicator.
+ */
+ sal_Int32 GetInsertionPosition() const;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsTransferableData.hxx b/sd/source/ui/slidesorter/inc/controller/SlsTransferableData.hxx
new file mode 100644
index 000000000..863c2fe73
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsTransferableData.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sdxfer.hxx>
+
+#include <vcl/bitmapex.hxx>
+
+#include <vector>
+
+class SdDrawDocument;
+namespace sd::slidesorter { class SlideSorterViewShell; }
+
+namespace sd::slidesorter::controller {
+
+/** Represent previews and other information so that they can be
+ attached to an existing transferable.
+*/
+class TransferableData final
+ : public SdTransferable::UserData,
+ public SfxListener
+{
+public:
+ class Representative
+ {
+ public:
+ Representative (const BitmapEx& rBitmap, const bool bIsExcluded)
+ : maBitmap(rBitmap), mbIsExcluded(bIsExcluded) {}
+
+ BitmapEx maBitmap;
+ bool mbIsExcluded;
+ };
+
+ static rtl::Reference<SdTransferable> CreateTransferable (
+ SdDrawDocument* pSrcDoc,
+ SlideSorterViewShell* pViewShell,
+ ::std::vector<TransferableData::Representative>&& rRepresentatives);
+
+ static std::shared_ptr<TransferableData> GetFromTransferable (const SdTransferable* pTransferable);
+
+ TransferableData (
+ SlideSorterViewShell* pViewShell,
+ ::std::vector<TransferableData::Representative>&& rRepresentatives);
+ virtual ~TransferableData() override;
+
+ const ::std::vector<Representative>& GetRepresentatives() const { return maRepresentatives;}
+
+ /** Return the view shell for which the transferable was created.
+ */
+ SlideSorterViewShell* GetSourceViewShell() const { return mpViewShell;}
+
+private:
+ SlideSorterViewShell* mpViewShell;
+ const ::std::vector<Representative> maRepresentatives;
+
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) override;
+};
+
+} // end of namespace ::sd::slidesorter::controller
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx b/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx
new file mode 100644
index 000000000..d9f5845af
--- /dev/null
+++ b/sd/source/ui/slidesorter/inc/controller/SlsVisibleAreaManager.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <model/SlsSharedPageDescriptor.hxx>
+#include <optional>
+#include <tools/gen.hxx>
+#include <vector>
+
+namespace sd::slidesorter
+{
+class SlideSorter;
+}
+
+namespace sd::slidesorter::controller
+{
+/** Manage requests for scrolling page objects into view.
+*/
+class VisibleAreaManager
+{
+public:
+ explicit VisibleAreaManager(SlideSorter& rSlideSorter);
+ ~VisibleAreaManager();
+ VisibleAreaManager(const VisibleAreaManager&) = delete;
+ VisibleAreaManager& operator=(const VisibleAreaManager&) = delete;
+
+ void ActivateCurrentSlideTracking();
+ void DeactivateCurrentSlideTracking();
+ bool IsCurrentSlideTrackingActive() const { return mbIsCurrentSlideTrackingActive; }
+
+ /** Request the current slide to be moved into the visible area.
+ This request is only obeyed when the current slide tracking is
+ active.
+ @see ActivateCurrentSlideTracking() and DeactivateCurrentSlideTracking()
+ */
+ void RequestCurrentSlideVisible();
+
+ /** Request to make the specified page object visible.
+ */
+ void RequestVisible(const model::SharedPageDescriptor& rpDescriptor, const bool bForce = false);
+
+ /** Temporarily disable the update of the visible area.
+ */
+ class TemporaryDisabler
+ {
+ public:
+ explicit TemporaryDisabler(SlideSorter const& rSlideSorter);
+ ~TemporaryDisabler();
+
+ private:
+ VisibleAreaManager& mrVisibleAreaManager;
+ };
+
+private:
+ SlideSorter& mrSlideSorter;
+
+ /** List of rectangle that someone wants to be moved into the visible
+ area.
+ Cleared on every call to ForgetVisibleRequests() and MakeVisible().
+ */
+ ::std::vector<::tools::Rectangle> maVisibleRequests;
+
+ Point maRequestedVisibleTopLeft;
+ bool mbIsCurrentSlideTrackingActive;
+ int mnDisableCount;
+
+ void MakeVisible();
+ ::std::optional<Point> GetRequestedTopLeft() const;
+};
+
+} // end of namespace ::sd::slidesorter::view
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */