editeng/source/editeng/editview.cxx          |   30 +++++++++++
 editeng/source/editeng/impedit.cxx           |    6 +-
 editeng/source/editeng/impedit.hxx           |   19 +++----
 editeng/source/editeng/impedit3.cxx          |    7 ++
 include/editeng/editview.hxx                 |   10 +++
 sc/qa/unit/tiledrendering/tiledrendering.cxx |   17 ++++++
 sc/source/ui/inc/tabview.hxx                 |   41 ++++------------
 sc/source/ui/view/tabview3.cxx               |   68 +++++++--------------------
 8 files changed, 106 insertions(+), 92 deletions(-)

New commits:
commit a76cb22a9a51f8815f0735e119cf614b3d08f2c8
Author: Marco Cecchetti <marco.cecche...@collabora.com>
Date:   Sun Oct 9 21:50:55 2016 +0200

    LOK: Calc: missing invalidate when ending larger-than-cell edit text
    
    - reason: when text content goes further than the cell border the
    output area of the edit view is grown (extended to an adjacent cell),
    on the contrary the output area of edit views used only for
    invalidating windows of other view shells is never updated, so, in
    other views, only the tile where the edit cell is placed is
    invalidated;
    
    - solution: instead of adding fake edit views for invalidation porpuse
    (and having to updated the output area of each of them when required),
    the new solution provides each new edit view, created on cell editing,
    with a set of `foreign` windows related to other views, they are added
    and removed to this collection owned by an edit view still using the
    ScExtraEditViewManager, which has been in turn simplified; when
    EdiEngine::UpdateViews is invoked not only the window where the edit
    view lives is invalidated but also all `foreign` windows in the owned
    set;
    
    - note: ScTiledRenderingTest::testTextEditViewInvalidations unit test
    has been enhanced in order to test correct invalidation when text
    content goes out of the starting tile.
    
    Change-Id: Id223fb1a032d3b18d2cf70df31f704abd245b3ac
    Reviewed-on: https://gerrit.libreoffice.org/29625
    Reviewed-by: Marco Cecchetti <mrcek...@gmail.com>
    Tested-by: Marco Cecchetti <mrcek...@gmail.com>

diff --git a/editeng/source/editeng/editview.cxx 
b/editeng/source/editeng/editview.cxx
index ee6a864..ba4c4c8 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -295,6 +295,36 @@ vcl::Window* EditView::GetWindow() const
     return pImpEditView->pOutWin;
 }
 
+EditView::OutWindowSet&  EditView::GetOtherViewWindows()
+{
+    return pImpEditView->aOutWindowSet;
+}
+
+bool EditView::HasOtherViewWindow( vcl::Window* pWin )
+{
+    OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet;
+    auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin);
+    return (found != rOutWindowSet.end());
+}
+
+bool EditView::AddOtherViewWindow( vcl::Window* pWin )
+{
+    if (HasOtherViewWindow(pWin))
+        return false;
+    pImpEditView->aOutWindowSet.emplace_back(pWin);
+    return true;
+}
+
+bool EditView::RemoveOtherViewWindow( vcl::Window* pWin )
+{
+    OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet;
+    auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin);
+    if (found == rOutWindowSet.end())
+        return false;
+    rOutWindowSet.erase(found);
+    return true;
+}
+
 void EditView::SetVisArea( const Rectangle& rRect )
 {
     pImpEditView->SetVisDocStartPos( rRect.TopLeft() );
diff --git a/editeng/source/editeng/impedit.cxx 
b/editeng/source/editeng/impedit.cxx
index 83a8e35..8e3b093 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -79,13 +79,13 @@ ImpEditView::ImpEditView( EditView* pView, EditEngine* 
pEng, vcl::Window* pWindo
     pOutWin             = pWindow;
     pPointer            = nullptr;
     pBackgroundColor    = nullptr;
-    mpViewShell = nullptr;
-    mpOtherShell = nullptr;
+    mpViewShell         = nullptr;
+    mpOtherShell        = nullptr;
     nScrollDiffX        = 0;
     nExtraCursorFlags   = 0;
     nCursorBidiLevel    = CURSOR_BIDILEVEL_DONTKNOW;
     pCursor             = nullptr;
-       pDragAndDropInfo = nullptr;
+    pDragAndDropInfo    = nullptr;
     bReadOnly           = false;
     bClickedInSelection = false;
     eSelectionMode      = EE_SELMODE_TXTONLY;
diff --git a/editeng/source/editeng/impedit.hxx 
b/editeng/source/editeng/impedit.hxx
index a1430c6..ee6e6d8 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -219,17 +219,18 @@ class ImpEditView : public 
vcl::unohelper::DragAndDropClient
     using vcl::unohelper::DragAndDropClient::dragOver;
 
 private:
-    EditView*           pEditView;
-    vcl::Cursor*        pCursor;
-    Color*              pBackgroundColor;
+    EditView*                 pEditView;
+    vcl::Cursor*              pCursor;
+    Color*                    pBackgroundColor;
     /// Containing view shell, if any.
-    OutlinerViewShell* mpViewShell;
+    OutlinerViewShell*        mpViewShell;
     /// An other shell, just listening to our state, if any.
-    OutlinerViewShell* mpOtherShell;
-    EditEngine*         pEditEngine;
-    VclPtr<vcl::Window> pOutWin;
-    Pointer*            pPointer;
-    DragAndDropInfo*    pDragAndDropInfo;
+    OutlinerViewShell*        mpOtherShell;
+    EditEngine*               pEditEngine;
+    VclPtr<vcl::Window>       pOutWin;
+    EditView::OutWindowSet    aOutWindowSet;
+    Pointer*                  pPointer;
+    DragAndDropInfo*          pDragAndDropInfo;
 
     css::uno::Reference< css::datatransfer::dnd::XDragSourceListener > 
mxDnDListener;
 
diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index be42d6a..908bf9f 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -292,6 +292,13 @@ void ImpEditEngine::UpdateViews( EditView* pCurView )
             // convert to window coordinates ....
             aClipRect = pView->pImpEditView->GetWindowPos( aClipRect );
             pView->GetWindow()->Invalidate( aClipRect );
+
+            EditView::OutWindowSet& rOutWindowSet = 
pView->GetOtherViewWindows();
+            for (auto pWin: rOutWindowSet)
+            {
+                if (pWin)
+                    pWin->Invalidate(aClipRect);
+            }
         }
     }
 
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 69ef384..5a3a6a4 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -85,6 +85,9 @@ class EDITENG_DLLPUBLIC EditView
     friend class ImpEditEngine;
     friend class EditSelFunctionSet;
 
+public:
+    typedef std::vector<VclPtr<vcl::Window>> OutWindowSet;
+
 public: // Needed for Undo
     ImpEditView*    GetImpEditView() const      { return pImpEditView; }
     ImpEditEngine*  GetImpEditEngine() const;
@@ -104,7 +107,12 @@ public:
     EditEngine*     GetEditEngine() const;
 
     void            SetWindow( vcl::Window* pWin );
-    vcl::Window*         GetWindow() const;
+    vcl::Window*    GetWindow() const;
+
+    OutWindowSet&   GetOtherViewWindows();
+    bool            HasOtherViewWindow( vcl::Window* pWin );
+    bool            AddOtherViewWindow( vcl::Window* pWin );
+    bool            RemoveOtherViewWindow( vcl::Window* pWin );
 
     void            Paint( const Rectangle& rRect, OutputDevice* pTargetDevice 
= nullptr );
     void            Invalidate();
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx 
b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 811dcf7..bd4f00d 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -715,6 +715,23 @@ void ScTiledRenderingTest::testTextEditViewInvalidations()
     CPPUNIT_ASSERT(lcl_hasEditView(*pViewData));
     CPPUNIT_ASSERT(aView2.m_bInvalidateTiles);
 
+    // text edit a cell in view #1 until
+    // we can be sure we are out of the initial tile
+    for (int i = 0; i < 40; ++i)
+    {
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+        pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+    }
+    Scheduler::ProcessEventsToIdle();
+
+    // text edit a cell in view #1 inside the new tile and
+    // check that view #2 receive a tile invalidate message
+    aView2.m_bInvalidateTiles = false;
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+    pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(aView2.m_bInvalidateTiles);
+
     // view #3
     SfxLokHelper::createView();
     ViewCallback aView3;
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index 01e097a..4de89b7 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -82,62 +82,43 @@ public:
 
 class ScExtraEditViewManager
 {
+private:
+    enum ModifierTagType { Adder, Remover };
+
 public:
     ScExtraEditViewManager(ScTabViewShell* pThisViewShell, 
VclPtr<ScGridWindow>* pGridWin)
         : mpThisViewShell(pThisViewShell)
         , mpGridWin(pGridWin)
         , mpOtherEditView(nullptr)
-        , mpOtherEngine(nullptr)
-        , maSameEditViewChecker()
-        , nTotalActiveEditViews(0)
+        , nTotalWindows(0)
     {}
 
     ~ScExtraEditViewManager();
 
     void Add(SfxViewShell* pViewShell, ScSplitPos eWhich)
     {
-        Apply(pViewShell, eWhich, &ScExtraEditViewManager::Adder);
+        Apply<Adder>(pViewShell, eWhich);
     }
 
     void Remove(SfxViewShell* pViewShell, ScSplitPos eWhich)
     {
-        Apply(pViewShell, eWhich, &ScExtraEditViewManager::Remover);
+        Apply<Remover>(pViewShell, eWhich);
     }
 
 private:
-    class SameEditViewChecker
-    {
-    public:
-        SameEditViewChecker()
-            : mpOtherEditView(nullptr)
-            , mpWindow(nullptr)
-        {}
-        void SetEditView(EditView* pOtherEditView) { mpOtherEditView = 
pOtherEditView; }
-        void SetWindow(ScGridWindow* pWindow) { mpWindow = pWindow; }
-        bool operator() (const EditView* pView) const;
-
-    private:
-        EditView* mpOtherEditView;
-        ScGridWindow* mpWindow;
-    };
-
-private:
-    typedef void (ScExtraEditViewManager::* FuncType)(ScGridWindow* );
+    template<ModifierTagType ModifierTag>
+    void Apply(SfxViewShell* pViewShell, ScSplitPos eWhich);
 
-    void Apply(SfxViewShell* pViewShell, ScSplitPos eWhich, FuncType fHandler);
-    void Adder(ScGridWindow* pWin);
-    void Remover(ScGridWindow* pWin);
+    template<ModifierTagType ModifierTag>
+    void Modifier(ScGridWindow* pWin);
 
 private:
     ScTabViewShell* mpThisViewShell;
     VclPtr<ScGridWindow>* mpGridWin;
     EditView* mpOtherEditView;
-    EditEngine* mpOtherEngine;
-    SameEditViewChecker maSameEditViewChecker;
-    int nTotalActiveEditViews;
+    int nTotalWindows;
 };
 
-
 class ScTabView : boost::noncopyable
 {
 private:
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index cd85deb..f3b56e2 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -99,10 +99,11 @@ using namespace com::sun::star;
 
 ScExtraEditViewManager::~ScExtraEditViewManager()
 {
-    assert(nTotalActiveEditViews == 0);
+    DBG_ASSERT(nTotalWindows == 0, "ScExtraEditViewManager dtor: some out 
window has not yet been removed!");
 }
 
-void ScExtraEditViewManager::Apply(SfxViewShell* pViewShell, ScSplitPos 
eWhich, FuncType fHandler)
+template<ScExtraEditViewManager::ModifierTagType ModifierTag>
+void ScExtraEditViewManager::Apply(SfxViewShell* pViewShell, ScSplitPos eWhich)
 {
     ScTabViewShell* pOtherViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
     if (pOtherViewShell != nullptr && pOtherViewShell != mpThisViewShell)
@@ -110,68 +111,37 @@ void ScExtraEditViewManager::Apply(SfxViewShell* 
pViewShell, ScSplitPos eWhich,
         mpOtherEditView = pOtherViewShell->GetViewData().GetEditView(eWhich);
         if (mpOtherEditView != nullptr)
         {
-            mpOtherEngine = mpOtherEditView->GetEditEngine();
-            if (mpOtherEngine != nullptr)
+            DBG_ASSERT(mpOtherEditView->GetEditEngine(), "Edit view has no 
valid engine.");
+            for (int i = 0; i < 4; ++i)
             {
-                maSameEditViewChecker.SetEditView(mpOtherEditView);
-                for (int i = 0; i < 4; ++i)
+                ScGridWindow* pWin = mpGridWin[i].get();
+                if (pWin != nullptr)
                 {
-                    (this->*fHandler)(mpGridWin[i].get());
+                    Modifier<ModifierTag>(pWin);
                 }
             }
         }
     }
 }
 
-void ScExtraEditViewManager::Adder(ScGridWindow* pWin)
+template<ScExtraEditViewManager::ModifierTagType ModifierTag>
+void ScExtraEditViewManager::Modifier(ScGridWindow* /*pWin*/)
 {
-    if (pWin != nullptr)
-    {
-        EditEngine::ViewsType& rEditViews = mpOtherEngine->GetEditViews();
-        maSameEditViewChecker.SetWindow(pWin);
-        auto found = std::find_if(rEditViews.begin(), rEditViews.end(), 
maSameEditViewChecker);
-        if (found == rEditViews.end())
-        {
-            EditView* pThisEditView = new EditView( mpOtherEngine, pWin );
-            if (pThisEditView != nullptr)
-            {
-                pThisEditView->SetOutputArea(mpOtherEditView->GetOutputArea());
-                pThisEditView->SetVisArea(mpOtherEditView->GetVisArea());
-                mpOtherEngine->InsertView(pThisEditView);
-                ++nTotalActiveEditViews;
-            }
-        }
-    }
+    SAL_WARN("sc", "ScExtraEditViewManager::Modifier<ModifierTag>: 
non-specialized version should not be invoked.");
 }
 
-void ScExtraEditViewManager::Remover(ScGridWindow* pWin)
+template<>
+void 
ScExtraEditViewManager::Modifier<ScExtraEditViewManager::Adder>(ScGridWindow* 
pWin)
 {
-    if (pWin != nullptr)
-    {
-        EditEngine::ViewsType& rEditViews = mpOtherEngine->GetEditViews();
-        maSameEditViewChecker.SetWindow(pWin);
-        auto found = std::find_if(rEditViews.begin(), rEditViews.end(), 
maSameEditViewChecker);
-        if (found != rEditViews.end())
-        {
-            EditView* pView = *found;
-            if (pView)
-            {
-                mpOtherEngine->RemoveView(pView);
-                delete pView;
-                pView = nullptr;
-                --nTotalActiveEditViews;
-            }
-        }
-    }
+    if (mpOtherEditView->AddOtherViewWindow(pWin))
+        ++nTotalWindows;
 }
 
-bool ScExtraEditViewManager::SameEditViewChecker::operator() (const EditView* 
pView) const
+template<>
+void 
ScExtraEditViewManager::Modifier<ScExtraEditViewManager::Remover>(ScGridWindow* 
pWin)
 {
-    return ( pView != nullptr
-          && pView->GetWindow() == mpWindow
-          && pView->GetEditEngine() == mpOtherEditView->GetEditEngine()
-          && pView->GetOutputArea() == mpOtherEditView->GetOutputArea()
-          && pView->GetVisArea() == mpOtherEditView->GetVisArea() );
+    if (mpOtherEditView->RemoveOtherViewWindow(pWin))
+        --nTotalWindows;
 }
 
 // ---  public functions
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to