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