diff options
Diffstat (limited to '')
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: */ |