include/sfx2/lokhelper.hxx | 21 +++ sc/inc/scmod.hxx | 2 sc/qa/unit/tiledrendering/tiledrendering.cxx | 111 +++++++++++++++++ sc/source/ui/app/inputhdl.cxx | 16 +- sc/source/ui/app/scmod.cxx | 5 sc/source/ui/inc/tabview.hxx | 3 sc/source/ui/inc/tabvwsh.hxx | 3 sc/source/ui/view/gridwin4.cxx | 86 +++++++++++++ sc/source/ui/view/tabview3.cxx | 170 +++++++++++++++++++++++++++ sc/source/ui/view/tabview5.cxx | 20 +++ sc/source/ui/view/tabvwsh4.cxx | 22 +++ sc/source/ui/view/tabvwsh5.cxx | 11 + sc/source/ui/view/viewdata.cxx | 48 +++++++ 13 files changed, 499 insertions(+), 19 deletions(-)
New commits: commit feb25b3ca32b8d4077927d2e6251dc84a5830e60 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Sep 28 12:20:10 2016 +0200 Calc: implemented parallel cell text editing Change-Id: If8cc7a637cee6ba66813d55b25160fee13a2a219 diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 6e25044..0c118fb 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 6f4fd48..3479c29 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -63,6 +63,7 @@ public: void testUndoShells(); void testCreateViewGraphicSelection(); void testTextEditViews(); + void testTextEditViewInvalidations(); void testGraphicInvalidate(); CPPUNIT_TEST_SUITE(ScTiledRenderingTest); @@ -78,6 +79,7 @@ public: CPPUNIT_TEST(testUndoShells); CPPUNIT_TEST(testCreateViewGraphicSelection); CPPUNIT_TEST(testTextEditViews); + CPPUNIT_TEST(testTextEditViewInvalidations); CPPUNIT_TEST(testGraphicInvalidate); CPPUNIT_TEST_SUITE_END(); @@ -364,6 +366,7 @@ public: bool m_bGraphicSelection; bool m_bGraphicViewSelection; bool m_bFullInvalidateTiles; + bool m_bInvalidateTiles; bool m_bViewLock; ViewCallback() @@ -372,6 +375,7 @@ public: m_bTextViewSelectionInvalidated(false), m_bGraphicViewSelection(false), m_bFullInvalidateTiles(false), + m_bInvalidateTiles(false), m_bViewLock(false) { } @@ -425,6 +429,10 @@ public: { m_bFullInvalidateTiles = true; } + else + { + m_bInvalidateTiles = true; + } } } } @@ -669,6 +677,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 0e21f09..d2cc7fc 100644 --- a/sc/source/ui/inc/tabview.hxx +++ b/sc/source/ui/inc/tabview.hxx @@ -447,6 +447,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 1ff4dc4..1adf3f0 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 3057200..a8b2102 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -26,6 +26,7 @@ #include <svx/fmshell.hxx> #include <svx/svdoole2.hxx> #include <sfx2/bindings.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/viewfrm.hxx> #include <vcl/cursor.hxx> @@ -1862,6 +1863,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 d19ec5a..710b6a7 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" @@ -55,7 +56,6 @@ #include <officecfg/Office/Calc.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> - using namespace com::sun::star; void ScTabView::Init() @@ -160,6 +160,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 a14e50e..058b992 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> @@ -77,6 +78,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 ), @@ -932,12 +949,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"); } @@ -1107,6 +1130,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 ) @@ -1396,6 +1436,7 @@ void ScViewData::ResetEditView() { if (bEditActive[i]) { + lcl_LOKRemoveEditView(GetViewShell(), (ScSplitPos)(i)); pEngine = pEditView[i]->GetEditEngine(); pEngine->RemoveView(pEditView[i]); pEditView[i]->SetOutputArea( Rectangle() ); commit 34f4926bdeaed961a845890029d840523cb9c588 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Mon Sep 19 17:21:39 2016 +0200 Calc: edit engine could be accessed after being destroyed ScTabView <---------------- ScTabViewShell +ScViewData +ScInputHandler +EditView[4] +EditEngine +ImpEditEngine +vector<pointer<EditView>> On tab view shell destruction: ~ScTabViewShell -> ~ScTabView -> ScViewData::KillEditView -> EditEngine::RemoveView but it occurs after the following: ~ScTabViewShell -> ~ScInputHandler -> ~EditEngine since data members are destroyed before ancestor classes. Change-Id: Ida56b8009c0d8a3cd23952259d78318e96ae5124 diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 2ea037f..9978071 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -563,14 +563,14 @@ ScInputHandler::~ScInputHandler() if ( pInputWin && pInputWin->GetInputHandler() == this ) pInputWin->SetInputHandler( nullptr ); - delete pRangeFindList; - delete pEditDefaults; - delete pEngine; - delete pLastState; - delete pDelayTimer; - delete pColumnData; - delete pFormulaData; - delete pFormulaDataPara; + delete pRangeFindList; pRangeFindList = nullptr; + delete pEditDefaults; pEditDefaults = nullptr; + delete pEngine; pEngine = nullptr; + delete pLastState; pLastState = nullptr; + delete pDelayTimer; pDelayTimer = nullptr; + delete pColumnData; pColumnData = nullptr; + delete pFormulaData; pFormulaData = nullptr; + delete pFormulaDataPara; pFormulaDataPara = nullptr; } void ScInputHandler::SetRefScale( const Fraction& rX, const Fraction& rY ) diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 167d125..a14e50e 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1409,11 +1409,16 @@ void ScViewData::ResetEditView() void ScViewData::KillEditView() { + EditEngine* pEngine = nullptr; for (sal_uInt16 i=0; i<4; i++) if (pEditView[i]) { if (bEditActive[i]) - pEditView[i]->GetEditEngine()->RemoveView(pEditView[i]); + { + pEngine = pEditView[i]->GetEditEngine(); + if (pEngine) + pEngine->RemoveView(pEditView[i]); + } delete pEditView[i]; pEditView[i] = nullptr; } commit c90267d86e3bcccf178cb423d6b81fa9f34cca07 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Fri Sep 16 12:36:06 2016 +0200 LOK - when a view is enabled, the existing edit views are killed A view is notified about killing its own edit view, if any, in 4 cases: - before being deactivated - soon after being activated - when a 'cursor position changed' event occurs in any view - when a 'selection changed' event occurs in any view Now these notifications are skipped when LOK is active. Change-Id: I94020987a35b1450ec41e2fa5fcce8cfa7e92130 diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx index ec93563..d142bcd 100644 --- a/sc/inc/scmod.hxx +++ b/sc/inc/scmod.hxx @@ -215,7 +215,7 @@ public: ScInputHandler* GetRefInputHdl() { return pRefInputHandler;} void ViewShellGone(ScTabViewShell* pViewSh); - void ViewShellChanged(); + void ViewShellChanged(bool bStopEditing = true); // communication with function-autopilot void InputGetSelection( sal_Int32& rStart, sal_Int32& rEnd ); void InputSetSelection( sal_Int32 nStart, sal_Int32 nEnd ); diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 25af056..6f4fd48 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -62,6 +62,7 @@ public: void testColRowResize(); void testUndoShells(); void testCreateViewGraphicSelection(); + void testTextEditViews(); void testGraphicInvalidate(); CPPUNIT_TEST_SUITE(ScTiledRenderingTest); @@ -76,6 +77,7 @@ public: CPPUNIT_TEST(testColRowResize); CPPUNIT_TEST(testUndoShells); CPPUNIT_TEST(testCreateViewGraphicSelection); + CPPUNIT_TEST(testTextEditViews); CPPUNIT_TEST(testGraphicInvalidate); CPPUNIT_TEST_SUITE_END(); @@ -616,6 +618,57 @@ void ScTiledRenderingTest::testUndoShells() comphelper::LibreOfficeKit::setActive(false); } +bool lcl_hasEditView(ScViewData& rViewData) +{ + bool bResult = false; + for (unsigned int i=0; i<4; i++) + { + bResult = rViewData.HasEditView( (ScSplitPos) i ); + if (bResult) break; + } + return bResult; +} + +void ScTiledRenderingTest::testTextEditViews() +{ + comphelper::LibreOfficeKit::setActive(); + + ScModelObj* pModelObj = createDoc("small.ods"); + CPPUNIT_ASSERT(pModelObj); + ScViewData* pViewData = ScDocShell::GetViewData(); + CPPUNIT_ASSERT(pViewData); + + // view #1 + ViewCallback aView1; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1); + CPPUNIT_ASSERT(!lcl_hasEditView(*pViewData)); + + // text edit a cell in view #1 + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(lcl_hasEditView(*pViewData)); + + // view #2 + SfxLokHelper::createView(); + ViewCallback aView2; + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2); + + // move cell cursor i view #2 + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DOWN); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DOWN); + Scheduler::ProcessEventsToIdle(); + + // check that text edit view in view #1 has not be killed + CPPUNIT_ASSERT(lcl_hasEditView(*pViewData)); + + mxComponent->dispose(); + mxComponent.clear(); + + comphelper::LibreOfficeKit::setActive(false); +} + void ScTiledRenderingTest::testCreateViewGraphicSelection() { // Load a document diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index 5fc5258..bc68854 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -20,6 +20,7 @@ #include <config_features.h> #include <com/sun/star/ui/dialogs/XSLTFilterDialog.hpp> +#include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include "scitems.hxx" @@ -1386,12 +1387,12 @@ ScInputHandler* ScModule::GetInputHdl( ScTabViewShell* pViewSh, bool bUseRef ) return pHdl; } -void ScModule::ViewShellChanged() +void ScModule::ViewShellChanged(bool bStopEditing /*=true*/) { ScInputHandler* pHdl = GetInputHdl(); ScTabViewShell* pShell = ScTabViewShell::GetActiveViewShell(); if ( pShell && pHdl ) - pShell->UpdateInputHandler(); + pShell->UpdateInputHandler(false, bStopEditing); } void ScModule::SetInputMode( ScInputMode eMode, const OUString* pInitText ) diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index cd0f3e0..7e3641f 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -155,6 +155,9 @@ private: bool bChartAreaValid; // if chart is drawn bool bForceFocusOnCurCell; // #i123629# + bool bInPrepareClose; + bool bInDispose; + ScRangeListRef aChartSource; Rectangle aChartPos; SCTAB nChartDestTab; diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index e5b86c7..a57e952 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -99,11 +99,20 @@ #include <com/sun/star/chart2/XChartType.hpp> #include <sfx2/lokhelper.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/lok.hxx> extern SfxViewShell* pScActiveViewShell; // global.cxx using namespace com::sun::star; +struct BoolLock +{ + bool& mflag; + explicit BoolLock( bool& flag ) : mflag(flag) + { mflag = true; } + ~BoolLock() { mflag = false; } +}; + void ScTabViewShell::Activate(bool bMDI) { SfxViewShell::Activate(bMDI); @@ -114,7 +123,7 @@ void ScTabViewShell::Activate(bool bMDI) { // for input row (ClearCache) ScModule* pScMod = SC_MOD(); - pScMod->ViewShellChanged(); + pScMod->ViewShellChanged(/*bStopEditing=*/ !comphelper::LibreOfficeKit::isActive()); ActivateView( true, bFirstActivate ); @@ -154,7 +163,7 @@ void ScTabViewShell::Activate(bool bMDI) } } - UpdateInputHandler( true ); + UpdateInputHandler( /*bForce=*/ true, /*bStopEditing=*/ !comphelper::LibreOfficeKit::isActive() ); if ( bFirstActivate ) { @@ -237,7 +246,7 @@ void ScTabViewShell::Deactivate(bool bMDI) bIsActive = false; ScInputHandler* pHdl = SC_MOD()->GetInputHdl(this); - if( bMDI ) + if( bMDI && !comphelper::LibreOfficeKit::isActive()) { // during shell deactivation, shells must not be switched, or the loop // through the shell stack (in SfxDispatcher::DoDeactivate_Impl) will not work @@ -275,12 +284,15 @@ void ScTabViewShell::SetActive() bool ScTabViewShell::PrepareClose(bool bUI) { + BoolLock aBoolLock(bInPrepareClose); // Call EnterHandler even in formula mode here, // so a formula change in an embedded object isn't lost // (ScDocShell::PrepareClose isn't called then). ScInputHandler* pHdl = SC_MOD()->GetInputHdl( this ); if ( pHdl && pHdl->IsInputMode() ) + { pHdl->EnterHandler(); + } // draw text edit mode must be closed FuPoor* pPoor = GetDrawFuncPtr(); @@ -1670,6 +1682,8 @@ ScTabViewShell::ScTabViewShell( SfxViewFrame* pViewFrame, bReadOnly(false), bChartAreaValid(false), bForceFocusOnCurCell(false), + bInPrepareClose(false), + bInDispose(false), nCurRefDlgId(0), pAccessibilityBroadcaster(nullptr), mbInSwitch(false) @@ -1719,6 +1733,8 @@ ScTabViewShell::ScTabViewShell( SfxViewFrame* pViewFrame, ScTabViewShell::~ScTabViewShell() { + bInDispose = true; + // Notify other LOK views that we are going away. SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", "false"); SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""); diff --git a/sc/source/ui/view/tabvwsh5.cxx b/sc/source/ui/view/tabvwsh5.cxx index 674dc65..943afe5 100644 --- a/sc/source/ui/view/tabvwsh5.cxx +++ b/sc/source/ui/view/tabvwsh5.cxx @@ -18,6 +18,7 @@ */ #include "scitems.hxx" +#include <comphelper/lok.hxx> #include <svl/smplhint.hxx> #include <svl/zforlist.hxx> #include <svx/numfmtsh.hxx> @@ -67,8 +68,14 @@ void ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) case FID_KILLEDITVIEW: case FID_KILLEDITVIEW_NOPAINT: - StopEditShell(); - KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT ); + if (!comphelper::LibreOfficeKit::isActive() + || this == SfxViewShell::Current() + || bInPrepareClose + || bInDispose) + { + StopEditShell(); + KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT ); + } break; case SFX_HINT_DOCCHANGED: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits