editeng/source/items/borderline.cxx | 5 include/editeng/borderline.hxx | 2 include/svx/sdr/table/tablecontroller.hxx | 8 + svx/source/table/tablecontroller.cxx | 222 +++++++++++++++++++++++++++++- 4 files changed, 234 insertions(+), 3 deletions(-)
New commits: commit 22ec6b5a369d2a1a8a334f405f304facfbb0e4b9 Author: David Tardon <dtar...@redhat.com> Date: Mon Jun 3 14:22:07 2013 +0200 copy values from the original item set ... because SfxAbstractDialog::GetOutputItemSet() only contains the items that have been _changed_ in the dialog. Change-Id: Iaf20bb42b65e420fe4e7aff979378eff7b5e5df2 (cherry picked from commit 9cd71f996e3625e8174c46bf85e336c1ee90df7f) Signed-off-by: David Tardon <dtar...@redhat.com> diff --git a/svx/source/table/tablecontroller.cxx b/svx/source/table/tablecontroller.cxx index 79f5aca..b91ea92 100644 --- a/svx/source/table/tablecontroller.cxx +++ b/svx/source/table/tablecontroller.cxx @@ -745,7 +745,8 @@ void SvxTableController::onFormatTable( SfxRequest& rReq ) // Even Cancel Button is returning positive(101) value, if( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) { - SfxItemSet aNewSet( *(pDlg->GetOutputItemSet ()) ); + SfxItemSet aNewSet( aNewAttr ); + aNewSet.Put( *(pDlg->GetOutputItemSet ()) ); SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) ); commit 352c89983e108f687c8eed79bdac00c36c641e22 Author: David Tardon <dtar...@redhat.com> Date: Sat Jun 1 09:43:50 2013 +0200 fdo#62224 reconstruct border state for table dialog Change-Id: I68a4cd1974579119a2d6dccba008441a9bec78df (cherry picked from commit 67e87f8b88a5a6a741717cc4a8e64f65f9c9cd52) Signed-off-by: David Tardon <dtar...@redhat.com> diff --git a/editeng/source/items/borderline.cxx b/editeng/source/items/borderline.cxx index 9e1d8f6..70ff353 100644 --- a/editeng/source/items/borderline.cxx +++ b/editeng/source/items/borderline.cxx @@ -683,6 +683,11 @@ bool SvxBorderLine::HasPriority( const SvxBorderLine& rOtherLine ) const 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/include/editeng/borderline.hxx b/include/editeng/borderline.hxx index 067e216..a7713b7 100644 --- a/include/editeng/borderline.hxx +++ b/include/editeng/borderline.hxx @@ -160,7 +160,7 @@ namespace editeng { static BorderWidthImpl getWidthImpl( SvxBorderStyle nStyle ); }; -// ============================================================================ +EDITENG_DLLPUBLIC bool operator!=( const SvxBorderLine& rLeft, const SvxBorderLine& rRight ); } // namespace editeng diff --git a/include/svx/sdr/table/tablecontroller.hxx b/include/svx/sdr/table/tablecontroller.hxx index 5efdd87..2f4126c 100644 --- a/include/svx/sdr/table/tablecontroller.hxx +++ b/include/svx/sdr/table/tablecontroller.hxx @@ -33,6 +33,8 @@ class SdrObjEditView; class SdrObject; class SfxItemSet; +class SvxBoxInfoItem; +class SvxBoxItem; namespace sdr { namespace table { @@ -78,6 +80,12 @@ public: 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); diff --git a/svx/source/table/tablecontroller.cxx b/svx/source/table/tablecontroller.cxx index a561590..79f5aca 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 <svx/sdr/table/tablecontroller.hxx> #include <tablemodel.hxx> @@ -724,7 +725,6 @@ void SvxTableController::onFormatTable( SfxRequest& rReq ) 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 ) ) ); @@ -732,7 +732,13 @@ void SvxTableController::onFormatTable( SfxRequest& rReq ) 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 ); @@ -2581,6 +2587,217 @@ IMPL_LINK_NOARG(SvxTableController, UpdateHdl) 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: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits