[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.1' - 3 commits - include/sfx2 sc/inc sc/qa sc/source
Marco Cecchetti
marco.cecchetti at collabora.com
Fri Sep 30 16:26:20 UTC 2016
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.cecchetti at 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.cecchetti at 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.cecchetti at 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:
More information about the Libreoffice-commits
mailing list