sc/qa/unit/tiledrendering/data/two_sheets.ods |binary
 sc/qa/unit/tiledrendering/tiledrendering.cxx  |  144 ++++++++++++++++++--------
 sc/source/ui/view/tabview5.cxx                |    4 
 3 files changed, 104 insertions(+), 44 deletions(-)

New commits:
commit 834cbc4ccf09853b2830d7ebf6c5ce5c45a357cc
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Tue Apr 9 11:46:11 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Apr 10 09:47:53 2024 +0200

    kit: Update formulas when switching tabs
    
    we moved to not forcing a redraw on switching tabs
    at:
    
    commit 9f3ee2b27ceeab175fb865a55cfeabd66fbb128d
    Date:   Sun Jan 14 16:29:56 2024 +0000
    
        don't invalidate when switching tabs
    
    but in a scenario (to which two_sheets.ods is updated to capture) where
    there is no view/user active on a sheet B that depends on cells in sheet
    A, then when A is updated, B does not update automatically to reflect
    the changes in A.
    
    So, on switching to a tab, do the check for out of date formulas on
    the switched to tab.
    
    Change-Id: Ibbba83119adbd323b42314dbd9bcba6f797e5934
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165911
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/qa/unit/tiledrendering/data/two_sheets.ods 
b/sc/qa/unit/tiledrendering/data/two_sheets.ods
index 6aa1d03be62c..bd9be5f635fe 100644
Binary files a/sc/qa/unit/tiledrendering/data/two_sheets.ods and 
b/sc/qa/unit/tiledrendering/data/two_sheets.ods differ
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx 
b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 6a5eb4a18e4a..6368a7f68b2e 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -635,6 +635,14 @@ public:
         break;
         }
     }
+
+    void ClearAllInvalids()
+    {
+        m_bInvalidateTiles = false;
+        m_aInvalidations.clear();
+        m_aInvalidationsParts.clear();
+        m_aInvalidationsMode.clear();
+    }
 };
 } //namespace
 
@@ -1821,6 +1829,44 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, 
testPageDownInvalidation)
     CPPUNIT_ASSERT_EQUAL(tools::Rectangle(15, 15, 1230, 225), 
aView1.m_aInvalidations[0]);
 }
 
+static Bitmap getTile(ScModelObj* pModelObj, int nTilePosX, int nTilePosY, 
tools::Long nTileWidth, tools::Long nTileHeight)
+{
+    size_t nCanvasSize = 1024;
+    size_t nTileSize = 256;
+    std::vector<unsigned char> aPixmap(nCanvasSize * nCanvasSize * 4, 0);
+    ScopedVclPtrInstance<VirtualDevice> xDevice(DeviceFormat::WITHOUT_ALPHA);
+    xDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+    xDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(Size(nCanvasSize, 
nCanvasSize),
+            Fraction(1.0), Point(), aPixmap.data());
+    pModelObj->paintTile(*xDevice, nCanvasSize, nCanvasSize, nTilePosX, 
nTilePosY, nTileWidth, nTileHeight);
+    xDevice->EnableMapMode(false);
+    return xDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize));
+}
+
+namespace
+{
+void lcl_typeCharsInCell(const std::string& aStr, SCCOL nCol, SCROW nRow, 
ScTabViewShell* pView,
+    ScModelObj* pModelObj, bool bInEdit = false, bool bCommit = true)
+{
+    if (!bInEdit)
+        pView->SetCursor(nCol, nRow);
+
+    for (const char& cChar : aStr)
+    {
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, cChar, 0);
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, cChar, 0);
+        Scheduler::ProcessEventsToIdle();
+    }
+
+    if (bCommit)
+    {
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN);
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN);
+        Scheduler::ProcessEventsToIdle();
+    }
+}
+} //namespace
+
 CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testSheetChangeNoInvalidation)
 {
     const bool oldPartInInvalidation = 
comphelper::LibreOfficeKit::isPartInInvalidation();
@@ -1830,20 +1876,70 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, 
testSheetChangeNoInvalidation)
     ScViewData* pViewData = ScDocShell::GetViewData();
     CPPUNIT_ASSERT(pViewData);
 
+    // Set View to initial 100%
+    pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 28050, 10605));
+    pModelObj->setClientZoom(256, 256, 1920, 1920);
+
+    ScTabViewShell* pView = 
dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
+    CPPUNIT_ASSERT(pView);
+
     int nView1 = SfxLokHelper::getView();
     ViewCallback aView1;
     CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData));
 
     SfxLokHelper::setView(nView1);
-    aView1.m_bInvalidateTiles = false;
-    aView1.m_aInvalidations.clear();
-    aView1.m_aInvalidationsParts.clear();
-    aView1.m_aInvalidationsMode.clear();
+
+    aView1.ClearAllInvalids();
+
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
+    Scheduler::ProcessEventsToIdle();
+    // switching sheets should trigger no unnecessary invalidations
+    CPPUNIT_ASSERT(!aView1.m_bInvalidateTiles);
+
+    // Get the known columns/rows of this sheet 2 now we have switched to it so
+    // it knows what range to broadcast invalidations for if it knows cells 
need
+    // to be redrawn.
+    tools::JsonWriter aJsonWriter1;
+    pModelObj->getRowColumnHeaders(tools::Rectangle(0, 15, 19650, 5400), 
aJsonWriter1);
+    aJsonWriter1.finishAndGetAsOString();
+    Scheduler::ProcessEventsToIdle();
+    aView1.ClearAllInvalids();
+
+    // switching back should also trigger no unnecessary invalidations
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEUP | 
KEY_MOD1);
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEUP | 
KEY_MOD1);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(!aView1.m_bInvalidateTiles);
+
+    // The 2nd sheet has formulas that depend on B1 in the first sheet. So if
+    // we change B1 there should be an invalidation in the second sheet for the
+    // range that depends on it. Because this is a single user document with no
+    // active view on the 2nd sheet this will happen on switching back to 
sheet 2
+    lcl_typeCharsInCell("101", 1, 0, pView, pModelObj); // Type '101' in B1
+    aView1.ClearAllInvalids();
+
     pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
     pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
     Scheduler::ProcessEventsToIdle();
-    // switching sheets should trigger no invalidations
+    CPPUNIT_ASSERT(aView1.m_bInvalidateTiles);
+    aView1.ClearAllInvalids();
+
+    // Paint it to make it valid again
+    getTile(pModelObj, 0, 0, 3840, 3840);
+
+    // switching back to sheet 1 should trigger no unnecessary invalidations
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEUP | 
KEY_MOD1);
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEUP | 
KEY_MOD1);
+    Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT(!aView1.m_bInvalidateTiles);
+
+    // switching to sheet 2 should trigger no unnecessary invalidations this 
time
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::PAGEDOWN | 
KEY_MOD1);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(!aView1.m_bInvalidateTiles);
+
     comphelper::LibreOfficeKit::setPartInInvalidation(oldPartInInvalidation);
 }
 
@@ -2531,30 +2627,6 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, 
testSortAscendingDescending)
     CPPUNIT_ASSERT_EQUAL("rows"_ostr, aView.m_sInvalidateSheetGeometry);
 }
 
-namespace
-{
-void lcl_typeCharsInCell(const std::string& aStr, SCCOL nCol, SCROW nRow, 
ScTabViewShell* pView,
-    ScModelObj* pModelObj, bool bInEdit = false, bool bCommit = true)
-{
-    if (!bInEdit)
-        pView->SetCursor(nCol, nRow);
-
-    for (const char& cChar : aStr)
-    {
-        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, cChar, 0);
-        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, cChar, 0);
-        Scheduler::ProcessEventsToIdle();
-    }
-
-    if (bCommit)
-    {
-        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN);
-        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN);
-        Scheduler::ProcessEventsToIdle();
-    }
-}
-} //namespace
-
 CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testAutoInputStringBlock)
 {
     ScModelObj* pModelObj = createDoc("empty.ods");
@@ -3777,20 +3849,6 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, 
testExtendedAreasDontOverlap)
                          aView1.m_aInvalidations[1].Top());
 }
 
-static Bitmap getTile(ScModelObj* pModelObj, int nTilePosX, int nTilePosY, 
tools::Long nTileWidth, tools::Long nTileHeight)
-{
-    size_t nCanvasSize = 1024;
-    size_t nTileSize = 256;
-    std::vector<unsigned char> aPixmap(nCanvasSize * nCanvasSize * 4, 0);
-    ScopedVclPtrInstance<VirtualDevice> xDevice(DeviceFormat::WITHOUT_ALPHA);
-    xDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
-    xDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(Size(nCanvasSize, 
nCanvasSize),
-            Fraction(1.0), Point(), aPixmap.data());
-    pModelObj->paintTile(*xDevice, nCanvasSize, nCanvasSize, nTilePosX, 
nTilePosY, nTileWidth, nTileHeight);
-    xDevice->EnableMapMode(false);
-    return xDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize));
-}
-
 // Ensure that editing a shape not in the topleft tile has its text shown 
inside the shape
 // center while editing
 CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testEditShapeText)
diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx
index 2ba41b775bd6..40f63d36bdb8 100644
--- a/sc/source/ui/view/tabview5.cxx
+++ b/sc/source/ui/view/tabview5.cxx
@@ -285,8 +285,10 @@ void ScTabView::ImplTabChanged(bool bSameTabButMoved)
     SfxLokCallbackInterface* pCallback = 
pViewShell->getLibreOfficeKitViewCallback();
     pViewShell->setLibreOfficeKitViewCallback(nullptr);
     comphelper::ScopeGuard aOutputGuard(
-        [pViewShell, pCallback] {
+        [this, pViewShell, pCallback] {
             pViewShell->setLibreOfficeKitViewCallback(pCallback);
+            // But possibly update any out of date formulas on the tab we 
switched to
+            UpdateFormulas();
         });
 
     if (pDrawView)

Reply via email to