sd/source/ui/slideshow/slideshowimpl.cxx |  106 +++++++++++++++++++++++++++++++
 sd/source/ui/slideshow/slideshowimpl.hxx |    5 +
 2 files changed, 110 insertions(+), 1 deletion(-)

New commits:
commit 7da04200f9f7ac6ed3e573107282da8428ef65e6
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Wed Nov 15 15:23:20 2023 +0100
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Mon Nov 20 11:28:54 2023 +0100

    Update SlideShow on DrawModel changes
    
    It may happen that DrawModel changes while a SlideShow is running,
    e.g. from EditView/Scripts/UNO API. We can try to suppress these
    as we already try with EditView in that mode. As an alternative
    it is also possible to react to these changes in the SLideShow
    in a useful manner.
    This is the 2nd try, main change is to do all of this directly
    in SlideShow, so no chechs/tests in common code are needed.
    
    Change-Id: Iaa393d78af1fc40003c83d896508abe31cd790d5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159447
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx 
b/sd/source/ui/slideshow/slideshowimpl.cxx
index f4f4bfe77019..de62af1ac9e5 100644
--- a/sd/source/ui/slideshow/slideshowimpl.cxx
+++ b/sd/source/ui/slideshow/slideshowimpl.cxx
@@ -61,6 +61,7 @@
 #include <svx/srchdlg.hxx>
 #include <svx/hyperdlg.hxx>
 #include <svx/svxids.hrc>
+#include <svx/unoapi.hxx>
 #include <AnimationChildWindow.hxx>
 #include <notifydocumentevent.hxx>
 #include "slideshowimpl.hxx"
@@ -545,10 +546,19 @@ SlideshowImpl::SlideshowImpl( const Reference< 
XPresentation2 >& xPresentation,
         mnUserPaintColor = pOptions->GetPresentationPenColor();
         mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
     }
+
+    // to be able to react on various changes in the DrawModel, this class
+    // is now derived from SfxListener and registers itself at the DrawModel
+    if (nullptr != mpDoc)
+        StartListening(*mpDoc);
 }
 
 SlideshowImpl::~SlideshowImpl()
 {
+    // stop listening to DrawModel (see above)
+    if (nullptr != mpDoc)
+        EndListening(*mpDoc);
+
     SdModule *pModule = SD_MOD();
     //rhbz#806663 SlideshowImpl can outlive SdModule
     SdOptions* pOptions = pModule ?
@@ -3045,6 +3055,102 @@ sal_Bool SAL_CALL SlideshowImpl::hasElements(  )
     return getSlideCount() != 0;
 }
 
+namespace
+{
+    class AsyncUpdateSlideshow_Impl
+    {
+    public:
+        struct AsyncUpdateSlideshowData
+        {
+            SlideshowImpl* pSlideshowImpl;
+            uno::Reference< css::drawing::XDrawPage > XCurrentSlide;
+        };
+
+        static void AsyncUpdateSlideshow(
+            SlideshowImpl* pSlideshowImpl,
+            uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide)
+        {
+            AsyncUpdateSlideshowData* pNew(new AsyncUpdateSlideshowData);
+            pNew->pSlideshowImpl = pSlideshowImpl;
+            pNew->XCurrentSlide = rXCurrentSlide;
+            Application::PostUserEvent(LINK(nullptr, 
AsyncUpdateSlideshow_Impl, Update), pNew);
+            // coverity[leaked_storage] - pDisruptor takes care of its own 
destruction at idle time
+        }
+
+        DECL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, void);
+    };
+
+    IMPL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, pData, void)
+    {
+        AsyncUpdateSlideshowData* 
pSlideData(static_cast<AsyncUpdateSlideshowData*>(pData));
+        pSlideData->pSlideshowImpl->gotoSlide(pSlideData->XCurrentSlide);
+        delete pSlideData;
+    }
+}
+
+void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
+{
+    if (SfxHintId::ThisIsAnSdrHint != rHint.GetId())
+        // nothing to do for non-SdrHints
+        return;
+
+    if (nullptr == mpDoc)
+        // better do nothing when no DrawModel (should not happen)
+        return;
+
+    const SdrHintKind eHintKind(static_cast<const SdrHint&>(rHint).GetKind());
+
+    if (SdrHintKind::ObjectChange == eHintKind)
+    {
+        // Object changed, object & involved page included in rHint.
+        uno::Reference< css::drawing::XDrawPage > 
XCurrentSlide(getCurrentSlide());
+        if (!XCurrentSlide.is())
+            return;
+
+        SdrPage* pCurrentSlide(GetSdrPageFromXDrawPage(XCurrentSlide));
+        if (nullptr == pCurrentSlide)
+            return;
+
+        const SdrPage* pHintPage(static_cast<const SdrHint&>(rHint).GetPage());
+        if (nullptr == pHintPage)
+            return;
+
+        bool bCurrentSlideIsInvolved(false);
+
+        if (pHintPage->IsMasterPage())
+        {
+            if (pCurrentSlide->TRG_HasMasterPage())
+            {
+                // current slide uses MasterPage on which the change happened
+                bCurrentSlideIsInvolved = (pHintPage == 
&pCurrentSlide->TRG_GetMasterPage());
+            }
+        }
+        else
+        {
+            // object on current slide was changed
+            bCurrentSlideIsInvolved = (pHintPage == pCurrentSlide);
+        }
+
+        if (!bCurrentSlideIsInvolved)
+            // nothing to do when current slide is not involved
+            return;
+
+        // Refresh current slide. Need to do that asynchronous, else e.g.
+        // text edit changes EditEngine/Outliner are not progressed far
+        // enough (ObjectChanged broadcast which we are in here seems
+        // to early for some cases)
+        AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide);
+    }
+    else if (SdrHintKind::PageOrderChange == eHintKind)
+    {
+        // order of pages (object pages or master pages) changed 
(Insert/Remove/ChangePos)
+        // probably needs refresh of AnimationSlideController in 
mpSlideController
+        gotoFirstSlide();
+    }
+
+    // maybe need to add reactions here to other Hint-Types
+}
+
 Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
 {
     return mxShow;
diff --git a/sd/source/ui/slideshow/slideshowimpl.hxx 
b/sd/source/ui/slideshow/slideshowimpl.hxx
index 48802ba54499..b235a78358f0 100644
--- a/sd/source/ui/slideshow/slideshowimpl.hxx
+++ b/sd/source/ui/slideshow/slideshowimpl.hxx
@@ -127,7 +127,7 @@ private:
 
 typedef comphelper::WeakComponentImplHelper< 
css::presentation::XSlideShowController, css::container::XIndexAccess > 
SlideshowImplBase;
 
-class SlideshowImpl final : public SlideshowImplBase
+class SlideshowImpl final : public SlideshowImplBase, public SfxListener
 {
 friend class SlideShow;
 friend class SlideShowView;
@@ -183,6 +183,9 @@ public:
     virtual css::uno::Type SAL_CALL getElementType(  ) override;
     virtual sal_Bool SAL_CALL hasElements(  ) override;
 
+    //  SfxListener
+    virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+
     // will be called from the SlideShowListenerProxy when this event is fired 
from the XSlideShow
     void slideEnded(const bool bReverse);
     void contextMenuShow(const css::awt::Point& point);

Reply via email to