summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolan.mcnamara@collabora.com>2024-04-09 11:46:11 +0100
committerCaolán McNamara <caolan.mcnamara@collabora.com>2024-04-10 09:47:53 +0200
commit834cbc4ccf09853b2830d7ebf6c5ce5c45a357cc (patch)
tree3a59a999c6bfefdde566b58d4b412ce2d4e5d93d
parent164bde27bab3c4a4166230d60d591b54efe703c0 (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.odsbin7082 -> 8651 bytes
-rw-r--r--sc/qa/unit/tiledrendering/tiledrendering.cxx144
-rw-r--r--sc/source/ui/view/tabview5.cxx4
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
index 6aa1d03be62c..bd9be5f635fe 100644
--- a/sc/qa/unit/tiledrendering/data/two_sheets.ods
+++ b/sc/qa/unit/tiledrendering/data/two_sheets.ods
Binary files 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)