[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - include/svx sd/qa svx/source

Miklos Vajna vmiklos at collabora.co.uk
Mon May 2 07:36:42 UTC 2016


 include/svx/svddrag.hxx                      |    4 ++
 include/svx/svdotable.hxx                    |    3 +
 include/svx/svdundo.hxx                      |    3 +
 sd/qa/unit/tiledrendering/data/table.odp     |binary
 sd/qa/unit/tiledrendering/tiledrendering.cxx |   52 +++++++++++++++++++++++++++
 svx/source/svdraw/svddrag.cxx                |    1 
 svx/source/svdraw/svddrgmt.cxx               |    6 +++
 svx/source/svdraw/svdundo.cxx                |    7 +++
 svx/source/table/svdotable.cxx               |   14 ++++++-
 svx/source/table/tablerow.cxx                |    4 ++
 svx/source/table/tablerow.hxx                |    2 +
 svx/source/table/tableundo.cxx               |    3 +
 12 files changed, 98 insertions(+), 1 deletion(-)

New commits:
commit 5c32e526d7cc1f623ca1b60a16537efa5740dd6c
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Apr 25 10:57:49 2016 +0200

    tdf#99452 svx: fix undo of table row edge drag
    
    The problem as seen by the user: if you have a table of 2 rows and 1 column,
    and the separator line is dragged upwards by the mouse, then undo doesn't
    restore the original situation.
    
    Two items are created on the undo stack: sd::UndoGeoObject and
    sdr::table::TableRowUndo. Let's say the table height is 8000 mm100 and the two
    cell heights are 4000 and 4000. If the user resizes the first cell, so that its
    height is 2000, then the new table height will be 6000. The problem is that
    when undo is executed, first sd::UndoGeoObject resizes the table, distributing
    the newly available 2000 between the existing rows, and then
    sdr::table::TableRowUndo sets the row height of the first row: the height of
    the second cell will be larger than expected. Fix the problem by not doing a
    relayout during sd::UndoGeoObject, but doing a relayout after
    sdr::table::TableRowUndo in this case.
    
    This is done by:
    
    1) Adding a new SdrDragStat::mbEndDragChangesLayout, so that
    SdrTableObj::applySpecialDrag() can inform SdrDragObjOwn::EndSdrDrag() that
    TableRowUndo will do the layout instead of UndoGeoObject. (This is done only in
    case a row edge is dragged, as otherwise it's not guaranteed that a
    TableRowUndo will follow the UndoGeoObject on the undo stack.)
    
    2) Adding a new SdrUndoGeoObj::mbSkipChangeLayout, so that
    SdrTableObj::applySpecialDrag() can let SdrUndoGeoObj::Undo() not do the
    layout.
    
    3) Adding a sdr::table::SdrTableObjImpl::mbSkipChangeLayout, so that
    SdrUndoGeoObj::Undo() can let SdrTableObj::NbcSetLogicRect() not do the layout.
    
    4) Marking the table model as modified in TableRowUndo::setData(), so it does
    the layout at the end of the undo group.
    
    (cherry picked from commits cafc53f8b4c08443524b1da6f4918d49afd45bb5,
    8d1fa417bc49a9e9eee923e3ce6a37d7b0f056f1 and
    758e6f39d96237881198818e3bac432012be61d8)
    
    Conflicts:
    	sd/qa/unit/tiledrendering/tiledrendering.cxx
    	svx/source/table/svdotable.cxx
    
    Change-Id: I8adde3cdad5741e6fcb420e333ce336e18c77cf1
    Reviewed-on: https://gerrit.libreoffice.org/24392
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/include/svx/svddrag.hxx b/include/svx/svddrag.hxx
index ac2a978..aa4a03e 100644
--- a/include/svx/svddrag.hxx
+++ b/include/svx/svddrag.hxx
@@ -55,6 +55,8 @@ protected:
 
     bool      bEndDragChangesAttributes;
     bool      bEndDragChangesGeoAndAttributes;
+    /// Table row drag: table will re-layout itself later.
+    bool      mbEndDragChangesLayout;
     bool      bMouseIsUp;
 
     bool      bShown;    // Xor visible?
@@ -133,6 +135,8 @@ public:
     void         SetEndDragChangesAttributes(bool bOn) { bEndDragChangesAttributes=bOn; }
     bool         IsEndDragChangesGeoAndAttributes() const   { return bEndDragChangesGeoAndAttributes; }
     void         SetEndDragChangesGeoAndAttributes(bool bOn) { bEndDragChangesGeoAndAttributes=bOn; }
+    bool         IsEndDragChangesLayout() const   { return mbEndDragChangesLayout; }
+    void         SetEndDragChangesLayout(bool bOn) { mbEndDragChangesLayout=bOn; }
 
     // Is set by the view and can be evaluated by Obj
     bool         IsMouseDown() const                  { return !bMouseIsUp; }
diff --git a/include/svx/svdotable.hxx b/include/svx/svdotable.hxx
index f70d768..408f0b8 100644
--- a/include/svx/svdotable.hxx
+++ b/include/svx/svdotable.hxx
@@ -261,6 +261,9 @@ public:
     /// Add an undo action that should be on the undo stack after ending text edit.
     void AddUndo(SdrUndoAction* pUndo);
 
+    /// Next time layouting would be done, skip it (to layout at the end of multiple actions).
+    void SetSkipChangeLayout(bool bSkipChangeLayout);
+
     virtual void onEditOutlinerStatusEvent( EditStatus* pEditStatus ) override;
 
 
diff --git a/include/svx/svdundo.hxx b/include/svx/svdundo.hxx
index 966e408..7d4973f 100644
--- a/include/svx/svdundo.hxx
+++ b/include/svx/svdundo.hxx
@@ -213,6 +213,8 @@ protected:
     SdrObjGeoData*              pRedoGeo;
     // If we have a group object:
     SdrUndoGroup*               pUndoGroup;
+    /// If we have a table object, should its layout change?
+    bool mbSkipChangeLayout;
 
 public:
     SdrUndoGeoObj(SdrObject& rNewObj);
@@ -222,6 +224,7 @@ public:
     virtual void Redo() override;
 
     virtual OUString GetComment() const override;
+    void SetSkipChangeLayout(bool bOn) { mbSkipChangeLayout=bOn; }
 };
 
 /**
diff --git a/sd/qa/unit/tiledrendering/data/table.odp b/sd/qa/unit/tiledrendering/data/table.odp
new file mode 100644
index 0000000..6d92898
Binary files /dev/null and b/sd/qa/unit/tiledrendering/data/table.odp differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 6ebb6ab..7e527ef 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -24,6 +24,8 @@
 #include <sfx2/dispatch.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <svl/srchitem.hxx>
+#include <comphelper/lok.hxx>
+#include <svx/svdotable.hxx>
 
 #include <DrawDocShell.hxx>
 #include <ViewShell.hxx>
@@ -54,6 +56,7 @@ public:
     void testSearch();
     void testSearchAll();
     void testSearchAllSelections();
+    void testResizeTable();
 #endif
 
     CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
@@ -68,6 +71,7 @@ public:
     CPPUNIT_TEST(testSearch);
     CPPUNIT_TEST(testSearchAll);
     CPPUNIT_TEST(testSearchAllSelections);
+    CPPUNIT_TEST(testResizeTable);
 #endif
     CPPUNIT_TEST_SUITE_END();
 
@@ -450,6 +454,54 @@ void SdTiledRenderingTest::testSearchAllSelections()
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), m_aSelection.size());
 }
 
+void SdTiledRenderingTest::testResizeTable()
+{
+    // Load the document.
+    comphelper::LibreOfficeKit::setActive();
+    SdXImpressDocument* pXImpressDocument = createDoc("table.odp");
+    sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+    SdPage* pActualPage = pViewShell->GetActualPage();
+    SdrObject* pObject = pActualPage->GetObj(0);
+    auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+    CPPUNIT_ASSERT(pTableObject);
+
+    // Select the table by marking it + starting and ending text edit.
+    SdrView* pView = pViewShell->GetView();
+    pView->MarkObj(pObject, pView->GetSdrPageView());
+    pView->SdrBeginTextEdit(pObject);
+    pView->SdrEndTextEdit();
+
+    // Remember the original row heights.
+    uno::Reference<table::XColumnRowRange> xTable(pTableObject->getTable(), uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> xRows(xTable->getRows(), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xRow1(xRows->getByIndex(0), uno::UNO_QUERY);
+    sal_Int32 nExpectedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+    uno::Reference<beans::XPropertySet> xRow2(xRows->getByIndex(1), uno::UNO_QUERY);
+    sal_Int32 nExpectedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+
+    // Resize the upper row, decrease its height by 1 cm.
+    Point aInnerRowEdge = pObject->GetSnapRect().Center();
+    pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, convertMm100ToTwip(aInnerRowEdge.getX()), convertMm100ToTwip(aInnerRowEdge.getY()));
+    pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, convertMm100ToTwip(aInnerRowEdge.getX()), convertMm100ToTwip(aInnerRowEdge.getY() - 1000));
+
+    // Remember the resized row heights.
+    sal_Int32 nResizedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+    CPPUNIT_ASSERT(nResizedRow1 < nExpectedRow1);
+    sal_Int32 nResizedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+    CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nResizedRow2);
+
+    // Now undo the resize.
+    pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
+
+    // Check the undo result.
+    sal_Int32 nActualRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+    CPPUNIT_ASSERT_EQUAL(nExpectedRow1, nActualRow1);
+    sal_Int32 nActualRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+    // Expected was 4000, actual was 4572, i.e. the second row after undo was larger than expected.
+    CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nActualRow2);
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 #endif
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
diff --git a/svx/source/svdraw/svddrag.cxx b/svx/source/svdraw/svddrag.cxx
index 91cd2d1..2f44f47 100644
--- a/svx/source/svdraw/svddrag.cxx
+++ b/svx/source/svdraw/svddrag.cxx
@@ -50,6 +50,7 @@ void SdrDragStat::Reset()
     pDragMethod=nullptr;
     bEndDragChangesAttributes=false;
     bEndDragChangesGeoAndAttributes=false;
+    mbEndDragChangesLayout=false;
     bMouseIsUp=false;
     Clear(true);
     aActionRect=Rectangle();
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index bff9a6c..9d70c20 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -1423,6 +1423,12 @@ bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
         }
 
         bRet = pObj->applySpecialDrag(DragStat());
+        if (DragStat().IsEndDragChangesLayout())
+        {
+            auto pGeoUndo = dynamic_cast<SdrUndoGeoObj*>(pUndo);
+            if (pGeoUndo)
+                pGeoUndo->SetSkipChangeLayout(true);
+        }
 
         if(bRet)
         {
diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx
index b3cf6ae..9567d9e 100644
--- a/svx/source/svdraw/svdundo.cxx
+++ b/svx/source/svdraw/svdundo.cxx
@@ -603,6 +603,7 @@ SdrUndoGeoObj::SdrUndoGeoObj(SdrObject& rNewObj)
      , pUndoGeo(nullptr)
      , pRedoGeo(nullptr)
      , pUndoGroup(nullptr)
+     , mbSkipChangeLayout(false)
 {
     SdrObjList* pOL=rNewObj.GetSubList();
     if (pOL!=nullptr && pOL->GetObjCount() && dynamic_cast<const E3dScene* >( &rNewObj) ==  nullptr)
@@ -645,7 +646,13 @@ void SdrUndoGeoObj::Undo()
     {
         delete pRedoGeo;
         pRedoGeo=pObj->GetGeoData();
+
+        auto pTableObj = dynamic_cast<sdr::table::SdrTableObj*>(pObj);
+        if (pTableObj && mbSkipChangeLayout)
+            pTableObj->SetSkipChangeLayout(true);
         pObj->SetGeoData(*pUndoGeo);
+        if (pTableObj && mbSkipChangeLayout && pTableObj)
+            pTableObj->SetSkipChangeLayout(false);
     }
 }
 
diff --git a/svx/source/table/svdotable.cxx b/svx/source/table/svdotable.cxx
index 5b979fe..4fbcb1f 100644
--- a/svx/source/table/svdotable.cxx
+++ b/svx/source/table/svdotable.cxx
@@ -206,6 +206,7 @@ public:
     TableStyleSettings maTableStyle;
     Reference< XIndexAccess > mxTableStyle;
     std::vector<std::unique_ptr<SdrUndoAction>> maUndos;
+    bool mbSkipChangeLayout;
 
     void SetModel(SdrModel* pOldModel, SdrModel* pNewModel);
 
@@ -262,6 +263,7 @@ sal_Int32 SdrTableObjImpl::lastColCount;
 SdrTableObjImpl::SdrTableObjImpl()
 : mpTableObj( nullptr )
 , mpLayouter( nullptr )
+, mbSkipChangeLayout(false)
 {
 }
 
@@ -1950,7 +1952,11 @@ void SdrTableObj::NbcSetLogicRect(const Rectangle& rRect)
     const bool bWidth = maLogicRect.getWidth() != maRect.getWidth();
     const bool bHeight = maLogicRect.getHeight() != maRect.getHeight();
     maRect = maLogicRect;
-    NbcAdjustTextFrameWidthAndHeight( !bHeight, !bWidth );
+    if (mpImpl->mbSkipChangeLayout)
+        // Avoid distributing newly available space between existing cells.
+        NbcAdjustTextFrameWidthAndHeight();
+    else
+        NbcAdjustTextFrameWidthAndHeight(!bHeight, !bWidth);
     SetRectsDirty();
 }
 
@@ -2098,6 +2104,11 @@ void SdrTableObj::AddUndo(SdrUndoAction* pUndo)
     mpImpl->maUndos.push_back(std::unique_ptr<SdrUndoAction>(pUndo));
 }
 
+void SdrTableObj::SetSkipChangeLayout(bool bSkipChangeLayout)
+{
+    mpImpl->mbSkipChangeLayout = bSkipChangeLayout;
+}
+
 
 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
@@ -2341,6 +2352,7 @@ bool SdrTableObj::applySpecialDrag(SdrDragStat& rDrag)
                 if( GetModel() && IsInserted() )
                 {
                     rDrag.SetEndDragChangesAttributes(true);
+                    rDrag.SetEndDragChangesLayout(true);
                 }
 
                 mpImpl->DragEdge( pEdgeHdl->IsHorizontalEdge(), pEdgeHdl->GetPointNum(), pEdgeHdl->GetValidDragOffset( rDrag ) );
diff --git a/svx/source/table/tablerow.cxx b/svx/source/table/tablerow.cxx
index d86f7e9..37212b7 100644
--- a/svx/source/table/tablerow.cxx
+++ b/svx/source/table/tablerow.cxx
@@ -157,6 +157,10 @@ void TableRow::removeColumns( sal_Int32 nIndex, sal_Int32 nCount )
     }
 }
 
+TableModelRef const & TableRow::getModel() const
+{
+    return mxTableModel;
+}
 
 // XCellRange
 
diff --git a/svx/source/table/tablerow.hxx b/svx/source/table/tablerow.hxx
index cc8c236..5fdd940 100644
--- a/svx/source/table/tablerow.hxx
+++ b/svx/source/table/tablerow.hxx
@@ -48,6 +48,8 @@ public:
 
     void insertColumns( sal_Int32 nIndex, sal_Int32 nCount, CellVector::iterator* pIter = nullptr );
     void removeColumns( sal_Int32 nIndex, sal_Int32 nCount );
+    /// Reference to the table model containing this row.
+    TableModelRef const & getModel() const;
 
     // XCellRange
     virtual css::uno::Reference< css::table::XCell > SAL_CALL getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw (css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception) override;
diff --git a/svx/source/table/tableundo.cxx b/svx/source/table/tableundo.cxx
index 250675e..59d08a2 100644
--- a/svx/source/table/tableundo.cxx
+++ b/svx/source/table/tableundo.cxx
@@ -492,6 +492,9 @@ void TableRowUndo::setData( const Data& rData )
     mxRow->mbIsVisible = rData.mbIsVisible;
     mxRow->mbIsStartOfNewPage = rData.mbIsStartOfNewPage;
     mxRow->maName = rData.maName;
+
+    // Trigger re-layout of the table.
+    mxRow->getModel()->setModified(true);
  }
 
 


More information about the Libreoffice-commits mailing list