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@redhat.com>
Context
- [PATCH libreoffice-4-0] fdo#62224 reconstruct border state for table dialog · David Tardon (via Code Review)
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.