[Libreoffice-commits] core.git: cui/source cui/uiconfig editeng/source include/editeng sc/inc sc/source
Dennis Francis
dennisfrancis.in at gmail.com
Mon Dec 7 05:50:16 PST 2015
cui/source/inc/border.hxx | 5
cui/source/tabpages/border.cxx | 86 +++++++++++-
cui/uiconfig/ui/borderpage.ui | 14 +
editeng/source/items/frmitems.cxx | 9 -
include/editeng/boxitem.hxx | 5
sc/inc/markdata.hxx | 15 ++
sc/source/core/data/document.cxx | 80 +++++++++++
sc/source/core/data/markdata.cxx | 267 +++++++++++++++++++++++++++++++++++++-
sc/source/ui/inc/undoblk.hxx | 4
sc/source/ui/undo/undoblk3.cxx | 8 -
sc/source/ui/view/viewfunc.cxx | 22 ++-
11 files changed, 499 insertions(+), 16 deletions(-)
New commits:
commit 2e512174f2116d86682037459fd5ab5164e9f510
Author: Dennis Francis <dennisfrancis.in at gmail.com>
Date: Sun Nov 1 03:49:38 2015 +0530
tdf#34449 : ability of deleting borders of a cell from adjacent cell
Change-Id: Ieb13a9ea88faa220d1ee352b0e47268a7fda5f38
Reviewed-on: https://gerrit.libreoffice.org/19715
Reviewed-by: Eike Rathke <erack at redhat.com>
Tested-by: Eike Rathke <erack at redhat.com>
diff --git a/cui/source/inc/border.hxx b/cui/source/inc/border.hxx
index 81fee64..ba780e1 100644
--- a/cui/source/inc/border.hxx
+++ b/cui/source/inc/border.hxx
@@ -98,6 +98,7 @@ private:
VclPtr<CheckBox> m_pMergeWithNextCB;
// #i29550#
VclPtr<CheckBox> m_pMergeAdjacentBordersCB;
+ VclPtr<CheckBox> m_pRemoveAdjcentCellBordersCB;
ImageList aShadowImgLstH;
ImageList aShadowImgLst;
@@ -113,6 +114,8 @@ private:
bool mbBLTREnabled; ///< true = Bottom-left to top-right border enabled.
bool mbUseMarginItem;
bool mbSync;
+ bool mbRemoveAdjacentCellBorders;
+ bool bIsCalcDoc;
std::set<sal_Int16> maUsedBorderStyles;
@@ -125,6 +128,7 @@ private:
DECL_LINK_TYPED( ModifyDistanceHdl_Impl, Edit&, void);
DECL_LINK_TYPED( ModifyWidthHdl_Impl, Edit&, void);
DECL_LINK_TYPED( SyncHdl_Impl, Button*, void);
+ DECL_LINK_TYPED( RemoveAdjacentCellBorderHdl_Impl, Button*, void);
sal_uInt16 GetPresetImageId( sal_uInt16 nValueSetIdx ) const;
sal_uInt16 GetPresetStringId( sal_uInt16 nValueSetIdx ) const;
@@ -142,6 +146,7 @@ private:
bool bValid );
bool IsBorderLineStyleAllowed( sal_Int16 nStyle ) const;
+ void UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset );
};
diff --git a/cui/source/tabpages/border.cxx b/cui/source/tabpages/border.cxx
index 180fd28..a4853ba 100644
--- a/cui/source/tabpages/border.cxx
+++ b/cui/source/tabpages/border.cxx
@@ -44,10 +44,13 @@
#include <svl/int64item.hxx>
#include <sfx2/itemconnect.hxx>
#include <sal/macros.h>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include "borderconn.hxx"
using namespace ::editeng;
-
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::lang::XServiceInfo;
+using ::com::sun::star::uno::UNO_QUERY;
/*
@@ -99,7 +102,9 @@ SvxBorderTabPage::SvxBorderTabPage(vcl::Window* pParent, const SfxItemSet& rCore
mbTLBREnabled( false ),
mbBLTREnabled( false ),
mbUseMarginItem( false ),
- mbSync(true)
+ mbSync(true),
+ mbRemoveAdjacentCellBorders( false ),
+ bIsCalcDoc( false )
{
get(m_pWndPresets, "presets");
@@ -130,6 +135,7 @@ SvxBorderTabPage::SvxBorderTabPage(vcl::Window* pParent, const SfxItemSet& rCore
get(m_pPropertiesFrame, "properties");
get(m_pMergeWithNextCB, "mergewithnext");
get(m_pMergeAdjacentBordersCB, "mergeadjacent");
+ get(m_pRemoveAdjcentCellBordersCB, "rmadjcellborders");
if ( GetDPIScaleFactor() > 1 )
{
@@ -331,6 +337,21 @@ SvxBorderTabPage::SvxBorderTabPage(vcl::Window* pParent, const SfxItemSet& rCore
// checkbox "Merge adjacent line styles" only visible for Writer dialog format.table
AddItemConnection( new sfx::CheckBoxConnection( SID_SW_COLLAPSING_BORDERS, *m_pMergeAdjacentBordersCB, sfx::ITEMCONN_DEFAULT ) );
m_pMergeAdjacentBordersCB->Hide();
+
+ if( pDocSh )
+ {
+ Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY );
+ if ( xSI.is() )
+ bIsCalcDoc = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument");
+ }
+ if( bIsCalcDoc )
+ {
+ m_pRemoveAdjcentCellBordersCB->SetClickHdl(LINK(this, SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl));
+ m_pRemoveAdjcentCellBordersCB->Show();
+ m_pRemoveAdjcentCellBordersCB->Enable( false );
+ }
+ else
+ m_pRemoveAdjcentCellBordersCB->Hide();
}
SvxBorderTabPage::~SvxBorderTabPage()
@@ -365,6 +386,7 @@ void SvxBorderTabPage::dispose()
m_pPropertiesFrame.clear();
m_pMergeWithNextCB.clear();
m_pMergeAdjacentBordersCB.clear();
+ m_pRemoveAdjcentCellBordersCB.clear();
SfxTabPage::dispose();
}
@@ -596,6 +618,10 @@ void SvxBorderTabPage::Reset( const SfxItemSet* rSet )
else
mbSync = false;
m_pSynchronizeCB->Check(mbSync);
+
+ mbRemoveAdjacentCellBorders = false;
+ m_pRemoveAdjcentCellBordersCB->Check( false );
+ m_pRemoveAdjcentCellBordersCB->Enable( false );
}
void SvxBorderTabPage::ChangesApplied()
@@ -645,6 +671,7 @@ bool SvxBorderTabPage::FillItemSet( SfxItemSet* rCoreAttrs )
aBoxItem.SetLine( m_pFrameSel->GetFrameBorderStyle( eTypes1[i].first ), eTypes1[i].second );
+ aBoxItem.SetRemoveAdjacentCellBorder( mbRemoveAdjacentCellBorders );
// border hor/ver and TableFlag
::std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> eTypes2[] = {
@@ -843,6 +870,7 @@ IMPL_LINK_NOARG_TYPED(SvxBorderTabPage, SelPreHdl_Impl, ValueSet*, void)
m_pWndPresets->SetNoSelection();
LinesChanged_Impl( nullptr );
+ UpdateRemoveAdjCellBorderCB( nLine + 1 );
}
@@ -1172,6 +1200,7 @@ IMPL_LINK_NOARG_TYPED(SvxBorderTabPage, LinesChanged_Impl, LinkParamNone*, void)
m_pSynchronizeCB->Enable( m_pRightMF->IsEnabled() || m_pTopMF->IsEnabled() ||
m_pBottomMF->IsEnabled() || m_pLeftMF->IsEnabled() );
}
+ UpdateRemoveAdjCellBorderCB( -1 );
}
@@ -1197,6 +1226,59 @@ IMPL_LINK_TYPED( SvxBorderTabPage, SyncHdl_Impl, Button*, pBox, void)
mbSync = static_cast<CheckBox*>(pBox)->IsChecked();
}
+IMPL_LINK_TYPED( SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl, Button*, pBox, void)
+{
+ mbRemoveAdjacentCellBorders = static_cast<CheckBox*>(pBox)->IsChecked();
+}
+
+void SvxBorderTabPage::UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset )
+{
+ if( !bIsCalcDoc )
+ return;
+ const SfxItemSet& rOldSet = GetItemSet();
+ const SvxBoxInfoItem* pOldBoxInfoItem = static_cast<const SvxBoxInfoItem*>(GetOldItem( rOldSet, SID_ATTR_BORDER_INNER ));
+ const SvxBoxItem* pOldBoxItem = static_cast<const SvxBoxItem*>(GetOldItem( rOldSet, SID_ATTR_BORDER_OUTER ));
+ if( !pOldBoxInfoItem || !pOldBoxItem )
+ return;
+ ::std::pair<svx::FrameBorderType, SvxBoxInfoItemValidFlags> eTypes1[] = {
+ { svx::FRAMEBORDER_TOP,SvxBoxInfoItemValidFlags::TOP },
+ { svx::FRAMEBORDER_BOTTOM,SvxBoxInfoItemValidFlags::BOTTOM },
+ { svx::FRAMEBORDER_LEFT,SvxBoxInfoItemValidFlags::LEFT },
+ { svx::FRAMEBORDER_RIGHT,SvxBoxInfoItemValidFlags::RIGHT },
+ };
+ SvxBoxItemLine eTypes2[] = {
+ SvxBoxItemLine::TOP,
+ SvxBoxItemLine::BOTTOM,
+ SvxBoxItemLine::LEFT,
+ SvxBoxItemLine::RIGHT,
+ };
+
+ // Check if current selection involves deletion of at least one border
+ bool bBorderDeletionReq = false;
+ for ( sal_uInt32 i=0; i < SAL_N_ELEMENTS( eTypes1 ); ++i )
+ {
+ if( pOldBoxItem->GetLine( eTypes2[i] ) || !( pOldBoxInfoItem->IsValid( eTypes1[i].second ) ) )
+ {
+ if( m_pFrameSel->GetFrameBorderState( eTypes1[i].first ) == svx::FRAMESTATE_HIDE )
+ {
+ bBorderDeletionReq = true;
+ break;
+ }
+ }
+ }
+
+ if( !bBorderDeletionReq && ( nPreset == IID_PRE_CELL_NONE || nPreset == IID_PRE_TABLE_NONE ) )
+ bBorderDeletionReq = true;
+
+ m_pRemoveAdjcentCellBordersCB->Enable( bBorderDeletionReq );
+
+ if( !bBorderDeletionReq )
+ {
+ mbRemoveAdjacentCellBorders = false;
+ m_pRemoveAdjcentCellBordersCB->Check( false );
+ }
+}
+
void SvxBorderTabPage::DataChanged( const DataChangedEvent& rDCEvt )
{
if( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
diff --git a/cui/uiconfig/ui/borderpage.ui b/cui/uiconfig/ui/borderpage.ui
index 4e1943e..d25dbed 100644
--- a/cui/uiconfig/ui/borderpage.ui
+++ b/cui/uiconfig/ui/borderpage.ui
@@ -102,6 +102,20 @@
<property name="top_attach">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="rmadjcellborders">
+ <property name="label" translatable="yes">Remove border from adjacent cells as well</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
</object>
</child>
</object>
diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx
index 10211e4..69c18f3 100644
--- a/editeng/source/items/frmitems.cxx
+++ b/editeng/source/items/frmitems.cxx
@@ -1611,7 +1611,8 @@ SvxBoxItem::SvxBoxItem( const SvxBoxItem& rCpy ) :
nTopDist ( rCpy.nTopDist ),
nBottomDist ( rCpy.nBottomDist ),
nLeftDist ( rCpy.nLeftDist ),
- nRightDist ( rCpy.nRightDist )
+ nRightDist ( rCpy.nRightDist ),
+ bRemoveAdjCellBorder ( rCpy.bRemoveAdjCellBorder )
{
pTop = rCpy.GetTop() ? new SvxBorderLine( *rCpy.GetTop() ) : nullptr;
@@ -1632,8 +1633,8 @@ SvxBoxItem::SvxBoxItem( const sal_uInt16 nId ) :
nTopDist ( 0 ),
nBottomDist ( 0 ),
nLeftDist ( 0 ),
- nRightDist ( 0 )
-
+ nRightDist ( 0 ),
+ bRemoveAdjCellBorder ( false )
{
}
@@ -1655,6 +1656,7 @@ SvxBoxItem& SvxBoxItem::operator=( const SvxBoxItem& rBox )
nBottomDist = rBox.nBottomDist;
nLeftDist = rBox.nLeftDist;
nRightDist = rBox.nRightDist;
+ bRemoveAdjCellBorder = rBox.bRemoveAdjCellBorder;
SetLine( rBox.GetTop(), SvxBoxItemLine::TOP );
SetLine( rBox.GetBottom(), SvxBoxItemLine::BOTTOM );
SetLine( rBox.GetLeft(), SvxBoxItemLine::LEFT );
@@ -1685,6 +1687,7 @@ bool SvxBoxItem::operator==( const SfxPoolItem& rAttr ) const
( nBottomDist == rBoxItem.nBottomDist ) &&
( nLeftDist == rBoxItem.nLeftDist ) &&
( nRightDist == rBoxItem.nRightDist ) &&
+ ( bRemoveAdjCellBorder == rBoxItem.bRemoveAdjCellBorder ) &&
CmpBrdLn( pTop, rBoxItem.GetTop() ) &&
CmpBrdLn( pBottom, rBoxItem.GetBottom() ) &&
CmpBrdLn( pLeft, rBoxItem.GetLeft() ) &&
diff --git a/include/editeng/boxitem.hxx b/include/editeng/boxitem.hxx
index 7b1efd8..563a1b5 100644
--- a/include/editeng/boxitem.hxx
+++ b/include/editeng/boxitem.hxx
@@ -60,6 +60,7 @@ class EDITENG_DLLPUBLIC SvxBoxItem : public SfxPoolItem
nBottomDist,
nLeftDist,
nRightDist;
+ bool bRemoveAdjCellBorder;
public:
static SfxPoolItem* CreateDefault();
@@ -100,9 +101,13 @@ public:
sal_uInt16 GetDistance( SvxBoxItemLine nLine ) const;
sal_uInt16 GetDistance() const;
+ bool IsRemoveAdjacentCellBorder() const { return bRemoveAdjCellBorder; }
+
void SetDistance( sal_uInt16 nNew, SvxBoxItemLine nLine );
inline void SetDistance( sal_uInt16 nNew );
+ void SetRemoveAdjacentCellBorder( bool bSet = true ) { bRemoveAdjCellBorder = bSet; }
+
// Line width plus Space plus inward distance
// bIgnoreLine = TRUE -> Also return distance, when no Line is set
sal_uInt16 CalcLineSpace( SvxBoxItemLine nLine, bool bIgnoreLine = false ) const;
diff --git a/sc/inc/markdata.hxx b/sc/inc/markdata.hxx
index 20777a6..6e3eafc 100644
--- a/sc/inc/markdata.hxx
+++ b/sc/inc/markdata.hxx
@@ -21,6 +21,7 @@
#define INCLUDED_SC_INC_MARKDATA_HXX
#include "address.hxx"
+#include "rangelst.hxx"
#include "scdllapi.h"
#include <set>
@@ -55,6 +56,11 @@ private:
bool bMarking:1; // area is being marked -> no MarkToMulti
bool bMarkIsNeg:1; // cancel if multi selection
+ ScRangeList aTopEnvelope; // list of ranges in the top envelope of the multi selection
+ ScRangeList aBottomEnvelope; // list of ranges in the bottom envelope of the multi selection
+ ScRangeList aLeftEnvelope; // list of ranges in the left envelope of the multi selection
+ ScRangeList aRightEnvelope; // list of ranges in the right envelope of the multi selection
+
public:
ScMarkData();
@@ -122,6 +128,15 @@ public:
void InsertTab( SCTAB nTab );
void DeleteTab( SCTAB nTab );
+ // Generate envelopes if mutimarked and fills the passed ScRange object with
+ // the smallest range that includes the marked area plus its envelopes.
+ void GetSelectionCover( ScRange& rRange );
+ // Get top, bottom, left and right envelopes
+ const ScRangeList& GetTopEnvelope() const { return aTopEnvelope; }
+ const ScRangeList& GetBottomEnvelope() const { return aBottomEnvelope; }
+ const ScRangeList& GetLeftEnvelope() const { return aLeftEnvelope; }
+ const ScRangeList& GetRightEnvelope() const { return aRightEnvelope; }
+
// iterators for table access
typedef std::set<SCTAB>::iterator iterator;
typedef std::set<SCTAB>::const_iterator const_iterator;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 5225443..129695a 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5591,6 +5591,86 @@ void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
}
}
}
+ if( pLineOuter && pLineOuter->IsRemoveAdjacentCellBorder() )
+ {
+ SvxBoxItem aTmp0( *pLineOuter );
+ aTmp0.SetLine( NULL, SvxBoxItemLine::TOP );
+ aTmp0.SetLine( NULL, SvxBoxItemLine::BOTTOM );
+ aTmp0.SetLine( NULL, SvxBoxItemLine::LEFT );
+ aTmp0.SetLine( NULL, SvxBoxItemLine::RIGHT );
+ SvxBoxItem aLeft( aTmp0 );
+ SvxBoxItem aRight( aTmp0 );
+ SvxBoxItem aTop( aTmp0 );
+ SvxBoxItem aBottom( aTmp0 );
+
+ SvxBoxInfoItem aTmp1( *pLineInner );
+ aTmp1.SetTable( false );
+ aTmp1.SetLine( NULL, SvxBoxInfoItemLine::HORI );
+ aTmp1.SetLine( NULL, SvxBoxInfoItemLine::VERT );
+ aTmp1.SetValid( SvxBoxInfoItemValidFlags::ALL, false );
+ aTmp1.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, true );
+ SvxBoxInfoItem aLeftInfo( aTmp1 );
+ SvxBoxInfoItem aRightInfo( aTmp1 );
+ SvxBoxInfoItem aTopInfo( aTmp1 );
+ SvxBoxInfoItem aBottomInfo( aTmp1 );
+
+ if( pLineInner->IsValid( SvxBoxInfoItemValidFlags::TOP ) && !pLineOuter->GetTop() )
+ aTopInfo.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, true );
+
+ if( pLineInner->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) && !pLineOuter->GetBottom() )
+ aBottomInfo.SetValid( SvxBoxInfoItemValidFlags::TOP, true );
+
+ if( pLineInner->IsValid( SvxBoxInfoItemValidFlags::LEFT ) && !pLineOuter->GetLeft() )
+ aLeftInfo.SetValid( SvxBoxInfoItemValidFlags::RIGHT, true );
+
+ if( pLineInner->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) && !pLineOuter->GetRight() )
+ aRightInfo.SetValid( SvxBoxInfoItemValidFlags::LEFT, true );
+
+ const ScRangeList& rRangeListTopEnvelope = rMark.GetTopEnvelope();
+ const ScRangeList& rRangeListBottomEnvelope = rMark.GetBottomEnvelope();
+ const ScRangeList& rRangeListLeftEnvelope = rMark.GetLeftEnvelope();
+ const ScRangeList& rRangeListRightEnvelope = rMark.GetRightEnvelope();
+
+ ScMarkData::const_iterator itr1 = rMark.begin(), itrEnd1 = rMark.end();
+ for ( ; itr1 != itrEnd1 && *itr1 < nMax; ++itr1 )
+ {
+ if ( maTabs[*itr1] )
+ {
+ size_t nEnvelopeRangeCount = rRangeListTopEnvelope.size();
+ for ( size_t j=0; j < nEnvelopeRangeCount; j++ )
+ {
+ const ScRange* pRange = rRangeListTopEnvelope[ j ];
+ maTabs[*itr1]->ApplyBlockFrame( &aTop, &aTopInfo,
+ pRange->aStart.Col(), pRange->aStart.Row(),
+ pRange->aEnd.Col(), pRange->aEnd.Row() );
+ }
+ nEnvelopeRangeCount = rRangeListBottomEnvelope.size();
+ for ( size_t j=0; j < nEnvelopeRangeCount; j++ )
+ {
+ const ScRange* pRange = rRangeListBottomEnvelope[ j ];
+ maTabs[*itr1]->ApplyBlockFrame( &aBottom, &aBottomInfo,
+ pRange->aStart.Col(), pRange->aStart.Row(),
+ pRange->aEnd.Col(), pRange->aEnd.Row() );
+ }
+ nEnvelopeRangeCount = rRangeListLeftEnvelope.size();
+ for ( size_t j=0; j < nEnvelopeRangeCount; j++ )
+ {
+ const ScRange* pRange = rRangeListLeftEnvelope[ j ];
+ maTabs[*itr1]->ApplyBlockFrame( &aLeft, &aLeftInfo,
+ pRange->aStart.Col(), pRange->aStart.Row(),
+ pRange->aEnd.Col(), pRange->aEnd.Row() );
+ }
+ nEnvelopeRangeCount = rRangeListRightEnvelope.size();
+ for ( size_t j=0; j < nEnvelopeRangeCount; j++ )
+ {
+ const ScRange* pRange = rRangeListRightEnvelope[ j ];
+ maTabs[*itr1]->ApplyBlockFrame( &aRight, &aRightInfo,
+ pRange->aStart.Col(), pRange->aStart.Row(),
+ pRange->aEnd.Col(), pRange->aEnd.Row() );
+ }
+ }
+ }
+ }
}
void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx
index 137a2e4..b8eaac7 100644
--- a/sc/source/core/data/markdata.cxx
+++ b/sc/source/core/data/markdata.cxx
@@ -20,8 +20,10 @@
#include "markdata.hxx"
#include "markarr.hxx"
#include "rangelst.hxx"
+#include "segmenttree.hxx"
#include <columnspanset.hxx>
#include <fstalgorithm.hxx>
+#include <unordered_map>
#include <osl/diagnose.h>
@@ -40,7 +42,11 @@ ScMarkData::ScMarkData(const ScMarkData& rData) :
maTabMarked( rData.maTabMarked ),
aMarkRange( rData.aMarkRange ),
aMultiRange( rData.aMultiRange ),
- pMultiSel( nullptr )
+ pMultiSel( nullptr ),
+ aTopEnvelope( rData.aTopEnvelope ),
+ aBottomEnvelope( rData.aBottomEnvelope ),
+ aLeftEnvelope( rData.aLeftEnvelope ),
+ aRightEnvelope( rData.aRightEnvelope )
{
bMarked = rData.bMarked;
bMultiMarked = rData.bMultiMarked;
@@ -69,6 +75,10 @@ ScMarkData& ScMarkData::operator=(const ScMarkData& rData)
bMultiMarked = rData.bMultiMarked;
bMarking = rData.bMarking;
bMarkIsNeg = rData.bMarkIsNeg;
+ aTopEnvelope = rData.aTopEnvelope;
+ aBottomEnvelope = rData.aBottomEnvelope;
+ aLeftEnvelope = rData.aLeftEnvelope;
+ aRightEnvelope = rData.aRightEnvelope;
maTabMarked = rData.maTabMarked;
@@ -94,6 +104,10 @@ void ScMarkData::ResetMark()
bMarked = bMultiMarked = false;
bMarking = bMarkIsNeg = false;
+ aTopEnvelope.RemoveAll();
+ aBottomEnvelope.RemoveAll();
+ aLeftEnvelope.RemoveAll();
+ aRightEnvelope.RemoveAll();
}
void ScMarkData::SetMarkArea( const ScRange& rRange )
@@ -553,6 +567,257 @@ void ScMarkData::DeleteTab( SCTAB nTab )
maTabMarked.swap(tabMarked);
}
+static void lcl_AddRanges(ScRange& rRangeDest, const ScRange& rNewRange )
+{
+ SCCOL nStartCol = rNewRange.aStart.Col();
+ SCROW nStartRow = rNewRange.aStart.Row();
+ SCCOL nEndCol = rNewRange.aEnd.Col();
+ SCROW nEndRow = rNewRange.aEnd.Row();
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartCol, nEndCol );
+ if ( nStartCol < rRangeDest.aStart.Col() )
+ rRangeDest.aStart.SetCol( nStartCol );
+ if ( nStartRow < rRangeDest.aStart.Row() )
+ rRangeDest.aStart.SetRow( nStartRow );
+ if ( nEndCol > rRangeDest.aEnd.Col() )
+ rRangeDest.aEnd.SetCol( nEndCol );
+ if ( nEndRow > rRangeDest.aEnd.Row() )
+ rRangeDest.aEnd.SetRow( nEndRow );
+}
+
+void ScMarkData::GetSelectionCover( ScRange& rRange )
+{
+ if( bMultiMarked )
+ {
+ rRange = aMultiRange;
+ SCCOL nStartCol = aMultiRange.aStart.Col(), nEndCol = aMultiRange.aEnd.Col();
+ PutInOrder( nStartCol, nEndCol );
+ nStartCol = ( nStartCol == 0 ) ? nStartCol : nStartCol - 1;
+ nEndCol = ( nEndCol == MAXCOL ) ? nEndCol : nEndCol + 1;
+ std::unique_ptr<ScFlatBoolRowSegments> pPrevColMarkedRows;
+ std::unique_ptr<ScFlatBoolRowSegments> pCurColMarkedRows;
+ std::unordered_map<SCROW,ScFlatBoolColSegments> aRowToColSegmentsInTopEnvelope;
+ std::unordered_map<SCROW,ScFlatBoolColSegments> aRowToColSegmentsInBottomEnvelope;
+ ScFlatBoolRowSegments aNoRowsMarked;
+ aNoRowsMarked.setFalse( 0, MAXROW );
+
+ const ScMarkArray* pArray = pMultiSel;
+ bool bPrevColUnMarked = false;
+
+ for ( SCCOL nCol=nStartCol; nCol <= nEndCol; nCol++ )
+ {
+ SCROW nTop, nBottom;
+ bool bCurColUnMarked = !pArray[nCol].HasMarks();
+ if ( !bCurColUnMarked )
+ {
+ pCurColMarkedRows.reset( new ScFlatBoolRowSegments() );
+ pCurColMarkedRows->setFalse( 0, MAXROW );
+ ScMarkArrayIter aMarkIter( pArray + nCol );
+ ScFlatBoolRowSegments::ForwardIterator aPrevItr ( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked ); // For finding left envelope
+ ScFlatBoolRowSegments::ForwardIterator aPrevItr1( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked ); // For finding right envelope
+ SCROW nTopPrev = 0, nBottomPrev = 0; // For right envelope
+ while ( aMarkIter.Next( nTop, nBottom ) )
+ {
+ pCurColMarkedRows->setTrue( nTop, nBottom );
+ if( bPrevColUnMarked && ( nCol > nStartCol ))
+ {
+ ScRange aAddRange(nCol - 1, nTop, aMultiRange.aStart.Tab(),
+ nCol - 1, nBottom, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Left envelope
+ aLeftEnvelope.Append( aAddRange );
+ }
+ else if( nCol > nStartCol )
+ {
+ SCROW nTop1 = nTop, nBottom1 = nTop;
+ while( nTop1 <= nBottom && nBottom1 <= nBottom )
+ {
+ bool bRangeMarked = false;
+ aPrevItr.getValue( nTop1, bRangeMarked );
+ if( bRangeMarked )
+ {
+ nTop1 = aPrevItr.getLastPos() + 1;
+ nBottom1 = nTop1;
+ }
+ else
+ {
+ nBottom1 = aPrevItr.getLastPos();
+ if( nBottom1 > nBottom )
+ nBottom1 = nBottom;
+ ScRange aAddRange( nCol - 1, nTop1, aMultiRange.aStart.Tab(),
+ nCol - 1, nBottom1, aMultiRange.aStart.Tab() );
+ lcl_AddRanges( rRange, aAddRange ); // Left envelope
+ aLeftEnvelope.Append( aAddRange );
+ nTop1 = ++nBottom1;
+ }
+ }
+ while( nTopPrev <= nBottom && nBottomPrev <= nBottom )
+ {
+ bool bRangeMarked;
+ aPrevItr1.getValue( nTopPrev, bRangeMarked );
+ if( bRangeMarked )
+ {
+ nBottomPrev = aPrevItr1.getLastPos();
+ if( nTopPrev < nTop )
+ {
+ if( nBottomPrev >= nTop )
+ {
+ nBottomPrev = nTop - 1;
+ ScRange aAddRange( nCol, nTopPrev, aMultiRange.aStart.Tab(),
+ nCol, nBottomPrev, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Right envelope
+ aRightEnvelope.Append( aAddRange );
+ nTopPrev = nBottomPrev = (nBottom + 1);
+ }
+ else
+ {
+ ScRange aAddRange( nCol, nTopPrev, aMultiRange.aStart.Tab(),
+ nCol, nBottomPrev, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Right envelope
+ aRightEnvelope.Append( aAddRange );
+ nTopPrev = ++nBottomPrev;
+ }
+ }
+ else
+ nTopPrev = nBottomPrev = ( nBottom + 1 );
+ }
+ else
+ {
+ nBottomPrev = aPrevItr1.getLastPos();
+ nTopPrev = ++nBottomPrev;
+ }
+ }
+ }
+ if( nTop )
+ {
+ ScRange aAddRange( nCol, nTop - 1, aMultiRange.aStart.Tab(),
+ nCol, nTop - 1, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Top envelope
+ aRowToColSegmentsInTopEnvelope[nTop - 1].setTrue( nCol, nCol );
+ }
+ if( nBottom < MAXROW )
+ {
+ ScRange aAddRange(nCol, nBottom + 1, aMultiRange.aStart.Tab(),
+ nCol, nBottom + 1, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Bottom envelope
+ aRowToColSegmentsInBottomEnvelope[nBottom + 1].setTrue( nCol, nCol );
+ }
+ }
+
+ while( nTopPrev <= MAXROW && nBottomPrev <= MAXROW && ( nCol > nStartCol ) )
+ {
+ bool bRangeMarked;
+ aPrevItr1.getValue( nTopPrev, bRangeMarked );
+ if( bRangeMarked )
+ {
+ nBottomPrev = aPrevItr1.getLastPos();
+ ScRange aAddRange(nCol, nTopPrev, aMultiRange.aStart.Tab(),
+ nCol, nBottomPrev, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Right envelope
+ aRightEnvelope.Append( aAddRange );
+ nTopPrev = ++nBottomPrev;
+ }
+ else
+ {
+ nBottomPrev = aPrevItr1.getLastPos();
+ nTopPrev = ++nBottomPrev;
+ }
+ }
+ }
+ else if( nCol > nStartCol )
+ {
+ bPrevColUnMarked = true;
+ SCROW nTopPrev = 0, nBottomPrev = 0;
+ bool bRangeMarked = false;
+ ScFlatBoolRowSegments::ForwardIterator aPrevItr( pPrevColMarkedRows.get() ? *pPrevColMarkedRows : aNoRowsMarked );
+ while( nTopPrev <= MAXROW && nBottomPrev <= MAXROW )
+ {
+ aPrevItr.getValue(nTopPrev, bRangeMarked);
+ if( bRangeMarked )
+ {
+ nBottomPrev = aPrevItr.getLastPos();
+ ScRange aAddRange(nCol, nTopPrev, aMultiRange.aStart.Tab(),
+ nCol, nBottomPrev, aMultiRange.aStart.Tab());
+ lcl_AddRanges( rRange, aAddRange ); // Right envelope
+ aRightEnvelope.Append( aAddRange );
+ nTopPrev = ++nBottomPrev;
+ }
+ else
+ {
+ nBottomPrev = aPrevItr.getLastPos();
+ nTopPrev = ++nBottomPrev;
+ }
+ }
+ }
+ if ( bCurColUnMarked )
+ pPrevColMarkedRows.reset( nullptr );
+ else
+ pPrevColMarkedRows.reset( pCurColMarkedRows.release() );
+ }
+ for( auto& rKV : aRowToColSegmentsInTopEnvelope )
+ {
+ SCCOL nStart = nStartCol;
+ ScFlatBoolColSegments::RangeData aRange;
+ while( nStart <= nEndCol )
+ {
+ if( !rKV.second.getRangeData( nStart, aRange ) )
+ break;
+ if( aRange.mbValue ) // is marked
+ aTopEnvelope.Append( ScRange( aRange.mnCol1, rKV.first, aMultiRange.aStart.Tab(),
+ aRange.mnCol2, rKV.first, aMultiRange.aStart.Tab() ) );
+ nStart = aRange.mnCol2 + 1;
+ }
+ }
+ for( auto& rKV : aRowToColSegmentsInBottomEnvelope )
+ {
+ SCCOL nStart = nStartCol;
+ ScFlatBoolColSegments::RangeData aRange;
+ while( nStart <= nEndCol )
+ {
+ if( !rKV.second.getRangeData( nStart, aRange ) )
+ break;
+ if( aRange.mbValue ) // is marked
+ aBottomEnvelope.Append( ScRange( aRange.mnCol1, rKV.first, aMultiRange.aStart.Tab(),
+ aRange.mnCol2, rKV.first, aMultiRange.aStart.Tab() ) );
+ nStart = aRange.mnCol2 + 1;
+ }
+ }
+ }
+ else if( bMarked )
+ {
+ aMarkRange.PutInOrder();
+ SCROW nRow1, nRow2, nRow1New, nRow2New;
+ SCCOL nCol1, nCol2, nCol1New, nCol2New;
+ SCTAB nTab1, nTab2;
+ aMarkRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ nCol1New = nCol1;
+ nCol2New = nCol2;
+ nRow1New = nRow1;
+ nRow2New = nRow2;
+ // Each envelope will have zero or more ranges for single rectangle selection.
+ if( nCol1 > 0 )
+ {
+ aLeftEnvelope.Append( ScRange( nCol1 - 1, nRow1, nTab1, nCol1 - 1, nRow2, nTab2 ) );
+ --nCol1New;
+ }
+ if( nRow1 > 0 )
+ {
+ aTopEnvelope.Append( ScRange( nCol1, nRow1 - 1, nTab1, nCol2, nRow1 - 1, nTab2 ) );
+ --nRow1New;
+ }
+ if( nCol2 < MAXCOL )
+ {
+ aRightEnvelope.Append( ScRange( nCol2 + 1, nRow1, nTab1, nCol2 + 1, nRow2, nTab2 ) );
+ ++nCol2New;
+ }
+ if( nRow2 < MAXROW )
+ {
+ aBottomEnvelope.Append( ScRange( nCol1, nRow2 + 1, nTab1, nCol2, nRow2 + 1, nTab2 ) );
+ ++nRow2New;
+ }
+ rRange = ScRange( nCol1New, nRow1New, nTab1, nCol2New, nRow2New, nTab2 );
+ }
+}
+
//iterators
ScMarkData::iterator ScMarkData::begin()
{
diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx
index 2bafcdd..3187163 100644
--- a/sc/source/ui/inc/undoblk.hxx
+++ b/sc/source/ui/inc/undoblk.hxx
@@ -322,7 +322,8 @@ public:
ScDocument* pNewUndoDoc, bool bNewMulti,
const ScPatternAttr* pNewApply,
const SvxBoxItem* pNewOuter = nullptr,
- const SvxBoxInfoItem* pNewInner = nullptr );
+ const SvxBoxInfoItem* pNewInner = nullptr,
+ const ScRange* pRangeCover = nullptr );
virtual ~ScUndoSelectionAttr();
virtual void Undo() override;
@@ -336,6 +337,7 @@ public:
private:
ScMarkData aMarkData;
ScRange aRange;
+ ScRange aRangeCover;
std::unique_ptr<ScEditDataArray> mpDataArray;
ScDocument* pUndoDoc;
bool bMulti;
diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx
index f7e0e28..aa04576 100644
--- a/sc/source/ui/undo/undoblk3.cxx
+++ b/sc/source/ui/undo/undoblk3.cxx
@@ -349,7 +349,8 @@ ScUndoSelectionAttr::ScUndoSelectionAttr( ScDocShell* pNewDocShell,
SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
ScDocument* pNewUndoDoc, bool bNewMulti,
const ScPatternAttr* pNewApply,
- const SvxBoxItem* pNewOuter, const SvxBoxInfoItem* pNewInner )
+ const SvxBoxItem* pNewOuter, const SvxBoxInfoItem* pNewInner,
+ const ScRange* pRangeCover )
: ScSimpleUndo( pNewDocShell ),
aMarkData ( rMark ),
aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
@@ -361,6 +362,7 @@ ScUndoSelectionAttr::ScUndoSelectionAttr( ScDocShell* pNewDocShell,
pApplyPattern = const_cast<ScPatternAttr*>(static_cast<const ScPatternAttr*>( &pPool->Put( *pNewApply ) ));
pLineOuter = pNewOuter ? const_cast<SvxBoxItem*>(static_cast<const SvxBoxItem*>( &pPool->Put( *pNewOuter ) )) : nullptr;
pLineInner = pNewInner ? const_cast<SvxBoxInfoItem*>(static_cast<const SvxBoxInfoItem*>( &pPool->Put( *pNewInner ) )) : nullptr;
+ aRangeCover = pRangeCover ? *pRangeCover : aRange;
}
ScUndoSelectionAttr::~ScUndoSelectionAttr()
@@ -392,7 +394,7 @@ void ScUndoSelectionAttr::DoChange( const bool bUndo )
SetViewMarkData( aMarkData );
- ScRange aEffRange( aRange );
+ ScRange aEffRange( aRangeCover );
if ( rDoc.HasAttrib( aEffRange, HASATTR_MERGED ) ) // merged cells?
rDoc.ExtendMerge( aEffRange );
@@ -403,7 +405,7 @@ void ScUndoSelectionAttr::DoChange( const bool bUndo )
if (bUndo) // only for Undo
{
- ScRange aCopyRange = aRange;
+ ScRange aCopyRange = aRangeCover;
SCTAB nTabCount = rDoc.GetTableCount();
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index ebcee5d..cb140c8 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1019,7 +1019,10 @@ void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem
if (bRecord && !pDoc->IsUndoEnabled())
bRecord = false;
- ScRange aMarkRange;
+ bool bRemoveAdjCellBorder = false;
+ if( pNewOuter )
+ bRemoveAdjCellBorder = pNewOuter->IsRemoveAdjacentCellBorder();
+ ScRange aMarkRange, aMarkRangeWithEnvelope;
aFuncMark.MarkToSimple();
bool bMulti = aFuncMark.IsMultiMarked();
if (bMulti)
@@ -1035,6 +1038,10 @@ void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem
aFuncMark.SetMarkArea(aMarkRange);
MarkDataChanged();
}
+ if( bRemoveAdjCellBorder )
+ aFuncMark.GetSelectionCover( aMarkRangeWithEnvelope );
+ else
+ aMarkRangeWithEnvelope = aMarkRange;
ScDocShell* pDocSh = GetViewData().GetDocShell();
@@ -1045,31 +1052,34 @@ void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem
ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
SCTAB nStartTab = aMarkRange.aStart.Tab();
SCTAB nTabCount = pDoc->GetTableCount();
+ bool bCopyOnlyMarked = false;
+ if( !bRemoveAdjCellBorder )
+ bCopyOnlyMarked = bMulti;
pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
ScMarkData::iterator itr = aFuncMark.begin(), itrEnd = aFuncMark.end();
for (; itr != itrEnd; ++itr)
if (*itr != nStartTab)
pUndoDoc->AddUndoTab( *itr, *itr );
- ScRange aCopyRange = aMarkRange;
+ ScRange aCopyRange = aMarkRangeWithEnvelope;
aCopyRange.aStart.SetTab(0);
aCopyRange.aEnd.SetTab(nTabCount-1);
- pDoc->CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, bMulti, pUndoDoc, &aFuncMark );
+ pDoc->CopyToDocument( aCopyRange, InsertDeleteFlags::ATTRIB, bCopyOnlyMarked, pUndoDoc, &aFuncMark );
pDocSh->GetUndoManager()->AddUndoAction(
new ScUndoSelectionAttr(
pDocSh, aFuncMark,
aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
- pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
+ pUndoDoc, bCopyOnlyMarked, &rAttr, pNewOuter, pNewInner, &aMarkRangeWithEnvelope ) );
}
sal_uInt16 nExt = SC_PF_TESTMERGE;
- pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
+ pDocSh->UpdatePaintExt( nExt, aMarkRangeWithEnvelope ); // content before the change
pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
- pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
+ pDocSh->UpdatePaintExt( nExt, aMarkRangeWithEnvelope ); // content after the change
aFuncMark.MarkToMulti();
pDoc->ApplySelectionPattern( rAttr, aFuncMark );
More information about the Libreoffice-commits
mailing list