summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>2018-02-27 16:56:44 +0100
committerEike Rathke <erack@redhat.com>2018-03-13 00:23:40 +0100
commit4f29ce6a67b81e7f28e1c86d60ff15ec1d180661 (patch)
tree1b6095f1c1805fe084ac106c52d3748f9fce8783
parenta1a60f79c6ffccfd49034a6251031e1f9a0c63a0 (diff)
tdf#114552 Improve image scaling in Calc
When anchor type "To cell (resize with cell)" is selected, we do now:: 1. Consider aspect ratio when scaling graphic objects with cell This only works when the image fits into one cell. When the image is over multiple cells, we need to respect the end anchor, so we need to keep the existing behavior (no aspect ratio considered). 2. Always scale images if anchor type is "resize with cell" Previously it would only scale if the image is larger than the cell. Now we always enlarge the image if the cell is enlarged, and shrink the image if the cell is shrinked _and_ the image no longer fits into the shrinked cell Change-Id: Ib2a24819d0058bcebce73ea97bbf70a963d74584 Reviewed-on: https://gerrit.libreoffice.org/50451 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Eike Rathke <erack@redhat.com>
-rw-r--r--sc/inc/drwlayer.hxx1
-rw-r--r--sc/inc/userdat.hxx21
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx22
-rw-r--r--sc/qa/unit/subsequent_filters-test.cxx2
-rw-r--r--sc/qa/unit/ucalc.cxx8
-rw-r--r--sc/source/core/data/drwlayer.cxx154
-rw-r--r--sc/source/core/data/table5.cxx10
-rw-r--r--sc/source/ui/view/drawvie3.cxx2
8 files changed, 167 insertions, 53 deletions
diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx
index 123463855a25..5f695160cc42 100644
--- a/sc/inc/drwlayer.hxx
+++ b/sc/inc/drwlayer.hxx
@@ -184,6 +184,7 @@ public:
static void SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell );
static void UpdateCellAnchorFromPositionEnd( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect = true );
static ScAnchorType GetAnchorType( const SdrObject& );
+ std::vector<SdrObject*> GetObjectsAnchoredToRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow);
std::map<SCROW, std::vector<SdrObject*>> GetObjectsAnchoredToRange(SCTAB nTab, SCCOL nCol, SCROW nStartRow, SCROW nEndRow);
bool HasObjectsAnchoredInRange(ScRange& rRange);
void MoveObject(SdrObject* pObj, ScAddress& rNewPosition);
diff --git a/sc/inc/userdat.hxx b/sc/inc/userdat.hxx
index fd903dfc1010..04c6893faded 100644
--- a/sc/inc/userdat.hxx
+++ b/sc/inc/userdat.hxx
@@ -25,6 +25,7 @@
#include <svtools/imap.hxx>
#include "global.hxx"
#include "address.hxx"
+#include "drwlayer.hxx"
// Object IDs for UserData
#define SC_UD_OBJDATA 1
@@ -41,13 +42,31 @@ public:
Point maStartOffset;
Point maEndOffset;
Type meType;
- tools::Rectangle maLastRect;
bool mbResizeWithCell = false;
+ bool mbWasInHiddenRow = false;
explicit ScDrawObjData();
+ tools::Rectangle getShapeRect() { return maShapeRect; };
+ tools::Rectangle getLastCellRect() { return maLastCellRect; };
+ void setShapeRect(const ScDocument* rDoc, tools::Rectangle rNewRect, bool bIsVisible=true)
+ {
+ // bIsVisible should be false when the object is hidden obviously. we dont want to store the old cell rect in that
+ // case because it will have height=0
+ if (maStart.IsValid() && mbResizeWithCell && bIsVisible)
+ maLastCellRect = ScDrawLayer::GetCellRect(*rDoc, maStart, true);
+ maShapeRect = rNewRect;
+ mbWasInHiddenRow = !bIsVisible;
+ };
+
private:
virtual ScDrawObjData* Clone( SdrObject* pObj ) const override;
+
+ // Stores the last cell rect this shape was anchored to.
+ // Needed when the cell is resized to resize the image accordingly.
+ tools::Rectangle maLastCellRect;
+ // Stores the rect of the shape to which this ScDrawObjData belongs.
+ tools::Rectangle maShapeRect;
};
class ScIMapInfo : public SdrObjUserData
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 688378166014..26b925d14a16 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -2166,7 +2166,7 @@ void ScExportTest::testCellAnchoredGroupXLS()
ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
CPPUNIT_ASSERT_MESSAGE("Upper left of bounding rectangle should be nonnegative.",
- pData->maLastRect.Left() >= 0 || pData->maLastRect.Top() >= 0);
+ pData->getShapeRect().Left() >= 0 || pData->getShapeRect().Top() >= 0);
xDocSh->DoClose();
}
@@ -3529,7 +3529,7 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get anchor data
ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
ScAddress aDataStart = pData->maStart;
ScAddress aDataEnd = pData->maEnd;
@@ -3537,7 +3537,7 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get non rotated anchor data
ScDrawObjData* pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
ScAddress aNDataStart = pNData->maStart;
ScAddress aNDataEnd = pNData->maEnd;
@@ -3550,12 +3550,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get anchor data
pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
// Get non rotated anchor data
pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
// Check if data has moved to new rows
CPPUNIT_ASSERT_EQUAL( pData->maStart.Row(), aDataStart.Row() + 2 );
@@ -3591,12 +3591,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get anchor data
pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
// Get non rotated anchor data
pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
// Check if data after save it
CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
@@ -3611,12 +3611,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get anchor data
pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
// Get non rotated anchor data
pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
// Check if data has moved to new rows
CPPUNIT_ASSERT_EQUAL(pData->maStart.Col(), SCCOL(aDataStart.Col() + 1));
@@ -3652,12 +3652,12 @@ void ScExportTest::testMoveCellAnchoredShapesODS()
// Get anchor data
pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
// Get non rotated anchor data
pNData = ScDrawLayer::GetNonRotatedObjData( pObj );
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve non rotated user data for this object.", pNData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pNData->getShapeRect().IsEmpty());
// Check if data after save it
CPPUNIT_ASSERT_EQUAL(pData->maStart, aDataStart);
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 3ec2982ada04..2e876434ce49 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -1761,7 +1761,7 @@ void ScFiltersTest::testCellAnchoredShapesODS()
CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve user data for this object.", pData);
- CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->maLastRect.IsEmpty());
+ CPPUNIT_ASSERT_MESSAGE("Bounding rectangle should have been calculated upon import.", !pData->getShapeRect().IsEmpty());
}
xDocSh->DoClose();
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 2b03df58ad9f..0f60db22a8ba 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2732,13 +2732,17 @@ void Test::testGraphicsInGroup()
m_pDoc->ShowRows(0, 100, 0, false);
m_pDoc->SetDrawPageSize(0);
+
+ const long TOLERANCE = 30; //30 hmm
+
CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
- aOrigRect.Left() == rNewRect.Left() && aOrigRect.Right() == rNewRect.Right());
+ testEqualsWithTolerance(aOrigRect.Left(), rNewRect.Left(), TOLERANCE) &&
+ testEqualsWithTolerance(aOrigRect.Right(), rNewRect.Right(), TOLERANCE));
CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
(rNewRect.Bottom() - rNewRect.Top()) <= 1);
m_pDoc->ShowRows(0, 100, 0, true);
m_pDoc->SetDrawPageSize(0);
- CPPUNIT_ASSERT_EQUAL_MESSAGE("Should not change when page anchored",
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Should not change when cell anchored",
const_cast<const tools::Rectangle &>(aOrigRect), rNewRect);
}
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 341444525220..3cadfdb55979 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -624,40 +624,96 @@ namespace
static_cast<long>(aRange.getMaxX()), static_cast<long>(aRange.getMaxY()));
}
}
-void ScDrawLayer::ResizeLastRectFromAnchor( const SdrObject* pObj, ScDrawObjData& rData, bool bUseLogicRect, bool bNegativePage, bool bCanResize, bool bHiddenAsZero )
+
+void ScDrawLayer::ResizeLastRectFromAnchor(const SdrObject* pObj, ScDrawObjData& rData,
+ bool bUseLogicRect, bool bNegativePage, bool bCanResize,
+ bool bHiddenAsZero)
{
- rData.maLastRect = ( bUseLogicRect ? pObj->GetLogicRect() : pObj->GetSnapRect() );
+ tools::Rectangle aRect = bUseLogicRect ? pObj->GetLogicRect() : pObj->GetSnapRect();
SCCOL nCol1 = rData.maStart.Col();
SCROW nRow1 = rData.maStart.Row();
SCTAB nTab1 = rData.maStart.Tab();
SCCOL nCol2 = rData.maEnd.Col();
SCROW nRow2 = rData.maEnd.Row();
SCTAB nTab2 = rData.maEnd.Tab();
- Point aPos( pDoc->GetColOffset( nCol1, nTab1, bHiddenAsZero ), pDoc->GetRowOffset( nRow1, nTab1, bHiddenAsZero ) );
- aPos.setX(TwipsToHmm( aPos.X() ));
- aPos.setY(TwipsToHmm( aPos.Y() ));
+ Point aPos(pDoc->GetColOffset(nCol1, nTab1, bHiddenAsZero),
+ pDoc->GetRowOffset(nRow1, nTab1, bHiddenAsZero));
+ aPos.setX(TwipsToHmm(aPos.X()));
+ aPos.setY(TwipsToHmm(aPos.Y()));
aPos += lcl_calcAvailableDiff(*pDoc, nCol1, nRow1, nTab1, rData.maStartOffset);
+ aRect.SetPos(aPos);
- if( bCanResize )
+ if (bCanResize)
{
- Point aEnd( pDoc->GetColOffset( nCol2, nTab2, bHiddenAsZero ), pDoc->GetRowOffset( nRow2, nTab2, bHiddenAsZero ) );
- aEnd.setX(TwipsToHmm( aEnd.X() ));
- aEnd.setY(TwipsToHmm( aEnd.Y() ));
- aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
+ tools::Rectangle aLastCellRect = rData.getLastCellRect();
- tools::Rectangle aNew = tools::Rectangle( aPos, aEnd );
- if ( bNegativePage )
- MirrorRectRTL( aNew );
+ // If the row was hidden before, or we don't have a valid cell rect, calculate the
+ // new rect based on the end point.
+ // Also when the end point is set, we need to consider it.
+ if (rData.mbWasInHiddenRow || aLastCellRect.IsEmpty() || nRow1 != nRow2 || nCol1 != nCol2)
+ {
+ Point aEnd(pDoc->GetColOffset(nCol2, nTab2, bHiddenAsZero),
+ pDoc->GetRowOffset(nRow2, nTab2, bHiddenAsZero));
+ aEnd.setX(TwipsToHmm(aEnd.X()));
+ aEnd.setY(TwipsToHmm(aEnd.Y()));
+ aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
- rData.maLastRect = lcl_makeSafeRectangle(aNew);
- }
- else
- {
- if ( bNegativePage )
- aPos.setX( -aPos.X() - rData.maLastRect.GetWidth() );
- // shouldn't we initialise maLastRect with the object rectangle ?
- rData.maLastRect.SetPos( aPos );
+ aRect = tools::Rectangle(aPos, aEnd);
+ }
+ else if (!aLastCellRect.IsEmpty())
+ {
+ // We calculate based on the last cell rect to be able to scale the image
+ // as much as the cell was scaled.
+ // Still, we keep the image in its current cell (to keep start anchor == end anchor)
+ tools::Rectangle aCurrentCellRect = GetCellRect(*GetDocument(), rData.maStart, true);
+ double fWidthFactor = static_cast<double>(aCurrentCellRect.GetWidth())
+ / static_cast<double>(aLastCellRect.GetWidth());
+ double fHeightFactor = static_cast<double>(aCurrentCellRect.GetHeight())
+ / static_cast<double>(aLastCellRect.GetHeight());
+
+ bool bIsGrowingLarger = aLastCellRect.GetWidth() * aLastCellRect.GetHeight()
+ < aCurrentCellRect.GetWidth() * aCurrentCellRect.GetHeight();
+
+ if (pObj->shouldKeepAspectRatio())
+ {
+ tools::Rectangle aRectIncludingOffset = aRect;
+ aRectIncludingOffset.setWidth(aRect.GetWidth() + rData.maStartOffset.X());
+ aRectIncludingOffset.setHeight(aRect.GetHeight() + rData.maStartOffset.Y());
+ double fMaxWidthFactor = static_cast<double>(aCurrentCellRect.GetWidth())
+ / static_cast<double>(aRectIncludingOffset.GetWidth());
+ double fMaxHeightFactor = static_cast<double>(aCurrentCellRect.GetHeight())
+ / static_cast<double>(aRectIncludingOffset.GetHeight());
+ double fMaxFactor = std::min(fMaxHeightFactor, fMaxWidthFactor);
+
+ if (bIsGrowingLarger) // cell is growing larger
+ {
+ // To actually grow the image, we need to take the max
+ fWidthFactor = fHeightFactor = std::max(fWidthFactor, fHeightFactor);
+ // But we don't want the image to become larger than the current cell
+ fWidthFactor = fHeightFactor = std::min(fWidthFactor, fMaxFactor);
+ }
+ else // cell is growing smaller, take the min
+ {
+ fWidthFactor = fHeightFactor = std::min(fWidthFactor, fHeightFactor);
+ }
+ }
+
+ // When shrinking the cell, and the image still fits in the smaller cell, don't resize it at all
+ if (bIsGrowingLarger
+ || rData.getShapeRect().GetUnion(aCurrentCellRect) != aCurrentCellRect)
+ {
+ aRect.setWidth(
+ rtl::math::round(static_cast<double>(aRect.GetWidth()) * fWidthFactor));
+ aRect.setHeight(
+ rtl::math::round(static_cast<double>(aRect.GetHeight()) * fHeightFactor));
+ }
+ }
}
+
+ if (bNegativePage)
+ MirrorRectRTL(aRect);
+
+ rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect), pObj->IsVisible());
}
void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos )
@@ -695,7 +751,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (rData.meType == ScDrawObjData::ValidationCircle)
{
// Validation circle for detective.
- rData.maLastRect = pObj->GetLogicRect();
+ rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
aPos.setX(TwipsToHmm( aPos.X() ));
@@ -717,13 +773,13 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
{
if (bRecording)
AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
- rData.maLastRect = lcl_makeSafeRectangle(aRect);
- pObj->SetLogicRect(rData.maLastRect);
+ rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect));
+ pObj->SetLogicRect(rData.getShapeRect());
}
}
else if (rData.meType == ScDrawObjData::DetectiveArrow)
{
- rData.maLastRect = pObj->GetLogicRect();
+ rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
basegfx::B2DPolygon aCalcPoly;
Point aOrigStartPos(pObj->GetPoint(0));
Point aOrigEndPos(pObj->GetPoint(1));
@@ -750,7 +806,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (bRecording)
AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
- rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
+ rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
pObj->SetPoint( aStartPos, 0 );
}
@@ -766,7 +822,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (bRecording)
AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
- rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
+ rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
pObj->SetPoint( aEndPos, 1 );
}
}
@@ -788,7 +844,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (bRecording)
AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
- rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
+ rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
pObj->SetPoint( aEndPos, 1 );
}
@@ -806,7 +862,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if (bRecording)
AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
- rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
+ rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
pObj->SetPoint( aStartPos, 0 );
}
}
@@ -821,7 +877,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
//First time positioning, must be able to at least move it
ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData( pObj, true );
- if (rData.maLastRect.IsEmpty())
+ if (rData.getShapeRect().IsEmpty())
{
// Every shape it is saved with an negative offset relative to cell
ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType(*pObj);
@@ -881,7 +937,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
// is guaranteed to get consistent results)
ResizeLastRectFromAnchor( pObj, rData, true, bNegativePage, bCanResize, false );
// aFullRect contains the unrotated size and position of the shape (regardless of any hidden row/columns)
- tools::Rectangle aFullRect = rData.maLastRect;
+ tools::Rectangle aFullRect = rData.getShapeRect();
// get current size and position from the anchor for use later
ResizeLastRectFromAnchor( pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize );
@@ -894,7 +950,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
// an Anchor based on the SnapRect ( which is what you see on the screen )
ScDrawLayer::GetCellAnchorFromPosition( *pObj, rData, *pDoc, nTab1, false, false );
// reset shape to true 'maybe affected by hidden rows/cols' size calculated previously
- pObj->SetLogicRect(rNoRotatedAnchor.maLastRect);
+ pObj->SetLogicRect(rNoRotatedAnchor.getShapeRect());
}
// update anchor with snap rect
@@ -902,7 +958,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
if( bCanResize )
{
- tools::Rectangle aNew = rData.maLastRect;
+ tools::Rectangle aNew = rData.getShapeRect();
if ( pObj->GetSnapRect() != aNew )
{
@@ -924,8 +980,8 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
}
// order of these lines is important, modify rData.maLastRect carefully it is used as both
// a value and a flag for initialisation
- rData.maLastRect = lcl_makeSafeRectangle(rData.maLastRect);
- pObj->SetSnapRect(rData.maLastRect);
+ rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(rData.getShapeRect()), pObj->IsVisible());
+ 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 );
@@ -933,7 +989,7 @@ void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegati
}
else
{
- Point aPos( rData.maLastRect.getX(), rData.maLastRect.getY() );
+ Point aPos( rData.getShapeRect().getX(), rData.getShapeRect().getY() );
if ( pObj->GetRelativePos() != aPos )
{
if (bRecording)
@@ -1922,7 +1978,7 @@ void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument
// doing an initialisation hack
if ( ScDrawObjData* pAnchor = GetObjData( &rObj ) )
{
- pAnchor->maLastRect = rObj.GetSnapRect();
+ pAnchor->setShapeRect(&rDoc, rObj.GetSnapRect());
}
}
@@ -2012,6 +2068,30 @@ ScAnchorType ScDrawLayer::GetAnchorType( const SdrObject &rObj )
return SCA_CELL;
}
+std::vector<SdrObject*>
+ScDrawLayer::GetObjectsAnchoredToRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow)
+{
+ SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
+ if (!pPage || pPage->GetObjCount() < 1)
+ return std::vector<SdrObject*>();
+
+ std::vector<SdrObject*> aObjects;
+ SdrObjListIter aIter( *pPage, SdrIterMode::Flat );
+ SdrObject* pObject = aIter.Next();
+ ScRange aRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab);
+ while (pObject)
+ {
+ if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
+ {
+ ScDrawObjData* pObjData = GetObjData(pObject);
+ if (pObjData && aRange.In(pObjData->maStart))
+ aObjects.push_back(pObject);
+ }
+ pObject = aIter.Next();
+ }
+ return aObjects;
+}
+
std::map<SCROW, std::vector<SdrObject*>>
ScDrawLayer::GetObjectsAnchoredToRange(SCTAB nTab, SCCOL nCol, SCROW nStartRow, SCROW nEndRow)
{
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index bae5895ec2a5..41de2787dbef 100644
--- a/sc/source/core/data/table5.cxx
+++ b/sc/source/core/data/table5.cxx
@@ -586,6 +586,16 @@ bool ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
else
bChanged = mpHiddenRows->setFalse(nStartRow, nEndRow);
+ std::vector<SdrObject*> aRowDrawObjects;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer) {
+ aRowDrawObjects = pDrawLayer->GetObjectsAnchoredToRows(GetTab(), nStartRow, nEndRow);
+ for (auto aObj : aRowDrawObjects)
+ {
+ aObj->SetVisible(!bHidden);
+ }
+ }
+
if (bChanged)
{
SetStreamValid(false);
diff --git a/sc/source/ui/view/drawvie3.cxx b/sc/source/ui/view/drawvie3.cxx
index b49acf847132..4be43b1354d1 100644
--- a/sc/source/ui/view/drawvie3.cxx
+++ b/sc/source/ui/view/drawvie3.cxx
@@ -159,7 +159,7 @@ void adjustAnchoredPosition(const SdrHint& rHint, const ScDocument& rDoc, SCTAB
if (pAnchor->meType == ScDrawObjData::CellNote)
return;
- if (pAnchor->maLastRect == pObj->GetSnapRect())
+ if (pAnchor->getShapeRect() == pObj->GetSnapRect())
return;
if (pAnchor->maStart.Tab() != nTab)