diff options
-rw-r--r-- | include/sfx2/lokhelper.hxx | 21 | ||||
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrendering.cxx | 58 | ||||
-rw-r--r-- | sc/source/ui/inc/tabview.hxx | 3 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin4.cxx | 86 | ||||
-rw-r--r-- | sc/source/ui/view/tabview3.cxx | 170 | ||||
-rw-r--r-- | sc/source/ui/view/tabview5.cxx | 20 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 41 |
7 files changed, 397 insertions, 2 deletions
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 6e25044f3691..0c118fbca896 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -11,8 +11,10 @@ #define INCLUDED_SFX2_LOKHELPER_HXX #include <sfx2/dllapi.h> +#include <sfx2/viewsh.hxx> #include <cstddef> #include <rtl/string.hxx> +#include <comphelper/lok.hxx> class SfxViewShell; @@ -31,7 +33,9 @@ public: static std::size_t getViewsCount(); /// Get viewIds of all existing views. static bool getViewIds(int* pArray, size_t nSize); - + /// Iterate over any view shell, except pThisViewShell, passing it to the f function. + template<typename ViewShellType, typename FunctionType> + static void forEachOtherView(ViewShellType* pThisViewShell, FunctionType f); /// Invoke the LOK callback of all views except pThisView, with a payload of rKey-rPayload. static void notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload); /// Same as notifyOtherViews(), but works on a selected "other" view, not on all of them. @@ -40,6 +44,21 @@ public: static void notifyInvalidation(SfxViewShell* pThisView, const OString& rPayload); }; +template<typename ViewShellType, typename FunctionType> +void SfxLokHelper::forEachOtherView(ViewShellType* pThisViewShell, FunctionType f) +{ + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ViewShellType* pOtherViewShell = dynamic_cast<ViewShellType*>(pViewShell); + if (pOtherViewShell != nullptr && pOtherViewShell != pThisViewShell) + { + f(pOtherViewShell); + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } +} + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index a39db6ea2206..83c56d13ce3f 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -64,6 +64,7 @@ public: void testUndoShells(); void testCreateViewGraphicSelection(); void testTextEditViews(); + void testTextEditViewInvalidations(); void testGraphicInvalidate(); CPPUNIT_TEST_SUITE(ScTiledRenderingTest); @@ -80,6 +81,7 @@ public: CPPUNIT_TEST(testUndoShells); CPPUNIT_TEST(testCreateViewGraphicSelection); CPPUNIT_TEST(testTextEditViews); + CPPUNIT_TEST(testTextEditViewInvalidations); CPPUNIT_TEST(testGraphicInvalidate); CPPUNIT_TEST_SUITE_END(); @@ -386,6 +388,7 @@ public: bool m_bGraphicSelection; bool m_bGraphicViewSelection; bool m_bFullInvalidateTiles; + bool m_bInvalidateTiles; bool m_bViewLock; ViewCallback() @@ -395,6 +398,7 @@ public: m_bGraphicSelection(false), m_bGraphicViewSelection(false), m_bFullInvalidateTiles(false), + m_bInvalidateTiles(false), m_bViewLock(false) { } @@ -448,6 +452,10 @@ public: { m_bFullInvalidateTiles = true; } + else + { + m_bInvalidateTiles = true; + } } } } @@ -692,6 +700,56 @@ void ScTiledRenderingTest::testTextEditViews() comphelper::LibreOfficeKit::setActive(false); } +void ScTiledRenderingTest::testTextEditViewInvalidations() +{ + comphelper::LibreOfficeKit::setActive(); + + ScModelObj* pModelObj = createDoc("small.ods"); + CPPUNIT_ASSERT(pModelObj); + ScViewData* pViewData = ScDocShell::GetViewData(); + CPPUNIT_ASSERT(pViewData); + + // view #1 + ViewCallback aView1; + int nView1 = SfxLokHelper::getView(); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1); + CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); + + // view #2 + SfxLokHelper::createView(); + ViewCallback aView2; + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2); + + // text edit a cell in view #1 + SfxLokHelper::setView(nView1); + aView2.m_bInvalidateTiles = false; + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(lcl_hasEditView(*pViewData)); + CPPUNIT_ASSERT(aView2.m_bInvalidateTiles); + + // view #3 + SfxLokHelper::createView(); + ViewCallback aView3; + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView3); + + // text edit a cell in view #1 + SfxLokHelper::setView(nView1); + aView3.m_bInvalidateTiles = false; + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'y', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'y', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView3.m_bInvalidateTiles); + + mxComponent->dispose(); + mxComponent.clear(); + + comphelper::LibreOfficeKit::setActive(false); +} + void ScTiledRenderingTest::testCreateViewGraphicSelection() { // Load a document diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx index 34793bf24b1e..4cd3d79fe19d 100644 --- a/sc/source/ui/inc/tabview.hxx +++ b/sc/source/ui/inc/tabview.hxx @@ -449,6 +449,9 @@ public: void InvalidateAttribs(); + void OnLibreOfficeKitTabChanged(); + void AddEditViewToOtherView(SfxViewShell* pViewShell, ScSplitPos eWhich); + void RemoveEditViewFromOtherView(SfxViewShell* pViewShell, ScSplitPos eWhich); void MakeEditView( ScEditEngineDefaulter* pEngine, SCCOL nCol, SCROW nRow ); void KillEditView( bool bNoPaint ); void UpdateEditView(); diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index b650fc4a293e..a52fc5bda7c8 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -967,6 +967,92 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI pCrsr->Show(); } + + if (comphelper::LibreOfficeKit::isActive()) + { + ScTabViewShell* pThisViewShell = pViewData->GetViewShell(); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + + while (pViewShell) + { + if (pViewShell != pThisViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); + if (pTabViewShell) + { + ScViewData& rOtherViewData = pTabViewShell->GetViewData(); + ScSplitPos eOtherWhich = rOtherViewData.GetEditActivePart(); + + bool bOtherEditMode = rOtherViewData.HasEditView(eOtherWhich); + SCCOL nCol1 = rOtherViewData.GetEditStartCol(); + SCROW nRow1 = rOtherViewData.GetEditStartRow(); + SCCOL nCol2 = rOtherViewData.GetEditEndCol(); + SCROW nRow2 = rOtherViewData.GetEditEndRow(); + bOtherEditMode = bOtherEditMode + && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 <= nY2 ); + if (bOtherEditMode && rOtherViewData.GetRefTabNo() == nTab) + { + EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich); + Point aOtherScrPos = rOtherViewData.GetScrPos( nX1, nY1, eOtherWhich ); + if ( bLayoutRTL ) + { + long nEndPixel = pViewData->GetScrPos( nX2+1, maVisibleRange.mnRow1, eWhich ).X(); + aOtherScrPos.X() = nEndPixel + 1; + } + + long nScreenX = aOutputData.nScrX; + long nScreenY = aOutputData.nScrY; + long nScreenW = aOutputData.GetScrW(); + long nScreenH = aOutputData.GetScrH(); + + rDevice.SetLineColor(); + rDevice.SetFillColor(pEditView->GetBackgroundColor()); + Point aStart = rOtherViewData.GetScrPos( nCol1, nRow1, eOtherWhich ); + Point aEnd = rOtherViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich ); + + // don't overwrite grid + long nLayoutSign = bLayoutRTL ? -1 : 1; + aEnd.X() -= 2 * nLayoutSign; + aEnd.Y() -= 2; + + Rectangle aBackground(aStart, aEnd); + + aBackground += Point(nScreenX, nScreenY); + rDevice.SetMapMode(aDrawMode); + + + // paint the background + rDevice.DrawRect(rDevice.PixelToLogic(aBackground)); + + if (bIsTiledRendering) + { + auto aOrigin = aOriginalMode.GetOrigin(); + aOrigin.setX(aOrigin.getX() / TWIPS_PER_PIXEL + nScrX); + aOrigin.setY(aOrigin.getY() / TWIPS_PER_PIXEL + nScrY); + static const double twipFactor = 15 * 1.76388889; // 26.45833335 + aOrigin = Point(aOrigin.getX() * twipFactor, + aOrigin.getY() * twipFactor); + MapMode aNew = rDevice.GetMapMode(); + aNew.SetOrigin(aOrigin); + rDevice.SetMapMode(aNew); + } + + pOtherEditView->Paint(rDevice.PixelToLogic(Rectangle(Point(nScreenX, nScreenY), Size(nScreenW, nScreenH))), &rDevice); + rDevice.SetMapMode(MAP_PIXEL); + } + + } + } + + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + + } + + + + + if (pViewData->HasEditView(eWhich)) { // flush OverlayManager before changing the MapMode diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx index b3a2219642ba..0aaaa6dec6fb 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -27,6 +27,7 @@ #include <svx/sdr/overlay/overlaymanager.hxx> #include <svx/svdoole2.hxx> #include <sfx2/bindings.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/viewfrm.hxx> #include <vcl/cursor.hxx> @@ -1888,6 +1889,175 @@ void ScTabView::SetTabNo( SCTAB nTab, bool bNew, bool bExtendSelection, bool bSa pRefDlg->ViewShellChanged(); } } + + OnLibreOfficeKitTabChanged(); + } +} + +class ExtraEditViewManager +{ +public: + ExtraEditViewManager(ScTabViewShell* pThisViewShell, VclPtr<ScGridWindow>* pGridWin) + : mpThisViewShell(pThisViewShell) + , mpGridWin(pGridWin) + , mpOtherEditView(nullptr) + , mpOtherEngine(nullptr) + , mpEditViews(nullptr) + , maSameEditViewChecker() + {} + + void Add(SfxViewShell* pViewShell, ScSplitPos eWhich) + { + Apply(pViewShell, eWhich, &ExtraEditViewManager::Adder); + } + + void Remove(SfxViewShell* pViewShell, ScSplitPos eWhich) + { + Apply(pViewShell, eWhich, &ExtraEditViewManager::Remover); + } + +private: + class SameEditViewChecker + { + public: + SameEditViewChecker() + : mpOtherEditView(nullptr) + , mpWindow(nullptr) + {} + void SetEditView(EditView* pOtherEditView) { mpOtherEditView = pOtherEditView; } + void SetWindow(ScGridWindow* pWindow) { mpWindow = pWindow; } + bool operator() (EditView* pView) + { + return ( pView != nullptr + && pView->GetWindow() == mpWindow + && pView->GetEditEngine() == mpOtherEditView->GetEditEngine() + && pView->GetOutputArea() == mpOtherEditView->GetOutputArea() + && pView->GetVisArea() == mpOtherEditView->GetVisArea() ); + } + + private: + EditView* mpOtherEditView; + ScGridWindow* mpWindow; + }; + +private: + typedef void (ExtraEditViewManager::* FuncType)(ScGridWindow* ); + + void Apply(SfxViewShell* pViewShell, ScSplitPos eWhich, FuncType fHandler) + { + ScTabViewShell* pOtherViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); + if (pOtherViewShell != nullptr && pOtherViewShell != mpThisViewShell) + { + mpOtherEditView = pOtherViewShell->GetViewData().GetEditView(eWhich); + if (mpOtherEditView != nullptr) + { + mpOtherEngine = mpOtherEditView->GetEditEngine(); + if (mpOtherEngine != nullptr) + { + mpEditViews = &(mpOtherEngine->GetEditViews()); + maSameEditViewChecker.SetEditView(mpOtherEditView); + for (int i = 0; i < 4; ++i) + { + (this->*fHandler)(mpGridWin[i]); + } + } + } + } + } + + void Adder(ScGridWindow* pWin) + { + if (pWin != nullptr) + { + maSameEditViewChecker.SetWindow(pWin); + auto found = std::find_if(mpEditViews->begin(), mpEditViews->end(), maSameEditViewChecker); + if (found == mpEditViews->end()) + { + EditView* pThisEditView = new EditView( mpOtherEngine, pWin ); + if (pThisEditView != nullptr) + { + pThisEditView->SetOutputArea(mpOtherEditView->GetOutputArea()); + pThisEditView->SetVisArea(mpOtherEditView->GetVisArea()); + mpOtherEngine->InsertView(pThisEditView); + } + } + } + } + + void Remover(ScGridWindow* pWin) + { + if (pWin != nullptr) + { + maSameEditViewChecker.SetWindow(pWin); + auto found = std::find_if(mpEditViews->begin(), mpEditViews->end(), maSameEditViewChecker); + if (found != mpEditViews->end()) + { + EditView* pView = *found; + if (pView) + { + mpOtherEngine->RemoveView(pView); + delete pView; + pView = nullptr; + } + } + } + } + +private: + ScTabViewShell* mpThisViewShell; + VclPtr<ScGridWindow>* mpGridWin; + EditView* mpOtherEditView; + EditEngine* mpOtherEngine; + EditEngine::ViewsType* mpEditViews; + SameEditViewChecker maSameEditViewChecker; +}; + +void ScTabView::AddEditViewToOtherView(SfxViewShell* pViewShell, ScSplitPos eWhich) +{ + ExtraEditViewManager aExtraEditViewManager(aViewData.GetViewShell(), pGridWin); + aExtraEditViewManager.Add(pViewShell, eWhich); +} + +void ScTabView::RemoveEditViewFromOtherView(SfxViewShell* pViewShell, ScSplitPos eWhich) +{ + ExtraEditViewManager aExtraEditViewManager(aViewData.GetViewShell(), pGridWin); + aExtraEditViewManager.Remove(pViewShell, eWhich); +} + +void ScTabView::OnLibreOfficeKitTabChanged() +{ + if (comphelper::LibreOfficeKit::isActive()) + { + ScTabViewShell* pThisViewShell = aViewData.GetViewShell(); + SCTAB nThisTabNo = pThisViewShell->GetViewData().GetTabNo(); + auto lTabSwitch = + [pThisViewShell, nThisTabNo] (ScTabViewShell* pOtherViewShell) + { + ScViewData& rOtherViewData = pOtherViewShell->GetViewData(); + SCTAB nOtherTabNo = rOtherViewData.GetTabNo(); + if (nThisTabNo == nOtherTabNo) + { + for (int i = 0; i < 4; ++i) + { + if (rOtherViewData.HasEditView( (ScSplitPos)(i))) + { + pThisViewShell->AddEditViewToOtherView(pOtherViewShell, (ScSplitPos)(i)); + } + } + } + else + { + for (int i = 0; i < 4; ++i) + { + if (rOtherViewData.HasEditView( (ScSplitPos)(i))) + { + pThisViewShell->RemoveEditViewFromOtherView(pOtherViewShell, (ScSplitPos)(i)); + } + } + } + }; + + SfxLokHelper::forEachOtherView(pThisViewShell, lTabSwitch); } } diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx index a9d3dcab6707..10a39b3a2555 100644 --- a/sc/source/ui/view/tabview5.cxx +++ b/sc/source/ui/view/tabview5.cxx @@ -25,6 +25,7 @@ #include <svx/svdoutl.hxx> #include <sfx2/bindings.hxx> #include <sfx2/dispatch.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/objsh.hxx> #include "tabview.hxx" @@ -54,7 +55,6 @@ #include <officecfg/Office/Calc.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> - using namespace com::sun::star; void ScTabView::Init() @@ -159,6 +159,24 @@ ScTabView::~ScTabView() DELETEZ(pDrawOld); DELETEZ(pDrawActual); + if (comphelper::LibreOfficeKit::isActive()) + { + ScTabViewShell* pThisViewShell = GetViewData().GetViewShell(); + + auto lRemoveEditView = + [pThisViewShell] (ScTabViewShell* pOtherViewShell) + { + ScViewData& rOtherViewData = pOtherViewShell->GetViewData(); + for (int k = 0; k < 4; ++k) + { + if (rOtherViewData.HasEditView((ScSplitPos)(k))) + pThisViewShell->RemoveEditViewFromOtherView(pOtherViewShell, (ScSplitPos)(k)); + } + }; + + SfxLokHelper::forEachOtherView(pThisViewShell, lRemoveEditView); + } + aViewData.KillEditView(); // solange GridWin's noch existieren if (pDrawView) diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 240661d11c18..77d9f42df304 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -20,6 +20,7 @@ #include "scitems.hxx" #include <editeng/eeitem.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/viewfrm.hxx> #include <editeng/adjustitem.hxx> #include <svx/algitem.hxx> @@ -76,6 +77,22 @@ using namespace com::sun::star; static bool bMoveArea = false; // Member? sal_uInt16 nEditAdjust = SVX_ADJUST_LEFT; // Member! +namespace { + +void lcl_LOKRemoveEditView(ScTabViewShell* pTabViewShell, ScSplitPos eWhich) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + auto lRemoveEditView = + [pTabViewShell, eWhich] (ScTabViewShell* pOtherViewShell) + { pOtherViewShell->RemoveEditViewFromOtherView(pTabViewShell, eWhich); }; + + SfxLokHelper::forEachOtherView(pTabViewShell, lRemoveEditView); + } +} + +} // anonymous namespace + ScViewDataTable::ScViewDataTable() : eZoomType( SvxZoomType::PERCENT ), aZoomX( 1,1 ), @@ -958,12 +975,18 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich, { // if the view is already there don't call anything that changes the cursor position if (bEditActive[eWhich]) + { bWasThere = true; + } else + { + lcl_LOKRemoveEditView(GetViewShell(), eWhich); pEditView[eWhich]->SetEditEngine(pNewEngine); + } if (pEditView[eWhich]->GetWindow() != pWin) { + lcl_LOKRemoveEditView(GetViewShell(), eWhich); pEditView[eWhich]->SetWindow(pWin); OSL_FAIL("EditView Window has changed"); } @@ -1133,6 +1156,23 @@ void ScViewData::SetEditEngine( ScSplitPos eWhich, pEditView[eWhich]->Invalidate(); // needed? // needed, wenn position changed + + if (comphelper::LibreOfficeKit::isActive()) + { + ScTabViewShell* pThisViewShell = GetViewShell(); + SCTAB nThisTabNo = GetTabNo(); + auto lAddEditView = + [pThisViewShell, nThisTabNo, eWhich] (ScTabViewShell* pOtherViewShell) + { + ScViewData& rOtherViewData = pOtherViewShell->GetViewData(); + SCTAB nOtherTabNo = rOtherViewData.GetTabNo(); + if (nThisTabNo == nOtherTabNo) + pOtherViewShell->AddEditViewToOtherView(pThisViewShell, eWhich); + }; + + SfxLokHelper::forEachOtherView(pThisViewShell, lAddEditView); + } + } IMPL_LINK_TYPED( ScViewData, EditEngineHdl, EditStatus&, rStatus, void ) @@ -1422,6 +1462,7 @@ void ScViewData::ResetEditView() { if (bEditActive[i]) { + lcl_LOKRemoveEditView(GetViewShell(), (ScSplitPos)(i)); pEngine = pEditView[i]->GetEditEngine(); pEngine->RemoveView(pEditView[i]); pEditView[i]->SetOutputArea( Rectangle() ); |