sd/source/ui/slideshow/slideshowimpl.cxx |   96 ++++++++++++++++++++++++++++---
 sd/source/ui/slideshow/slideshowimpl.hxx |    6 +
 2 files changed, 94 insertions(+), 8 deletions(-)

New commits:
commit 878b4ffc3e2c80c7f65b75c35fea26b978b71daf
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Fri Nov 24 16:02:17 2023 +0100
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Tue Nov 28 11:52:04 2023 +0100

    Update SlideShow on DrawModel changes II
    
    Change-Id: Idfbbb7744cc7b2182647b45f509399535a2d4df2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159930
    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 97216f9bec79..7619624544b4 100644
--- a/sd/source/ui/slideshow/slideshowimpl.cxx
+++ b/sd/source/ui/slideshow/slideshowimpl.cxx
@@ -517,6 +517,8 @@ SlideshowImpl::SlideshowImpl( const Reference< 
XPresentation2 >& xPresentation,
 , mdUserPaintStrokeWidth ( 150.0 )
 , mnEndShowEvent(nullptr)
 , mnContextMenuEvent(nullptr)
+, mnEventObjectChange(nullptr)
+, mnEventPageOrderChange(nullptr)
 , mxPresentation( xPresentation )
 {
     if( mpViewShell )
@@ -598,6 +600,10 @@ void 
SlideshowImpl::disposing(std::unique_lock<std::mutex>&)
         Application::RemoveUserEvent( mnEndShowEvent );
     if( mnContextMenuEvent )
         Application::RemoveUserEvent( mnContextMenuEvent );
+    if( mnEventObjectChange )
+        Application::RemoveUserEvent( mnEventObjectChange );
+    if( mnEventPageOrderChange )
+        Application::RemoveUserEvent( mnEventPageOrderChange );
 
     maInputFreezeTimer.Stop();
 
@@ -3094,16 +3100,19 @@ namespace
         {
             SlideshowImpl* pSlideshowImpl;
             uno::Reference< css::drawing::XDrawPage > XCurrentSlide;
+            SdrHintKind eHintKind;
         };
 
-        static void AsyncUpdateSlideshow(
+        static ImplSVEvent* AsyncUpdateSlideshow(
             SlideshowImpl* pSlideshowImpl,
-            uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide)
+            uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
+            SdrHintKind eHintKind)
         {
             AsyncUpdateSlideshowData* pNew(new AsyncUpdateSlideshowData);
             pNew->pSlideshowImpl = pSlideshowImpl;
             pNew->XCurrentSlide = rXCurrentSlide;
-            Application::PostUserEvent(LINK(nullptr, 
AsyncUpdateSlideshow_Impl, Update), pNew);
+            pNew->eHintKind = eHintKind;
+            return Application::PostUserEvent(LINK(nullptr, 
AsyncUpdateSlideshow_Impl, Update), pNew);
             // coverity[leaked_storage] - pDisruptor takes care of its own 
destruction at idle time
         }
 
@@ -3113,11 +3122,64 @@ namespace
     IMPL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, pData, void)
     {
         AsyncUpdateSlideshowData* 
pSlideData(static_cast<AsyncUpdateSlideshowData*>(pData));
-        pSlideData->pSlideshowImpl->gotoSlide(pSlideData->XCurrentSlide);
+        
pSlideData->pSlideshowImpl->AsyncNotifyEvent(pSlideData->XCurrentSlide, 
pSlideData->eHintKind);
         delete pSlideData;
     }
 }
 
+void SlideshowImpl::AsyncNotifyEvent(
+    const uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
+    const SdrHintKind eHintKind)
+{
+    if (SdrHintKind::ObjectChange == eHintKind)
+    {
+        mnEventObjectChange = nullptr;
+
+        // refresh single slide
+        gotoSlide(rXCurrentSlide);
+    }
+    else if (SdrHintKind::PageOrderChange == eHintKind)
+    {
+        mnEventPageOrderChange = nullptr;
+
+        // order of pages (object pages or master pages) changed 
(Insert/Remove/ChangePos)
+        // rXCurrentSlide is the current slide before the change.
+        Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), 
UNO_QUERY_THROW );
+        Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), 
UNO_QUERY_THROW );
+        const sal_Int32 nNewSlideCount(xSlides.is() ? xSlides->getCount() : 0);
+
+        if (nNewSlideCount != mpSlideController->getSlideNumberCount())
+        {
+            // need to reinitialize AnimationSlideController
+            OUString aPresSlide( maPresSettings.maPresPage );
+            createSlideList( maPresSettings.mbAll, aPresSlide );
+        }
+
+        // Check if current slide before change is still valid (maybe removed)
+        const sal_Int32 nSlideCount(mpSlideController->getSlideNumberCount());
+        bool bSlideStillValid(false);
+
+        for (sal_Int32 nSlide(0); !bSlideStillValid && nSlide < nSlideCount; 
nSlide++)
+        {
+            if (rXCurrentSlide == mpSlideController->getSlideByNumber(nSlide))
+            {
+                bSlideStillValid = true;
+            }
+        }
+
+        if(bSlideStillValid)
+        {
+            // stay on that slide
+            gotoSlide(rXCurrentSlide);
+        }
+        else
+        {
+            // not possible to stay on that slide, go to 1st slide (kinda 
restart)
+            gotoFirstSlide();
+        }
+    }
+}
+
 void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
 {
     if (SfxHintId::ThisIsAnSdrHint != rHint.GetId())
@@ -3132,6 +3194,10 @@ void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, 
const SfxHint& rHint)
 
     if (SdrHintKind::ObjectChange == eHintKind)
     {
+        if (nullptr != mnEventObjectChange)
+            // avoid multiple events
+            return;
+
         // Object changed, object & involved page included in rHint.
         uno::Reference< css::drawing::XDrawPage > 
XCurrentSlide(getCurrentSlide());
         if (!XCurrentSlide.is())
@@ -3168,14 +3234,28 @@ void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, 
const SfxHint& rHint)
         // 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
-        // too early for some cases)
-        AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide);
+        // to early for some cases)
+        mnEventObjectChange = 
AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
     }
     else if (SdrHintKind::PageOrderChange == eHintKind)
     {
+        // Unfortunately we get multiple events, e.g. when drag/drop position 
change in
+        // slide sorter on left side of EditView. This includes some with page 
number +1,
+        // then again -1 (it's a position change). Problem is that in-between 
already
+        // a re-schedule seems to happen, so indeed AsyncNotifyEvent will 
change to +1/-1
+        // already. Since we get even more, at least try to take the last one. 
I found no
+        // good solution yet for this.
+        if (nullptr != mnEventPageOrderChange)
+            Application::RemoveUserEvent( mnEventPageOrderChange );
+
         // order of pages (object pages or master pages) changed 
(Insert/Remove/ChangePos)
-        // probably needs refresh of AnimationSlideController in 
mpSlideController
-        gotoFirstSlide();
+        uno::Reference< css::drawing::XDrawPage > 
XCurrentSlide(getCurrentSlide());
+        mnEventPageOrderChange = 
AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
+    }
+    else if (SdrHintKind::ModelCleared == eHintKind)
+    {
+        // immediately end presentation
+        endPresentation();
     }
 
     // maybe need to add reactions here to other Hint-Types
diff --git a/sd/source/ui/slideshow/slideshowimpl.hxx 
b/sd/source/ui/slideshow/slideshowimpl.hxx
index b235a78358f0..9c0ae75dd5e9 100644
--- a/sd/source/ui/slideshow/slideshowimpl.hxx
+++ b/sd/source/ui/slideshow/slideshowimpl.hxx
@@ -198,6 +198,10 @@ public:
     /// ends the presentation async
     void endPresentation();
 
+    // possibly triggered from events @SlideshowImpl::Notify if needed, but 
asychron to
+    // allow the noted event to completely finish in the core
+    void AsyncNotifyEvent(const css::uno::Reference< css::drawing::XDrawPage 
>&, const SdrHintKind);
+
     ViewShell* getViewShell() const { return mpViewShell; }
 
     void paint();
@@ -339,6 +343,8 @@ private:
 
     ImplSVEvent * mnEndShowEvent;
     ImplSVEvent * mnContextMenuEvent;
+    ImplSVEvent * mnEventObjectChange;
+    ImplSVEvent * mnEventPageOrderChange;
 
     css::uno::Reference< css::presentation::XPresentation2 > mxPresentation;
     ::rtl::Reference< SlideShowListenerProxy > mxListenerProxy;

Reply via email to