LibreOffice Module sc (master) 1
drwlayer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <com/sun/star/uno/Reference.hxx>
21#include <com/sun/star/chart/XChartDocument.hpp>
22#include <com/sun/star/chart2/XChartDocument.hpp>
23#include <com/sun/star/embed/XClassifiedObject.hpp>
24#include <com/sun/star/embed/XEmbeddedObject.hpp>
25
26#include <scitems.hxx>
27#include <editeng/eeitem.hxx>
29#include <sot/exchange.hxx>
30#include <svx/objfac3d.hxx>
31#include <svx/xtable.hxx>
32#include <svx/svdoutl.hxx>
33#include <svx/svditer.hxx>
34#include <svx/svdlayer.hxx>
35#include <svx/svdoashp.hxx>
36#include <svx/svdobj.hxx>
37#include <svx/svdocapt.hxx>
38#include <svx/svdomeas.hxx>
39#include <svx/svdoole2.hxx>
40#include <svx/svdopath.hxx>
41#include <svx/svdundo.hxx>
42#include <svx/sdsxyitm.hxx>
43#include <svx/svxids.hrc>
45#include <editeng/unolingu.hxx>
46#include <svx/drawitem.hxx>
47#include <editeng/fhgtitem.hxx>
49#include <sfx2/objsh.hxx>
50#include <svl/itempool.hxx>
51#include <utility>
52#include <vcl/canvastools.hxx>
53#include <vcl/svapp.hxx>
54#include <vcl/settings.hxx>
55#include <tools/globname.hxx>
57#include <osl/diagnose.h>
58
61
62#include <drwlayer.hxx>
63#include <drawpage.hxx>
64#include <global.hxx>
65#include <document.hxx>
66#include <userdat.hxx>
67#include <markdata.hxx>
68#include <globstr.hrc>
69#include <scresid.hxx>
70#include <scmod.hxx>
71#include <postit.hxx>
72#include <attrib.hxx>
73#include <charthelper.hxx>
74#include <table.hxx>
76
77#include <memory>
78#include <algorithm>
79#include <cstdlib>
80
81namespace com::sun::star::embed { class XEmbeddedObject; }
82
83#define DET_ARROW_OFFSET 1000
84
85using namespace ::com::sun::star;
86
87static E3dObjFactory* pF3d = nullptr;
88static sal_uInt16 nInst = 0;
89
91
92bool bDrawIsInUndo = false; //TODO: Member
93
95 const ScAddress& rNS, const ScAddress& rNE ) :
96 SdrUndoObj( *pObjP ),
97 aOldStt( rOS ),
98 aOldEnd( rOE ),
99 aNewStt( rNS ),
100 aNewEnd( rNE )
101{
102}
103
105{
106}
107
109{
111 OSL_ENSURE(pData,"ScUndoObjData: Data missing");
112 if (pData)
113 {
114 pData->maStart = aOldStt;
115 pData->maEnd = aOldEnd;
116 }
117
118 // Undo also an untransformed anchor
120 if (pData)
121 {
122 pData->maStart = aOldStt;
123 pData->maEnd = aOldEnd;
124 }
125}
126
128{
130 OSL_ENSURE(pData,"ScUndoObjData: Data missing");
131 if (pData)
132 {
133 pData->maStart = aNewStt;
134 pData->maEnd = aNewEnd;
135 }
136
137 // Redo also an untransformed anchor
139 if (pData)
140 {
141 pData->maStart = aNewStt;
142 pData->maEnd = aNewEnd;
143 }
144}
145
147 SdrUndoObj( *pObjP ),
148 mpDoc( pDoc ),
149 mnTab( nTab )
150{
153}
154
156{
157}
158
160{
161 // Trigger Object Change
162 if (mxObj->IsInserted() && mxObj->getSdrPageFromSdrObject())
163 {
164 SdrHint aHint(SdrHintKind::ObjectChange, *mxObj);
165 mxObj->getSdrModelFromSdrObject().Broadcast(aHint);
166 }
167
170 else
172}
173
175{
178 else
180
181 // Trigger Object Change
182 if (mxObj->IsInserted() && mxObj->getSdrPageFromSdrObject())
183 {
184 SdrHint aHint(SdrHintKind::ObjectChange, *mxObj);
185 mxObj->getSdrModelFromSdrObject().Broadcast(aHint);
186 }
187}
188
190 nTab( nTabNo )
191{
192}
193
195{
196}
197
199 nTab( nTabNo )
200{
201}
202
204{
205}
206
207#define MAXMM 10000000
208
209
211{
213}
214
216{
217 if (!pClipDoc)
218 return ScRange();
219
220 SCCOL nClipStartX;
221 SCROW nClipStartY;
222 SCCOL nClipEndX;
223 SCROW nClipEndY;
224 pClipDoc->GetClipStart(nClipStartX, nClipStartY);
225 pClipDoc->GetClipArea(nClipEndX, nClipEndY, true);
226 nClipEndX = nClipEndX + nClipStartX;
227 nClipEndY += nClipStartY; // GetClipArea returns the difference
228
229 return ScRange(nClipStartX, nClipStartY, nClipTab, nClipEndX, nClipEndY, nClipTab);
230}
231
232ScDrawLayer::ScDrawLayer( ScDocument* pDocument, OUString _aName ) :
234 nullptr,
235 pGlobalDrawPersist ? pGlobalDrawPersist : (pDocument ? pDocument->GetDocumentShell() : nullptr)),
236 aName(std::move( _aName )),
237 pDoc( pDocument ),
238 bRecording( false ),
239 bAdjustEnabled( true ),
240 bHyphenatorSet( false )
241{
243
244 pGlobalDrawPersist = nullptr; // Only use once
245
246 SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : nullptr;
248 if ( pObjSh )
249 {
250 SetObjectShell( pObjSh );
251
252 // set color table
253 const SvxColorListItem* pColItem = pObjSh->GetItem( SID_COLOR_TABLE );
254 if ( pColItem )
255 pXCol = pColItem->GetColorList();
256 }
257 SetPropertyList( static_cast<XPropertyList *> (pXCol.get()) );
258
260
261 SetScaleUnit(MapUnit::Map100thMM);
262 SfxItemPool& rPool = GetItemPool();
263 rPool.SetDefaultMetric(MapUnit::Map100thMM);
264 SvxFrameDirectionItem aModeItem( SvxFrameDirection::Environment, EE_PARA_WRITINGDIR );
265 rPool.SetPoolDefaultItem( aModeItem );
266
267 // #i33700#
268 // Set shadow distance defaults as PoolDefaultItems. Details see bug.
271
272 // default for script spacing depends on locale, see SdDrawDocument ctor in sd
274 if (MsLangId::isKorean(eOfficeLanguage) || eOfficeLanguage == LANGUAGE_JAPANESE)
275 {
276 // secondary is edit engine pool
278 }
279
280 rPool.FreezeIdRanges(); // the pool is also used directly
281
282 SdrLayerAdmin& rAdmin = GetLayerAdmin();
283 rAdmin.NewLayer("vorne", SC_LAYER_FRONT.get());
284 rAdmin.NewLayer("hinten", SC_LAYER_BACK.get());
285 rAdmin.NewLayer("intern", SC_LAYER_INTERN.get());
286 // tdf#140252 use same name as in ctor of SdrLayerAdmin
288 rAdmin.NewLayer("hidden", SC_LAYER_HIDDEN.get());
289
290 // Set link for URL-Fields
291 ScModule* pScMod = SC_MOD();
292 Outliner& rOutliner = GetDrawOutliner();
293 rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
294
295 Outliner& rHitOutliner = GetHitTestOutliner();
296 rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
297
298 // set FontHeight pool defaults without changing static SdrEngineDefaults
299 SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool();
300 if ( pOutlinerPool )
301 {
302 m_pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
303 m_pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK )); // 12Pt
304 m_pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL )); // 12Pt
305 }
306 SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool();
307 if ( pHitOutlinerPool )
308 {
309 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
310 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK )); // 12Pt
311 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL )); // 12Pt
312 }
313
314 // initial undo mode as in Calc document
315 if( pDoc )
317
318 // URL-Buttons have no handler anymore, all is done by themselves
319
320 if( !nInst++ )
321 {
322 pF3d = new E3dObjFactory;
323 }
324}
325
327{
328 Broadcast(SdrHint(SdrHintKind::ModelCleared));
329
330 ClearModel(true);
331
332 pUndoGroup.reset();
333 if( !--nInst )
334 {
335 delete pF3d;
336 pF3d = nullptr;
337 }
338}
339
341{
342 if (!bHyphenatorSet)
343 {
344 css::uno::Reference< css::linguistic2::XHyphenator >
345 xHyphenator = LinguMgr::GetHyphenator();
346
347 GetDrawOutliner().SetHyphenator( xHyphenator );
348 GetHitTestOutliner().SetHyphenator( xHyphenator );
349
350 bHyphenatorSet = true;
351 }
352}
353
355{
356 return new ScDrawPage(*this, bMasterPage);
357}
358
360{
361 bool bFound = false;
362
363 sal_uInt16 nCount = GetPageCount();
364 for (sal_uInt16 i=0; i<nCount && !bFound; i++)
365 if (GetPage(i)->GetObjCount())
366 bFound = true;
367
368 return bFound;
369}
370
372{
373 // Allocated model (for clipboard etc) must not have a pointer
374 // to the original model's document, pass NULL as document:
375
376 return new ScDrawLayer( nullptr, aName );
377}
378
380{
381 if (bDrawIsInUndo)
382 return false; // not inserted
383
384 rtl::Reference<ScDrawPage> pPage = static_cast<ScDrawPage*>(AllocPage( false ).get());
385 InsertPage(pPage.get(), static_cast<sal_uInt16>(nTab));
386 if (bRecording)
387 AddCalcUndo(std::make_unique<SdrUndoNewPage>(*pPage));
388
389 ResetTab(nTab, pDoc->GetTableCount()-1);
390 return true; // inserted
391}
392
394{
395 if (bDrawIsInUndo)
396 return;
397
398 Broadcast( ScTabDeletedHint( nTab ) );
399 if (bRecording)
400 {
401 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
402 AddCalcUndo(std::make_unique<SdrUndoDelPage>(*pPage)); // Undo-Action becomes the page owner
403 RemovePage( static_cast<sal_uInt16>(nTab) ); // just deliver, not deleting
404 }
405 else
406 DeletePage( static_cast<sal_uInt16>(nTab) ); // just get rid of it
407
408 ResetTab(nTab, pDoc->GetTableCount()-1);
409}
410
411void ScDrawLayer::ScRenamePage( SCTAB nTab, const OUString& rNewName )
412{
413 ScDrawPage* pPage = static_cast<ScDrawPage*>( GetPage(static_cast<sal_uInt16>(nTab)) );
414 if (pPage)
415 pPage->SetName(rNewName);
416}
417
418void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos, sal_uInt16 nNewPos )
419{
420 MovePage( nOldPos, nNewPos );
421 sal_uInt16 nMinPos = std::min(nOldPos, nNewPos);
422 ResetTab(nMinPos, pDoc->GetTableCount()-1);
423}
424
425void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos )
426{
427 if (bDrawIsInUndo)
428 return;
429
430 SdrPage* pOldPage = GetPage(nOldPos);
431 SdrPage* pNewPage = GetPage(nNewPos);
432
433 // Copying
434
435 if (pOldPage && pNewPage)
436 {
437 SCTAB nOldTab = static_cast<SCTAB>(nOldPos);
438 SCTAB nNewTab = static_cast<SCTAB>(nNewPos);
439
440 SdrObjListIter aIter( pOldPage, SdrIterMode::Flat );
441 SdrObject* pOldObject = aIter.Next();
442 while (pOldObject)
443 {
444 ScDrawObjData* pOldData = GetObjData(pOldObject);
445 if (pOldData)
446 {
447 pOldData->maStart.SetTab(nOldTab);
448 pOldData->maEnd.SetTab(nOldTab);
449 }
450
451 // Clone to target SdrModel
452 rtl::Reference<SdrObject> pNewObject(pOldObject->CloneSdrObject(*this));
453 pNewObject->NbcMove(Size(0,0));
454 pNewPage->InsertObject( pNewObject.get() );
455 ScDrawObjData* pNewData = GetObjData(pNewObject.get());
456 if (pNewData)
457 {
458 pNewData->maStart.SetTab(nNewTab);
459 pNewData->maEnd.SetTab(nNewTab);
460 }
461
462 if (bRecording)
463 AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pNewObject ) );
464
465 pOldObject = aIter.Next();
466 }
467 }
468
469 ResetTab(static_cast<SCTAB>(nNewPos), pDoc->GetTableCount()-1);
470}
471
473{
474 SCTAB nPageSize = static_cast<SCTAB>(GetPageCount());
475 if (nPageSize < 0)
476 // No drawing pages exist.
477 return;
478
479 if (nEnd >= nPageSize)
480 // Avoid iterating beyond the last existing page.
481 nEnd = nPageSize - 1;
482
483 for (SCTAB i = nStart; i <= nEnd; ++i)
484 {
485 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(i));
486 if (!pPage)
487 continue;
488
489 SdrObjListIter aIter(pPage, SdrIterMode::Flat);
490 for (SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next())
491 {
493 if (!pData)
494 continue;
495
496 pData->maStart.SetTab(i);
497 pData->maEnd.SetTab(i);
498 }
499 }
500}
501
502static bool IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 )
503{
504 return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 &&
505 rPos.Row() >= nRow1 && rPos.Row() <= nRow2;
506}
507
508void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
509 SCCOL nDx,SCROW nDy, bool bUpdateNoteCaptionPos )
510{
511 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
512 OSL_ENSURE(pPage,"Page not found");
513 if (!pPage)
514 return;
515
516 bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
517
518 const size_t nCount = pPage->GetObjCount();
519 for ( size_t i = 0; i < nCount; ++i )
520 {
521 SdrObject* pObj = pPage->GetObj( i );
522 ScDrawObjData* pData = GetObjDataTab( pObj, nTab );
523 if( pData )
524 {
525 const ScAddress aOldStt = pData->maStart;
526 const ScAddress aOldEnd = pData->maEnd;
527 bool bChange = false;
528 if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) )
529 {
530 pData->maStart.IncCol( nDx );
531 pData->maStart.IncRow( nDy );
532 bChange = true;
533 }
534 if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) )
535 {
536 pData->maEnd.IncCol( nDx );
537 pData->maEnd.IncRow( nDy );
538 bChange = true;
539 }
540 if (bChange)
541 {
542 if ( dynamic_cast<const SdrRectObj*>( pObj) != nullptr && pData->maStart.IsValid() && pData->maEnd.IsValid() )
543 pData->maStart.PutInOrder( pData->maEnd );
544
545 // Update also an untransformed anchor that's what we stored ( and still do ) to xml
546 ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData( pObj );
547 if ( pNoRotatedAnchor )
548 {
549 const ScAddress aOldSttNoRotatedAnchor = pNoRotatedAnchor->maStart;
550 const ScAddress aOldEndNoRotatedAnchor = pNoRotatedAnchor->maEnd;
551 if ( aOldSttNoRotatedAnchor.IsValid() && IsInBlock( aOldSttNoRotatedAnchor, nCol1,nRow1, nCol2,nRow2 ) )
552 {
553 pNoRotatedAnchor->maStart.IncCol(nDx);
554 pNoRotatedAnchor->maStart.IncRow(nDy);
555 }
556 if ( aOldEndNoRotatedAnchor.IsValid() && IsInBlock( aOldEndNoRotatedAnchor, nCol1,nRow1, nCol2,nRow2 ) )
557 {
558 pNoRotatedAnchor->maEnd.IncCol(nDx);
559 pNoRotatedAnchor->maEnd.IncRow(nDy);
560 }
561 }
562
563 AddCalcUndo( std::make_unique<ScUndoObjData>( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ) );
564 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
565 }
566 }
567 }
568}
569
570void ScDrawLayer::SetPageSize(sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos,
571 const ScObjectHandling eObjectHandling)
572{
573 SdrPage* pPage = GetPage(nPageNo);
574 if (!pPage)
575 return;
576
577 if ( rSize != pPage->GetSize() )
578 {
579 pPage->SetSize( rSize );
580 Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() on the views
581 }
582
583 // Do not call RecalcPos while loading, because row height is not finished, when SetPageSize
584 // is called first time. Instead the objects are initialized from ScXMLImport::endDocument() and
585 // RecalcPos is called from there.
586 if (!pDoc || pDoc->IsImportingXML())
587 return;
588
589 // Implement Detective lines (adjust to new heights / widths)
590 // even if size is still the same
591 // (individual rows/columns can have been changed))
592
593 bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) );
594
595 // Disable mass broadcasts from drawing objects' position changes.
596 bool bWasLocked = isLocked();
597 setLock(true);
598
599 const size_t nCount = pPage->GetObjCount();
600 for ( size_t i = 0; i < nCount; ++i )
601 {
602 SdrObject* pObj = pPage->GetObj( i );
603 ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) );
604 if( pData ) // cell anchored
605 {
608 {
609 switch (eObjectHandling)
610 {
612 RecalcPos(pObj, *pData, bNegativePage, bUpdateNoteCaptionPos);
613 break;
615 MoveRTL(pObj);
616 break;
618 MirrorRTL(pObj);
619 break;
620 }
621 }
622 else // DetectiveArrow and CellNote
623 RecalcPos(pObj, *pData, bNegativePage, bUpdateNoteCaptionPos);
624 }
625 else // page anchored
626 {
627 switch (eObjectHandling)
628 {
630 MoveRTL(pObj);
631 break;
633 MirrorRTL(pObj);
634 break;
635 case ScObjectHandling::RecalcPosMode: // does not occur for page anchored shapes
636 break;
637 }
638 }
639 }
640
641 setLock(bWasLocked);
642}
643
644namespace
645{
646 //Can't have a zero width dimension
647 tools::Rectangle lcl_makeSafeRectangle(const tools::Rectangle &rNew)
648 {
649 tools::Rectangle aRect = rNew;
650 if (aRect.Bottom() == aRect.Top())
651 aRect.SetBottom( aRect.Top()+1 );
652 if (aRect.Right() == aRect.Left())
653 aRect.SetRight( aRect.Left()+1 );
654 return aRect;
655 }
656
657 Point lcl_calcAvailableDiff(const ScDocument &rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const Point &aWantedDiff)
658 {
659 Point aAvailableDiff(aWantedDiff);
662 if (aAvailableDiff.Y() > nHeight)
663 aAvailableDiff.setY( nHeight );
664 if (aAvailableDiff.X() > nWidth)
665 aAvailableDiff.setX( nWidth );
666 return aAvailableDiff;
667 }
668
669 tools::Rectangle lcl_UpdateCalcPoly(basegfx::B2DPolygon &rCalcPoly, int nWhichPoint, const Point &rPos)
670 {
671 rCalcPoly.setB2DPoint(nWhichPoint, basegfx::B2DPoint(rPos.X(), rPos.Y()));
673 return tools::Rectangle(static_cast<tools::Long>(aRange.getMinX()), static_cast<tools::Long>(aRange.getMinY()),
674 static_cast<tools::Long>(aRange.getMaxX()), static_cast<tools::Long>(aRange.getMaxY()));
675 }
676
677bool lcl_AreRectanglesApproxEqual(const tools::Rectangle& rRectA, const tools::Rectangle& rRectB)
678{
679 // Twips <-> Hmm conversions introduce +-1 differences although there are no real changes in the object.
680 // Therefore test with == is not appropriate in some cases.
681 if (std::abs(rRectA.Left() - rRectB.Left()) > 1)
682 return false;
683 if (std::abs(rRectA.Top() - rRectB.Top()) > 1)
684 return false;
685 if (std::abs(rRectA.Right() - rRectB.Right()) > 1)
686 return false;
687 if (std::abs(rRectA.Bottom() - rRectB.Bottom()) > 1)
688 return false;
689 return true;
690}
691
692bool lcl_NeedsMirrorYCorrection(const SdrObject* pObj)
693{
694 return pObj->GetObjIdentifier() == SdrObjKind::CustomShape
695 && static_cast<const SdrObjCustomShape*>(pObj)->IsMirroredY();
696}
697
698void lcl_SetLogicRectFromAnchor(SdrObject* pObj, const ScDrawObjData& rAnchor, const ScDocument* pDoc)
699{
700 // This is only used during initialization. At that time, shape handling is always LTR. No need
701 // to consider negative page.
702 if (!pObj || !pDoc || !rAnchor.maEnd.IsValid() || !rAnchor.maStart.IsValid())
703 return;
704
705 // In case of a vertical mirrored custom shape, LibreOffice uses internally an additional 180deg
706 // in aGeo.nRotationAngle and in turn has a different logic rectangle position. We remove flip,
707 // set the logic rectangle, and apply flip again. You cannot simple use a 180deg-rotated
708 // rectangle, because custom shape mirroring is internally applied after the other
709 // transformations.
710 const bool bNeedsMirrorYCorrection = lcl_NeedsMirrorYCorrection(pObj); // remember state
711 if (bNeedsMirrorYCorrection)
712 {
713 const tools::Rectangle aRect(pObj->GetSnapRect());
714 const Point aLeft(aRect.Left(), (aRect.Top() + aRect.Bottom()) >> 1);
715 const Point aRight(aLeft.X() + 1000, aLeft.Y());
716 pObj->NbcMirror(aLeft, aRight);
717 }
718
719 // Build full sized logic rectangle from start and end given in anchor.
720 const tools::Rectangle aStartCellRect(
721 pDoc->GetMMRect(rAnchor.maStart.Col(), rAnchor.maStart.Row(), rAnchor.maStart.Col(),
722 rAnchor.maStart.Row(), rAnchor.maStart.Tab(), false /*bHiddenAsZero*/));
723 Point aStartPoint(aStartCellRect.Left(), aStartCellRect.Top());
724 aStartPoint.AdjustX(rAnchor.maStartOffset.getX());
725 aStartPoint.AdjustY(rAnchor.maStartOffset.getY());
726
727 const tools::Rectangle aEndCellRect(
728 pDoc->GetMMRect(rAnchor.maEnd.Col(), rAnchor.maEnd.Row(), rAnchor.maEnd.Col(),
729 rAnchor.maEnd.Row(), rAnchor.maEnd.Tab(), false /*bHiddenAsZero*/));
730 Point aEndPoint(aEndCellRect.Left(), aEndCellRect.Top());
731 aEndPoint.AdjustX(rAnchor.maEndOffset.getX());
732 aEndPoint.AdjustY(rAnchor.maEndOffset.getY());
733
734 // Set this as new, full sized logical rectangle
735 tools::Rectangle aNewRectangle(aStartPoint, aEndPoint);
736 aNewRectangle.Normalize();
737 if (!lcl_AreRectanglesApproxEqual(pObj->GetLogicRect(), aNewRectangle))
738 pObj->NbcSetLogicRect(lcl_makeSafeRectangle(aNewRectangle));
739
740 // The shape has the correct logical rectangle now. Reapply the above removed mirroring.
741 if (bNeedsMirrorYCorrection)
742 {
743 const tools::Rectangle aRect(pObj->GetSnapRect());
744 const Point aLeft(aRect.Left(), (aRect.Top() + aRect.Bottom()) >> 1);
745 const Point aRight(aLeft.X() + 1000, aLeft.Y());
746 pObj->NbcMirror(aLeft, aRight);
747 }
748}
749
750} // namespace
751
753 bool bNegativePage, bool bCanResize)
754{
755 tools::Rectangle aRect = pObj->GetSnapRect();
756 SCCOL nCol1 = rData.maStart.Col();
757 SCROW nRow1 = rData.maStart.Row();
758 SCTAB nTab1 = rData.maStart.Tab();
759 SCCOL nCol2 = rData.maEnd.Col();
760 SCROW nRow2 = rData.maEnd.Row();
761 SCTAB nTab2 = rData.maEnd.Tab();
762 Point aPos(pDoc->GetColOffset(nCol1, nTab1, /*bHiddenAsZero*/true),
763 pDoc->GetRowOffset(nRow1, nTab1, /*bHiddenAsZero*/true));
764 aPos.setX(convertTwipToMm100(aPos.X()));
765 aPos.setY(convertTwipToMm100(aPos.Y()));
766 aPos += lcl_calcAvailableDiff(*pDoc, nCol1, nRow1, nTab1, rData.maStartOffset);
767
768 // this sets the needed changed position (translation)
769 aRect.SetPos(aPos);
770
771 if (bCanResize)
772 {
773 // all this stuff is additional stuff to evtl. not only translate the
774 // range (Rectangle), but also check for and evtl. do corrections for it's size
775 const tools::Rectangle aLastCellRect(rData.getLastCellRect());
776
777 // If the row was hidden before, or we don't have a valid cell rect, calculate the
778 // new rect based on the end point.
779 // Also when the end point is set, we need to consider it.
780 if (rData.mbWasInHiddenRow || aLastCellRect.IsEmpty() || nRow1 != nRow2 || nCol1 != nCol2)
781 {
782 Point aEnd(pDoc->GetColOffset(nCol2, nTab2, /*bHiddenAsZero*/true),
783 pDoc->GetRowOffset(nRow2, nTab2, /*bHiddenAsZero*/true));
784 aEnd.setX(convertTwipToMm100(aEnd.X()));
785 aEnd.setY(convertTwipToMm100(aEnd.Y()));
786 aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
787
788 aRect = tools::Rectangle(aPos, aEnd);
789 }
790 else if (!aLastCellRect.IsEmpty())
791 {
792 // We calculate based on the last cell rect to be able to scale the image
793 // as much as the cell was scaled.
794 // Still, we keep the image in its current cell (to keep start anchor == end anchor)
795 const tools::Rectangle aCurrentCellRect(GetCellRect(*GetDocument(), rData.maStart, true));
796 tools::Long nCurrentWidth(aCurrentCellRect.GetWidth());
797 tools::Long nCurrentHeight(aCurrentCellRect.GetHeight());
798 const tools::Long nLastWidth(aLastCellRect.GetWidth());
799 const tools::Long nLastHeight(aLastCellRect.GetHeight());
800
801 // tdf#116931 Avoid and correct nifty numerical problems with the integer
802 // based and converted values (GetCellRect uses multiplies with HMM_PER_TWIPS)
803 if(nCurrentWidth + 1 == nLastWidth || nCurrentWidth == nLastWidth + 1)
804 {
805 nCurrentWidth = nLastWidth;
806 }
807
808 if(nCurrentHeight + 1 == nLastHeight || nCurrentHeight == nLastHeight + 1)
809 {
810 nCurrentHeight = nLastHeight;
811 }
812
813 // get initial ScalingFactors
814 double fWidthFactor(nCurrentWidth == nLastWidth || 0 == nLastWidth
815 ? 1.0
816 : static_cast<double>(nCurrentWidth) / static_cast<double>(nLastWidth));
817 double fHeightFactor(nCurrentHeight == nLastHeight || 0 == nLastHeight
818 ? 1.0
819 : static_cast<double>(nCurrentHeight) / static_cast<double>(nLastHeight));
820
821 // check if we grow or shrink - and at all
822 const bool bIsGrowing(nCurrentWidth > nLastWidth || nCurrentHeight > nLastHeight);
823 const bool bIsShrinking(nCurrentWidth < nLastWidth || nCurrentHeight < nLastHeight);
824 const bool bIsSizeChanged(bIsGrowing || bIsShrinking);
825
826 // handle AspectRatio, only needed if size does change
827 if(bIsSizeChanged && pObj->shouldKeepAspectRatio())
828 {
829 tools::Rectangle aRectIncludingOffset = aRect;
830 aRectIncludingOffset.setWidth(aRect.GetWidth() + rData.maStartOffset.X());
831 aRectIncludingOffset.setHeight(aRect.GetHeight() + rData.maStartOffset.Y());
832 tools::Long nWidth = aRectIncludingOffset.GetWidth();
833 assert(nWidth && "div-by-zero");
834 double fMaxWidthFactor = static_cast<double>(nCurrentWidth)
835 / static_cast<double>(nWidth);
836 tools::Long nHeight = aRectIncludingOffset.GetHeight();
837 assert(nHeight && "div-by-zero");
838 double fMaxHeightFactor = static_cast<double>(nCurrentHeight)
839 / static_cast<double>(nHeight);
840 double fMaxFactor = std::min(fMaxHeightFactor, fMaxWidthFactor);
841
842 if(bIsGrowing) // cell is growing larger
843 {
844 // To actually grow the image, we need to take the max
845 fWidthFactor = std::max(fWidthFactor, fHeightFactor);
846 }
847 else if(bIsShrinking) // cell is growing smaller, take the min
848 {
849 fWidthFactor = std::min(fWidthFactor, fHeightFactor);
850 }
851
852 // We don't want the image to become larger than the current cell
853 fWidthFactor = fHeightFactor = std::min(fWidthFactor, fMaxFactor);
854 }
855
856 if(bIsSizeChanged)
857 {
858 // tdf#116931 re-organized scaling (if needed)
859 // Check if we need to scale at all. Always scale on growing.
860 bool bNeedToScale(bIsGrowing);
861
862 if(!bNeedToScale && bIsShrinking)
863 {
864 // Check if original still fits into space. Do *not* forget to
865 // compare with evtl. numerically corrected aCurrentCellRect
866 const bool bFitsInX(aRect.Right() <= aCurrentCellRect.Left() + nCurrentWidth);
867 const bool bFitsInY(aRect.Bottom() <= aCurrentCellRect.Top() + nCurrentHeight);
868
869 // If the image still fits in the smaller cell, don't resize it at all
870 bNeedToScale = (!bFitsInX || !bFitsInY);
871 }
872
873 if(bNeedToScale)
874 {
875 // tdf#116931 use transformations now. Translation is already applied
876 // (see aRect.SetPos above), so only scale needs to be applied - relative
877 // to *new* CellRect (which is aCurrentCellRect).
878 // Prepare scale relative to top-left of aCurrentCellRect
879 basegfx::B2DHomMatrix aChange;
880
881 aChange.translate(-aCurrentCellRect.Left(), -aCurrentCellRect.Top());
882 aChange.scale(fWidthFactor, fHeightFactor);
883 aChange.translate(aCurrentCellRect.Left(), aCurrentCellRect.Top());
884
885 // create B2DRange and transform by prepared scale
887
888 aNewRange.transform(aChange);
889
890 // apply to aRect
891 aRect = tools::Rectangle(
892 basegfx::fround(aNewRange.getMinX()), basegfx::fround(aNewRange.getMinY()),
893 basegfx::fround(aNewRange.getMaxX()), basegfx::fround(aNewRange.getMaxY()));
894 }
895 }
896 }
897 }
898
899 if (bNegativePage)
900 MirrorRectRTL(aRect);
901
902 rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect), pObj->IsVisible());
903}
904
906{
907 // This is called from ScXMLImport::endDocument()
908 if (!pDoc || !pObj)
909 return;
910 if (!rData.getShapeRect().IsEmpty())
911 return; // already initialized, should not happen
914 return; // handled in RecalcPos
915
916 // Prevent multiple broadcasts during the series of changes.
917 bool bWasLocked = pObj->getSdrModelFromSdrObject().isLocked();
918 pObj->getSdrModelFromSdrObject().setLock(true);
919
920 // rNoRotatedAnchor refers in its start and end addresses and its start and end offsets to
921 // the logic rectangle of the object. The values are so, as if no hidden columns and rows
922 // exists and if it is a LTR sheet. These values are directly used for XML in ODF file.
923 ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData(pObj, true /*bCreate*/);
924
925 // From XML import, rData contains temporarily the anchor information as they are given in
926 // XML. Copy it to rNoRotatedAnchor, where it belongs. rData will later contain the anchor
927 // of the transformed object as visible on screen.
928 rNoRotatedAnchor.maStart = rData.maStart;
929 rNoRotatedAnchor.maEnd = rData.maEnd;
930 rNoRotatedAnchor.maStartOffset = rData.maStartOffset;
931 rNoRotatedAnchor.maEndOffset = rData.maEndOffset;
932
933 SCCOL nCol1 = rNoRotatedAnchor.maStart.Col();
934 SCROW nRow1 = rNoRotatedAnchor.maStart.Row();
935 SCTAB nTab1 = rNoRotatedAnchor.maStart.Tab(); // Used as parameter several times
936
937 // Object has coordinates relative to left/top of containing cell in XML. Change object to
938 // absolute coordinates as internally used.
939 const tools::Rectangle aRect(
940 pDoc->GetMMRect(nCol1, nRow1, nCol1, nRow1, nTab1, false /*bHiddenAsZero*/));
941 const Size aShift(aRect.Left(), aRect.Top());
942 pObj->NbcMove(aShift);
943
944 const ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType(*pObj);
945 if (aAnchorType == SCA_CELL_RESIZE)
946 {
947 if (pObj->GetObjIdentifier() == SdrObjKind::Line)
948 {
949 // Horizontal lines might have wrong start and end anchor because of erroneously applied
950 // 180deg rotation (tdf#137446). Other lines have wrong end anchor. Coordinates in
951 // object are correct. Use them for recreating the anchor.
952 const basegfx::B2DPolygon aPoly(
953 static_cast<SdrPathObj*>(pObj)->GetPathPoly().getB2DPolygon(0));
954 const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0));
955 const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1));
956 const Point aPointLT(FRound(std::min(aB2DPoint0.getX(), aB2DPoint1.getX())),
957 FRound(std::min(aB2DPoint0.getY(), aB2DPoint1.getY())));
958 const Point aPointRB(FRound(std::max(aB2DPoint0.getX(), aB2DPoint1.getX())),
959 FRound(std::max(aB2DPoint0.getY(), aB2DPoint1.getY())));
960 const tools::Rectangle aObjRect(aPointLT, aPointRB);
961 GetCellAnchorFromPosition(aObjRect, rNoRotatedAnchor, *pDoc, nTab1,
962 false /*bHiddenAsZero*/);
963 }
964 else if (pObj->GetObjIdentifier() == SdrObjKind::Measure)
965 {
966 // Measure lines might have got wrong start and end anchor from XML import. Recreate
967 // anchor from start and end point.
968 SdrMeasureObj* pMeasureObj = static_cast<SdrMeasureObj*>(pObj);
969 // tdf#137576. The logic rectangle has likely no current values here, but only the
970 // 1cm x 1cm default size. The call of TakeUnrotatedSnapRect is currently (LO 7.2)
971 // the only way to force a recalc of the logic rectangle.
972 tools::Rectangle aObjRect;
973 pMeasureObj->TakeUnrotatedSnapRect(aObjRect);
974 GetCellAnchorFromPosition(aObjRect, rNoRotatedAnchor, *pDoc, rData.maStart.Tab(),
975 false /*bHiddenAsZero*/);
976 }
977 else
978 {
979 // In case there are hidden rows or cols, versions 7.0 and earlier have written width and
980 // height in file so that hidden row or col are count as zero. XML import bases the
981 // logical rectangle of the object on it. Shapes have at least wrong size, when row or col
982 // are shown. We try to regenerate the logic rectangle as far as possible from the anchor.
983 // ODF specifies anyway, that the size has to be ignored, if end cell attributes exist.
984 lcl_SetLogicRectFromAnchor(pObj, rNoRotatedAnchor, pDoc);
985 }
986 }
987 else // aAnchorType == SCA_CELL, other types will not occur here.
988 {
989 // XML has no end cell address in this case. We generate it from position.
990 UpdateCellAnchorFromPositionEnd(*pObj, rNoRotatedAnchor, *pDoc, nTab1,
991 true /*bUseLogicRect*/);
992 }
993
994 // Make sure maShapeRect of rNoRotatedAnchor is not empty. Method ScDrawView::Notify()
995 // needs it to detect a change in object geometry. For example a 180deg rotation effects only
996 // logic rect.
997 rNoRotatedAnchor.setShapeRect(GetDocument(), pObj->GetLogicRect(), true);
998
999 // Start and end addresses and offsets in rData refer to the actual snap rectangle of the
1000 // shape. We initialize them here based on the "full" sized object. Adaptation to reduced size
1001 // (by hidden row/col) is done later in RecalcPos.
1002 GetCellAnchorFromPosition(pObj->GetSnapRect(), rData, *pDoc, nTab1, false /*bHiddenAsZero*/);
1003
1004 // As of ODF 1.3 strict there is no attribute to store whether an object is hidden. So a "visible"
1005 // object might actually be hidden by being in hidden row or column. We detect it here.
1006 // Note, that visibility by hidden row or column refers to the snap rectangle.
1007 if (pObj->IsVisible()
1008 && (pDoc->RowHidden(rData.maStart.Row(), rData.maStart.Tab())
1009 || pDoc->ColHidden(rData.maStart.Col(), rData.maStart.Tab())))
1010 pObj->SetVisible(false);
1011
1012 // Set visibility. ToDo: Really used?
1013 rNoRotatedAnchor.setShapeRect(GetDocument(), pObj->GetLogicRect(), pObj->IsVisible());
1014
1015 // And set maShapeRect in rData. It stores not only the current rectangles, but currently,
1016 // existence of maShapeRect is the flag for initialization is done.
1017 rData.setShapeRect(GetDocument(), pObj->GetSnapRect(), pObj->IsVisible());
1018
1019 pObj->getSdrModelFromSdrObject().setLock(bWasLocked);
1020}
1021
1022void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos )
1023{
1024 OSL_ENSURE( pDoc, "ScDrawLayer::RecalcPos - missing document" );
1025 if( !pDoc )
1026 return;
1027
1028 if (rData.meType == ScDrawObjData::CellNote)
1029 {
1030 OSL_ENSURE( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" );
1031 /* #i109372# On insert/remove rows/columns/cells: Updating the caption
1032 position must not be done, if the cell containing the note has not
1033 been moved yet in the document. The calling code now passes an
1034 additional boolean stating if the cells are already moved. */
1035 if( bUpdateNoteCaptionPos )
1036 /* When inside an undo action, there may be pending note captions
1037 where cell note is already deleted (thus document cannot find
1038 the note object anymore). The caption will be deleted later
1039 with drawing undo. */
1040 if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) )
1041 pNote->UpdateCaptionPos( rData.maStart );
1042 return;
1043 }
1044
1045 bool bValid1 = rData.maStart.IsValid();
1046 SCCOL nCol1 = rData.maStart.Col();
1047 SCROW nRow1 = rData.maStart.Row();
1048 SCTAB nTab1 = rData.maStart.Tab();
1049 bool bValid2 = rData.maEnd.IsValid();
1050 SCCOL nCol2 = rData.maEnd.Col();
1051 SCROW nRow2 = rData.maEnd.Row();
1052 SCTAB nTab2 = rData.maEnd.Tab();
1053
1055 {
1056 // Validation circle for detective.
1057 rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
1058
1059 // rData.maStart should contain the address of the be validated cell.
1060 tools::Rectangle aRect = GetCellRect(*GetDocument(), rData.maStart, true);
1061 aRect.AdjustLeft( -250 );
1062 aRect.AdjustRight(250 );
1063 aRect.AdjustTop( -70 );
1064 aRect.AdjustBottom(70 );
1065 if ( bNegativePage )
1066 MirrorRectRTL( aRect );
1067
1068 if ( pObj->GetLogicRect() != aRect )
1069 {
1070 if (bRecording)
1071 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1072 rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(aRect));
1073 // maStart has the meaning of "to be validated cell" in a validation circle. For usual
1074 // drawing objects it has the meaning "left/top of logic/snap rect". Because the rectangle
1075 // is expanded above, SetLogicRect() will set maStart to one cell left and one cell above
1076 // of the to be validated cell. We need to backup the old value and restore it.
1077 ScAddress aBackup(rData.maStart);
1078 pObj->SetLogicRect(rData.getShapeRect());
1079 rData.maStart = aBackup;
1080 }
1081 }
1082 else if (rData.meType == ScDrawObjData::DetectiveArrow)
1083 {
1084 rData.setShapeRect(GetDocument(), pObj->GetLogicRect());
1085 basegfx::B2DPolygon aCalcPoly;
1086 Point aOrigStartPos(pObj->GetPoint(0));
1087 Point aOrigEndPos(pObj->GetPoint(1));
1088 aCalcPoly.append(basegfx::B2DPoint(aOrigStartPos.X(), aOrigStartPos.Y()));
1089 aCalcPoly.append(basegfx::B2DPoint(aOrigEndPos.X(), aOrigEndPos.Y()));
1090 //TODO: do not create multiple Undos for one object (last one can be omitted then)
1091
1092 SCCOL nLastCol;
1093 SCROW nLastRow;
1094 if( bValid1 )
1095 {
1096 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
1097 if (!pDoc->ColHidden(nCol1, nTab1, nullptr, &nLastCol))
1098 aPos.AdjustX(pDoc->GetColWidth( nCol1, nTab1 ) / 4 );
1099 if (!pDoc->RowHidden(nRow1, nTab1, nullptr, &nLastRow))
1100 aPos.AdjustY(pDoc->GetRowHeight( nRow1, nTab1 ) / 2 );
1101 aPos.setX(convertTwipToMm100(aPos.X()));
1102 aPos.setY(convertTwipToMm100(aPos.Y()));
1103 Point aStartPos = aPos;
1104 if ( bNegativePage )
1105 aStartPos.setX( -aStartPos.X() ); // don't modify aPos - used below
1106 if ( pObj->GetPoint( 0 ) != aStartPos )
1107 {
1108 if (bRecording)
1109 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1110
1111 rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
1112 pObj->SetPoint( aStartPos, 0 );
1113 }
1114
1115 if( !bValid2 )
1116 {
1117 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
1118 if (aEndPos.Y() < 0)
1119 aEndPos.AdjustY(2 * DET_ARROW_OFFSET);
1120 if ( bNegativePage )
1121 aEndPos.setX( -aEndPos.X() );
1122 if ( pObj->GetPoint( 1 ) != aEndPos )
1123 {
1124 if (bRecording)
1125 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1126
1127 rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
1128 pObj->SetPoint( aEndPos, 1 );
1129 }
1130 }
1131 }
1132 if( bValid2 )
1133 {
1134 Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) );
1135 if (!pDoc->ColHidden(nCol2, nTab2, nullptr, &nLastCol))
1136 aPos.AdjustX(pDoc->GetColWidth( nCol2, nTab2 ) / 4 );
1137 if (!pDoc->RowHidden(nRow2, nTab2, nullptr, &nLastRow))
1138 aPos.AdjustY(pDoc->GetRowHeight( nRow2, nTab2 ) / 2 );
1139 aPos.setX(convertTwipToMm100(aPos.X()));
1140 aPos.setY(convertTwipToMm100(aPos.Y()));
1141 Point aEndPos = aPos;
1142 if ( bNegativePage )
1143 aEndPos.setX( -aEndPos.X() ); // don't modify aPos - used below
1144 if ( pObj->GetPoint( 1 ) != aEndPos )
1145 {
1146 if (bRecording)
1147 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1148
1149 rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos));
1150 pObj->SetPoint( aEndPos, 1 );
1151 }
1152
1153 if( !bValid1 )
1154 {
1155 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
1156 if (aStartPos.X() < 0)
1157 aStartPos.AdjustX(2 * DET_ARROW_OFFSET);
1158 if (aStartPos.Y() < 0)
1159 aStartPos.AdjustY(2 * DET_ARROW_OFFSET);
1160 if ( bNegativePage )
1161 aStartPos.setX( -aStartPos.X() );
1162 if ( pObj->GetPoint( 0 ) != aStartPos )
1163 {
1164 if (bRecording)
1165 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1166
1167 rData.setShapeRect(GetDocument(), lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos));
1168 pObj->SetPoint( aStartPos, 0 );
1169 }
1170 }
1171 }
1172 } // end ScDrawObjData::DetectiveArrow
1173 else // start ScDrawObjData::DrawingObject
1174 {
1175 // Do not change hidden objects. That would produce zero height or width and loss of offsets.
1176 if (!pObj->IsVisible())
1177 return;
1178
1179 // Prevent multiple broadcasts during the series of changes.
1180 bool bWasLocked = pObj->getSdrModelFromSdrObject().isLocked();
1181 pObj->getSdrModelFromSdrObject().setLock(true);
1182
1183 bool bCanResize = bValid2 && !pObj->IsResizeProtect() && rData.mbResizeWithCell;
1184
1185 // update anchor with snap rect
1186 ResizeLastRectFromAnchor( pObj, rData, bNegativePage, bCanResize );
1187
1188 ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData( pObj, true /*bCreate*/);
1189
1190 if( bCanResize )
1191 {
1192 tools::Rectangle aNew = rData.getShapeRect();
1193 tools::Rectangle aOld(pObj->GetSnapRect());
1194 if (!lcl_AreRectanglesApproxEqual(aNew, aOld))
1195 {
1196 if (bRecording)
1197 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1198
1199 // ToDo: Implement NbcSetSnapRect of SdrMeasureObj. Then this can be removed.
1200 tools::Long nOldWidth = aOld.GetWidth();
1201 tools::Long nOldHeight = aOld.GetHeight();
1202 if (pObj->IsPolyObj() && nOldWidth && nOldHeight)
1203 {
1204 // Polyline objects need special treatment.
1205 Size aSizeMove(aNew.Left()-aOld.Left(), aNew.Top()-aOld.Top());
1206 pObj->NbcMove(aSizeMove);
1207
1208 double fXFrac = static_cast<double>(aNew.GetWidth()) / static_cast<double>(nOldWidth);
1209 double fYFrac = static_cast<double>(aNew.GetHeight()) / static_cast<double>(nOldHeight);
1210 pObj->NbcResize(aNew.TopLeft(), Fraction(fXFrac), Fraction(fYFrac));
1211 }
1212
1213 rData.setShapeRect(GetDocument(), lcl_makeSafeRectangle(rData.getShapeRect()), pObj->IsVisible());
1214 if (pObj->GetObjIdentifier() == SdrObjKind::CustomShape)
1215 pObj->AdjustToMaxRect(rData.getShapeRect());
1216 else
1217 pObj->SetSnapRect(rData.getShapeRect());
1218
1219 // The shape rectangle in the 'unrotated' anchor needs to be updated to the changed
1220 // object geometry. It is used in adjustAnchoredPosition() in ScDrawView::Notify().
1221 rNoRotatedAnchor.setShapeRect(pDoc, pObj->GetLogicRect(), pObj->IsVisible());
1222 }
1223 }
1224 else
1225 {
1226 const Point aPos(rData.getShapeRect().TopLeft());
1227 if ( pObj->GetRelativePos() != aPos )
1228 {
1229 if (bRecording)
1230 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
1231 pObj->SetRelativePos( aPos );
1232 rNoRotatedAnchor.setShapeRect(pDoc, pObj->GetLogicRect(), pObj->IsVisible());
1233 }
1234 }
1235 /*
1236 * If we were not allowed resize the object, then the end cell anchor
1237 * is possibly incorrect now, and if the object has no end-cell (e.g.
1238 * missing in original .xml) we are also forced to generate one
1239 */
1240 bool bEndAnchorIsBad = !bValid2 || pObj->IsResizeProtect();
1241 if (bEndAnchorIsBad)
1242 {
1243 // update 'rotated' anchor
1244 ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj, rData, *pDoc, nTab1, false);
1245 // update 'unrotated' anchor
1246 ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj, rNoRotatedAnchor, *pDoc, nTab1 );
1247 }
1248
1249 // End prevent multiple broadcasts during the series of changes.
1250 pObj->getSdrModelFromSdrObject().setLock(bWasLocked);
1251 if (!bWasLocked)
1252 pObj->BroadcastObjectChange();
1253 } // end ScDrawObjData::DrawingObject
1254}
1255
1256bool ScDrawLayer::GetPrintArea( ScRange& rRange, bool bSetHor, bool bSetVer ) const
1257{
1258 OSL_ENSURE( pDoc, "ScDrawLayer::GetPrintArea without document" );
1259 if ( !pDoc )
1260 return false;
1261
1262 SCTAB nTab = rRange.aStart.Tab();
1263 OSL_ENSURE( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab differ" );
1264
1265 bool bNegativePage = pDoc->IsNegativePage( nTab );
1266
1267 bool bAny = false;
1268 tools::Long nEndX = 0;
1269 tools::Long nEndY = 0;
1270 tools::Long nStartX = LONG_MAX;
1271 tools::Long nStartY = LONG_MAX;
1272
1273 // Calculate borders
1274
1275 if (!bSetHor)
1276 {
1277 nStartX = 0;
1278 SCCOL nStartCol = rRange.aStart.Col();
1279 SCCOL i;
1280 for (i=0; i<nStartCol; i++)
1281 nStartX +=pDoc->GetColWidth(i,nTab);
1282 nEndX = nStartX;
1283 SCCOL nEndCol = rRange.aEnd.Col();
1284 for (i=nStartCol; i<=nEndCol; i++)
1285 nEndX += pDoc->GetColWidth(i,nTab);
1286 nStartX = convertTwipToMm100(nStartX);
1287 nEndX = convertTwipToMm100(nEndX);
1288 }
1289 if (!bSetVer)
1290 {
1291 nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab);
1292 nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(),
1293 rRange.aEnd.Row(), nTab);
1294 nStartY = convertTwipToMm100(nStartY);
1295 nEndY = convertTwipToMm100(nEndY);
1296 }
1297
1298 if ( bNegativePage )
1299 {
1300 nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work
1301 nEndX = -nEndX;
1302 ::std::swap( nStartX, nEndX );
1303 }
1304
1305 const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1306 OSL_ENSURE(pPage,"Page not found");
1307 if (pPage)
1308 {
1309 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1310 SdrObject* pObject = aIter.Next();
1311 while (pObject)
1312 {
1313 //TODO: test Flags (hidden?)
1314
1315 tools::Rectangle aObjRect = pObject->GetCurrentBoundRect();
1316 bool bFit = true;
1317 if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
1318 bFit = false;
1319 if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
1320 bFit = false;
1321 // #i104716# don't include hidden note objects
1322 if ( bFit && pObject->GetLayer() != SC_LAYER_HIDDEN )
1323 {
1324 if (bSetHor)
1325 {
1326 if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
1327 if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right();
1328 }
1329 if (bSetVer)
1330 {
1331 if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top();
1332 if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
1333 }
1334 bAny = true;
1335 }
1336
1337 pObject = aIter.Next();
1338 }
1339 }
1340
1341 if ( bNegativePage )
1342 {
1343 nStartX = -nStartX; // reverse transformation, so the same cell address calculation works
1344 nEndX = -nEndX;
1345 ::std::swap( nStartX, nEndX );
1346 }
1347
1348 if (bAny)
1349 {
1350 OSL_ENSURE( nStartX<=nEndX && nStartY<=nEndY, "Start/End wrong in ScDrawLayer::GetPrintArea" );
1351
1352 if (bSetHor)
1353 {
1354 nStartX = o3tl::toTwips(nStartX, o3tl::Length::mm100);
1355 nEndX = o3tl::toTwips(nEndX, o3tl::Length::mm100);
1356 tools::Long nWidth;
1357
1358 nWidth = 0;
1359 rRange.aStart.SetCol( 0 );
1360 if (nWidth <= nStartX)
1361 {
1362 for (SCCOL nCol : pDoc->GetColumnsRange(nTab, 0, pDoc->MaxCol()))
1363 {
1364 nWidth += pDoc->GetColWidth(nCol,nTab);
1365 if (nWidth > nStartX)
1366 {
1367 rRange.aStart.SetCol( nCol );
1368 break;
1369 }
1370 }
1371 }
1372
1373 nWidth = 0;
1374 rRange.aEnd.SetCol( 0 );
1375 if (nWidth <= nEndX)
1376 {
1377 for (SCCOL nCol : pDoc->GetColumnsRange(nTab, 0, pDoc->MaxCol())) //TODO: start at Start
1378 {
1379 nWidth += pDoc->GetColWidth(nCol,nTab);
1380 if (nWidth > nEndX)
1381 {
1382 rRange.aEnd.SetCol( nCol );
1383 break;
1384 }
1385 }
1386 }
1387 }
1388
1389 if (bSetVer)
1390 {
1391 nStartY = o3tl::toTwips(nStartY, o3tl::Length::mm100);
1392 nEndY = o3tl::toTwips(nEndY, o3tl::Length::mm100);
1393 SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY);
1394 rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0);
1395 nRow = pDoc->GetRowForHeight( nTab, nEndY);
1396 rRange.aEnd.SetRow( nRow == pDoc->MaxRow() ? pDoc->MaxRow() :
1397 (nRow>0 ? (nRow-1) : 0));
1398 }
1399 }
1400 else
1401 {
1402 if (bSetHor)
1403 {
1404 rRange.aStart.SetCol(0);
1405 rRange.aEnd.SetCol(0);
1406 }
1407 if (bSetVer)
1408 {
1409 rRange.aStart.SetRow(0);
1410 rRange.aEnd.SetRow(0);
1411 }
1412 }
1413 return bAny;
1414}
1415
1416void ScDrawLayer::AddCalcUndo( std::unique_ptr<SdrUndoAction> pUndo )
1417{
1418 if (bRecording)
1419 {
1420 if (!pUndoGroup)
1421 pUndoGroup.reset(new SdrUndoGroup(*this));
1422
1423 pUndoGroup->AddAction( std::move(pUndo) );
1424 }
1425}
1426
1427void ScDrawLayer::BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager)
1428{
1429 SetDisableTextEditUsesCommonUndoManager(bDisableTextEditUsesCommonUndoManager);
1430 pUndoGroup.reset();
1431 bRecording = true;
1432}
1433
1434std::unique_ptr<SdrUndoGroup> ScDrawLayer::GetCalcUndo()
1435{
1436 std::unique_ptr<SdrUndoGroup> pRet = std::move(pUndoGroup);
1437 bRecording = false;
1439 return pRet;
1440}
1441
1442void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
1443 SCCOL nDx,SCROW nDy, bool bInsDel, bool bUpdateNoteCaptionPos )
1444{
1445 OSL_ENSURE( pDoc, "ScDrawLayer::MoveArea without document" );
1446 if ( !pDoc )
1447 return;
1448
1449 if (!bAdjustEnabled)
1450 return;
1451
1452 bool bNegativePage = pDoc->IsNegativePage( nTab );
1453
1454 tools::Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1455 lcl_ReverseTwipsToMM( aRect );
1456 //TODO: use twips directly?
1457
1458 Point aMove;
1459
1460 if (nDx > 0)
1461 for (SCCOL s=0; s<nDx; s++)
1462 aMove.AdjustX(pDoc->GetColWidth(s+nCol1,nTab) );
1463 else
1464 for (SCCOL s=-1; s>=nDx; s--)
1465 aMove.AdjustX( -(pDoc->GetColWidth(s+nCol1,nTab)) );
1466 if (nDy > 0)
1467 aMove.AdjustY(pDoc->GetRowHeight( nRow1, nRow1+nDy-1, nTab) );
1468 else
1469 aMove.AdjustY( -sal_Int16(pDoc->GetRowHeight( nRow1+nDy, nRow1-1, nTab)) );
1470
1471 if ( bNegativePage )
1472 aMove.setX( -aMove.X() );
1473
1474 Point aTopLeft = aRect.TopLeft(); // Beginning when zoomed out
1475 if (bInsDel)
1476 {
1477 if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL
1478 aTopLeft.AdjustX(aMove.X() );
1479 if ( aMove.Y() < 0 )
1480 aTopLeft.AdjustY(aMove.Y() );
1481 }
1482
1483 // Detectiv arrows: Adjust cell position
1484
1485 MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy, bUpdateNoteCaptionPos );
1486}
1487
1488bool ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
1489{
1490 OSL_ENSURE( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
1491 if ( !pDoc )
1492 return false;
1493
1494 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1495 OSL_ENSURE(pPage,"Page not found");
1496 if (!pPage)
1497 return false;
1498
1499 // for an empty page, there's no need to calculate the row heights
1500 if (!pPage->GetObjCount())
1501 return false;
1502
1503 tools::Rectangle aTestRect;
1504
1505 aTestRect.AdjustTop(pDoc->GetRowHeight( 0, nStartRow-1, nTab) );
1506
1507 if (nEndRow==pDoc->MaxRow())
1508 aTestRect.SetBottom( MAXMM );
1509 else
1510 {
1511 aTestRect.SetBottom( aTestRect.Top() );
1512 aTestRect.AdjustBottom(pDoc->GetRowHeight( nStartRow, nEndRow, nTab) );
1513 aTestRect.SetBottom(convertTwipToMm100(aTestRect.Bottom()));
1514 }
1515
1516 aTestRect.SetTop(convertTwipToMm100(aTestRect.Top()));
1517
1518 aTestRect.SetLeft( 0 );
1519 aTestRect.SetRight( MAXMM );
1520
1521 bool bNegativePage = pDoc->IsNegativePage( nTab );
1522 if ( bNegativePage )
1523 MirrorRectRTL( aTestRect );
1524
1525 bool bFound = false;
1526
1527 tools::Rectangle aObjRect;
1528 SdrObjListIter aIter( pPage );
1529 SdrObject* pObject = aIter.Next();
1530 while ( pObject && !bFound )
1531 {
1532 aObjRect = pObject->GetSnapRect(); //TODO: GetLogicRect ?
1533 if (aTestRect.Contains(aObjRect.TopLeft()) || aTestRect.Contains(aObjRect.BottomLeft()))
1534 bFound = true;
1535
1536 pObject = aIter.Next();
1537 }
1538
1539 return bFound;
1540}
1541
1543 SCCOL nCol2,SCROW nRow2, bool bAnchored )
1544{
1545 OSL_ENSURE( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" );
1546 if ( !pDoc )
1547 return;
1548
1549 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1550 OSL_ENSURE(pPage,"Page ?");
1551 if (!pPage)
1552 return;
1553
1554 pPage->RecalcObjOrdNums();
1555
1556 const size_t nObjCount = pPage->GetObjCount();
1557 if (!nObjCount)
1558 return;
1559
1560 tools::Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1561 tools::Rectangle aDelCircle = aDelRect;
1562 aDelCircle.AdjustLeft(-250);
1563 aDelCircle.AdjustRight(250);
1564 aDelCircle.AdjustTop(-70);
1565 aDelCircle.AdjustBottom(70);
1566
1567 std::vector<SdrObject*> ppObj;
1568 ppObj.reserve(nObjCount);
1569
1570 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1571 SdrObject* pObject = aIter.Next();
1572 while (pObject)
1573 {
1574 // do not delete note caption, they are always handled by the cell note
1575 // TODO: detective objects are still deleted, is this desired?
1576 if (!IsNoteCaption( pObject ))
1577 {
1578 tools::Rectangle aObjRect;
1580 if (pObjData && pObjData->meType == ScDrawObjData::ValidationCircle)
1581 {
1582 aObjRect = pObject->GetLogicRect();
1583 if(aDelCircle.Contains(aObjRect))
1584 ppObj.push_back(pObject);
1585 }
1586 else
1587 {
1588 aObjRect = pObject->GetCurrentBoundRect();
1589 if (aDelRect.Contains(aObjRect))
1590 {
1591 if (bAnchored)
1592 {
1594 if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
1595 ppObj.push_back(pObject);
1596 }
1597 else
1598 ppObj.push_back(pObject);
1599 }
1600 }
1601 }
1602
1603 pObject = aIter.Next();
1604 }
1605
1606 if (bRecording)
1607 for (auto p : ppObj)
1608 AddCalcUndo(std::make_unique<SdrUndoDelObj>(*p));
1609
1610 for (auto p : ppObj)
1611 pPage->RemoveObject(p->GetOrdNum());
1612}
1613
1615{
1616 OSL_ENSURE( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" );
1617 if ( !pDoc )
1618 return;
1619
1620 if ( !rMark.IsMultiMarked() )
1621 return;
1622
1623 const ScRange& aMarkRange = rMark.GetMultiMarkArea();
1624
1625 SCTAB nTabCount = pDoc->GetTableCount();
1626 for (const SCTAB nTab : rMark)
1627 {
1628 if (nTab >= nTabCount)
1629 break;
1630
1631 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1632 if (pPage)
1633 {
1634 pPage->RecalcObjOrdNums();
1635 const size_t nObjCount = pPage->GetObjCount();
1636 if (nObjCount)
1637 {
1638 // Rectangle around the whole selection
1639 tools::Rectangle aMarkBound = pDoc->GetMMRect(
1640 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1641 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
1642
1643 std::vector<SdrObject*> ppObj;
1644 ppObj.reserve(nObjCount);
1645
1646 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1647 SdrObject* pObject = aIter.Next();
1648 while (pObject)
1649 {
1650 // do not delete note caption, they are always handled by the cell note
1651 // TODO: detective objects are still deleted, is this desired?
1652 if (!IsNoteCaption( pObject ))
1653 {
1654 tools::Rectangle aObjRect = pObject->GetCurrentBoundRect();
1655 ScRange aRange = pDoc->GetRange(nTab, aObjRect);
1656 bool bObjectInMarkArea =
1657 aMarkBound.Contains(aObjRect) && rMark.IsAllMarked(aRange);
1660 bool bObjectAnchoredToMarkedCell
1661 = ((aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
1662 && pObjData && pObjData->maStart.IsValid()
1663 && rMark.IsCellMarked(pObjData->maStart.Col(),
1664 pObjData->maStart.Row()));
1665 if (bObjectInMarkArea || bObjectAnchoredToMarkedCell)
1666 {
1667 ppObj.push_back(pObject);
1668 }
1669 }
1670
1671 pObject = aIter.Next();
1672 }
1673
1674 // Delete objects (backwards)
1675
1676 if (bRecording)
1677 for (auto p : ppObj)
1678 AddCalcUndo(std::make_unique<SdrUndoDelObj>(*p));
1679
1680 for (auto p : ppObj)
1681 pPage->RemoveObject(p->GetOrdNum());
1682 }
1683 }
1684 else
1685 {
1686 OSL_FAIL("pPage?");
1687 }
1688 }
1689}
1690
1691void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const tools::Rectangle& rRange )
1692{
1693 // copy everything in the specified range into the same page (sheet) in the clipboard doc
1694
1695 SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab));
1696 if (!pSrcPage)
1697 return;
1698
1699 ScDrawLayer* pDestModel = nullptr;
1700 SdrPage* pDestPage = nullptr;
1701
1702 SdrObjListIter aIter( pSrcPage, SdrIterMode::Flat );
1703 SdrObject* pOldObject = aIter.Next();
1704 while (pOldObject)
1705 {
1706 tools::Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1707
1708 bool bObjectInArea = rRange.Contains(aObjRect);
1709 const ScDrawObjData* pObjData = ScDrawLayer::GetObjData(pOldObject);
1710 if (pObjData)
1711 {
1712 ScRange aClipRange = lcl_getClipRangeFromClipDoc(pClipDoc, nTab);
1713 bObjectInArea = bObjectInArea || aClipRange.Contains(pObjData->maStart);
1714 }
1715
1716 // do not copy internal objects (detective) and note captions
1717 if (bObjectInArea && pOldObject->GetLayer() != SC_LAYER_INTERN
1718 && !IsNoteCaption(pOldObject))
1719 {
1720 if ( !pDestModel )
1721 {
1722 pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer?
1723 if ( !pDestModel )
1724 {
1725 // allocate drawing layer in clipboard document only if there are objects to copy
1726
1727 pClipDoc->InitDrawLayer(); //TODO: create contiguous pages
1728 pDestModel = pClipDoc->GetDrawLayer();
1729 }
1730 if (pDestModel)
1731 pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) );
1732 }
1733
1734 OSL_ENSURE( pDestPage, "no page" );
1735 if (pDestPage)
1736 {
1737 // Clone to target SdrModel
1738 rtl::Reference<SdrObject> pNewObject(pOldObject->CloneSdrObject(*pDestModel));
1739
1740 uno::Reference< chart2::XChartDocument > xOldChart( ScChartHelper::GetChartFromSdrObject( pOldObject ) );
1741 if(!xOldChart.is())//#i110034# do not move charts as they lose all their data references otherwise
1742 pNewObject->NbcMove(Size(0,0));
1743 pDestPage->InsertObject( pNewObject.get() );
1744
1745 // no undo needed in clipboard document
1746 // charts are not updated
1747 }
1748 }
1749
1750 pOldObject = aIter.Next();
1751 }
1752}
1753
1754static bool lcl_IsAllInRange( const ::std::vector< ScRangeList >& rRangesVector, const ScRange& rClipRange )
1755{
1756 // check if every range of rRangesVector is completely in rClipRange
1757
1758 for( const ScRangeList& rRanges : rRangesVector )
1759 {
1760 for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
1761 {
1762 const ScRange & rRange = rRanges[ i ];
1763 if ( !rClipRange.Contains( rRange ) )
1764 {
1765 return false; // at least one range is not valid
1766 }
1767 }
1768 }
1769
1770 return true; // everything is fine
1771}
1772
1773static bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const ScRange& rSourceRange,
1774 const ScAddress& rDestPos, const ScDocument& rDoc )
1775{
1776 bool bChanged = false;
1777
1778 ScRange aErrorRange( ScAddress::UNINITIALIZED );
1779 for( ScRangeList& rRanges : rRangesVector )
1780 {
1781 for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
1782 {
1783 ScRange & rRange = rRanges[ i ];
1784 if ( rSourceRange.Contains( rRange ) )
1785 {
1786 SCCOL nDiffX = rDestPos.Col() - rSourceRange.aStart.Col();
1787 SCROW nDiffY = rDestPos.Row() - rSourceRange.aStart.Row();
1788 SCTAB nDiffZ = rDestPos.Tab() - rSourceRange.aStart.Tab();
1789 if (!rRange.Move( nDiffX, nDiffY, nDiffZ, aErrorRange, rDoc ))
1790 {
1791 assert(!"can't move range");
1792 }
1793 bChanged = true;
1794 }
1795 }
1796 }
1797
1798 return bChanged;
1799}
1800
1801void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const tools::Rectangle& rSourceRange,
1802 const ScAddress& rDestPos, const tools::Rectangle& rDestRange )
1803{
1804 OSL_ENSURE( pDoc, "ScDrawLayer::CopyFromClip without document" );
1805 if ( !pDoc )
1806 return;
1807
1808 if (!pClipModel)
1809 return;
1810
1811 if (bDrawIsInUndo) //TODO: can this happen?
1812 {
1813 OSL_FAIL("CopyFromClip, bDrawIsInUndo");
1814 return;
1815 }
1816
1817 bool bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 &&
1818 rDestRange.Left() > 0 && rDestRange.Right() > 0 ) ||
1819 ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 &&
1820 rDestRange.Left() < 0 && rDestRange.Right() < 0 );
1821 tools::Rectangle aMirroredSource = rSourceRange;
1822 if ( bMirrorObj )
1823 MirrorRectRTL( aMirroredSource );
1824
1825 SCTAB nDestTab = rDestPos.Tab();
1826
1827 SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab));
1828 SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab));
1829 OSL_ENSURE( pSrcPage && pDestPage, "draw page missing" );
1830 if ( !pSrcPage || !pDestPage )
1831 return;
1832
1833 SdrObjListIter aIter( pSrcPage, SdrIterMode::Flat );
1834 SdrObject* pOldObject = aIter.Next();
1835
1836 ScDocument* pClipDoc = pClipModel->GetDocument();
1837 // a clipboard document and its source share the same document item pool,
1838 // so the pointers can be compared to see if this is copy&paste within
1839 // the same document
1840 bool bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool();
1841 bool bDestClip = pDoc && pDoc->IsClipboard();
1842
1843 //#i110034# charts need correct sheet names for xml range conversion during load
1844 //so the target sheet name is temporarily renamed (if we have any SdrObjects)
1845 OUString aDestTabName;
1846 bool bRestoreDestTabName = false;
1847 if( pOldObject && !bSameDoc && !bDestClip )
1848 {
1849 if( pDoc && pClipDoc )
1850 {
1851 OUString aSourceTabName;
1852 if( pClipDoc->GetName( nSourceTab, aSourceTabName )
1853 && pDoc->GetName( nDestTab, aDestTabName ) )
1854 {
1855 if( aSourceTabName != aDestTabName &&
1856 pDoc->ValidNewTabName(aSourceTabName) )
1857 {
1858 bRestoreDestTabName = pDoc->RenameTab( nDestTab, aSourceTabName );
1859 }
1860 }
1861 }
1862 }
1863
1864 // first mirror, then move
1865 Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() );
1866
1867 tools::Long nDestWidth = rDestRange.GetWidth();
1868 tools::Long nDestHeight = rDestRange.GetHeight();
1869 tools::Long nSourceWidth = rSourceRange.GetWidth();
1870 tools::Long nSourceHeight = rSourceRange.GetHeight();
1871
1872 tools::Long nWidthDiff = nDestWidth - nSourceWidth;
1873 tools::Long nHeightDiff = nDestHeight - nSourceHeight;
1874
1875 Fraction aHorFract(1,1);
1876 Fraction aVerFract(1,1);
1877 bool bResize = false;
1878 // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes,
1879 // don't resize to empty size when pasting into hidden columns or rows
1880 if ( std::abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 )
1881 {
1882 aHorFract = Fraction( nDestWidth, nSourceWidth );
1883 bResize = true;
1884 }
1885 if ( std::abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 )
1886 {
1887 aVerFract = Fraction( nDestHeight, nSourceHeight );
1888 bResize = true;
1889 }
1890 Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving)
1891
1892 while (pOldObject)
1893 {
1894 tools::Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1895 // do not copy internal objects (detective) and note captions
1896
1897 SCTAB nClipTab = bRestoreDestTabName ? nDestTab : nSourceTab;
1898 ScRange aClipRange = lcl_getClipRangeFromClipDoc(pClipDoc, nClipTab);
1899
1900 bool bObjectInArea = rSourceRange.Contains(aObjRect);
1901 const ScDrawObjData* pObjData = ScDrawLayer::GetObjData(pOldObject);
1902 if (pObjData) // Consider images anchored to the copied cell
1903 bObjectInArea = bObjectInArea || aClipRange.Contains(pObjData->maStart);
1904 if (bObjectInArea && (pOldObject->GetLayer() != SC_LAYER_INTERN)
1905 && !IsNoteCaption(pOldObject))
1906 {
1907 // Clone to target SdrModel
1908 rtl::Reference<SdrObject> pNewObject(pOldObject->CloneSdrObject(*this));
1909
1910 if ( bMirrorObj )
1911 MirrorRTL( pNewObject.get() ); // first mirror, then move
1912
1913 pNewObject->NbcMove( aMove );
1914 if ( bResize )
1915 pNewObject->NbcResize( aRefPos, aHorFract, aVerFract );
1916
1917 pDestPage->InsertObject( pNewObject.get() );
1918 if (bRecording)
1919 AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pNewObject ) );
1920
1921 //#i110034# handle chart data references (after InsertObject)
1922
1923 if ( pNewObject->GetObjIdentifier() == SdrObjKind::OLE2 )
1924 {
1925 uno::Reference< embed::XEmbeddedObject > xIPObj = static_cast<SdrOle2Obj*>(pNewObject.get())->GetObjRef();
1926 uno::Reference< embed::XClassifiedObject > xClassified = xIPObj;
1927 SvGlobalName aObjectClassName;
1928 if ( xClassified.is() )
1929 {
1930 try {
1931 aObjectClassName = SvGlobalName( xClassified->getClassID() );
1932 } catch( uno::Exception& )
1933 {
1934 // TODO: handle error?
1935 }
1936 }
1937
1938 if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) )
1939 {
1940 uno::Reference< chart2::XChartDocument > xNewChart( ScChartHelper::GetChartFromSdrObject( pNewObject.get() ) );
1941 if( xNewChart.is() && !xNewChart->hasInternalDataProvider() )
1942 {
1943 OUString aChartName = static_cast<SdrOle2Obj*>(pNewObject.get())->GetPersistName();
1944 ::std::vector< ScRangeList > aRangesVector;
1945 pDoc->GetChartRanges( aChartName, aRangesVector, *pDoc );
1946 if( !aRangesVector.empty() )
1947 {
1948 bool bInSourceRange = false;
1949 if ( pClipDoc )
1950 {
1951 bInSourceRange = lcl_IsAllInRange( aRangesVector, aClipRange );
1952 }
1953
1954 // always lose references when pasting into a clipboard document (transpose)
1955 if ( ( bInSourceRange || bSameDoc ) && !bDestClip )
1956 {
1957 if ( bInSourceRange )
1958 {
1959 if ( rDestPos != aClipRange.aStart )
1960 {
1961 // update the data ranges to the new (copied) position
1962 if ( lcl_MoveRanges( aRangesVector, aClipRange, rDestPos, *pDoc ) )
1963 pDoc->SetChartRanges( aChartName, aRangesVector );
1964 }
1965 }
1966 else
1967 {
1968 // leave the ranges unchanged
1969 }
1970 }
1971 else
1972 {
1973 // pasting into a new document without the complete source data
1974 // -> break connection to source data and switch to own data
1975
1976 uno::Reference< chart::XChartDocument > xOldChartDoc( ScChartHelper::GetChartFromSdrObject( pOldObject ), uno::UNO_QUERY );
1977 uno::Reference< chart::XChartDocument > xNewChartDoc( xNewChart, uno::UNO_QUERY );
1978 if( xOldChartDoc.is() && xNewChartDoc.is() )
1979 xNewChartDoc->attachData( xOldChartDoc->getData() );
1980
1981 // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1982 }
1983 }
1984 }
1985 }
1986 }
1987 }
1988
1989 pOldObject = aIter.Next();
1990 }
1991
1992 if( bRestoreDestTabName )
1993 pDoc->RenameTab( nDestTab, aDestTabName );
1994}
1995
1997{
1998 OSL_ENSURE( pDoc, "ScDrawLayer::MirrorRTL - missing document" );
1999 if( !pDoc )
2000 return;
2001
2002 SdrObjKind nIdent = pObj->GetObjIdentifier();
2003
2004 // don't mirror OLE or graphics, otherwise ask the object
2005 // if it can be mirrored
2006 bool bCanMirror = ( nIdent != SdrObjKind::Graphic && nIdent != SdrObjKind::OLE2 );
2007 if (bCanMirror)
2008 {
2010 pObj->TakeObjInfo( aInfo );
2011 bCanMirror = aInfo.bMirror90Allowed;
2012 }
2013
2014 if (bCanMirror)
2015 {
2017 if (pData) // cell anchored
2018 {
2019 // Remember values from positive side.
2020 const tools::Rectangle aOldSnapRect = pObj->GetSnapRect();
2021 const tools::Rectangle aOldLogicRect = pObj->GetLogicRect();
2022 // Generate noRotate anchor if missing.
2023 ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj);
2024 if (!pNoRotatedAnchor)
2025 {
2026 ScDrawObjData aNoRotateAnchor;
2027 const tools::Rectangle aLogicRect(pObj->GetLogicRect());
2028 GetCellAnchorFromPosition(aLogicRect, aNoRotateAnchor,
2029 *pDoc, pData->maStart.Tab());
2030 aNoRotateAnchor.mbResizeWithCell = pData->mbResizeWithCell;
2031 SetNonRotatedAnchor(*pObj, aNoRotateAnchor);
2032 pNoRotatedAnchor = GetNonRotatedObjData(pObj);
2033 assert(pNoRotatedAnchor);
2034 }
2035 // Mirror object at vertical axis
2036 Point aRef1( 0, 0 );
2037 Point aRef2( 0, 1 );
2038 if (bRecording)
2039 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
2040 pObj->Mirror( aRef1, aRef2 );
2041
2042 // Adapt offsets in pNoRotatedAnchor so, that object will be moved to current position in
2043 // save and reload.
2044 const tools::Long nInverseShift = aOldSnapRect.Left() + aOldSnapRect.Right();
2045 const Point aLogicLT = pObj->GetLogicRect().TopLeft();
2046 const Point aMirroredLogicLT = aLogicLT + Point(nInverseShift, 0);
2047 const Point aOffsetDiff = aMirroredLogicLT - aOldLogicRect.TopLeft();
2048 // new Offsets
2049 pNoRotatedAnchor->maStartOffset += aOffsetDiff;
2050 pNoRotatedAnchor->maEndOffset += aOffsetDiff;
2051 }
2052 else // page anchored
2053 {
2054 Point aRef1( 0, 0 );
2055 Point aRef2( 0, 1 );
2056 if (bRecording)
2057 AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *pObj ) );
2058 pObj->Mirror( aRef1, aRef2 );
2059 }
2060 }
2061 else
2062 {
2063 // Move instead of mirroring:
2064 // New start position is negative of old end position
2065 // -> move by sum of start and end position
2066 tools::Rectangle aObjRect = pObj->GetSnapRect();
2067 Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
2068 if (bRecording)
2069 AddCalcUndo( std::make_unique<SdrUndoMoveObj>( *pObj, aMoveSize ) );
2070 pObj->Move( aMoveSize );
2071 }
2072
2073 // for cell anchored objects adapt rectangles in anchors
2075 if (pData)
2076 {
2077 pData->setShapeRect(GetDocument(), pObj->GetSnapRect(), pObj->IsVisible());
2078 ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj, true /*bCreate*/);
2079 pNoRotatedAnchor->setShapeRect(GetDocument(), pObj->GetLogicRect(), pObj->IsVisible());
2080 }
2081}
2082
2084{
2085 tools::Rectangle aObjRect = pObj->GetSnapRect();
2086 Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
2087 if (bRecording)
2088 AddCalcUndo( std::make_unique<SdrUndoMoveObj>( *pObj, aMoveSize ) );
2089 pObj->Move( aMoveSize );
2090
2091 // for cell anchored objects adapt rectangles in anchors
2093 if (pData)
2094 {
2095 pData->setShapeRect(GetDocument(), pObj->GetSnapRect(), pObj->IsVisible());
2096 ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData(pObj, true /*bCreate*/);
2097 pNoRotatedAnchor->setShapeRect(GetDocument(), pObj->GetLogicRect(), pObj->IsVisible());
2098 }
2099}
2100
2102{
2103 // mirror and swap left/right
2104 tools::Long nTemp = rRect.Left();
2105 rRect.SetLeft( -rRect.Right() );
2106 rRect.SetRight( -nTemp );
2107}
2108
2109tools::Rectangle ScDrawLayer::GetCellRect( const ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell )
2110{
2111 tools::Rectangle aCellRect;
2112 OSL_ENSURE( rDoc.ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
2113 if( rDoc.ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) )
2114 {
2115 // find top left position of passed cell address
2116 Point aTopLeft;
2117 for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol )
2118 aTopLeft.AdjustX(rDoc.GetColWidth( nCol, rPos.Tab() ) );
2119 if( rPos.Row() > 0 )
2120 aTopLeft.AdjustY(rDoc.GetRowHeight( 0, rPos.Row() - 1, rPos.Tab() ) );
2121
2122 // find bottom-right position of passed cell address
2123 ScAddress aEndPos = rPos;
2124 if( bMergedCell )
2125 {
2126 const ScMergeAttr* pMerge = rDoc.GetAttr( rPos, ATTR_MERGE );
2127 if( pMerge->GetColMerge() > 1 )
2128 aEndPos.IncCol( pMerge->GetColMerge() - 1 );
2129 if( pMerge->GetRowMerge() > 1 )
2130 aEndPos.IncRow( pMerge->GetRowMerge() - 1 );
2131 }
2132 Point aBotRight = aTopLeft;
2133 for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol )
2134 aBotRight.AdjustX(rDoc.GetColWidth( nCol, rPos.Tab() ) );
2135 aBotRight.AdjustY(rDoc.GetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() ) );
2136
2137 // twips -> 1/100 mm
2139 aBotRight = o3tl::convert(aBotRight, o3tl::Length::twip, o3tl::Length::mm100);
2140
2141 aCellRect = tools::Rectangle( aTopLeft, aBotRight );
2142 if( rDoc.IsNegativePage( rPos.Tab() ) )
2143 MirrorRectRTL( aCellRect );
2144 }
2145 return aCellRect;
2146}
2147
2149{
2150 OUString aName = pObj->GetName();
2151 if ( pObj->GetObjIdentifier() == SdrObjKind::OLE2 )
2152 {
2153 // For OLE, the user defined name (GetName) is used
2154 // if it's not empty (accepting possibly duplicate names),
2155 // otherwise the persist name is used so every object appears
2156 // in the Navigator at all.
2157
2158 if ( aName.isEmpty() )
2159 aName = static_cast<const SdrOle2Obj*>(pObj)->GetPersistName();
2160 }
2161 return aName;
2162}
2163
2164static bool IsNamedObject( const SdrObject* pObj, std::u16string_view rName )
2165{
2166 // sal_True if rName is the object's Name or PersistName
2167 // (used to find a named object)
2168
2169 return ( pObj->GetName() == rName ||
2170 ( pObj->GetObjIdentifier() == SdrObjKind::OLE2 &&
2171 static_cast<const SdrOle2Obj*>(pObj)->GetPersistName() == rName ) );
2172}
2173
2174SdrObject* ScDrawLayer::GetNamedObject( std::u16string_view rName, SdrObjKind nId, SCTAB& rFoundTab ) const
2175{
2176 sal_uInt16 nTabCount = GetPageCount();
2177 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
2178 {
2179 const SdrPage* pPage = GetPage(nTab);
2180 OSL_ENSURE(pPage,"Page ?");
2181 if (pPage)
2182 {
2183 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
2184 SdrObject* pObject = aIter.Next();
2185 while (pObject)
2186 {
2187 if ( nId == SdrObjKind::NONE || pObject->GetObjIdentifier() == nId )
2188 if ( IsNamedObject( pObject, rName ) )
2189 {
2190 rFoundTab = static_cast<SCTAB>(nTab);
2191 return pObject;
2192 }
2193
2194 pObject = aIter.Next();
2195 }
2196 }
2197 }
2198
2199 return nullptr;
2200}
2201
2203{
2204 OUString aBase = ScResId(STR_GRAPHICNAME) + " ";
2205
2206 bool bThere = true;
2207 OUString aGraphicName;
2208 SCTAB nDummy;
2209 tools::Long nId = pnCounter ? *pnCounter : 0;
2210 while (bThere)
2211 {
2212 ++nId;
2213 aGraphicName = aBase + OUString::number( nId );
2214 bThere = ( GetNamedObject( aGraphicName, SdrObjKind::NONE, nDummy ) != nullptr );
2215 }
2216
2217 if ( pnCounter )
2218 *pnCounter = nId;
2219
2220 return aGraphicName;
2221}
2222
2224{
2225 // make sure all graphic objects have names (after Excel import etc.)
2226
2227 sal_uInt16 nTabCount = GetPageCount();
2228 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
2229 {
2230 SdrPage* pPage = GetPage(nTab);
2231 OSL_ENSURE(pPage,"Page ?");
2232 if (pPage)
2233 {
2234 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups );
2235 SdrObject* pObject = aIter.Next();
2236
2237 /* The index passed to GetNewGraphicName() will be set to
2238 the used index in each call. This prevents the repeated search
2239 for all names from 1 to current index. */
2240 tools::Long nCounter = 0;
2241
2242 while (pObject)
2243 {
2244 if ( pObject->GetObjIdentifier() == SdrObjKind::Graphic && pObject->GetName().isEmpty())
2245 pObject->SetName( GetNewGraphicName( &nCounter ) );
2246
2247 pObject = aIter.Next();
2248 }
2249 }
2250 }
2251}
2252
2253namespace
2254{
2255 SdrObjUserData* GetFirstUserDataOfType(const SdrObject *pObj, sal_uInt16 nId)
2256 {
2257 sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
2258 for( sal_uInt16 i = 0; i < nCount; i++ )
2259 {
2260 SdrObjUserData* pData = pObj->GetUserData( i );
2261 if( pData && pData->GetInventor() == SdrInventor::ScOrSwDraw && pData->GetId() == nId )
2262 return pData;
2263 }
2264 return nullptr;
2265 }
2266
2267 void DeleteFirstUserDataOfType(SdrObject *pObj, sal_uInt16 nId)
2268 {
2269 sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
2270 for( sal_uInt16 i = nCount; i > 0; i-- )
2271 {
2272 SdrObjUserData* pData = pObj->GetUserData( i-1 );
2273 if( pData && pData->GetInventor() == SdrInventor::ScOrSwDraw && pData->GetId() == nId )
2274 pObj->DeleteUserData(i-1);
2275 }
2276 }
2277}
2278
2280{
2281 ScDrawObjData* pAnchor = GetNonRotatedObjData( &rObj, true );
2282 pAnchor->maStart = rAnchor.maStart;
2283 pAnchor->maEnd = rAnchor.maEnd;
2284 pAnchor->maStartOffset = rAnchor.maStartOffset;
2285 pAnchor->maEndOffset = rAnchor.maEndOffset;
2286 pAnchor->mbResizeWithCell = rAnchor.mbResizeWithCell;
2287}
2288
2290{
2291 ScDrawObjData* pAnchor = GetObjData( &rObj, true );
2292 pAnchor->maStart = rAnchor.maStart;
2293 pAnchor->maEnd = rAnchor.maEnd;
2294 pAnchor->maStartOffset = rAnchor.maStartOffset;
2295 pAnchor->maEndOffset = rAnchor.maEndOffset;
2296 pAnchor->mbResizeWithCell = rAnchor.mbResizeWithCell;
2297}
2298
2300 bool bResizeWithCell )
2301{
2302 if (!rObj.IsVisible())
2303 return;
2304 ScDrawObjData aAnchor;
2305 // set anchor in terms of the visual ( SnapRect )
2306 // object ( e.g. for when object is rotated )
2307 const tools::Rectangle aObjRect(rObj.GetSnapRect());
2309 aObjRect,
2310 aAnchor,
2311 rDoc,
2312 nTab);
2313
2314 aAnchor.mbResizeWithCell = bResizeWithCell;
2315 SetCellAnchored( rObj, aAnchor );
2316
2317 // absolutely necessary to set flag, ScDrawLayer::RecalcPos expects it.
2318 if ( ScDrawObjData* pAnchor = GetObjData( &rObj ) )
2319 {
2320 pAnchor->setShapeRect(&rDoc, rObj.GetSnapRect());
2321 }
2322
2323 // - keep also an anchor in terms of the Logic ( untransformed ) object
2324 // because that's what we stored ( and still do ) to xml
2325
2326 // Vertical flipped custom shapes need special treatment, see comment in
2327 // lcl_SetLogicRectFromAnchor
2328 tools::Rectangle aObjRect2;
2329 if (lcl_NeedsMirrorYCorrection(&rObj))
2330 {
2331 const tools::Rectangle aRect(rObj.GetSnapRect());
2332 const Point aLeft(aRect.Left(), (aRect.Top() + aRect.Bottom()) >> 1);
2333 const Point aRight(aLeft.X() + 1000, aLeft.Y());
2334 rObj.NbcMirror(aLeft, aRight);
2335 aObjRect2 = rObj.GetLogicRect();
2336 rObj.NbcMirror(aLeft, aRight);
2337 }
2338 else if (rObj.GetObjIdentifier() == SdrObjKind::Measure)
2339 {
2340 // tdf#137576. A SdrMeasureObj might have a wrong logic rect here. TakeUnrotatedSnapRect
2341 // calculates the current unrotated snap rectangle, sets logic rectangle and returns it.
2342 static_cast<SdrMeasureObj&>(rObj).TakeUnrotatedSnapRect(aObjRect2);
2343 }
2344 else
2345 aObjRect2 = rObj.GetLogicRect();
2346
2347 // Values in XML are so as if it is a LTR sheet. The object is shifted to negative page on loading
2348 // so that the snap rectangle appears mirrored. For transformed objects the shifted logic rectangle
2349 // is not the mirrored LTR rectangle. We calculate the mirrored LTR rectangle here.
2350 if (rDoc.IsNegativePage(nTab))
2351 {
2352 const tools::Rectangle aSnapRect(rObj.GetSnapRect());
2353 aObjRect2.Move(Size(-aSnapRect.Left() - aSnapRect.Right(), 0));
2354 MirrorRectRTL(aObjRect2);
2355 }
2356
2357 ScDrawObjData aNoRotatedAnchor;
2359 aObjRect2,
2360 aNoRotatedAnchor,
2361 rDoc,
2362 nTab);
2363
2364 aNoRotatedAnchor.mbResizeWithCell = bResizeWithCell;
2365 SetNonRotatedAnchor( rObj, aNoRotatedAnchor);
2366 // And update maShapeRect. It is used in adjustAnchoredPosition() in ScDrawView::Notify().
2367 if (ScDrawObjData* pAnchor = GetNonRotatedObjData(&rObj))
2368 {
2369 pAnchor->setShapeRect(&rDoc, rObj.GetLogicRect());
2370 }
2371}
2372
2374 const tools::Rectangle &rObjRect,
2375 ScDrawObjData &rAnchor,
2376 const ScDocument &rDoc,
2377 SCTAB nTab,
2378 bool bHiddenAsZero)
2379{
2380 ScRange aRange = rDoc.GetRange( nTab, rObjRect, bHiddenAsZero );
2381
2382 tools::Rectangle aCellRect;
2383
2384 rAnchor.maStart = aRange.aStart;
2385 aCellRect = rDoc.GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(),
2386 aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(), bHiddenAsZero );
2387 rAnchor.maStartOffset.setY( rObjRect.Top()-aCellRect.Top() );
2388 if (!rDoc.IsNegativePage(nTab))
2389 rAnchor.maStartOffset.setX( rObjRect.Left()-aCellRect.Left() );
2390 else
2391 rAnchor.maStartOffset.setX( aCellRect.Right()-rObjRect.Right() );
2392
2393 rAnchor.maEnd = aRange.aEnd;
2394 aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(),
2395 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), bHiddenAsZero );
2396 if (!rObjRect.IsEmpty())
2397 rAnchor.maEndOffset.setY( rObjRect.Bottom()-aCellRect.Top() );
2398 if (!rDoc.IsNegativePage(nTab))
2399 {
2400 if (!rObjRect.IsEmpty())
2401 rAnchor.maEndOffset.setX( rObjRect.Right()-aCellRect.Left() );
2402 }
2403 else
2404 rAnchor.maEndOffset.setX( aCellRect.Right()-rObjRect.Left() );
2405}
2406
2407void ScDrawLayer::UpdateCellAnchorFromPositionEnd( const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect )
2408{
2409 tools::Rectangle aObjRect(bUseLogicRect ? rObj.GetLogicRect() : rObj.GetSnapRect());
2410 ScRange aRange = rDoc.GetRange( nTab, aObjRect );
2411
2412 ScDrawObjData* pAnchor = &rAnchor;
2413 pAnchor->maEnd = aRange.aEnd;
2414
2415 tools::Rectangle aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(),
2416 aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab() );
2417 pAnchor->maEndOffset.setY( aObjRect.Bottom()-aCellRect.Top() );
2418 if (!rDoc.IsNegativePage(nTab))
2419 pAnchor->maEndOffset.setX( aObjRect.Right()-aCellRect.Left() );
2420 else
2421 pAnchor->maEndOffset.setX( aCellRect.Right()-aObjRect.Left() );
2422}
2423
2425{
2426 // Cell anchored object always has a user data, to store the anchor cell
2427 // info. If it doesn't then it's page-anchored.
2428 return GetFirstUserDataOfType(&rObj, SC_UD_OBJDATA) != nullptr;
2429}
2430
2432{
2433 // Cell anchored object always has a user data, to store the anchor cell
2434 // info. If it doesn't then it's page-anchored.
2435 ScDrawObjData* pDrawObjData = GetObjData(const_cast<SdrObject*>(&rObj));
2436 if (!pDrawObjData)
2437 return false;
2438
2439 return pDrawObjData->mbResizeWithCell;
2440}
2441
2443{
2444 DeleteFirstUserDataOfType(&rObj, SC_UD_OBJDATA);
2445 DeleteFirstUserDataOfType(&rObj, SC_UD_OBJDATA);
2446}
2447
2449{
2450 //If this object has a cell anchor associated with it
2451 //then it's cell-anchored, otherwise it's page-anchored
2452 const ScDrawObjData* pObjData = ScDrawLayer::GetObjData(const_cast<SdrObject*>(&rObj));
2453
2454 // When there is no cell anchor, it is page anchored.
2455 if (!pObjData)
2456 return SCA_PAGE;
2457
2458 // It's cell-anchored, check if the object resizes with the cell
2459 if (pObjData->mbResizeWithCell)
2460 return SCA_CELL_RESIZE;
2461
2462 return SCA_CELL;
2463}
2464
2465std::vector<SdrObject*>
2467{
2468 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
2469 if (!pPage || pPage->GetObjCount() < 1)
2470 return std::vector<SdrObject*>();
2471
2472 std::vector<SdrObject*> aObjects;
2473 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
2474 SdrObject* pObject = aIter.Next();
2475 ScRange aRange( 0, nStartRow, nTab, pDoc->MaxCol(), nEndRow, nTab);
2476 while (pObject)
2477 {
2478 if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
2479 {
2480 ScDrawObjData* pObjData = GetObjData(pObject);
2481 if (pObjData && aRange.Contains(pObjData->maStart))
2482 aObjects.push_back(pObject);
2483 }
2484 pObject = aIter.Next();
2485 }
2486 return aObjects;
2487}
2488
2489std::map<SCROW, std::vector<SdrObject*>>
2491{
2492 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
2493 if (!pPage || pPage->GetObjCount() < 1)
2494 return std::map<SCROW, std::vector<SdrObject*>>();
2495
2496 std::map<SCROW, std::vector<SdrObject*>> aRowObjects;
2497 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
2498 SdrObject* pObject = aIter.Next();
2499 ScRange aRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab);
2500 while (pObject)
2501 {
2502 if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
2503 {
2504 ScDrawObjData* pObjData = GetObjData(pObject);
2505 if (pObjData && aRange.Contains(pObjData->maStart))
2506 aRowObjects[pObjData->maStart.Row()].push_back(pObject);
2507 }
2508 pObject = aIter.Next();
2509 }
2510 return aRowObjects;
2511}
2512
2514{
2515 // This only works for one table at a time
2516 assert(rRange.aStart.Tab() == rRange.aEnd.Tab());
2517
2518 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(rRange.aStart.Tab()));
2519 if (!pPage || pPage->GetObjCount() < 1)
2520 return false;
2521
2522 SdrObjListIter aIter( pPage, SdrIterMode::Flat );
2523 SdrObject* pObject = aIter.Next();
2524 while (pObject)
2525 {
2526 if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
2527 {
2528 ScDrawObjData* pObjData = GetObjData(pObject);
2529 if (pObjData && rRange.Contains(pObjData->maStart)) // Object is in given range
2530 return true;
2531 }
2532 pObject = aIter.Next();
2533 }
2534 return false;
2535}
2536
2537std::vector<SdrObject*> ScDrawLayer::GetObjectsAnchoredToCols(SCTAB nTab, SCCOL nStartCol,
2538 SCCOL nEndCol)
2539{
2540 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
2541 if (!pPage || pPage->GetObjCount() < 1)
2542 return std::vector<SdrObject*>();
2543
2544 std::vector<SdrObject*> aObjects;
2545 SdrObjListIter aIter(pPage, SdrIterMode::Flat);
2546 SdrObject* pObject = aIter.Next();
2547 ScRange aRange(nStartCol, 0, nTab, nEndCol, pDoc->MaxRow(), nTab);
2548 while (pObject)
2549 {
2550 if (!dynamic_cast<SdrCaptionObj*>(pObject)) // Caption objects are handled differently
2551 {
2552 ScDrawObjData* pObjData = GetObjData(pObject);
2553 if (pObjData && aRange.Contains(pObjData->maStart))
2554 aObjects.push_back(pObject);
2555 }
2556 pObject = aIter.Next();
2557 }
2558 return aObjects;
2559}
2560
2561void ScDrawLayer::MoveObject(SdrObject* pObject, const ScAddress& rNewPosition)
2562{
2563 // Get anchor data
2564 ScDrawObjData* pObjData = GetObjData(pObject, false);
2565 if (!pObjData)
2566 return;
2567 const ScAddress aOldStart = pObjData->maStart;
2568 const ScAddress aOldEnd = pObjData->maEnd;
2569
2570 // Set start address
2571 pObjData->maStart = rNewPosition;
2572
2573 // Set end address
2574 const SCCOL nObjectColSpan = aOldEnd.Col() - aOldStart.Col();
2575 const SCROW nObjectRowSpan = aOldEnd.Row() - aOldStart.Row();
2576 ScAddress aNewEnd = rNewPosition;
2577 aNewEnd.IncRow(nObjectRowSpan);
2578 aNewEnd.IncCol(nObjectColSpan);
2579 pObjData->maEnd = aNewEnd;
2580
2581 // Update draw object according to new anchor
2582 RecalcPos(pObject, *pObjData, false, false);
2583}
2584
2586{
2587 sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
2588 sal_uInt16 nFound = 0;
2589 for( sal_uInt16 i = 0; i < nCount; i++ )
2590 {
2591 SdrObjUserData* pData = pObj->GetUserData( i );
2592 if( pData && pData->GetInventor() == SdrInventor::ScOrSwDraw && pData->GetId() == SC_UD_OBJDATA && ++nFound == 2 )
2593 return static_cast<ScDrawObjData*>(pData);
2594 }
2595 if( pObj && bCreate )
2596 {
2598 pObj->AppendUserData(std::unique_ptr<SdrObjUserData>(pData));
2599 return pData;
2600 }
2601 return nullptr;
2602}
2603
2605{
2606 if (SdrObjUserData *pData = GetFirstUserDataOfType(pObj, SC_UD_OBJDATA))
2607 return static_cast<ScDrawObjData*>(pData);
2608
2609 if( pObj && bCreate )
2610 {
2612 pObj->AppendUserData(std::unique_ptr<SdrObjUserData>(pData));
2613 return pData;
2614 }
2615 return nullptr;
2616}
2617
2619{
2620 ScDrawObjData* pData = GetObjData( pObj );
2621 if ( pData )
2622 {
2623 if ( pData->maStart.IsValid() )
2624 pData->maStart.SetTab( nTab );
2625 if ( pData->maEnd.IsValid() )
2626 pData->maEnd.SetTab( nTab );
2627 }
2628 return pData;
2629}
2630
2632{
2633 ScDrawObjData* pData = pObj ? GetObjData( pObj ) : nullptr;
2634 return pData && pData->meType == ScDrawObjData::CellNote;
2635}
2636
2638{
2639 ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : nullptr;
2640 return (pData && pData->meType == ScDrawObjData::CellNote) ? pData : nullptr;
2641}
2642
2644{
2645 if (SdrObjUserData *pData = GetFirstUserDataOfType(pObj, SC_UD_MACRODATA))
2646 return static_cast<ScMacroInfo*>(pData);
2647
2648 if ( bCreate )
2649 {
2651 pObj->AppendUserData(std::unique_ptr<SdrObjUserData>(pData));
2652 return pData;
2653 }
2654 return nullptr;
2655}
2656
2658{
2659 OSL_ENSURE(!pGlobalDrawPersist,"Multiple SetGlobalDrawPersist");
2660 pGlobalDrawPersist = pPersist;
2661}
2662
2663void ScDrawLayer::SetChanged( bool bFlg /* = true */ )
2664{
2665 if ( bFlg && pDoc )
2668}
2669
2670css::uno::Reference< css::uno::XInterface > ScDrawLayer::createUnoModel()
2671{
2672 css::uno::Reference< css::uno::XInterface > xRet;
2673 if( pDoc && pDoc->GetDocumentShell() )
2674 xRet = pDoc->GetDocumentShell()->GetModel();
2675
2676 return xRet;
2677}
2678
2679/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr auto convertTwipToMm100(N n)
const LanguageTag & GetLanguageTag() const
static const AllSettings & GetSettings()
virtual rtl::Reference< SdrPage > RemovePage(sal_uInt16 nPgNum) override
void SetObjectShell(SfxObjectShell *pShell)
virtual void InsertPage(SdrPage *pPage, sal_uInt16 nPos=0xFFFF) override
void SetName(const OUString &rName)
LanguageType getLanguageType(bool bResolveSystem=true) const
static css::uno::Reference< css::linguistic2::XHyphenator > GetHyphenator()
static bool isKorean(LanguageType nLang)
SfxItemPool * GetEditTextObjectPool() const
void SetCalcFieldValueHdl(const Link< EditFieldInfo *, void > &rLink)
@ UNINITIALIZED
Definition: address.hxx:220
SCTAB Tab() const
Definition: address.hxx:283
void SetCol(SCCOL nColP)
Definition: address.hxx:291
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:316
bool IsValid() const
Definition: address.hxx:305
SCROW Row() const
Definition: address.hxx:274
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
SCCOL Col() const
Definition: address.hxx:279
static css::uno::Reference< css::chart2::XChartDocument > GetChartFromSdrObject(const SdrObject *pObject)
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4224
SC_DLLPUBLIC ScRange GetRange(SCTAB nTab, const tools::Rectangle &rMMRect, bool bHiddenAsZero=true) const
Definition: documen3.cxx:1811
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4183
SC_DLLPUBLIC tools::Long GetColOffset(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4287
SC_DLLPUBLIC void InitDrawLayer(SfxObjectShell *pDocShell=nullptr)
Definition: documen9.cxx:98
SC_DLLPUBLIC bool ValidNewTabName(const OUString &rName) const
Definition: document.cxx:376
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:891
bool IsClipboard() const
Definition: document.hxx:1592
SC_DLLPUBLIC bool RenameTab(SCTAB nTab, const OUString &rName, bool bExternalDocument=false)
Definition: document.cxx:864
SCROW GetRowForHeight(SCTAB nTab, tools::Long nHeight) const
Given the height i.e.
Definition: document.cxx:4256
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6169
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:892
bool ValidColRowTab(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.hxx:901
SC_DLLPUBLIC void GetChartRanges(std::u16string_view rChartName, std::vector< ScRangeList > &rRanges, const ScDocument &rSheetNameDoc)
Definition: documen5.cxx:168
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Definition: document.cxx:6729
SC_DLLPUBLIC bool IsNegativePage(SCTAB nTab) const
Definition: document.cxx:1005
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1082
SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4492
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1081
void GetClipArea(SCCOL &nClipX, SCROW &nClipY, bool bIncludeFiltered)
Definition: document.cxx:3177
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4508
void SetChartRanges(std::u16string_view rChartName, const std::vector< ScRangeList > &rRanges)
Definition: documen5.cxx:185
bool IsUndoEnabled() const
Definition: document.hxx:1593
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:216
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4777
SC_DLLPUBLIC ScColumnsRange GetColumnsRange(SCTAB nTab, SCCOL nColBegin, SCCOL nColEnd) const
Definition: document.cxx:2577
void SetChartListenerCollectionNeedsUpdate(bool bFlg)
Definition: document.hxx:2235
void GetClipStart(SCCOL &nClipX, SCROW &nClipY)
Definition: document.cxx:3229
SC_DLLPUBLIC tools::Rectangle GetMMRect(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: documen3.cxx:2002
SC_DLLPUBLIC tools::Long GetRowOffset(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4295
bool IsImportingXML() const
Definition: document.hxx:2222
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:316
static SfxObjectShell * pGlobalDrawPersist
Definition: drwlayer.hxx:224
void ScCopyPage(sal_uInt16 nOldPos, sal_uInt16 nNewPos)
Definition: drwlayer.cxx:425
static ScDrawObjData * GetObjDataTab(SdrObject *pObj, SCTAB nTab)
Definition: drwlayer.cxx:2618
static tools::Rectangle GetCellRect(const ScDocument &rDoc, const ScAddress &rPos, bool bMergedCell)
Returns the rectangle for the passed cell address in 1/100 mm.
Definition: drwlayer.cxx:2109
virtual css::uno::Reference< css::uno::XInterface > createUnoModel() override
Definition: drwlayer.cxx:2670
void ResetTab(SCTAB nStart, SCTAB nEnd)
Definition: drwlayer.cxx:472
std::map< SCROW, std::vector< SdrObject * > > GetObjectsAnchoredToRange(SCTAB nTab, SCCOL nCol, SCROW nStartRow, SCROW nEndRow)
Definition: drwlayer.cxx:2490
void MoveArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCCOL nDx, SCROW nDy, bool bInsDel, bool bUpdateNoteCaptionPos)
Definition: drwlayer.cxx:1442
void ScRenamePage(SCTAB nTab, const OUString &rNewName)
Definition: drwlayer.cxx:411
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2604
bool bAdjustEnabled
Definition: drwlayer.hxx:104
static OUString GetVisibleName(const SdrObject *pObj)
Definition: drwlayer.cxx:2148
void UseHyphenator()
Definition: drwlayer.cxx:340
static void GetCellAnchorFromPosition(const tools::Rectangle &rRectangle, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bHiddenAsZero=true)
Definition: drwlayer.cxx:2373
static void SetNonRotatedAnchor(SdrObject &, const ScDrawObjData &rAnchor)
Definition: drwlayer.cxx:2279
static bool IsNoteCaption(SdrObject *pObj)
Returns true, if the passed object is the caption of a cell note.
Definition: drwlayer.cxx:2631
void CopyFromClip(ScDrawLayer *pClipModel, SCTAB nSourceTab, const tools::Rectangle &rSourceRange, const ScAddress &rDestPos, const tools::Rectangle &rDestRange)
Definition: drwlayer.cxx:1801
ScDocument * GetDocument() const
Definition: drwlayer.hxx:130
void SetPageSize(sal_uInt16 nPageNo, const Size &rSize, bool bUpdateNoteCaptionPos, const ScObjectHandling eObjectHandling=ScObjectHandling::RecalcPosMode)
Definition: drwlayer.cxx:570
static ScMacroInfo * GetMacroInfo(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2643
void EnsureGraphicNames()
Definition: drwlayer.cxx:2223
static void SetCellAnchoredFromPosition(SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell)
Definition: drwlayer.cxx:2299
std::vector< SdrObject * > GetObjectsAnchoredToCols(SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol)
Definition: drwlayer.cxx:2537
std::unique_ptr< SdrUndoGroup > pUndoGroup
Definition: drwlayer.hxx:102
bool bRecording
Definition: drwlayer.hxx:103
void RecalcPos(SdrObject *pObj, ScDrawObjData &rData, bool bNegativePage, bool bUpdateNoteCaptionPos)
Definition: drwlayer.cxx:1022
void DeleteObjectsInArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bAnchored=false)
Definition: drwlayer.cxx:1542
virtual ~ScDrawLayer() override
Definition: drwlayer.cxx:326
bool HasObjectsAnchoredInRange(const ScRange &rRange)
Definition: drwlayer.cxx:2513
static void SetPageAnchored(SdrObject &)
Definition: drwlayer.cxx:2442
bool ScAddPage(SCTAB nTab)
Definition: drwlayer.cxx:379
void BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager)
Definition: drwlayer.cxx:1427
std::unique_ptr< SdrUndoGroup > GetCalcUndo()
Definition: drwlayer.cxx:1434
void ScMovePage(sal_uInt16 nOldPos, sal_uInt16 nNewPos)
Definition: drwlayer.cxx:418
void DeleteObjectsInSelection(const ScMarkData &rMark)
Definition: drwlayer.cxx:1614
static ScAnchorType GetAnchorType(const SdrObject &)
Definition: drwlayer.cxx:2448
static ScDrawObjData * GetNonRotatedObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2585
static bool IsResizeWithCell(const SdrObject &rObj)
Definition: drwlayer.cxx:2431
static ScDrawObjData * GetNoteCaptionData(SdrObject *pObj, SCTAB nTab)
Returns the object data, if the passed object is a cell note caption.
Definition: drwlayer.cxx:2637
bool HasObjectsInRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow)
Definition: drwlayer.cxx:1488
void MirrorRTL(SdrObject *pObj)
Definition: drwlayer.cxx:1996
void ScRemovePage(SCTAB nTab)
Definition: drwlayer.cxx:393
bool GetPrintArea(ScRange &rRange, bool bSetHor, bool bSetVer) const
Definition: drwlayer.cxx:1256
void MoveObject(SdrObject *pObj, const ScAddress &rNewPosition)
Definition: drwlayer.cxx:2561
void AddCalcUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: drwlayer.cxx:1416
ScDrawLayer(ScDocument *pDocument, OUString aName)
Definition: drwlayer.cxx:232
virtual rtl::Reference< SdrPage > AllocPage(bool bMasterPage) override
Definition: drwlayer.cxx:354
static void SetCellAnchored(SdrObject &, const ScDrawObjData &rAnchor)
Definition: drwlayer.cxx:2289
void CopyToClip(ScDocument *pClipDoc, SCTAB nTab, const tools::Rectangle &rRange)
Definition: drwlayer.cxx:1691
void MoveCells(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCCOL nDx, SCROW nDy, bool bUpdateNoteCaptionPos)
Definition: drwlayer.cxx:508
void MoveRTL(SdrObject *pObj)
Definition: drwlayer.cxx:2083
ScDocument * pDoc
Definition: drwlayer.hxx:101
static void MirrorRectRTL(tools::Rectangle &rRect)
Definition: drwlayer.cxx:2101
void InitializeCellAnchoredObj(SdrObject *pObj, ScDrawObjData &rData)
Definition: drwlayer.cxx:905
OUString aName
Definition: drwlayer.hxx:100
bool HasObjects() const
Definition: drwlayer.cxx:359
std::vector< SdrObject * > GetObjectsAnchoredToRows(SCTAB nTab, SCROW nStartRow, SCROW nEndRow)
Definition: drwlayer.cxx:2466
void ResizeLastRectFromAnchor(const SdrObject *pObj, ScDrawObjData &rData, bool bNegativePage, bool bCanResize)
Definition: drwlayer.cxx:752
static void UpdateCellAnchorFromPositionEnd(const SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect=true)
Definition: drwlayer.cxx:2407
static void SetGlobalDrawPersist(SfxObjectShell *pPersist)
Definition: drwlayer.cxx:2657
bool bHyphenatorSet
Definition: drwlayer.hxx:105
virtual void SetChanged(bool bFlg=true) override
Definition: drwlayer.cxx:2663
static bool IsCellAnchored(const SdrObject &rObj)
Definition: drwlayer.cxx:2424
OUString GetNewGraphicName(tools::Long *pnCounter=nullptr) const
Definition: drwlayer.cxx:2202
virtual SdrModel * AllocModel() const override
Definition: drwlayer.cxx:371
SdrObject * GetNamedObject(std::u16string_view rName, SdrObjKind nId, SCTAB &rFoundTab) const
Definition: drwlayer.cxx:2174
bool mbWasInHiddenRow
Definition: userdat.hxx:42
ScAddress maStart
Definition: userdat.hxx:36
const tools::Rectangle & getShapeRect() const
Definition: userdat.hxx:46
Point maStartOffset
Definition: userdat.hxx:38
const tools::Rectangle & getLastCellRect() const
Definition: userdat.hxx:47
Point maEndOffset
Definition: userdat.hxx:39
@ ValidationCircle
Definition: userdat.hxx:34
void setShapeRect(const ScDocument *rDoc, tools::Rectangle rNewRect, bool bIsVisible=true)
Definition: userdat.hxx:48
bool mbResizeWithCell
Definition: userdat.hxx:41
ScAddress maEnd
Definition: userdat.hxx:37
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
bool IsAllMarked(const ScRange &rRange) const
Definition: markdata.cxx:565
const ScRange & GetMultiMarkArea() const
Definition: markdata.hxx:84
bool IsMultiMarked() const
Definition: markdata.hxx:81
bool IsCellMarked(SCCOL nCol, SCROW nRow, bool bNoSimple=false) const
Definition: markdata.cxx:270
SCCOL GetColMerge() const
Definition: attrib.hxx:68
SCROW GetRowMerge() const
Definition: attrib.hxx:69
Additional class containing cell annotation data.
Definition: postit.hxx:58
bool Move(SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ, ScRange &rErrorRange, const ScDocument &rDoc)
Definition: address.cxx:2330
ScAddress aEnd
Definition: address.hxx:498
bool Contains(const ScAddress &) const
is Address& fully in Range?
Definition: address.hxx:718
ScAddress aStart
Definition: address.hxx:497
ScTabDeletedHint(SCTAB nTabNo)
Definition: drwlayer.cxx:189
virtual ~ScTabDeletedHint() override
Definition: drwlayer.cxx:194
virtual ~ScTabSizeChangedHint() override
Definition: drwlayer.cxx:203
ScTabSizeChangedHint(SCTAB nTabNo)
Definition: drwlayer.cxx:198
virtual void Redo() override
Definition: drwlayer.cxx:174
ScDocument * mpDoc
Definition: drwlayer.hxx:79
virtual ~ScUndoAnchorData() override
Definition: drwlayer.cxx:155
bool mbWasResizeWithCell
Definition: drwlayer.hxx:78
virtual void Undo() override
Definition: drwlayer.cxx:159
bool mbWasCellAnchored
Definition: drwlayer.hxx:77
ScUndoAnchorData(SdrObject *pObj, ScDocument *pDoc, SCTAB nTab)
Definition: drwlayer.cxx:146
virtual ~ScUndoObjData() override
Definition: drwlayer.cxx:104
ScAddress aOldEnd
Definition: drwlayer.hxx:62
ScAddress aNewStt
Definition: drwlayer.hxx:63
ScAddress aNewEnd
Definition: drwlayer.hxx:64
virtual void Redo() override
Definition: drwlayer.cxx:127
virtual void Undo() override
Definition: drwlayer.cxx:108
ScAddress aOldStt
Definition: drwlayer.hxx:61
ScUndoObjData(SdrObject *pObj, const ScAddress &rOS, const ScAddress &rOE, const ScAddress &rNS, const ScAddress &rNE)
Definition: drwlayer.cxx:94
const OUString & GetControlLayerName() const
SdrLayer * NewLayer(const OUString &rName, sal_uInt16 nPos=0xFFFF)
virtual void TakeUnrotatedSnapRect(tools::Rectangle &rRect) const override
bool isLocked() const
virtual void SetChanged(bool bFlg=true)
void SetVOCInvalidationIsReliable(bool b)
virtual void MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
void ClearModel(bool bCalledFromDestructor)
SdrOutliner & GetDrawOutliner(const SdrTextObj *pObj=nullptr) const
void setLock(bool bLock)
const SfxItemPool & GetItemPool() const
void SetScaleUnit(MapUnit eMap)
void EnableUndo(bool bEnable)
rtl::Reference< SfxItemPool > m_pItemPool
void SetSwapGraphics()
void SetDisableTextEditUsesCommonUndoManager(bool bNew)
virtual void DeletePage(sal_uInt16 nPgNum)
void SetPropertyList(XPropertyListRef const &p)
const SdrPage * GetPage(sal_uInt16 nPgNum) const
const SdrLayerAdmin & GetLayerAdmin() const
sal_uInt16 GetPageCount() const
SdrOutliner & GetHitTestOutliner() const
SdrObject * Next()
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
SdrObject * GetObj(size_t nNum) const
size_t GetObjCount() const
void RecalcObjOrdNums()
virtual rtl::Reference< SdrObject > RemoveObject(size_t nObjNum)
bool IsResizeProtect() const
virtual void NbcSetLogicRect(const tools::Rectangle &rRect)
virtual void NbcResize(const Point &rRef, const Fraction &xFact, const Fraction &yFact)
void AppendUserData(std::unique_ptr< SdrObjUserData > pData)
virtual Point GetPoint(sal_uInt32 i) const
void BroadcastObjectChange() const
sal_uInt16 GetUserDataCount() const
void SetVisible(bool bVisible)
virtual void Mirror(const Point &rRef1, const Point &rRef2)
virtual bool IsPolyObj() const
virtual void Move(const Size &rSiz)
virtual const tools::Rectangle & GetCurrentBoundRect() const
virtual void NbcMirror(const Point &rRef1, const Point &rRef2)
SdrModel & getSdrModelFromSdrObject() const
virtual const tools::Rectangle & GetSnapRect() const
virtual void SetLogicRect(const tools::Rectangle &rRect)
const OUString & GetName() const
SdrObjUserData * GetUserData(sal_uInt16 nNum) const
virtual void AdjustToMaxRect(const tools::Rectangle &rMaxRect, bool bShrinkOnly=false)
void SetPoint(const Point &rPnt, sal_uInt32 i)
virtual SdrObjKind GetObjIdentifier() const
virtual void SetSnapRect(const tools::Rectangle &rRect)
bool IsVisible() const
virtual SdrLayerID GetLayer() const
void DeleteUserData(sal_uInt16 nNum)
virtual rtl::Reference< SdrObject > CloneSdrObject(SdrModel &rTargetModel) const
virtual void SetRelativePos(const Point &rPnt)
virtual bool shouldKeepAspectRatio() const
virtual void NbcMove(const Size &rSiz)
virtual Point GetRelativePos() const
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const
virtual const tools::Rectangle & GetLogicRect() const
const OUString & GetPersistName() const
Size GetSize() const
virtual void SetSize(const Size &aSiz)
rtl::Reference< SdrObject > mxObj
SfxItemPool * GetSecondaryPool() const
void FreezeIdRanges()
void SetPoolDefaultItem(const SfxPoolItem &)
void SetDefaultMetric(MapUnit eNewMetric)
css::uno::Reference< css::frame::XModel3 > GetModel() const
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
static sal_uInt16 IsChart(const SvGlobalName &rName)
const XColorListRef & GetColorList() const
static XColorListRef GetStdColorList()
void translate(double fX, double fY)
void scale(double fX, double fY)
void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix &rMatrix)
TYPE getMaxX() const
TYPE getMinX() const
TYPE getMinY() const
TYPE getMaxY() const
TYPE getX() const
TYPE getY() const
constexpr tools::Long GetWidth() const
bool Contains(const Point &rPOINT) const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr tools::Long Top() const
constexpr Point TopLeft() const
void SetPos(const Point &rPoint)
void setWidth(tools::Long n)
constexpr void SetRight(tools::Long v)
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
constexpr tools::Long GetHeight() const
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void setHeight(tools::Long n)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
constexpr Point BottomLeft() const
int nCount
#define MAXMM
Definition: drwlayer.cxx:207
static sal_uInt16 nInst
Definition: drwlayer.cxx:88
bool bDrawIsInUndo
Definition: drwlayer.cxx:92
static E3dObjFactory * pF3d
Definition: drwlayer.cxx:87
#define DET_ARROW_OFFSET
Definition: drwlayer.cxx:83
static bool lcl_IsAllInRange(const ::std::vector< ScRangeList > &rRangesVector, const ScRange &rClipRange)
Definition: drwlayer.cxx:1754
static bool lcl_MoveRanges(::std::vector< ScRangeList > &rRangesVector, const ScRange &rSourceRange, const ScAddress &rDestPos, const ScDocument &rDoc)
Definition: drwlayer.cxx:1773
static ScRange lcl_getClipRangeFromClipDoc(ScDocument *pClipDoc, SCTAB nClipTab)
Definition: drwlayer.cxx:215
static bool IsNamedObject(const SdrObject *pObj, std::u16string_view rName)
Definition: drwlayer.cxx:2164
static bool IsInBlock(const ScAddress &rPos, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: drwlayer.cxx:502
static void lcl_ReverseTwipsToMM(tools::Rectangle &rRect)
Definition: drwlayer.cxx:210
ScObjectHandling
Definition: drwlayer.hxx:91
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT(EE_CHAR_START+2)
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT_CTL(EE_CHAR_START+20)
constexpr TypedWhichId< SvxFrameDirectionItem > EE_PARA_WRITINGDIR(EE_PARA_START+0)
constexpr TypedWhichId< SvxScriptSpaceItem > EE_PARA_ASIANCJKSPACING(EE_PARA_START+4)
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT_CJK(EE_CHAR_START+19)
EmbeddedObjectRef * pObject
ScAnchorType
Definition: global.hxx:373
@ SCA_CELL_RESIZE
Definition: global.hxx:375
@ SCA_CELL
Definition: global.hxx:374
@ SCA_PAGE
Definition: global.hxx:376
constexpr SdrLayerID SC_LAYER_HIDDEN(4)
constexpr SdrLayerID SC_LAYER_FRONT(0)
constexpr SdrLayerID SC_LAYER_INTERN(2)
constexpr SdrLayerID SC_LAYER_BACK(1)
constexpr SdrLayerID SC_LAYER_CONTROLS(3)
tools::Long FRound(double fVal)
OUString aName
void * p
#define LANGUAGE_JAPANESE
const long LONG_MAX
std::unique_ptr< sal_Int32[]> pData
B2DRange getRange(const B2DPolygon &rCandidate)
B2IRange fround(const B2DRange &rRange)
int i
constexpr auto toTwips(N number, Length from)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
long Long
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
sal_Int16 nId
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
#define SC_MOD()
Definition: scmod.hxx:249
SdrMetricItem makeSdrShadowXDistItem(tools::Long nDist)
SdrMetricItem makeSdrShadowYDistItem(tools::Long nDist)
UNDERLYING_TYPE get() const
SdrObjKind
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
#define SC_UD_MACRODATA
Definition: userdat.hxx:29
#define SC_UD_OBJDATA
Definition: userdat.hxx:27