diff options
author | Caolán McNamara <caolan.mcnamara@collabora.com> | 2024-04-09 11:46:11 +0100 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2024-04-10 09:47:53 +0200 |
commit | 834cbc4ccf09853b2830d7ebf6c5ce5c45a357cc (patch) | |
tree | 3a59a999c6bfefdde566b58d4b412ce2d4e5d93d | |
parent | 164bde27bab3c4a4166230d60d591b54efe703c0 (diff) |
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.mcnamara@collabora.com>
-rw-r--r-- | sc/qa/unit/tiledrendering/data/two_sheets.ods | bin | 7082 -> 8651 bytes | |||
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrendering.cxx | 144 | ||||
-rw-r--r-- | sc/source/ui/view/tabview5.cxx | 4 |
3 files changed, 104 insertions, 44 deletions
diff --git a/sc/qa/unit/tiledrendering/data/two_sheets.ods b/sc/qa/unit/tiledrendering/data/two_sheets.ods Binary files differindex 6aa1d03be62c..bd9be5f635fe 100644 --- a/sc/qa/unit/tiledrendering/data/two_sheets.ods +++ b/sc/qa/unit/tiledrendering/data/two_sheets.ods 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) |