diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/source/ui/slidesorter/inc | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/slidesorter/inc')
35 files changed, 4596 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx b/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.hxx new file mode 100644 index 000000000..12993fdbb --- /dev/null +++ b/sd/source/ui/slidesorter/inc/cache/SlsCacheContext.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 <sal/types.h> +#include <com/sun/star/uno/Reference.hxx> +#include <memory> +#include <vector> + +namespace com::sun::star::uno +{ +class XInterface; +} + +class SdrPage; + +namespace sd::slidesorter::cache +{ +typedef const SdrPage* CacheKey; + +/** This interface allows the individualisation of different instances of + the PreviewCache. +*/ +class CacheContext +{ +public: + virtual ~CacheContext() {} + + /** This method is called when the asynchronous creation of a preview + has been finished. + @param aKey + The key of the page for which the preview has been created. + */ + virtual void NotifyPreviewCreation(CacheKey aKey) = 0; + + /** Called to determine whether the system is idle and a preview can be + created without annoying the user. + */ + virtual bool IsIdle() = 0; + + /** This method is used to determine whether a page is currently visible + or not. It is called when the cache becomes too large and some + previews have to be released or scaled down. + */ + virtual bool IsVisible(CacheKey aKey) = 0; + + /** Return the page associated with the given key. Note that different + keys may map to a single page (this may be the case with custom + slide shows.) + */ + virtual const SdrPage* GetPage(CacheKey aKey) = 0; + + /** This method is used when the request queue is filled. It asks for + the list of visible entries and maybe for the list of not visible + entries and creates preview creation requests for them. + @param bVisible + When this is <FALSE/> then the implementation can decide whether + to allow rendering of previews that are not visible (ahead of + time). When not then return an empty pointer or an empty vector. + */ + virtual std::shared_ptr<std::vector<CacheKey>> GetEntryList(bool bVisible) = 0; + + /** Return the priority that defines the order in which previews are + created for different keys/pages. Typically the visible pages come + first, then top-down, left-to-right. + */ + virtual sal_Int32 GetPriority(CacheKey aKey) = 0; + + /** Return the model to which the pages belong for which the called + cache manages the previews. Different caches that belong to the + same model but have different preview sizes may access previews of + each other in order to create fast previews of the previews. + */ + virtual css::uno::Reference<css::uno::XInterface> GetModel() = 0; +}; + +typedef std::shared_ptr<CacheContext> SharedCacheContext; + +} // end of namespace ::sd::slidesorter::cache + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx b/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx new file mode 100644 index 000000000..4fb596195 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCache.hxx @@ -0,0 +1,141 @@ +/* -*- 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 <cache/SlsCacheContext.hxx> +#include <vcl/bitmapex.hxx> +#include <memory> + +class Size; + +namespace sd::slidesorter::cache +{ +class GenericPageCache; + +/** The page cache is responsible for the creation and storage of preview + bitmaps of pages that are shown by the slide sorter. + + <p>Bitmaps for previews and a cache are used to speed up the display + (painting) of the slide sorter. But, of course, we have to limit this + time-space-tradeoff by limiting the amount of space that can be use to + store bitmaps.</p> + + <p>There are several strategies employed by this class to shorten the + perceived time that is used to paint the slide sorter: + <ul> + <li>Rendering pages ahead of time. Additionally to rendering the + visible slides we try to render part or all of the slides that are not + (yet) visible. This, of course, makes sense only when the computer is + otherwise idle while doing that.</li> + <li>When the size of the slides on the screen changes we mark the + bitmaps as needing an update but use them while the new bitmap in the + correct size is not available.</li> + <li>Give the UI the chance to handle user events between the rendering + of differe slides.</li> + <li>Limit the amount of space that may be used for storing preview + bitmaps and throw.</li> + </p> + + <p>There is another somewhat similar methods for requesting new previews: + GetPreviewBitmap() schedules a re-rendering (when necessary) and + returns the preview what is currently available, either as a preview of + the preview or, when nothing has changed since the last call, as the + final thing. + </p> +*/ +class PageCache +{ +public: + /** The page cache is created with a reference to the slide sorter so + that it has access to both the view and the model and so can fill + itself with requests for all or just the visible pages. + + It is the task of the PageCacheManager to create new objects of this + class. + */ + PageCache(const Size& rPreviewSize, const bool bDoSuperSampling, + const SharedCacheContext& rpCacheContext); + + ~PageCache(); + + void ChangeSize(const Size& rPreviewSize, const bool bDoSuperSampling); + + /** Request a preview bitmap for the specified page object in the + specified size. The returned bitmap may be a preview of the + preview, i.e. either a scaled (up or down) version of a previous + preview (of the wrong size) or an empty bitmap. In this case a + request for the generation of a new preview is created and inserted + into the request queue. When the preview is available in the right + size the page shape will be told to paint itself again. When it + then calls this method again if receives the correctly sized preview + bitmap. + @param rRequestData + This data is used to determine the preview. + @param bResize + When <TRUE/> then when the available bitmap has not the + requested size, it is scaled before it is returned. When + <FALSE/> then the bitmap is returned in the wrong size and it is + the task of the caller to scale it. + @return + Returns a bitmap that is either empty, contains a scaled (up or + down) version or is the requested bitmap. + */ + BitmapEx GetPreviewBitmap(const CacheKey aKey, const bool bResize); + + BitmapEx GetMarkedPreviewBitmap(const CacheKey aKey); + void SetMarkedPreviewBitmap(const CacheKey aKey, const BitmapEx& rBitmap); + + /** When the requested preview bitmap does not yet exist or is not + up-to-date then the rendering of one is scheduled. Otherwise this + method does nothing. + */ + void RequestPreviewBitmap(const CacheKey aKey); + + /** Tell the cache that the bitmap associated with the given request + data is not up-to-date anymore. This will invalidate all previews + in other caches that represent the same page as well. + A new preview is requested and will lead + eventually to a repaint of the associated page object. + */ + void InvalidatePreviewBitmap(const CacheKey aKey); + + /** Call this method when all preview bitmaps have to be generated anew. + This is the case when the size of the page objects on the screen has + changed or when the model has changed. + */ + void InvalidateCache(); + + /** With the precious flag you can control whether a bitmap can be + removed or reduced in size to make room for other bitmaps or is so + precious that it will not touched. A typical use is to set the + precious flag for exactly the visible pages. + */ + void SetPreciousFlag(const CacheKey aKey, const bool bIsPrecious); + + void Pause(); + void Resume(); + +private: + std::unique_ptr<GenericPageCache> mpImplementation; +}; + +} // end of namespace ::sd::slidesorter::cache + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx b/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx new file mode 100644 index 000000000..eaddea5b2 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/cache/SlsPageCacheManager.hxx @@ -0,0 +1,155 @@ +/* -*- 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 <com/sun/star/uno/XInterface.hpp> +#include <memory> +#include <vector> + +class Size; +class SdrPage; + +namespace sd::slidesorter::cache { + +class BitmapCache; + +/** Provide and manage the preview bitmap caches for all slide sorter + instances. There is one cache per active slide sorter plus a small + number of caches that are no longer in use. The later are kept to speed + up the switching between views. +*/ +class PageCacheManager +{ +public: + typedef std::vector< std::pair<Size, std::shared_ptr<BitmapCache> > > BestFittingPageCaches; + typedef css::uno::Reference<css::uno::XInterface> DocumentKey; + + /** Return the one instance of the PageCacheManager class. + */ + static std::shared_ptr<PageCacheManager> Instance(); + + /** Look up the cache for the given model in which the previews have the + specified size. If no such cache exists, then one is created. When + a new BitmapCache is created its Recycle() method is called with a + sorted list of existing caches from which the new one initialize its + previews. + @return + The returned cache lives as long as somebody keeps a shared + pointer and the ReleaseCache() method has not been called. + */ + std::shared_ptr<BitmapCache> GetCache ( + const DocumentKey& pDocument, + const Size& rPreviewSize); + + /** Tell the cache manager to release its own reference to the specified + cache. After that the cache will live as long as the caller (and + maybe others) holds its reference. + */ + void ReleaseCache (const std::shared_ptr<BitmapCache>& rpCache); + + /** This is an information to the cache manager that the size of preview + bitmaps in the specified cache has changed. + + */ + std::shared_ptr<BitmapCache> ChangeSize ( + const std::shared_ptr<BitmapCache>& rpCache, + const Size& rOldPreviewSize, + const Size& rNewPreviewSize); + + /** Invalidate the preview bitmap for one slide that belongs to the + specified document. The bitmaps for this slide in all caches are + marked as out-of-date and will be re-created when they are requested + the next time. + */ + bool InvalidatePreviewBitmap ( + const DocumentKey& pDocument, + const SdrPage* pPage); + + /** Invalidate the preview bitmaps for all slides that belong to the + specified document. This is necessary after model changes that + affect e.g. page number fields. + */ + void InvalidateAllPreviewBitmaps (const DocumentKey& pDocument); + + /** Invalidate all the caches that are currently in use and destroy + those that are not. This is used for example when the high contrast + mode is turned on or off. + */ + void InvalidateAllCaches(); + + /** Call this method when a page has been deleted and its preview + is not needed anymore. + */ + void ReleasePreviewBitmap (const SdrPage* pPage); + +private: + /** Singleton instance of the cache manager. Note that this is a weak + pointer. The (implementation class of) ViewShellBase holds a + shared_ptr so that the cache manager has the same life time as the + ViewShellBase. + */ + static std::weak_ptr<PageCacheManager> mpInstance; + + /// List of active caches. + class PageCacheContainer; + std::unique_ptr<PageCacheContainer> mpPageCaches; + + /// List of inactive, recently used caches. + class RecentlyUsedPageCaches; + std::unique_ptr<RecentlyUsedPageCaches> mpRecentlyUsedPageCaches; + + /** The maximal number of recently used caches that are kept alive after + they have become inactive, i.e. after they are not used anymore by a + slide sorter. + */ + static const sal_uInt32 mnMaximalRecentlyCacheCount = 2; + + PageCacheManager(); + ~PageCacheManager(); + + class Deleter; + friend class Deleter; + + std::shared_ptr<BitmapCache> GetRecentlyUsedCache( + const DocumentKey& pDocument, + const Size& rSize); + + /** Add the given cache to the list of recently used caches for the + document. There is one such list per document. Each least has at + most mnMaximalRecentlyCacheCount members. + */ + void PutRecentlyUsedCache( + DocumentKey const & pDocument, + const Size& rPreviewSize, + const std::shared_ptr<BitmapCache>& rpCache); + + /** This method is used internally to initialize a newly created + BitmapCache with already existing previews. + */ + void Recycle ( + const std::shared_ptr<BitmapCache>& rpCache, + const DocumentKey& pDocument, + const Size& rPreviewSize); +}; + +} // end of namespace ::sd::slidesorter::cache + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx new file mode 100644 index 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: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx new file mode 100644 index 000000000..90223a1bc --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlideSorterModel.hxx @@ -0,0 +1,227 @@ +/* -*- 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 <osl/mutex.hxx> +#include <vcl/region.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <vector> + +class SdDrawDocument; +class SdrPage; +class SdPage; +namespace sd::slidesorter +{ +class SlideSorter; +} +namespace com::sun::star::container +{ +class XIndexAccess; +} +namespace com::sun::star::drawing +{ +class XDrawPage; +} + +namespace sd::slidesorter::model +{ +inline sal_Int32 FromCoreIndex(const sal_uInt16 nCoreIndex) { return (nCoreIndex - 1) / 2; } + +/** The model of the slide sorter gives access to the slides that are to be + displayed in the slide sorter view. Via the SetDocumentSlides() method + this set of slides can be modified (but do not call it directly, use + SlideSorterController::SetDocumentSlides() instead.) +*/ +class SlideSorterModel final +{ +public: + SlideSorterModel(SlideSorter& rSlideSorter); + + ~SlideSorterModel(); + void Dispose(); + + /** This method is present to let the view create a ShowView for + displaying slides. + */ + SdDrawDocument* GetDocument(); + + /** Set a new edit mode and return whether the edit mode really + has been changed. When the edit mode is changed then the + previous page descriptor list is replaced by a new one which + has to be repainted. + @return + A return value of <TRUE/> indicates that the edit mode has + changed and thus the page descriptor list has been set up + to reflect that change. A repaint is necessary. + */ + bool SetEditMode(EditMode eEditMode); + + EditMode GetEditMode() const { return meEditMode; } + + /** Return the number of slides in the document regardless of whether + they are visible or not or whether they are hidden or not. + The number of slides depends on the set of slides available through + the XIndexAccess given to SetDocumentSlides(). + */ + sal_Int32 GetPageCount() const; + + /** Return a page descriptor for the page with the specified index. + Page descriptors are created on demand. The page descriptor is + found (or not found) in constant time. + @param nPageIndex + The index of the requested slide. The valid values + are 0 to GetPageCount()-1. + @param bCreate + When <TRUE/> and the requested page descriptor is missing then + it is created. When <FALSE/> then an empty reference is + returned for missing descriptors. + @return + When the given index is not valid, i.e. lower than zero or + larger than or equal to the number of pages then an empty + reference is returned. Note that the page count may change + between calls to GetPageCount() and GetPageDescriptor(). + */ + SharedPageDescriptor GetPageDescriptor(const sal_Int32 nPageIndex, + const bool bCreate = true) const; + + /** Return a page descriptor for the given XDrawPage. Page descriptors + are created on demand. The page descriptor is found (or not found) + in (at most) linear time. Note that all page descriptors in front of + the one associated with the given XDrawPage are created when not yet + present. When the XDrawPage is not found then all descriptors are + created. + @return + Returns the index to the requested page descriptor or -1 when + there is no such page descriptor. + */ + sal_Int32 GetIndex(const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) const; + + /** Return a page descriptor for the given SdrPage. Page descriptors + are created on demand. The page descriptor is found (or not found) + in (at most) linear time. Note that all page descriptors in front of + the one associated with the given XDrawPage are created when not yet + present. When the SdrPage is not found then all descriptors are + created. + @return + Returns the index to the requested page descriptor or -1 when + there is no such page descriptor. + */ + sal_Int32 GetIndex(const SdrPage* pPage) const; + + /** Return an index for accessing an SdrModel that corresponds to the + given SlideSorterModel index. In many cases we just have to apply + the n*2+1 magic. Only when a special model is set, like a custom + slide show, then the returned value is different. + */ + sal_uInt16 GetCoreIndex(const sal_Int32 nIndex) const; + + /** Call this method after the document has changed its structure. This + will get the model in sync with the SdDrawDocument. This method + tries not to throw away too much information already gathered. This + is especially important for previews of complex pages that take some + time to create. + */ + void Resync(); + + /** Delete all descriptors that currently are in the container. The size + of the container, however, is not altered. Use the AdaptSize + method for that. + */ + void ClearDescriptorList(); + + /** Set the selection of the document to exactly that of the called model. + */ + void SynchronizeDocumentSelection(); + + /** Set the selection of the called model to exactly that of the document. + */ + void SynchronizeModelSelection(); + + /** Return the mutex so that the caller can lock it and then safely + access the model. + */ + ::osl::Mutex& GetMutex() { return maMutex; } + + /** Set the XIndexAccess from which the called SlideSorterModel takes + its pages. + @param rxSlides + The set of slides accessible through this XIndexAccess are not + necessarily the same as the ones of the XModel of the + XController (although it typically is a subset). + */ + void SetDocumentSlides(const css::uno::Reference<css::container::XIndexAccess>& rxSlides); + + /** Return the set of pages that is currently displayed by the slide sorter. + */ + css::uno::Reference<css::container::XIndexAccess> GetDocumentSlides() const; + + /** This method is called when the edit mode has changed. It calls + SetDocumentSlides() with the set of slides or master pages obtained + from the model of the XController. + */ + void UpdatePageList(); + + bool IsReadOnly() const; + + /** The current selection is saved by copying the ST_Selected state into + ST_WasSelected for slides. + */ + void SaveCurrentSelection(); + + /** The current selection is restored from the ST_WasSelected state from + the slides. + @returns + The returned region has to be repainted to reflect the updated + selection states. + */ + vcl::Region RestoreSelection(); + + /** Typically called from controller::Listener this method handles the + insertion and deletion of single pages. + @return + Returns <TRUE/> when the given page is relevant for the current + page kind and edit mode. + */ + bool NotifyPageEvent(const SdrPage* pPage); + +private: + mutable ::osl::Mutex maMutex; + SlideSorter& mrSlideSorter; + css::uno::Reference<css::container::XIndexAccess> mxSlides; + EditMode meEditMode; + mutable ::std::vector<SharedPageDescriptor> maPageDescriptors; + + /** Resize the descriptor container according to current values of + page kind and edit mode. + */ + void AdaptSize(); + + SdPage* GetPage(const sal_Int32 nCoreIndex) const; + void InsertSlide(SdPage* pPage, bool bMarkSelected); + // return if this page was marked as selected before being removed + bool DeleteSlide(const SdPage* pPage); + void UpdateIndices(const sal_Int32 nFirstIndex); +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx b/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx new file mode 100644 index 000000000..289f85911 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsEnumeration.hxx @@ -0,0 +1,44 @@ +/* -*- 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> + +namespace sd::slidesorter::model +{ +/** Interface to generic enumerations. Designed to operate on shared + pointers. Therefore GetNextElement() returns T and not T&. +*/ +template <class T> class Enumeration +{ +public: + virtual ~Enumeration() {} + + virtual bool HasMoreElements() const = 0; + /** Returns T instead of T& so that it can handle shared pointers. + */ + virtual T GetNextElement() = 0; + virtual void Rewind() = 0; + virtual ::std::unique_ptr<Enumeration<T>> Clone() = 0; +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx new file mode 100644 index 000000000..4f3be3b42 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx @@ -0,0 +1,144 @@ +/* -*- 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/SlsVisualState.hxx> +#include <tools/gen.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <memory> + +namespace com::sun::star::drawing { class XDrawPage; } + +class SdPage; +class SdrPage; + +namespace sd::slidesorter::model { + +/** Each PageDescriptor object represents the preview of one draw page, + slide, or master page of a Draw or Impress document as they are displayed + in the slide sorter. This class gives access to some associated + information like prerendered preview or position on the screen. + + <p>Bounding boxes of page objects come in four varieties: + Model and screen/pixel coordinates and the bounding boxes of the actual + page objects and the larger bounding boxes that include page names and + fade symbol.</p> +*/ +class PageDescriptor + : public ::std::enable_shared_from_this<PageDescriptor> +{ +public: + /** Create a PageDescriptor for the given SdPage object. + @param rxPage + The page that is represented by the new PageDescriptor object. + @param pPage + The page pointer can in some situations not be detected from + rxPage, e.g. after undo of page deletion. Therefore supply it + separately. + @param nIndex + This index is displayed in the view as page number. It is not + necessarily the page index (not even when you add or subtract 1 + or use (x-1)/2 magic). + */ + PageDescriptor ( + const css::uno::Reference<css::drawing::XDrawPage>& rxPage, + SdPage* pPage, + const sal_Int32 nIndex); + + ~PageDescriptor(); + + /** Return the page that is represented by the descriptor as SdPage pointer . + */ + SdPage* GetPage() const { return mpPage;} + + /** Return the page that is represented by the descriptor as XDrawPage reference. + */ + const css::uno::Reference<css::drawing::XDrawPage>& GetXDrawPage() const { return mxPage;} + + /** Returns the index of the page as it is displayed in the view as page + number. The value may differ from the index returned by the + XDrawPage when there are hidden slides and the XIndexAccess used to + access the model filters them out. + */ + sal_Int32 GetPageIndex() const { return mnIndex;} + void SetPageIndex (const sal_Int32 nIndex); + + bool UpdateMasterPage(); + bool UpdateTransitionFlag(); + + enum State { ST_Visible, ST_Selected, ST_WasSelected, + ST_Focused, ST_MouseOver, ST_Current, ST_Excluded }; + + bool HasState (const State eState) const; + + bool SetState (const State eState, const bool bStateValue); + + /** Set the internal mbIsSelected flag to the selection state of the + page. Use this method to synchronize a page descriptor with the + page it describes and determine whether a redraw to update the + selection indicator is necessary. + @return + When the two selection states were different <TRUE/> is + returned. When they were the same this method returns + <FALSE/>. + */ + bool GetCoreSelection(); + + /** Set the selection flags of the SdPage objects to the corresponding + selection states of the page descriptors. + */ + void SetCoreSelection(); + + VisualState& GetVisualState() { return maVisualState;} + + ::tools::Rectangle GetBoundingBox() const; + Point GetLocation (const bool bIgnoreLocation) const; + void SetBoundingBox (const ::tools::Rectangle& rBoundingBox); + +private: + SdPage* mpPage; + css::uno::Reference<css::drawing::XDrawPage> mxPage; + SdrPage const* mpMasterPage; + + /** This index is displayed as page number in the view. It may or may + not be the actual page index. + */ + sal_Int32 mnIndex; + + ::tools::Rectangle maBoundingBox; + VisualState maVisualState; + + bool mbIsSelected : 1; + bool mbWasSelected : 1; + bool mbIsVisible : 1; + bool mbIsFocused : 1; + bool mbIsCurrent : 1; + bool mbIsMouseOver : 1; + bool mbHasTransition : 1; + + PageDescriptor (const PageDescriptor& rDescriptor) = delete; + + PageDescriptor& operator= (const PageDescriptor& rDescriptor) = delete; +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx new file mode 100644 index 000000000..6901a9ff1 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsPageEnumeration.hxx @@ -0,0 +1,95 @@ +/* -*- 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/SlsEnumeration.hxx> +#include <model/SlsSharedPageDescriptor.hxx> + +#include <functional> +#include <memory> + +namespace sd::slidesorter::model +{ +class SlideSorterModel; + +/** Public class of page enumerations that delegates its calls to an + implementation object that can filter pages by using a given predicate. + + @see PageEnumerationProvider + The PageEnumerationProvider has methods for creating different types + of page enumerations. +*/ +class PageEnumeration final : public Enumeration<SharedPageDescriptor> +{ +public: + /** Create a new page enumeration that enumerates a subset of the pages + of the given model. + @param rModel + The new page enumeration enumerates the pages of this model. + @param rPredicate + This predicate determines which pages to include in the + enumeration. Pages for which rPredicate returns <FALSE/> are + exclude. + */ + typedef ::std::function<bool(const SharedPageDescriptor&)> PagePredicate; + static PageEnumeration Create(const SlideSorterModel& rModel, const PagePredicate& rPredicate); + + /** This copy constructor creates a copy of the given enumeration. + */ + PageEnumeration(const PageEnumeration& rEnumeration); + + virtual ~PageEnumeration() override; + + /** Create and return an exact copy of the called object. + */ + virtual ::std::unique_ptr<Enumeration<SharedPageDescriptor>> Clone() override; + + PageEnumeration& operator=(const PageEnumeration& rEnumeration); + + /** Return <TRUE/> when the enumeration has more elements, i.e. it is + save to call GetNextElement() at least one more time. + */ + virtual bool HasMoreElements() const override; + + /** Return the next element of the enumeration. Call the + HasMoreElements() before to make sure that there exists at least one + more element. Calling this method with HasMoreElements() returning + <FALSE/> is an error. + */ + virtual SharedPageDescriptor GetNextElement() override; + + /** Rewind the enumeration so that the next call to GetNextElement() + will return its first element. + */ + virtual void Rewind() override; + +private: + /// Implementation object. + ::std::unique_ptr<Enumeration<SharedPageDescriptor>> mpImpl; + + /** This constructor expects an implementation object that holds + the predicate that filters the pages. + */ + PageEnumeration(::std::unique_ptr<Enumeration<SharedPageDescriptor>>&& pImpl); +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx new file mode 100644 index 000000000..b6de98d13 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsPageEnumerationProvider.hxx @@ -0,0 +1,51 @@ +/* -*- 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/SlsPageEnumeration.hxx> + +namespace sd::slidesorter::model +{ +class SlideSorterModel; + +/** Collection of methods that create enumeration of slides. +*/ +class PageEnumerationProvider +{ +public: + /** The returned enumeration of slides iterates over all slides of the + given model. + */ + static PageEnumeration CreateAllPagesEnumeration(const SlideSorterModel& rModel); + + /** The returned enumeration of slides iterates over the currently + selected slides of the given model. + */ + static PageEnumeration CreateSelectedPagesEnumeration(const SlideSorterModel& rModel); + + /** The returned enumeration of slides iterates over the slides + (partially) inside the visible area. + */ + static PageEnumeration CreateVisiblePagesEnumeration(const SlideSorterModel& rModel); +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx b/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx new file mode 100644 index 000000000..6ee1e2b22 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsSharedPageDescriptor.hxx @@ -0,0 +1,32 @@ +/* -*- 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> + +namespace sd::slidesorter::model +{ +class PageDescriptor; + +typedef std::shared_ptr<PageDescriptor> SharedPageDescriptor; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/model/SlsVisualState.hxx b/sd/source/ui/slidesorter/inc/model/SlsVisualState.hxx new file mode 100644 index 000000000..89eae16ca --- /dev/null +++ b/sd/source/ui/slidesorter/inc/model/SlsVisualState.hxx @@ -0,0 +1,47 @@ +/* -*- 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/gen.hxx> + +namespace sd::slidesorter::model +{ +/** This class gives access to values related to the visualization of page + objects. This includes animation state when blending from one state to + another. +*/ +class VisualState +{ +public: + VisualState(const sal_Int32 nPageId); + + const Point& GetLocationOffset() const { return maLocationOffset; } + void SetLocationOffset(const Point& rPoint); + + sal_Int32 mnPageId; // For debugging + +private: + Point maLocationOffset; +}; + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx new file mode 100644 index 000000000..0f3493ab3 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlideSorterView.hxx @@ -0,0 +1,225 @@ +/* -*- 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/SlsPageDescriptor.hxx> +#include <model/SlsSharedPageDescriptor.hxx> +#include <view/SlsLayouter.hxx> +#include <view/SlsILayerPainter.hxx> +#include <o3tl/deleter.hxx> + +#include <View.hxx> +#include <tools/gen.hxx> +#include <vcl/region.hxx> +#include <memory> + +namespace sd::slidesorter::cache { class PageCache; } +namespace sd::slidesorter::model { class SlideSorterModel; } +namespace sd { class Window; } +namespace sd::slidesorter { class SlideSorter; } +namespace sd::slidesorter::view { + +class LayeredDevice; +class PageObjectPainter; +class ToolTip; + +class SlideSorterView final + : public sd::View +{ +public: + + /** Create a new view for the slide sorter. + @param rViewShell + This reference is simply passed to the base class and not used + by this class. + + */ + explicit SlideSorterView (SlideSorter& rSlideSorter); + void Init(); + + virtual ~SlideSorterView() override; + void Dispose(); + + SlideSorterView(const SlideSorterView&) = delete; + SlideSorterView& operator=(const SlideSorterView&) = delete; + + /** Set the general way of layouting the page objects. Note that this + method does not trigger any repaints or layouts. + */ + bool SetOrientation (const Layouter::Orientation eOrientation); + Layouter::Orientation GetOrientation() const { return meOrientation;} + + void RequestRepaint(); + void RequestRepaint (const model::SharedPageDescriptor& rDescriptor); + void RequestRepaint (const ::tools::Rectangle& rRepaintBox); + void RequestRepaint (const vcl::Region& rRepaintRegion); + + ::tools::Rectangle GetModelArea() const; + + /** Return the index of the page that is rendered at the given position. + @param rPosition + The position is expected to be in pixel coordinates. + @return + The returned index is -1 when there is no page object at the + given position. + */ + sal_Int32 GetPageIndexAtPoint (const Point& rPosition) const; + + view::Layouter& GetLayouter(); + + virtual void ModelHasChanged() override; + + /** This method is typically called before a model change takes place. + All references to model data are released. PostModelChange() has to + be called to complete the handling of the model change. When the + calls to Pre- and PostModelChange() are very close to each other you + may call HandleModelChange() instead. + */ + void PreModelChange(); + + /** This method is typically called after a model change took place. + References to model data are re-allocated. Call this method only + after PreModelChange() has been called. + */ + void PostModelChange(); + + /** This method is a convenience function that simply calls + PreModelChange() and then PostModelChange(). + */ + void HandleModelChange(); + + void HandleDrawModeChange(); + + void Resize(); + virtual void CompleteRedraw ( + OutputDevice* pDevice, + const vcl::Region& rPaintArea, + sdr::contact::ViewObjectContactRedirector* pRedirector = nullptr) override; + void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea); + + virtual void ConfigurationChanged ( + utl::ConfigurationBroadcaster* pBroadcaster, + ConfigurationHints nHint) override; + + void HandleDataChangeEvent(); + + void Layout(); + /** This tells the view that it has to re-determine the visibility of + the page objects before painting them the next time. + */ + void InvalidatePageObjectVisibilities(); + + std::shared_ptr<cache::PageCache> const & GetPreviewCache(); + + /** Return the range of currently visible page objects including the + first and last one in that range. + @return + The returned pair of page object indices is empty when the + second index is lower than the first. + */ + Range const & GetVisiblePageRange(); + + /** Add a shape to the page. Typically used from inside + PostModelChange(). + */ + // void AddSdrObject (SdrObject& rObject); + + /** Add a listener that is called when the set of visible slides. + @param rListener + When this method is called multiple times for the same listener + the second and all following calls are ignored. Each listener + is added only once. + */ + void AddVisibilityChangeListener (const Link<LinkParamNone*,void>& rListener); + + /** Remove a listener that is called when the set of visible slides changes. + @param rListener + It is safe to pass a listener that was not added or has been + removed previously. Such calls are ignored. + */ + void RemoveVisibilityChangeListener (const Link<LinkParamNone*,void>& rListener); + + /** The page under the mouse is not highlighted in some contexts. Call + this method on context changes. + */ + void UpdatePageUnderMouse (); + void UpdatePageUnderMouse (const Point& rMousePosition); + void SetPageUnderMouse (const model::SharedPageDescriptor& rpDescriptor); + + bool SetState ( + const model::SharedPageDescriptor& rpDescriptor, + const model::PageDescriptor::State eState, + const bool bStateValue); + + void UpdateOrientation(); + + std::shared_ptr<PageObjectPainter> const & GetPageObjectPainter(); + const std::shared_ptr<LayeredDevice>& GetLayeredDevice() const { return mpLayeredDevice;} + + class DrawLock + { + public: + DrawLock (SlideSorter const & rSlideSorter); + ~DrawLock(); + /** When the DrawLock is disposed then it will not request a repaint + on destruction. + */ + void Dispose(); + private: + view::SlideSorterView& mrView; + VclPtr<sd::Window> mpWindow; + }; + + ToolTip& GetToolTip() const; + + virtual void DragFinished (sal_Int8 nDropAction) override; + +private: + SlideSorter& mrSlideSorter; + model::SlideSorterModel& mrModel; + bool mbIsDisposed; + ::std::unique_ptr<Layouter> mpLayouter; + bool mbPageObjectVisibilitiesValid; + std::shared_ptr<cache::PageCache> mpPreviewCache; + std::shared_ptr<LayeredDevice> mpLayeredDevice; + Range maVisiblePageRange; + Size maPreviewSize; + bool mbPreciousFlagUpdatePending; + Layouter::Orientation meOrientation; + model::SharedPageDescriptor mpPageUnderMouse; + std::shared_ptr<PageObjectPainter> mpPageObjectPainter; + vcl::Region maRedrawRegion; + SharedILayerPainter mpBackgroundPainter; + std::unique_ptr<ToolTip, o3tl::default_delete<ToolTip>> mpToolTip; + bool mbIsRearrangePending; + ::std::vector<Link<LinkParamNone*,void>> maVisibilityChangeListeners; + + /** Determine the visibility of all page objects. + */ + void DeterminePageObjectVisibilities(); + + void UpdatePreciousFlags(); + void RequestRearrange(); + void Rearrange(); +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx new file mode 100644 index 000000000..57b90af0a --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsILayerPainter.hxx @@ -0,0 +1,53 @@ +/* -*- 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> + +class OutputDevice; +namespace tools { class Rectangle; } + +namespace sd::slidesorter::view { + +class ILayerInvalidator +{ +public: + virtual ~ILayerInvalidator() {} + + virtual void Invalidate (const ::tools::Rectangle& rInvalidationBox) = 0; +}; +typedef std::shared_ptr<ILayerInvalidator> SharedILayerInvalidator; + +class ILayerPainter +{ +public: + virtual ~ILayerPainter() {} + + virtual void SetLayerInvalidator ( + const SharedILayerInvalidator& rpInvalidator) = 0; + virtual void Paint ( + OutputDevice& rDevice, + const ::tools::Rectangle& rRepaintArea) = 0; +}; +typedef std::shared_ptr<ILayerPainter> SharedILayerPainter; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx b/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx new file mode 100644 index 000000000..c74d06cb9 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsInsertAnimator.hxx @@ -0,0 +1,59 @@ +/* -*- 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 <memory> + +namespace sd::slidesorter::view +{ +class InsertPosition; + +/** Animate the positions of page objects to make room at the insert + position while a move or copy operation takes place. +*/ +class InsertAnimator +{ +public: + explicit InsertAnimator(SlideSorter& rSlideSorter); + InsertAnimator(const InsertAnimator&) = delete; + InsertAnimator& operator=(const InsertAnimator&) = delete; + + /** Set the position at which we have to make room for the display of an + icon. + */ + void SetInsertPosition(const InsertPosition& rInsertPosition); + + /** Restore the normal position of all page objects. + @param eMode + This flag controls whether to start an animation that ends in the + normal positions of all slides (AM_Animated) or to restore the + normal positions immediately (AM_Immediate). + */ + void Reset(const controller::Animator::AnimationMode eMode); + +private: + class Implementation; + std::shared_ptr<Implementation> mpImplementation; +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx b/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx new file mode 100644 index 000000000..3f4cc2218 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsInsertionIndicatorOverlay.hxx @@ -0,0 +1,101 @@ +/* -*- 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/SlsILayerPainter.hxx> +#include <controller/SlsTransferableData.hxx> + +#include <tools/gen.hxx> +#include <vcl/bitmapex.hxx> +#include <memory> +#include <vector> + +class OutputDevice; +class SdTransferable; + +namespace sd::slidesorter { class SlideSorter; } + +namespace sd::slidesorter::view { + +class FramePainter; + +/** The insertion indicator is painted as a vertical or horizontal bar + in the space between slides. +*/ +class InsertionIndicatorOverlay final + : public ILayerPainter, + public std::enable_shared_from_this<InsertionIndicatorOverlay> +{ +public: + InsertionIndicatorOverlay (SlideSorter& rSlideSorter); + virtual ~InsertionIndicatorOverlay() override; + + virtual void SetLayerInvalidator (const SharedILayerInvalidator& rpInvalidator) override; + + void Create (const SdTransferable* pTransferable); + + /** Given a position in model coordinates this method calculates the + insertion marker both as an index in the document and as a location + used for drawing the insertion indicator. + */ + void SetLocation (const Point& rPosition); + + Size GetSize() const; + + virtual void Paint ( + OutputDevice& rDevice, + const ::tools::Rectangle& rRepaintArea) override; + + bool IsVisible() const { return mbIsVisible;} + void Hide(); + void Show(); + + ::tools::Rectangle GetBoundingBox() const; + +private: + SlideSorter& mrSlideSorter; + bool mbIsVisible; + SharedILayerInvalidator mpLayerInvalidator; + // Center of the insertion indicator. + Point maLocation; + BitmapEx maIcon; + std::unique_ptr<FramePainter> mpShadowPainter; + + Point PaintRepresentatives ( + OutputDevice& rContent, + const Size& rPreviewSize, + const sal_Int32 nOffset, + const ::std::vector<controller::TransferableData::Representative>& rPages) const; + void PaintPageCount ( + OutputDevice& rDevice, + const sal_Int32 nSelectionCount, + const Size& rPreviewSize, + const Point& rFirstPageOffset) const; + /** Setup the insertion indicator by creating the icon. It consists of + scaled down previews of some of the selected pages. + */ + void Create ( + const ::std::vector<controller::TransferableData::Representative>& rPages, + const sal_Int32 nSelectionCount); +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx new file mode 100644 index 000000000..b91ae83c5 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsLayouter.hxx @@ -0,0 +1,237 @@ +/* -*- 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 <vcl/vclptr.hxx> +#include <tools/gen.hxx> +#include <sal/types.h> +#include <memory> + +namespace sd { class Window; } +namespace sd::slidesorter::model { class SlideSorterModel; } +namespace sd::slidesorter::view { class PageObjectLayouter; } +namespace sd::slidesorter::view { class Theme; } + +namespace sd::slidesorter::view { + +class InsertPosition; + +/** Calculate the size and position of page objects displayed by a slide + sorter. The layouter takes into account various input values: + 1.) Size of the window in which the slide sorter is displayed. + 2.) Desired and minimal and maximal widths of page objects. + 3.) Minimal and maximal number of columns. + 4.) Vertical and horizontal gaps between objects in adjacent columns. + 5.) Borders around every page object. + 6.) Vertical and horizontal borders between enclosing page and outer + page objects. + From these, it calculates various output values: + 1.) The width of page objects. + 2.) The number of columns. + 3.) The size of the enclosing page. + + <p>Sizes and lengths are all in pixel except where explicitly stated + otherwise.</p> + + <p>The GetIndex... methods may return indices that are larger than or + equal to (zero based) the number of pages. This is so because the + number of pages is not known to the class instances. Indices are + calculated with reference to the general grid layout of page + objects.</p> +*/ +class Layouter +{ +public: + enum Orientation { HORIZONTAL, VERTICAL, GRID }; + + Layouter ( + sd::Window *rpWindow, + const std::shared_ptr<Theme>& rpTheme); + ~Layouter(); + + std::shared_ptr<PageObjectLayouter> const & GetPageObjectLayouter() const; + /** Set the interval of valid column counts. When nMinimalColumnCount + <= nMaximalColumnCount is not fulfilled then the call is ignored. + @param nMinimalColumnCount + The default value is 1. The question whether higher values make + any sense is left to the caller. + @param nMaximalColumnCount + The default value is 5. + */ + void SetColumnCount (sal_Int32 nMinimalColumnCount, + sal_Int32 nMaximalColumnCount); + + /** Central method of this class. It takes the input values and + calculates the output values. Both given sizes must not be 0 in any + dimension or the call is ignored. + @param eOrientation + This defines the generally layout and specifies whether there may + be more than one row or more than one column. + @param rWindowSize + The size of the window in pixels that the slide sorter is + displayed in. This can differ from the size of mpWindow during + detection of whether or not the scroll bars should be visible. + @param rPreviewModelSize + Size of each page in model coordinates. + @param rpWindow + The map mode of this window is adapted to the new layout of the + page objects. + @return + The return value indicates whether the Get... methods can be + used to obtain valid values (<TRUE/>). + */ + bool Rearrange ( + const Orientation eOrientation, + const Size& rWindowSize, + const Size& rPreviewModelSize, + const sal_uInt32 nPageCount); + + /** Return the number of columns. + */ + sal_Int32 GetColumnCount() const; + + sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const; + + Size const & GetPageObjectSize() const; + + /** Return the bounding box in window coordinates of the nIndex-th page + object. + */ + ::tools::Rectangle GetPageObjectBox ( + const sal_Int32 nIndex, + const bool bIncludeBorderAndGap) const; + + /** Return the bounding box in model coordinates of the page that + contains the given amount of page objects. + */ + ::tools::Rectangle GetTotalBoundingBox() const; + + /** Return the index of the first fully or partially visible page + object. This takes into account only the vertical dimension. + @return + The second index may be larger than the number of existing + page objects. + */ + Range GetRangeOfVisiblePageObjects (const ::tools::Rectangle& rVisibleArea) const; + + /** Return the index of the page object that is rendered at the given + point. + @param rPosition + The position is expected to be in model coordinates relative to + the page origin. + @param bIncludePageBorders + When <TRUE/> then include the page borders into the calculation, + i.e. when a point lies in the border of a page object but not on + the actual page area the index of that page is returned; + otherwise -1 would be returned to indicate that no page object + has been hit. + @param bClampToValidRange + When <TRUE/> then values outside the valid range [0,mnPageCount) + are mapped to 0 (when smaller than 0) or mnPageCount-1 when + equal to or larger than mnPageCount. + When <FALSE/> then -1 is returned for values outside the valid range. + @return + The returned index may be larger than the number of existing + page objects. + */ + sal_Int32 GetIndexAtPoint ( + const Point& rModelPosition, + const bool bIncludePageBorders, + const bool bClampToValidRange = true) const; + + /** Return an object that describes the logical and visual properties of + where to do an insert operation when the user would release the + mouse button at the given position after a drag operation and of + where and how to display an insertion indicator. + @param rModelPosition + The position in the model coordinate system for which to + determine the insertion page index. The position does not have + to be over a page object to return a valid value. + @param rIndicatorSize + The size of the insertion indicator. This size is used to adapt + the location when at the left or right of a row or at the top or + bottom of a column. + @param rModel + The model is used to get access to the selection states of the + pages. This in turn is used to determine the visual bounding + boxes. + */ + InsertPosition GetInsertPosition ( + const Point& rModelPosition, + const Size& rIndicatorSize, + model::SlideSorterModel const & rModel) const; + + Range GetValidHorizontalSizeRange() const; + Range GetValidVerticalSizeRange() const; + + class Implementation; + +private: + std::unique_ptr<Implementation> mpImplementation; + VclPtr<sd::Window> mpWindow; +}; + +/** Collect all values concerning the logical and visual properties of the + insertion position that is used for drag-and-drop and copy-and-paste. +*/ +class InsertPosition +{ +public: + InsertPosition(); + bool operator== (const InsertPosition& rInsertPosition) const; + bool operator!= (const InsertPosition& rInsertPosition) const; + + void SetLogicalPosition ( + const sal_Int32 nRow, + const sal_Int32 nColumn, + const sal_Int32 nIndex, + const bool bIsAtRunStart, + const bool bIsAtRunEnd, + const bool bIsExtraSpaceNeeded); + void SetGeometricalPosition( + const Point& rLocation, + const Point& rLeadingOffset, + const Point& rTrailingOffset); + + sal_Int32 GetRow() const { return mnRow; } + sal_Int32 GetColumn() const { return mnColumn; } + sal_Int32 GetIndex() const { return mnIndex; } + const Point& GetLocation() const { return maLocation; } + const Point& GetLeadingOffset() const { return maLeadingOffset; } + const Point& GetTrailingOffset() const { return maTrailingOffset; } + bool IsAtRunStart() const { return mbIsAtRunStart; } + bool IsAtRunEnd() const { return mbIsAtRunEnd; } + bool IsExtraSpaceNeeded() const { return mbIsExtraSpaceNeeded; } + +private: + sal_Int32 mnRow; + sal_Int32 mnColumn; + sal_Int32 mnIndex; + bool mbIsAtRunStart : 1; + bool mbIsAtRunEnd : 1; + bool mbIsExtraSpaceNeeded : 1; + Point maLocation; + Point maLeadingOffset; + Point maTrailingOffset; +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx new file mode 100644 index 000000000..8bb77a988 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectLayouter.hxx @@ -0,0 +1,144 @@ +/* -*- 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/gen.hxx> +#include <vcl/image.hxx> + +namespace vcl { class Font; } +namespace sd { class Window; } + +namespace sd::slidesorter::view { + +/** In contrast to the Layouter that places page objects in the view, the + PageObjectLayouter places the parts of individual page objects like page + number area, borders, preview. +*/ +class PageObjectLayouter +{ +public: + /** Create a new PageObjectLayouter object. + @param rPageObjectSize + In general either the width or the height will be 0 in order to + signal that this size component has to be calculated from the other. + This calculation will make the preview as large as possible. + @param nPageCount + The page count is used to determine how wide the page number + area has to be, how many digits to except for the largest page number. + */ + PageObjectLayouter( + const Size& rPageObjectWindowSize, + const Size& rPreviewModelSize, + sd::Window *pWindow, + const sal_Int32 nPageCount); + ~PageObjectLayouter(); + + enum class Part { + // The focus indicator is painted outside the actual page object. + FocusIndicator, + // This is the outer bounding box that includes the preview, page + // number, title. + PageObject, + // Bounding box of the actual preview. + Preview, + // Bounding box of the page number. + PageNumber, + // Indicator whether or not there is a slide transition associated + // with this slide. + TransitionEffectIndicator, + // Indicator whether or not there is a custom animation associated + // with this slide. + CustomAnimationEffectIndicator + }; + /** Two coordinate systems are supported. They differ only in + translation not in scale. Both relate to pixel values in the window. + A position in the model coordinate system does not change when the window content is + scrolled up or down. In the window coordinate system (relative + to the top left point of the window)scrolling leads to different values. + */ + enum CoordinateSystem { + WindowCoordinateSystem, + ModelCoordinateSystem + }; + + /** Return the bounding box of the page object or one of its graphical + parts. + @param rWindow + This device is used to translate between model and window + coordinates. + @param rpPageDescriptor + The page for which to calculate the bounding box. This may be + NULL. When it is NULL then a generic bounding box is calculated + for the location (0,0). + @param ePart + The part of the page object for which to return the bounding + box. + @param eCoordinateSystem + The bounding box can be returned in model and in pixel + (window) coordinates. + @param bIgnoreLocation + Return a position ignoring the slides' location, ie. as if + we were the first slide. + */ + ::tools::Rectangle GetBoundingBox ( + const model::SharedPageDescriptor& rpPageDescriptor, + const Part ePart, + const CoordinateSystem eCoordinateSystem, + bool bIgnoreLocation = false); + + /// the size of the embedded preview: position independent, in window coordinate system + Size GetPreviewSize(); + + /// the maximum size of each tile, also position independent, in window coordinate system + Size GetGridMaxSize(); + + const Image& GetTransitionEffectIcon() const { return maTransitionEffectIcon;} + const Image& GetCustomAnimationEffectIcon() const { return maCustomAnimationEffectIcon;} + +private: + ::tools::Rectangle GetBoundingBox ( + const Point& rPageObjectLocation, + const Part ePart, + const CoordinateSystem eCoordinateSystem); + +private: + VclPtr<sd::Window> mpWindow; + ::tools::Rectangle maFocusIndicatorBoundingBox; + ::tools::Rectangle maPageObjectBoundingBox; + ::tools::Rectangle maPageNumberAreaBoundingBox; + ::tools::Rectangle maPreviewBoundingBox; + ::tools::Rectangle maTransitionEffectBoundingBox; + ::tools::Rectangle maCustomAnimationEffectBoundingBox; + const Image maTransitionEffectIcon; + const Image maCustomAnimationEffectIcon; + const std::shared_ptr<vcl::Font> mpPageNumberFont; + + Size GetPageNumberAreaSize (const int nPageCount); + ::tools::Rectangle CalculatePreviewBoundingBox ( + Size& rPageObjectSize, + const Size& rPreviewModelSize, + const sal_Int32 nPageNumberAreaWidth, + const sal_Int32 nFocusIndicatorWidth); +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx new file mode 100644 index 000000000..747c09500 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsPageObjectPainter.hxx @@ -0,0 +1,119 @@ +/* -*- 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 <view/SlsTheme.hxx> +#include <memory> + +namespace sd::slidesorter::cache { class PageCache; } +namespace sd::slidesorter { class SlideSorter; } + +namespace sd::slidesorter::view { + +class Layouter; +class PageObjectLayouter; +class FramePainter; + +class PageObjectPainter +{ +public: + PageObjectPainter (const SlideSorter& rSlideSorter); + ~PageObjectPainter(); + + void PaintPageObject ( + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor); + + /** Called when the theme changes, either because it is replaced with + another or because the system colors have changed. So, even when + the given theme is the same object as the one already in use by this + painter everything that depends on the theme is updated. + */ + void SetTheme (const std::shared_ptr<view::Theme>& rpTheme); + + /** Return a preview bitmap for the given page descriptor. When the + page is excluded from the show then the preview is marked + accordingly. + @rpDescriptor + Defines the page for which to return the preview. + @pReferenceDevice + When not <NULL/> then this reference device is used to created a + compatible bitmap. + @return + The returned bitmap may have a different size then the preview area. + */ + BitmapEx GetPreviewBitmap ( + const model::SharedPageDescriptor& rpDescriptor, + const OutputDevice* pReferenceDevice) const; + +private: + const Layouter& mrLayouter; + std::shared_ptr<cache::PageCache> mpCache; + std::shared_ptr<view::Theme> mpTheme; + std::shared_ptr<vcl::Font> mpPageNumberFont; + std::unique_ptr<FramePainter> mpShadowPainter; + std::unique_ptr<FramePainter> mpFocusBorderPainter; + + void PaintBackground ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const; + void PaintPreview ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const; + void PaintPageNumber ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const; + static void PaintTransitionEffect ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor); + static void PaintCustomAnimationEffect ( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor); + void PaintBorder ( + OutputDevice& rDevice, + const Theme::GradientColorType eColorType, + const ::tools::Rectangle& rBox) const; + void PaintBackgroundDetail( + PageObjectLayouter *pPageObjectLayouter, + OutputDevice& rDevice, + const model::SharedPageDescriptor& rpDescriptor) const; + + static BitmapEx CreateMarkedPreview( + const Size& rSize, + const BitmapEx& rPreview, + const BitmapEx& rOverlay, + const OutputDevice* pReferenceDevice); + + /** Update the local pointer to the page object layouter to the + one owned by the general layouter. + Return <TRUE/> when after the call we have a valid page object layouter. + */ + bool UpdatePageObjectLayouter(); +}; + +} // end of namespace sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx new file mode 100644 index 000000000..efb7b2a3e --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx @@ -0,0 +1,135 @@ +/* -*- 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 <vcl/bitmapex.hxx> +#include <tools/color.hxx> + +#include <memory> + +namespace vcl { class Font; } + +namespace sd::slidesorter::controller { class Properties; } + +namespace sd::slidesorter::view { + +const int Theme_FocusIndicatorWidth = 3; + +/** Collection of colors and styles that are used to paint the slide sorter + view. +*/ +class Theme +{ +public: + Theme (const std::shared_ptr<controller::Properties>& rpProperties); + + /** Call this method to update some colors as response to a change of + a system color change. + */ + void Update ( + const std::shared_ptr<controller::Properties>& rpProperties); + + // BitmapEx GetInsertIndicatorIcon() const; + + enum FontType { + Font_PageNumber, + Font_PageCount + }; + static std::shared_ptr<vcl::Font> GetFont ( + const FontType eType, + const OutputDevice& rDevice); + + enum ColorType { + Color_Background, + Color_PageNumberDefault, + Color_PageNumberHover, + Color_PageNumberHighContrast, + Color_PageNumberBrightBackground, + Color_PageNumberDarkBackground, + Color_Selection, + Color_PreviewBorder, + Color_PageCountFontColor, + ColorType_Size_ + }; + Color GetColor (const ColorType eType); + + enum GradientColorType { + Gradient_NormalPage, + Gradient_SelectedPage, + Gradient_SelectedAndFocusedPage, + Gradient_MouseOverPage, + Gradient_MouseOverSelected, + Gradient_MouseOverSelectedAndFocusedPage, + Gradient_FocusedPage, + GradientColorType_Size_ + }; + enum class GradientColorClass { + Border1, + Border2, + Fill1, + Fill2 + }; + Color GetGradientColor ( + const GradientColorType eType, + const GradientColorClass eClass); + void SetGradient ( + const GradientColorType eType, + const Color aBaseColor, + const sal_Int32 nSaturationOverride, + const sal_Int32 nBrightnessOverride, + const sal_Int32 nFillStartOffset, + const sal_Int32 nFillEndOffset, + const sal_Int32 nBorderStartOffset, + const sal_Int32 nBorderEndOffset); + + enum IconType + { + Icon_RawShadow, + Icon_RawInsertShadow, + Icon_HideSlideOverlay, + Icon_FocusBorder, + IconType_Size_ + }; + const BitmapEx& GetIcon (const IconType eType); + +private: + class GradientDescriptor + { + public: + Color maFillColor1; + Color maFillColor2; + Color maBorderColor1; + Color maBorderColor2; + }; + Color maBackgroundColor; + ::std::vector<GradientDescriptor> maGradients; + ::std::vector<BitmapEx> maIcons; + ::std::vector<Color> maColor; + + GradientDescriptor& GetGradient (const GradientColorType eType); + /** Guarded initialization of the specified icon in the maIcons + container. + */ + void InitializeIcon(const IconType eType, const OUString& rResourceId); +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx b/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx new file mode 100644 index 000000000..6c3557e64 --- /dev/null +++ b/sd/source/ui/slidesorter/inc/view/SlsToolTip.hxx @@ -0,0 +1,75 @@ +/* -*- 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 <rtl/ustring.hxx> +#include <vcl/timer.hxx> + +namespace sd::slidesorter +{ +class SlideSorter; +} + +namespace sd::slidesorter::view +{ +/** Manage the display of tool tips. The tool tip text changes when the + mouse is moved from slide to slide or from button to button. + After the mouse enters a slide the first display of the tool tip is + delayed for a short time in order to not draw attention from the slide + or its button bar. +*/ +class ToolTip +{ +public: + ToolTip(SlideSorter& rSlideSorter); + ~ToolTip(); + + /** Set a new page. This modifies the default help text. After a page + change a timer is started to delay the display of the tool tip for + the new page. + @param rpPage + When this is empty then the tool tip is hidden. + */ + void SetPage(const model::SharedPageDescriptor& rpPage); + + /** Hide the tool tip. + @return + Returns whether the tool tip was visible at the time this method + was called. + */ + bool Hide(); + +private: + SlideSorter& mrSlideSorter; + model::SharedPageDescriptor mpDescriptor; + OUString msCurrentHelpText; + void* mnHelpWindowHandle; + Timer maShowTimer; + Timer maHiddenTimer; + + void DoShow(); + + DECL_LINK(DelayTrigger, Timer*, void); +}; + +} // end of namespace ::sd::slidesorter::view + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |