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 9a97afad32594426f03f53868da1e89de1cccff4 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: Thu Apr 11 12:39:58 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/+/165847 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> 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 bd17ad469ff7..1e6294801caf 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -644,6 +644,14 @@ public: break; } } + + void ClearAllInvalids() + { + m_bInvalidateTiles = false; + m_aInvalidations.clear(); + m_aInvalidationsParts.clear(); + m_aInvalidationsMode.clear(); + } }; } //namespace @@ -1830,6 +1838,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(); @@ -1839,20 +1885,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); } @@ -2540,30 +2636,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"); @@ -3788,20 +3860,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)