[PATCH libreoffice-4-0] fdo#62224 reconstruct border state for table dialog

David Tardon (via Code Review) gerrit at gerrit.libreoffice.org
Mon Jun 3 06:23:41 PDT 2013


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/4144

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/44/4144/1

fdo#62224 reconstruct border state for table dialog

Change-Id: I68a4cd1974579119a2d6dccba008441a9bec78df
(cherry picked from commit 67e87f8b88a5a6a741717cc4a8e64f65f9c9cd52)

Conflicts:
	include/svx/sdr/table/tablecontroller.hxx

Change-Id: Id9d72360d234dd1f9dbb9fd252fc0abefff9ad63
---
M editeng/inc/editeng/borderline.hxx
M editeng/source/items/borderline.cxx
M svx/source/table/tablecontroller.cxx
M svx/source/table/tablecontroller.hxx
4 files changed, 232 insertions(+), 2 deletions(-)



diff --git a/editeng/inc/editeng/borderline.hxx b/editeng/inc/editeng/borderline.hxx
index 067e216..a7713b7 100644
--- a/editeng/inc/editeng/borderline.hxx
+++ b/editeng/inc/editeng/borderline.hxx
@@ -160,7 +160,7 @@
         static BorderWidthImpl getWidthImpl( SvxBorderStyle nStyle );
     };
 
-// ============================================================================
+EDITENG_DLLPUBLIC bool operator!=( const SvxBorderLine& rLeft, const SvxBorderLine& rRight );
 
 } // namespace editeng
 
diff --git a/editeng/source/items/borderline.cxx b/editeng/source/items/borderline.cxx
index 646a348..fe451c3 100644
--- a/editeng/source/items/borderline.cxx
+++ b/editeng/source/items/borderline.cxx
@@ -723,6 +723,11 @@
     return false;
 }
 
+bool operator!=( const SvxBorderLine& rLeft, const SvxBorderLine& rRight )
+{
+    return !(rLeft == rRight);
+}
+
 } // namespace editeng
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/table/tablecontroller.cxx b/svx/source/table/tablecontroller.cxx
index 9368675..f29946d 100644
--- a/svx/source/table/tablecontroller.cxx
+++ b/svx/source/table/tablecontroller.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <algorithm>
 
 #include "tablecontroller.hxx"
 
@@ -712,7 +713,6 @@
     if( !pArgs && pTableObj->GetModel() )
     {
         SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
-        MergeAttrFromSelectedCells(aNewAttr, sal_False);
 
         // merge drawing layer text distance items into SvxBoxItem used by the dialog
         SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
@@ -720,7 +720,13 @@
         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
+
+        SvxBoxInfoItem aBoxInfoItem( static_cast< const SvxBoxInfoItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER_INNER ) ) );
+
+        MergeAttrFromSelectedCells(aNewAttr, sal_False);
+        FillCommonBorderAttrFromSelectedCells( aBoxItem, aBoxInfoItem );
         aNewAttr.Put( aBoxItem );
+        aNewAttr.Put( aBoxInfoItem );
 
         SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
         std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
@@ -2573,6 +2579,217 @@
     return 0;
 }
 
+namespace
+{
+
+struct LinesState
+{
+    LinesState(SvxBoxItem& rBoxItem_, SvxBoxInfoItem& rBoxInfoItem_)
+        : rBoxItem(rBoxItem_)
+        , rBoxInfoItem(rBoxInfoItem_)
+    {
+        std::fill_n(aBorderSet, 4, false);
+        std::fill_n(aInnerLineSet, 2, false);
+        std::fill_n(aBorderIndeterminate, 4, false);
+        std::fill_n(aInnerLineIndeterminate, 2, false);
+    }
+
+    SvxBoxItem& rBoxItem;
+    SvxBoxInfoItem& rBoxInfoItem;
+    bool aBorderSet[4];
+    bool aInnerLineSet[2];
+    bool aBorderIndeterminate[4];
+    bool aInnerLineIndeterminate[2];
+};
+
+class BoxItemWrapper
+{
+public:
+    BoxItemWrapper(SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem, sal_uInt16 nBorderLine, sal_uInt16 nInnerLine, bool bBorder);
+
+    const SvxBorderLine* getLine() const;
+    void setLine(const SvxBorderLine* pLine);
+
+private:
+    SvxBoxItem& m_rBoxItem;
+    SvxBoxInfoItem& m_rBoxInfoItem;
+    const sal_uInt16 m_nLine;
+    const bool m_bBorder;
+};
+
+BoxItemWrapper::BoxItemWrapper(
+        SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem,
+        const sal_uInt16 nBorderLine, const sal_uInt16 nInnerLine, const bool bBorder)
+    : m_rBoxItem(rBoxItem)
+    , m_rBoxInfoItem(rBoxInfoItem)
+    , m_nLine(bBorder ? nBorderLine : nInnerLine)
+    , m_bBorder(bBorder)
+{
+    assert(bBorder ? (m_nLine <= BOX_LINE_RIGHT) : (m_nLine <= BOXINFO_LINE_VERT));
+}
+
+const SvxBorderLine* BoxItemWrapper::getLine() const
+{
+    if (m_bBorder)
+        return m_rBoxItem.GetLine(m_nLine);
+    else
+        return (m_nLine == BOXINFO_LINE_HORI) ? m_rBoxInfoItem.GetHori() : m_rBoxInfoItem.GetVert();
+}
+
+void BoxItemWrapper::setLine(const SvxBorderLine* pLine)
+{
+    if (m_bBorder)
+        m_rBoxItem.SetLine(pLine, m_nLine);
+    else
+        m_rBoxInfoItem.SetLine(pLine, m_nLine);
+}
+
+void lcl_MergeBorderLine(
+        LinesState& rLinesState, const SvxBorderLine* const pLine, const sal_uInt16 nLine,
+        const sal_uInt8 nValidFlag, const bool bBorder = true)
+{
+    const sal_uInt16 nInnerLine(bBorder ? 0 : ((nValidFlag & VALID_HORI) ? BOXINFO_LINE_HORI : BOXINFO_LINE_VERT));
+    BoxItemWrapper aBoxItem(rLinesState.rBoxItem, rLinesState.rBoxInfoItem, nLine, nInnerLine, bBorder);
+    bool& rbSet(bBorder ? rLinesState.aBorderSet[nLine] : rLinesState.aInnerLineSet[nInnerLine]);
+    bool& rbIndeterminate(bBorder ? rLinesState.aBorderIndeterminate[nLine] : rLinesState.aInnerLineIndeterminate[nInnerLine]);
+
+    if (rbSet)
+    {
+        if (!rbIndeterminate)
+        {
+            const SvxBorderLine* const pMergedLine(aBoxItem.getLine());
+            if ((pLine && !pMergedLine) || (!pLine && pMergedLine) || (pLine && (*pLine != *pMergedLine)))
+            {
+                aBoxItem.setLine(0);
+                rbIndeterminate = true;
+            }
+        }
+    }
+    else
+    {
+        aBoxItem.setLine(pLine);
+        rbSet = true;
+    }
+}
+
+void lcl_MergeBorderOrInnerLine(
+        LinesState& rLinesState, const SvxBorderLine* const pLine, const sal_uInt16 nLine,
+        const sal_uInt8 nValidFlag, const bool bBorder)
+{
+    if (bBorder)
+        lcl_MergeBorderLine(rLinesState, pLine, nLine, nValidFlag);
+    else
+    {
+        const bool bVertical = (nLine == BOX_LINE_LEFT) || (nLine == BOX_LINE_RIGHT);
+        lcl_MergeBorderLine(rLinesState, pLine, nLine, bVertical ? VALID_VERT : VALID_HORI, false);
+    }
+}
+
+void lcl_MergeCommonBorderAttr(LinesState& rLinesState, const SvxBoxItem& rCellBoxItem, const sal_Int32 nCellFlags)
+{
+    if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
+    {
+        // current cell is outside the selection
+
+        if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
+        {
+            if( nCellFlags & CELL_UPPER )
+                lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetBottom(), BOX_LINE_TOP, VALID_TOP);
+            else if( nCellFlags & CELL_LOWER )
+                lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetTop(), BOX_LINE_BOTTOM, VALID_BOTTOM);
+        }
+        else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
+        {
+            if( nCellFlags & CELL_BEFORE )
+                lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetRight(), BOX_LINE_LEFT, VALID_LEFT);
+            else if( nCellFlags & CELL_AFTER )
+                lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetLeft(), BOX_LINE_RIGHT, VALID_RIGHT);
+        }
+    }
+    else
+    {
+        // current cell is inside the selection
+
+        lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetTop(), BOX_LINE_TOP, VALID_TOP, nCellFlags & CELL_TOP);
+        lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetBottom(), BOX_LINE_BOTTOM, VALID_BOTTOM, nCellFlags & CELL_BOTTOM);
+        lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetLeft(), BOX_LINE_LEFT, VALID_LEFT, nCellFlags & CELL_LEFT);
+        lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetRight(), BOX_LINE_RIGHT, VALID_RIGHT, nCellFlags & CELL_RIGHT);
+    }
+}
+
+}
+
+void SvxTableController::FillCommonBorderAttrFromSelectedCells( SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem ) const
+{
+    if( mxTable.is() )
+    {
+        const sal_Int32 nRowCount = mxTable->getRowCount();
+        const sal_Int32 nColCount = mxTable->getColumnCount();
+        if( nRowCount && nColCount )
+        {
+            CellPos aStart, aEnd;
+            const_cast< SvxTableController* >( this )->getSelectedCells( aStart, aEnd );
+
+            // We are adding one more row/column around the block of selected cells.
+            // We will be checking the adjoining border of these too.
+            const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
+            const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
+
+            rBoxInfoItem.SetValid( sal_uInt8( ~0 ), sal_False );
+            LinesState aLinesState( rBoxItem, rBoxInfoItem );
+
+            /* Here we go through all the selected cells (enhanced by
+             * the adjoining row/column on each side) and determine the
+             * lines for presentation. The algorithm is simple:
+             * 1. if a border or inner line is set in all cells to the
+             *    same value, it will be used.
+             * 2. if a border or inner line is set only in some cells,
+             *    or it has different values, it will be set to
+             *    indeterminate state (SetValid() on rBoxInfoItem).
+             * 3. otherwise it will be unset.
+             */
+            for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
+            {
+                sal_uInt16 nRowFlags = 0;
+                nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
+                nRowFlags |= (nRow == aEnd.mnRow)   ? CELL_BOTTOM : 0;
+                nRowFlags |= (nRow < aStart.mnRow)  ? CELL_UPPER : 0;
+                nRowFlags |= (nRow > aEnd.mnRow)    ? CELL_LOWER : 0;
+
+                for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
+                {
+                    CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
+                    if( !xCell.is() )
+                        continue;
+
+                    sal_uInt16 nCellFlags = nRowFlags;
+                    nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
+                    nCellFlags |= (nCol == aEnd.mnCol)   ? CELL_RIGHT : 0;
+                    nCellFlags |= (nCol < aStart.mnCol)  ? CELL_BEFORE : 0;
+                    nCellFlags |= (nCol > aEnd.mnCol)    ? CELL_AFTER : 0;
+
+                    const SfxItemSet& rSet = xCell->GetItemSet();
+                    const SvxBoxItem& rCellBoxItem = static_cast< const SvxBoxItem& >( rSet.Get(SDRATTR_TABLE_BORDER ) );
+                    lcl_MergeCommonBorderAttr( aLinesState, rCellBoxItem, nCellFlags );
+                }
+            }
+
+            if (!aLinesState.aBorderIndeterminate[BOX_LINE_TOP])
+                aLinesState.rBoxInfoItem.SetValid(VALID_TOP);
+            if (!aLinesState.aBorderIndeterminate[BOX_LINE_BOTTOM])
+                aLinesState.rBoxInfoItem.SetValid(VALID_BOTTOM);
+            if (!aLinesState.aBorderIndeterminate[BOX_LINE_LEFT])
+                aLinesState.rBoxInfoItem.SetValid(VALID_LEFT);
+            if (!aLinesState.aBorderIndeterminate[BOX_LINE_RIGHT])
+                aLinesState.rBoxInfoItem.SetValid(VALID_RIGHT);
+            if (!aLinesState.aInnerLineIndeterminate[BOXINFO_LINE_HORI])
+                aLinesState.rBoxInfoItem.SetValid(VALID_HORI);
+            if (!aLinesState.aInnerLineIndeterminate[BOXINFO_LINE_VERT])
+                aLinesState.rBoxInfoItem.SetValid(VALID_VERT);
+        }
+    }
+}
+
 } }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/table/tablecontroller.hxx b/svx/source/table/tablecontroller.hxx
index c25b2f1..7a9d407 100644
--- a/svx/source/table/tablecontroller.hxx
+++ b/svx/source/table/tablecontroller.hxx
@@ -33,6 +33,8 @@
 class SdrObjEditView;
 class SdrObject;
 class SfxItemSet;
+class SvxBoxItem;
+class SvxBoxInfoItem;
 
 namespace sdr { namespace table {
 
@@ -76,6 +78,12 @@
 
     SVX_DLLPRIVATE void MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const;
     SVX_DLLPRIVATE void SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll);
+    /** Fill the values that are common for all selected cells.
+      *
+      * This lets the Borders dialog to display the line arrangement
+      * properly.
+      */
+    SVX_DLLPRIVATE void FillCommonBorderAttrFromSelectedCells(SvxBoxItem& rBox, SvxBoxInfoItem& rBoxInfo) const;
 
     SVX_DLLPRIVATE virtual bool GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const;
     SVX_DLLPRIVATE virtual bool SetAttributes(const SfxItemSet& rSet, bool bReplaceAll);

-- 
To view, visit https://gerrit.libreoffice.org/4144
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id9d72360d234dd1f9dbb9fd252fc0abefff9ad63
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: libreoffice-4-0
Gerrit-Owner: David Tardon <dtardon at redhat.com>



More information about the LibreOffice mailing list