summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2021-01-26 14:28:40 +0100
committerRegina Henschel <rb.henschel@t-online.de>2021-02-02 22:06:18 +0100
commit65129e0bc5abfe7afc612eb46f1434e627265a7d (patch)
treeff87893f8cde1a2bebd955f9e5417632bf6b8474 /sc/source/core
parente99608ce752f34ddb6611146c6cf4643c97d62f3 (diff)
tdf#137081, tdf137082 fixes shape handling in RTL sheets
The patch introduces an enum ScObjectHandling as parameter of ScDrawLayer::SetPageSize to distinguish page size changes from show or hide col/row from changes because of sheet flip for RTL. RTL is now handled this way: On save/reload objects are not mirrored but only shifted between positive and negative part of draw page. When a user flips sheet to RTL or back, the objects are mirrored. The 'noRotate' anchor is set to this meaning: maShapeRect contains the logic rectangle of the object at time the anchor was created. It is used to detect position relevant object changes in ScDrawView::Notify(). maStart contains the address of that cell, which is parent element of the object in xml. The logic rectangle need not be in that cell. Handling of DetectiveArrow and CellNote is not changed. Validation circles were not drawn, when switching to RTL mode (no bug report). That is fixed. SetVisualCellAnchored handles 'noRotate' anchor. That anchor is not visible on screen. I have changed the misleading name to SetNonRotatedAnchor. Change-Id: I3dd2d3e37c138c8418369c760293a1f19dddb753 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109959 Reviewed-by: Regina Henschel <rb.henschel@t-online.de> Tested-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/documen9.cxx4
-rw-r--r--sc/source/core/data/document.cxx14
-rw-r--r--sc/source/core/data/drwlayer.cxx162
-rw-r--r--sc/source/core/data/table2.cxx6
4 files changed, 148 insertions, 38 deletions
diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx
index 46d1b1c3750d..f44159d6c436 100644
--- a/sc/source/core/data/documen9.cxx
+++ b/sc/source/core/data/documen9.cxx
@@ -600,8 +600,10 @@ void ScDocument::SetImportingXML( bool bVal )
for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]; nTab++ )
if ( maTabs[nTab]->IsLoadingRTL() )
{
+ // SetLayoutRTL => SetDrawPageSize => ScDrawLayer::SetPageSize, includes RTL-mirroring;
+ // bImportingXML must be cleared first
maTabs[nTab]->SetLoadingRTL( false );
- SetLayoutRTL( nTab, true ); // includes mirroring; bImportingXML must be cleared first
+ SetLayoutRTL( nTab, true, ScObjectHandling::MoveRTLMode );
}
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index be588062c5df..48282126b0fc 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -945,7 +945,7 @@ void ScDocument::SetPendingRowHeights( SCTAB nTab, bool bSet )
maTabs[nTab]->SetPendingRowHeights( bSet );
}
-void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
+void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL, ScObjectHandling eObjectHandling)
{
if ( !(ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab]) )
return;
@@ -961,10 +961,9 @@ void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
}
maTabs[nTab]->SetLayoutRTL( bRTL ); // only sets the flag
- maTabs[nTab]->SetDrawPageSize();
-
- // mirror existing objects:
+ maTabs[nTab]->SetDrawPageSize(true, true, eObjectHandling);
+ // objects are already repositioned via SetDrawPageSize, only writing mode is missing
if (!mpDrawLayer)
return;
@@ -977,14 +976,7 @@ void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
SdrObject* pObject = aIter.Next();
while (pObject)
{
- // objects with ScDrawObjData are re-positioned in SetPageSize,
- // don't mirror again
- ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
- if ( !pData )
- mpDrawLayer->MirrorRTL( pObject );
-
pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB );
-
pObject = aIter.Next();
}
}
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 067b2bc38b0f..3d2eb834a6c0 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -570,7 +570,8 @@ void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SC
}
}
-void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos )
+void ScDrawLayer::SetPageSize(sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos,
+ const ScObjectHandling eObjectHandling)
{
SdrPage* pPage = GetPage(nPageNo);
if (!pPage)
@@ -582,31 +583,65 @@ void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpda
Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() on the views
}
- // Implement Detective lines (adjust to new heights / widths)
- // even if size is still the same
- // (individual rows/columns can have been changed))
-
// Do not call RecalcPos while loading, because row height is not finished, when SetPageSize
// is called first time. Instead the objects are initialized from ScXMLImport::endDocument() and
// RecalcPos is called from there.
if (!pDoc || pDoc->IsImportingXML())
return;
+ // Implement Detective lines (adjust to new heights / widths)
+ // even if size is still the same
+ // (individual rows/columns can have been changed))
+
bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) );
// Disable mass broadcasts from drawing objects' position changes.
bool bWasLocked = isLocked();
setLock(true);
+
const size_t nCount = pPage->GetObjCount();
for ( size_t i = 0; i < nCount; ++i )
{
SdrObject* pObj = pPage->GetObj( i );
ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) );
- if( pData )
- RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
+ if( pData ) // cell anchored
+ {
+ if (pData->meType == ScDrawObjData::DrawingObject
+ || pData->meType == ScDrawObjData::ValidationCircle)
+ {
+ switch (eObjectHandling)
+ {
+ case ScObjectHandling::RecalcPosMode:
+ RecalcPos(pObj, *pData, bNegativePage, bUpdateNoteCaptionPos);
+ break;
+ case ScObjectHandling::MoveRTLMode:
+ MoveRTL(pObj);
+ break;
+ case ScObjectHandling::MirrorRTLMode:
+ MirrorRTL(pObj);
+ break;
+ }
+ }
+ else // DetectiveArrow and CellNote
+ RecalcPos(pObj, *pData, bNegativePage, bUpdateNoteCaptionPos);
+ }
+ else // page anchored
+ {
+ switch (eObjectHandling)
+ {
+ case ScObjectHandling::MoveRTLMode:
+ MoveRTL(pObj);
+ break;
+ case ScObjectHandling::MirrorRTLMode:
+ MirrorRTL(pObj);
+ break;
+ case ScObjectHandling::RecalcPosMode: // does not occur for page anchored shapes
+ break;
+ }
+ }
}
- setLock(bWasLocked);
+ setLock(bWasLocked);
}
namespace
@@ -1177,9 +1212,9 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
else
pObj->SetSnapRect(rData.getShapeRect());
- // update 'unrotated anchor' it's the anchor we persist, it must be kept in sync
- // with the normal Anchor.
- ResizeLastRectFromAnchor(pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize);
+ // The shape rectangle in the 'unrotated' anchor needs to be updated to the changed
+ // object geometry. It is used in adjustAnchoredPosition() in ScDrawView::Notify().
+ rNoRotatedAnchor.setShapeRect(pDoc, pObj->GetLogicRect(), pObj->IsVisible());
}
}
else
@@ -1190,6 +1225,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (bRecording)
AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
pObj->SetRelativePos( aPos );
+ rNoRotatedAnchor.setShapeRect(pDoc, pObj->GetLogicRect(), pObj->IsVisible());
}
}
/*
@@ -1954,6 +1990,10 @@ void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const
void ScDrawLayer::MirrorRTL( SdrObject* pObj )
{
+ OSL_ENSURE( pDoc, "ScDrawLayer::MirrorRTL - missing document" );
+ if( !pDoc )
+ return;
+
sal_uInt16 nIdent = pObj->GetObjIdentifier();
// don't mirror OLE or graphics, otherwise ask the object
@@ -1968,23 +2008,87 @@ void ScDrawLayer::MirrorRTL( SdrObject* pObj )
if (bCanMirror)
{
- Point aRef1( 0, 0 );
- Point aRef2( 0, 1 );
- if (bRecording)
- AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
- pObj->Mirror( aRef1, aRef2 );
+ ScDrawObjData* pData = GetObjData(pObj);
+ if (pData) // cell anchored
+ {
+ // Remember values from positive side.
+ const tools::Rectangle aOldSnapRect = pObj->GetSnapRect();
+ const tools::Rectangle aOldLogicRect = pObj->GetLogicRect();
+ // Generate noRotate anchor if missing.
+ ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj);
+ if (!pNoRotatedAnchor)
+ {
+ ScDrawObjData aNoRotateAnchor;
+ const tools::Rectangle aLogicRect(pObj->GetLogicRect());
+ GetCellAnchorFromPosition(aLogicRect, aNoRotateAnchor,
+ *pDoc, pData->maStart.Tab());
+ aNoRotateAnchor.mbResizeWithCell = pData->mbResizeWithCell;
+ SetNonRotatedAnchor(*pObj, aNoRotateAnchor);
+ }
+ // Mirror object at vertical axis
+ Point aRef1( 0, 0 );
+ Point aRef2( 0, 1 );
+ if (bRecording)
+ AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
+ pObj->Mirror( aRef1, aRef2 );
+
+ // Adapt offsets in pNoRotatedAnchor so, that object will be moved to current position in
+ // save and reload.
+ const tools::Long nInverseShift = aOldSnapRect.Left() + aOldSnapRect.Right();
+ const Point aLogicLT = pObj->GetLogicRect().TopLeft();
+ const Point aMirroredLogicLT = aLogicLT + Point(nInverseShift, 0);
+ const Point aOffsetDiff = aMirroredLogicLT - aOldLogicRect.TopLeft();
+ // new Offsets
+ pNoRotatedAnchor->maStartOffset += aOffsetDiff;
+ pNoRotatedAnchor->maEndOffset += aOffsetDiff;
+ }
+ else // page anchored
+ {
+ Point aRef1( 0, 0 );
+ Point aRef2( 0, 1 );
+ if (bRecording)
+ AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
+ pObj->Mirror( aRef1, aRef2 );
+ }
}
else
{
// Move instead of mirroring:
// New start position is negative of old end position
// -> move by sum of start and end position
- tools::Rectangle aObjRect = pObj->GetLogicRect();
+ tools::Rectangle aObjRect = pObj->GetSnapRect();
Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
if (bRecording)
AddCalcUndo( std::make_unique<SdrUndoMoveObj>( *pObj, aMoveSize ) );
pObj->Move( aMoveSize );
}
+
+ // for cell anchored objects adapt rectangles in anchors
+ ScDrawObjData* pData = GetObjData(pObj);
+ if (pData)
+ {
+ pData->setShapeRect(GetDocument(), pObj->GetSnapRect(), pObj->IsVisible());
+ ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj, true /*bCreate*/);
+ pNoRotatedAnchor->setShapeRect(GetDocument(), pObj->GetLogicRect(), pObj->IsVisible());
+ }
+}
+
+void ScDrawLayer::MoveRTL(SdrObject* pObj)
+{
+ tools::Rectangle aObjRect = pObj->GetSnapRect();
+ Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
+ if (bRecording)
+ AddCalcUndo( std::make_unique<SdrUndoMoveObj>( *pObj, aMoveSize ) );
+ pObj->Move( aMoveSize );
+
+ // for cell anchored objects adapt rectangles in anchors
+ ScDrawObjData* pData = GetObjData(pObj);
+ if (pData)
+ {
+ pData->setShapeRect(GetDocument(), pObj->GetSnapRect(), pObj->IsVisible());
+ ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj, true /*bCreate*/);
+ pNoRotatedAnchor->setShapeRect(GetDocument(), pObj->GetLogicRect(), pObj->IsVisible());
+ }
}
void ScDrawLayer::MirrorRectRTL( tools::Rectangle& rRect )
@@ -2167,7 +2271,7 @@ namespace
}
}
-void ScDrawLayer::SetVisualCellAnchored( SdrObject &rObj, const ScDrawObjData &rAnchor )
+void ScDrawLayer::SetNonRotatedAnchor(SdrObject& rObj, const ScDrawObjData& rAnchor)
{
ScDrawObjData* pAnchor = GetNonRotatedObjData( &rObj, true );
pAnchor->maStart = rAnchor.maStart;
@@ -2235,19 +2339,29 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument
else
aObjRect2 = rObj.GetLogicRect();
- ScDrawObjData aVisAnchor;
+ // Values in XML are so as if it is a LTR sheet. The object is shifted to negative page on loading
+ // so that the snap rectangle appears mirrored. For transformed objects the shifted logic rectangle
+ // is not the mirrored LTR rectangle. We calculate the mirrored LTR rectangle here.
+ if (rDoc.IsNegativePage(nTab))
+ {
+ const tools::Rectangle aSnapRect(rObj.GetSnapRect());
+ aObjRect2.Move(Size(-aSnapRect.Left() - aSnapRect.Right(), 0));
+ MirrorRectRTL(aObjRect2);
+ }
+
+ ScDrawObjData aNoRotatedAnchor;
GetCellAnchorFromPosition(
aObjRect2,
- aVisAnchor,
+ aNoRotatedAnchor,
rDoc,
- nTab, false);
+ nTab);
- aVisAnchor.mbResizeWithCell = bResizeWithCell;
- SetVisualCellAnchored( rObj, aVisAnchor );
+ aNoRotatedAnchor.mbResizeWithCell = bResizeWithCell;
+ SetNonRotatedAnchor( rObj, aNoRotatedAnchor);
// And update maShapeRect. It is used in adjustAnchoredPosition() in ScDrawView::Notify().
if (ScDrawObjData* pAnchor = GetNonRotatedObjData(&rObj))
{
- pAnchor->setShapeRect(&rDoc, rObj.GetSnapRect());
+ pAnchor->setShapeRect(&rDoc, rObj.GetLogicRect());
}
}
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 0ba9421d8265..d25e7ce7c7f4 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -3910,7 +3910,8 @@ void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
// Calculate the size of the sheet and set the size on DrawPage
-void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
+void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos,
+ ScObjectHandling eObjectHandling)
{
ScDrawLayer* pDrawLayer = rDocument.GetDrawLayer();
if( pDrawLayer )
@@ -3926,7 +3927,8 @@ void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos
if ( IsLayoutRTL() ) // IsNegativePage
x = -x;
- pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
+ pDrawLayer->SetPageSize(static_cast<sal_uInt16>(nTab), Size(x, y), bUpdateNoteCaptionPos,
+ eObjectHandling);
}
// #i102616# actions that modify the draw page size count as sheet modification